基于SSH的反向代理实现公网回调本地服务,本地服务暴露到公网访问

作者:Hackyle

创建时间:2026-07-22 22:13:59 最近一次更新时间:2026-07-22 22:56:45

作为技术研发人员的你,经常会遇到这样的场景:

  • 本地开发了一个 Web 服务,联调时需要对接微信支付、支付宝回调,或者第三方 API Webhook,外部服务无法直接访问到我们的本地服务,怎么解决这个问题?
  • 你开发了一个WebDemo应用,要演示给客户看,客户也需要在线上体验,怎么把内部服务暴露到公网?
  • 你在家里运行了一个自己研发的狗粮投喂器,在外面时怎么发送投喂狗粮的指令。在外面只能通过互联网把指令传递到家里,怎么实现?

虽然市面上有很多内网穿透工具(如 Ngrok、frp)和第三方服务(如花生壳),但如果我们手头有一台带有公网 IP 的云服务器,直接利用 Linux 自带的 SSH 反向隧道功能,就能实现零成本、高安全的穿透效果。

接下来,让我们一步一步实现:

  • 你本地运行的SpringBoot服务:http://localhost:9898/hi
  • 可以通过你的公网IP访问:http://8.145.45.70:9898/hi

SSH 反向代理的基本原理

SSH 端口转发主要有三种:

  • 本地端口转发Local Port Forwarding
  • 远程端口转发Remote Port Forwarding
  • 动态端口转发Dynamic Port Forwarding

我们今天要解决的场景,使用的是:SSH Remote Port Forwarding,也就是 SSH 远程端口转发。

通常称为SSH 反向隧道,或者SSH 反向代理

需要注意:严格来说,SSH 的 -R 是远程端口转发,而不是传统意义上的 HTTP 反向代理。

可以这样理解:

  • 把远程主机的流量,转发到本地主机上
  • 将远程主机yyyy端口上的流量,转发到本地主机xxxx端口上。使得访问remote:xxxx就像在访问localhost:yyyy一样

主要流程

  • 内网发起连接: 本地机器(客户端)通过 SSH 主动连接公网服务器(服务端)。因为是从内网连向公网,所以能轻松穿透防火墙或 NAT。
  • 建立加密隧道: 连接建立后,双方维持一条持久安全的 TCP 加密管道。
  • 远程端口绑定: SSH 告知公网服务器:“在你的系统上监听一个指定端口(例如 8080),凡是发到这个端口的网络流量,全沿着我们这条隧道丢回给本地机器,再转给本地的程序(如 localhost:3000)”。

正如上图所示,当公网用户访问 http://203.0.113.50:8080 时,请求会被公网服务器捕捉,并通过 SSH Tunnel 原封不动地传递给防火墙后的本地计算机。

SSH反向代理语法

ssh -R [远程端口]:[本地地址]:[本地端口] [用户名]@[SSH服务器地址]

例如:ssh -R 8080:1ocalhost:80 ssh_user@ssh_server

  • 整体流程为:外网访问ssh_server:8080--> SSH服务器 --> 本地80端口(Web服务)
  • 访问远程服务器的8080端口时,流量自动转发到本地服务的80端口上
  • 这也就是:把远程主机的流量,转发到本地主机上
互联网
   │
   │ HTTP 请求
   ▼
阿里云公网服务器
公网 IP
   │
   │ SSH 反向隧道
   ▼
Windows 本地电脑
   │
   ▼
Spring Boot

实战步骤

主要步骤

  1. 云服务器的安全组添加指定端口
  2. 打开公网服务器SSH的远程转发选项
  3. 本地建立远程转发通道
  4. 用公网IP访问本地服务

步骤0:打开云服务器的安全组,允许指定端口通过

步骤 1:修改公网服务器 SSH 选项

默认情况下,SSH 反向端口转发绑定的是服务器的 127.0.0.1 接口。也就是说,默认只有服务器自己才能访问映射出来的端口,外部公网用户依然访问不到。

我们需要修改公网服务器的 SSH 配置,开启全局绑定能力:

# 1. 登录公网服务器
ssh root@8.145.45.70

# 2. 编辑 SSH 配置文件
sudo vim /etc/ssh/sshd_config

# 3. 找到并修改/取消注释以下配置:
GatewayPorts yes
ClientAliveInterval 30
ClientAliveCountMax 3

# 4. 重启 SSH 服务生效
sudo systemctl restart sshd

参数说明:

  • GatewayPorts yes:允许远程主机的反向端口映射绑定到 0.0.0.0(所有网络接口),这样外部公网流量才能进来。
  • ClientAlive*:配置心跳检测,防止连接闲置时被运营商或防火墙强行断开。

步骤 2:在本地机器建立反向隧道

在本地终端中运行以下命令:

ssh -N -o ExitOnForwardFailure=yes -R 0.0.0.0:9898:127.0.0.1:9898 root@8.145.45.70

命令详解:

  • -N:不执行远程命令,只建立隧道
  • ExitOnForwardFailure=yes:如果反向端口转发建立失败,SSH 直接退出。
  • -R:Remote Port Forwarding,远程端口转发
  • 0.0.0:9898:阿里云服务器监听 9898,0.0.0.0表示允许所有IP访问
  • 0.0.1:9898:转发到你本地 Windows 的 9898

步骤 3:验证与服务测试

在服务器上检查端口是否成功监听:

netstat -tuln | grep 9898
# 或者
ss -tulpn | grep 9898

如果看到类似于 0.0.0.0:9898或 *:9898的监听状态,说明绑定正确。

运行本地服务,本地访问:http://localhost:9898/hi

公网测试访问:http://8.145.45.70:9898/hi

失效自动断开

ssh -N -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -o ExitOnForwardFailure=yes -R 0.0.0.0:9898:127.0.0.1:9898 root@8.145.45.70

参数说明

  • ServerAliveInterval=60,每 60 秒发送一次保活请求。
  • ServerAliveCountMax=3,连续 3 次没有响应,则认为连接失效。
  • ExitOnForwardFailure=yes,如果反向端口转发建立失败,SSH 直接退出。
  • 这样可以避免SSH 看起来连接正常,但是端口转发实际上已经失效

保证连接稳定性(Autossh)

原生的 ssh 命令在遭遇网络波动、IP 变更或超时关机时,连接会直接断开且不会自动重连。要实现无人值守的稳健隧道,推荐配合 autossh 工具使用。

  1. 本地配置 SSH 免密登录(密钥认证)

因为 autossh 在后台自动重连时无法手动输入密码,必须先配置公钥认证:

# 生成本地密钥对(如果已经有则忽略)
ssh-keygen -t rsa -b 4096

# 将公钥推送至公网服务器
ssh-copy-id user@8.145.45.70
  1. 使用 Autossh 启动反向代理

Windows 本身没有官方原生的 autossh 安装包,需要借助WSL实现

安装: apt install autossh -y

开启连接:

autossh -M 0 -N
-o "ServerAliveInterval=30" \
-o "ServerAliveCountMax=3" \
-o "ExitOnForwardFailure=yes" \
-R 0.0.0.0:9898:127.0.0.1:9898 root@8.145.45.70

参数含义:

  • -M 0    不使用 autossh 独立监控端口
  • -N  不执行远程 Shell,只建立隧道
  • -R  SSH 反向端口转发
  • ServerAliveInterval=30  每 30 秒发送保活
  • ServerAliveCountMax=3   连续 3 次无响应后断开
  • ExitOnForwardFailure=yes    端口转发失败时立即退出

 

本文结束。

————————————————
版权声明:非明确标注皆为原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上本文链接及此声明。
原文链接:https://blog.hackyle.com/article/iWYpwjH4cuEl

留下你的评论

Name: 

Email: 

Link: 

TOP