← LeisureLinux 文章索引
LeisureLinux · 微信公众号文章

小龙女与公众号的异地恋:SSH 隧道 + autossh + goproxy 搞定动态 IP 发布,无需每次修改公众号后台配置 IP 白名单

AI/Agent 阅读原文(微信)↗

编按:逗死我了,标题和以下正文和附件都是 DeepSeek 杜撰的。 但是我对这个思路负责。对代码和写的一些具体内容,请各位看官自行判断。我没丢给它公众号后台必须手工配置 IP 白名单的信息。 标题的后半句是我手工添加的。

一个问题

我的\"小龙女\"AI 助手——部署在树莓派上,每天帮我自动抓取 RSS、生成 AI 解读、排版发布到LeisureLinux微信公众号。

这个小流程跑了好几个星期,一直很稳,直到有一天......

天光中一声脆响:

curl: (6) Could not resolve host: api.weixin.qq.com

公众号发布了。问题是——我的树莓派 IP 变了。

家里的宽带是 PPPoE 拨号,每次重新拨号 IP 就变。如果直接在外面部署一个 tinyproxy 或 squid,不仅要配安全组、开端口,还要担心代理暴露公网被扫描。对安全洁癖的我们来说,这不优雅。

需求梳理

  • 树莓派(发布脚本)需要一个稳定的 HTTP/HTTPS 代理出口
  • 不能依赖动态 IP,不受运营商拨号影响
  • VPS 不能开放 8888/8080/3128 等代理端口——安全组只留 22 端口
  • 全程加密,无人中转,无中间人
  • 断网能自动恢复,7×24 无人值守

架构一览

树莓派(发布脚本) VPS(中转跳板) 微信API服务器 ┌────────────┐ SSH隧道加密 ┌──────────┐ │ Python 脚本 │───HTTP────→ autossh ◇──────→ sshd:22 │──→ api.weixin.qq.com │ 发布公众号 │ 127.0.0.1:8888 ◇ │ 无额外端口 │ └──────┬─────┘ └──────────┘ │ SOCKS5:1080 ▼ ┌──────────────┐ │ goproxy │ socks5 → http 转换 │ 127.0.0.1 │ └──────────────┘

三层结构:

  1. autossh——建立 SSH 反向隧道,本地提供 SOCKS5 代理(:1080
  2. goproxy——把 SOCKS5 转成 HTTP/HTTPS 代理(:8888
  3. 发布脚本——通过 HTTP_PROXY=http://127.0.0.1:8888 调用

三条关键路径全部只监听 127.0.0.1,外网碰不到、扫不了、攻不进来。漂亮得像一把龙泉剑——铸在鞘里的锋芒,只在你需要的时候出鞘。

━━━ ━━━ ━━━

第一步:SSH 密钥免密登录

autossh 自动重连的前提是免密登录,否则断线后卡在密码输入,隧道永远起不来。

# 树莓派生成密钥(一路回车,不设密码)

ssh-keygen -t ed25519

# 推送到 VPS

ssh-copy-id root@你的VPS公网IP

测试一下是否能直接登录:

ssh root@你的VPS公网IP "echo OK"

如果打印出 OK,密钥配对成功。

━━━ ━━━ ━━━

第二步:安装 autossh(SSH 隧道守护神)

树莓派上安装:

sudo apt update
sudo apt install autossh -y

测试启动 SOCKS5 隧道

AUTOSSH_PIDFILE=/tmp/wechat_tunnel.pid AUTOSSH_GATETIME=0 autossh -M 0 -N -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -D 127.0.0.1:1080 root@你的VPS公网IP

参数解释:

参数 含义
-M 0 不占额外监控端口
AUTOSSH_GATETIME=0 断线立刻重连,不冷却
ServerAliveInterval=30 每 30 秒发 SSH 心跳
ServerAliveCountMax=3 连续 3 次心跳无响应判死
-D 127.0.0.1:1080 本地 SOCKS5 代理,仅本机可访

打开另一个终端,测试隧道连通性:

curl -x socks5://127.0.0.1:1080 https://api.weixin.qq.com
# 应该返回 {"errcode":40001,...} 而不是 Connection refused

━━━ ━━━ ━━━

第二步又半步:VPS 也配 SSH 保活(双向保活)

光客户端发心跳不够——有的云厂商/运营商会主动踢掉半天无交互的 SSH 连接。必须两端同时保活。

登录 VPS,修改 /etc/ssh/sshd_config

ClientAliveInterval 30 ClientAliveCountMax 3

重启 sshd:

sudo systemctl restart sshd

现在心跳是双向的,服务器也会主动探测客户端状态——\"双剑合璧,谁先倒下都不可能。\"

━━━ ━━━ ━━━

第三步:创建 systemd 服务(开机自启 + 崩溃重启)

手动跑隧道不是长久之计,万一树莓派重启/断电,或者 autossh 进程异常退出,发布定时就断了。用 systemd 托管,做到开机自启 + 进程崩溃自动拉起

创建服务文件 /etc/systemd/system/wechat-ssh-tunnel.service

[Unit] Description=Wechat Publish SSH SOCKS Tunnel After=network-online.target Wants=network-online.target

[Service] User=pi Restart=always RestartSec=5 Environment="AUTOSSH_GATETIME=0" ExecStart=/usr/bin/autossh -M 0 -N -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -D 127.0.0.1:1080 root@你的VPS公网IP

[Install] WantedBy=multi-user.target

启动并设为开机自启:

sudo systemctl daemon-reload
sudo systemctl enable wechat-ssh-tunnel
sudo systemctl start wechat-ssh-tunnel

# 检查状态
systemctl status wechat-ssh-tunnel

━━━ ━━━ ━━━

第四步:goproxy——SOCKS5 转 HTTP 代理

为什么需要转?

大部分 Python 库(requestsurllib3)和微信 API 调用时,HTTPS_PROXY 期望的是 HTTP 代理,原生 SOCKS5 支持需要额外装 requests[socks]。与其在每台机器上折腾依赖,不如在系统层做完协议转换。

goproxy 是一个用 Go 写的轻量级代理工具,单二进制文件,无依赖。

# 下载 goproxy(到 /home/pi/ 下)
cd /home/pi
wget https://github.com/snail007/goproxy/releases/latest/download/proxy-linux-arm64.tar.gz
tar xzf proxy-linux-arm64.tar.gz

创建 systemd 服务 /etc/systemd/system/wechat-goproxy.service

[Unit] Description=Socks5 to HTTP Proxy for Wechat API After=wechat-ssh-tunnel.service BindsTo=wechat-ssh-tunnel.service

[Service] User=pi Restart=always RestartSec=3

ExecStart=/home/pi/proxy http -s socks5://127.0.0.1:1080 -l 127.0.0.1:8888

[Install] WantedBy=multi-user.target

关键细节:

  • After + BindsTo:goproxy 依赖隧道服务启动,隧道挂了代理也挂,一起重启
  • -l 127.0.0.1:8888:HTTP 代理仅监听本机,局域网不能碰
<!-- -->
sudo systemctl daemon-reload
sudo systemctl enable wechat-goproxy
sudo systemctl start wechat-goproxy

# 全链路测试
curl -x http://127.0.0.1:8888 https://api.weixin.qq.com

━━━ ━━━ ━━━

第五步:发布脚本调用代理

代理环境变量只在当前进程生效,不影响系统其他服务:

#!/bin/bash
# 推送发布脚本
export HTTP_PROXY=http://127.0.0.1:8888
export HTTPS_PROXY=http://127.0.0.1:8888
export NO_PROXY="localhost,127.0.0.1,192.168.*"

python3 publish_wechat.py

在 Python 里,requests 自动识别环境变量:

    import os
os.environ['HTTP_PROXY'] = 'http://127.0.0.1:8888'
os.environ['HTTPS_PROXY'] = 'http://127.0.0.1:8888'
    import requests
resp = requests.post('https://api.weixin.qq.com/cgi-bin/token', params={

'grant_type': 'client_credential', 'appid': APPID, 'secret': SECRET

})

一步到位。代理对脚本透明。

━━━ ━━━ ━━━

完整安全架构总结

┌─────────────────────────────────────┐ │ VPS 安全组 │ │ 22/tcp SSH 其他端口: ❌全部关闭 │ └─────────────────────────────────────┘ │ SSH 加密隧道(autossh) │ ┌─────────────────────────────────────┐ │ 树莓派 127.0.0.1 │ │ │ │ :1080 SOCKS5(仅本机) │ │ ↓ goproxy 转换 │ │ :8888 HTTP(仅本机) │ │ ↓ │ │ 发布脚本 → 微信 API │ └─────────────────────────────────────┘

安全收益

  1. VPS 零入站端口暴露:安全组仅开 22 端口,没有 8888/8080/3128,没有 tinyproxy,安全组规则看一眼就知道——干净的就像没人住过的出租屋
  2. 双重 SSH 保活:客户端(ServerAliveInterval=30)+ 服务端(ClientAliveInterval=30),双向心跳检测
  3. 本地代理完全隔离:SOCKS5 和 HTTP 代理都只监听 127.0.0.1,局域网其他设备无法访问,即使不慎被攻击者拿到树莓派 shell,也无法用这个代理翻墙
  4. 全链路自动恢复:断网重连、进程崩溃、系统重启全部自动拉起,7×24 稳定运行

故障自检命令

# SSH 隧道状态
systemctl status wechat-ssh-tunnel

# HTTP 代理状态
systemctl status wechat-goproxy

# 全链路连通测试
curl -x http://127.0.0.1:8888 https://api.weixin.qq.com

# 查看隧道日志
    journalctl -u wechat-ssh-tunnel -f
# 查看代理日志
    journalctl -u wechat-goproxy -f

━━━ ━━━ ━━━

踩过的坑坑 1:autossh 不加 AUTOSSH_GATETIME=0

默认 autossh 有 30 秒冷却期,断线后要等半分钟才重连。对于定时发布来说,30 秒的窗口 + 刚好在那个窗口执行 cron——你的发布就失败了。AUTOSSH_GATETIME=0 让它断了秒连。

坑 2:goproxy 比隧道先启动

第一次配 systemd 时没加 BindsTo,树莓派重启后 goproxy 先启动、连接 127.0.0.1:1080 被拒、直接退出。加了 BindsTo=wechat-ssh-tunnel.service,systemd 保证隧道启动后再拉代理。

坑 3:NO_PROXY 不配全,代理把自己绕进去了

发布脚本里如果用微信 API 获取 token,api.weixin.qq.com 域名解析走代理没问题。但如果脚本里还有对本机服务的调用(比如 localhost:8080 的监控面板),没配 NO_PROXY 的话——请求走向代理 → 代理连接本机 → 代理又从本机连代理 → 死循环套娃。所以一定配好:

export NO_PROXY="localhost,127.0.0.1,192.168.*"

━━━ ━━━ ━━━

写在最后

这套方案最让我高兴的一点是:它解决了一个部署上的工程痛点,而不是引入一个新玩具。

  • 以前:配 tinyproxy → 配安全组 → 配 ACL → 每天担心被扫描 → 隔三差五在日志里看到奇怪 IP 在撞 8888 端口
  • 现在:autossh + goproxy 各一个 systemd 文件,VPS 安全组一眼望过去只有 22 端口,安心

树莓派换了三次 IP,隧道自动恢复,我一次都没有再去碰安全组。

如果你也在做本地 AI 自动发布公众号、或任何需要动态 IP 做稳定代理出口的场景,这套方案值得一试。

🐉 首发 LeisureLinux 公众号 | 实战出品

━━━ ━━━ ━━━

【WPAD,GoProxy,轻量服务器-哔哩哔哩】 https://b23.tv/Id2vcHD

【SSH隧道实现"外网穿透"访问云端受保护的服务-哔哩哔哩】 https://b23.tv/gfsb5WM

【SSH 客户端如何通过 HTTPS 代理访问 SSH Server-哔哩哔哩】 https://b23.tv/zSBVbq9

【[含源码]把 PAC 脚本用于 curl 自动使用对应的代理-哔哩哔哩】 https://b23.tv/1Q4ZxF4

不写代码、全靠「聊天」:Meta AI客服反成黑客帮凶,奥巴马白宫账号遭劫

性能飙升 30%!NGINX 1.30 稳定版发布:原生支持 MPTCP 与 HTTP/2 Backend

【技术前瞻】Claude Desktop + MCP:让 AI 成为你的 Kali 渗透助手

MTA(邮件传输代理)核心架构与工作原理解析

附录:一键部署脚本

# 请先配置 SSH 免密登录到 VPS

VPS_IP="你的VPS公网IP"

# 安装 autossh
sudo apt install autossh -y

# 创建隧道 systemd 服务
sudo tee /etc/systemd/system/wechat-ssh-tunnel.service > /dev/null <<EOF

[Unit] Description=Wechat Publish SSH SOCKS Tunnel After=network-online.target Wants=network-online.target

[Service] User=$USER Restart=always RestartSec=5 Environment="AUTOSSH_GATETIME=0" ExecStart=/usr/bin/autossh -M 0 -N -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -D 127.0.0.1:1080 root@$VPS_IP

[Install] WantedBy=multi-user.target EOF

# 下载 goproxy
cd /tmp
wget -q https://github.com/snail007/goproxy/releases/latest/download/proxy-linux-arm64.tar.gz
tar xzf proxy-linux-arm64.tar.gz
sudo mv proxy /usr/local/bin/goproxy

# 创建 goproxy systemd 服务
sudo tee /etc/systemd/system/wechat-goproxy.service > /dev/null <<EOF

[Unit] Description=Socks5 to HTTP Proxy for Wechat API After=wechat-ssh-tunnel.service BindsTo=wechat-ssh-tunnel.service

[Service] User=$USER Restart=always RestartSec=3

ExecStart=/usr/local/bin/goproxy http -s socks5://127.0.0.1:1080 -l 127.0.0.1:8888

[Install] WantedBy=multi-user.target EOF

# 启动服务
sudo systemctl daemon-reload
sudo systemctl enable --now wechat-ssh-tunnel
sudo systemctl enable --now wechat-goproxy

# 验证

sleep 3

curl -x http://127.0.0.1:8888 https://api.weixin.qq.com
echo ""
systemctl status wechat-ssh-tunnel wechat-goproxy --no-pager

本文整理自微信公众号 LeisureLinux 的原创内容(Linux / AI / 安全 硬核技术)。

· 阅读原文(微信公众号)

· 关注公众号 LeisureLinux,第一时间获取技术深度内容。

LeisureLinux 公众号二维码(微信扫一扫关注)