termal.in

← 博客

SSH 反向隧道(ssh -R):通过远程服务器暴露本地端口

· Termalin Team sshport-forwardingtunnelingtutorial

你的笔记本上跑着某个东西——一个开发服务器、一个 API,或者家里一台 NAT 之后的机器——而互联网另一头的某个东西需要访问它。没有公网 IP,没有路由器权限,也没时间搭 VPN。这正是 SSH 反向隧道 ssh -R 要解决的问题:它在一台你能连上的服务器上开出一个端口,再悄悄把打到这个端口的一切都转回你的机器。

这个参数常让人觉得方向反了,所以我们先把脑子里的模型理顺,再逐个过一遍真实场景。

思维模型:把 -L 镜像过来

每条 SSH 隧道都会在一台机器上开一个监听端口,并把到达该端口的流量送往另一台机器能够访问的某处。本地转发(-L)时,端口开在你的机器上,流量从服务器一侧出去。反向隧道正好是它的镜像:

使用 -R 时,监听端口开在远程服务器上,而对它发起的连接会从你这一侧出来。

全部的窍门就在这里。那台无法接受入站连接的机器,改为主动发起一条出站 SSH 连接——再让外来的连接顺着它反向进来。如果两者还是容易混,完整的全家福在 SSH 端口转发详解里。

从左到右读懂语法

ssh -R [bind_address:]remote_port:localhost:local_port user@server

可以这样读:在服务器上监听 remote_port,把到达的流量转发到 localhost:local_port——这个地址是从我的机器上解析的。 所以:

ssh -R 8080:localhost:3000 deploy@vps.example.com

会在 VPS 上打开 8080 端口,对它的每个连接都会落到你笔记本的 3000 端口。目标不一定非得是你的笔记本——-R 8080:192.168.1.50:80 会转发到你本地局域网里的另一台机器,用你的笔记本作为出口。

有个值得知道的用法:-R 0:localhost:3000 让服务器自行挑选任意空闲端口,并打印出 Allocated port 43022 for remote forward,这样你就知道拿到的是哪个端口。

人们真正拿它来做的三件事

**把本地开发服务器展示给客户。**你正在做的东西跑在 localhost:3000。与其为了演示而专门部署到某处:

ssh -N -R 8080:localhost:3000 deploy@demo.example.com

任何能访问 demo.example.com:8080 的人,现在看到的就是你笔记本上这个应用的实时画面。(-N 跳过远程 shell——你要的只是隧道。到底是任何人都能连,还是只有服务器自己能连,取决于 GatewayPorts——见下一节。)

**连上 NAT 之后的家用机器。**你家里那台机器不能接受连接,但能主动发起连接。让它向一台小 VPS 保持一条向外的隧道:

# on the home machine
ssh -N -R 2222:localhost:22 tunnel@vps.example.com

现在 VPS 的 2222 端口就是家里那台机器的 SSH 端口,于是从任何地方:

ssh -J vps.example.com -p 2222 you@localhost

就能借道 VPS 直接进入 NAT 后的那台机器。这是如何 SSH 连接家里的服务器的经典自托管方案。

**把 webhook 送到你的笔记本。**某个支付服务商或 git 托管方需要向你正在开发的处理程序发 POST 请求。把它们能访问到的端点通过隧道引回你这里:

ssh -N -R 9000:localhost:9000 deploy@vps.example.com

把 webhook 指向这台 VPS。如果你让隧道绑定在服务器的回环地址上(默认行为),就在 VPS 上用 nginx 或任意反向代理挡在 127.0.0.1:9000 前面——你能顺带拿到 TLS 终止,也不必把裸露的隧道端口暴露出去。

GatewayPorts:为什么别人连不上你的隧道

最常见的意外:你在服务器上测试时隧道是通的(curl localhost:8080 成功),但外面没人连得上。这是刻意设计的——默认情况下,无论你请求绑定哪个地址,sshd 都只把远程转发端口绑定到 127.0.0.1。

要把隧道开放给外界,服务器的 /etc/ssh/sshd_config 需要:

GatewayPorts clientspecified

然后重启 sshd,并显式请求绑定:ssh -R 0.0.0.0:8080:localhost:3000 ...。(GatewayPorts yes 会把每一条远程转发都绑定到所有网络接口,通常比你需要的范围更大。)这是服务器端的决定,客户端无法覆盖——它是一个有意为之的安全默认值,因为反向隧道等于从内部打了个洞,它暴露出来的任何东西,现在实际上都直接面向互联网。请就按这个前提对待它。

还有两个相关的服务器端开关可能坑到你:AllowTcpForwarding no 会彻底禁用隧道,PermitListen 则可以限制 -R 能申请哪些端口。

让隧道保持存活

反向隧道就是一条 TCP 连接,而空闲的 TCP 连接会断。只要用得比一次演示更久:

ssh -N -R 2222:localhost:22 \
    -o ServerAliveInterval=30 \
    -o ExitOnForwardFailure=yes \
    tunnel@vps.example.com
  • ServerAliveInterval 30 让流量持续流动,这样 NAT 表项和空闲超时就不会把连接回收掉。
  • ExitOnForwardFailure yes 让 ssh 在远程端口无法绑定时明确报错退出,而不是照样连上、却什么都没转发。
  • autossh 包裹这条命令,隧道一断就自动重启——这是让隧道扛过重启和不稳定网络的标准工具,通常以 autossh -M 0 -N -R ... 的形式跑在 systemd 单元里。

等某条隧道值得长期保留了,就用一行 RemoteForward 把它搬进 ~/.ssh/config,让它随主机条目一起带走——文件结构见 ssh_config 指南(英文):

Host homelink
    HostName vps.example.com
    User tunnel
    RemoteForward 2222 localhost:22
    ServerAliveInterval 30
    ExitOnForwardFailure yes

-L、-R、-D 一览

参数端口开在流量从哪出典型用途
-L你的机器服务器一侧把远程数据库/仪表盘拉到本地
-R服务器你这一侧暴露本地服务;连上 NAT 后的机器
-D你的机器服务器一侧,任意目标作为进入某个网络的 SOCKS 代理

什么时候反向隧道是错的工具

作为临时方案,反向隧道非常出色:演示、调试 webhook、抢救 NAT 后的机器。但作为长期方案它很糟糕。如果你要暴露的东西需要连续在线好几个月、要服务真实用户、要在你的笔记本休眠后依然可用——那就是入站流量(ingress),而入站流量值得配上真正的基础设施:服务器上的反向代理、VPN 或叠加网络、一次真正的部署。隧道的魅力在于它只是一条命令、不留任何常驻痕迹;一旦你开始为它写监控,就说明你已经用不着它了。

排查常见故障

  • Warning: remote port forwarding failed for listen port 8080(监听端口 8080 的远程转发失败)——该端口在服务器上已被占用。罪魁祸首往往是你自己上一条隧道:旧的 sshd 进程会一直占着端口,直到那条已死的连接超时。保活能避免这种僵尸连接;-R 0:... 可以绕开端口冲突;ExitOnForwardFailure 则把这条警告变成你不会错过的错误。
  • 在服务器上能用,从外面连被拒——监听器在服务器的回环地址上。这是 GatewayPorts 的默认行为在起作用;要么去配置它,要么用反向代理挡在这个端口前面。
  • 隧道连上了,但服务没响应——检查本地那一半:你指定的本地端口上到底有没有东西在监听?如果 -R 8080:localhost:3000 对应的 :3000 上什么都没跑,那每个访问者得到的都会是连接被拒。
  • SSH 连接本身都建立不起来——那是另一个问题,有它自己的排查清单:连接被拒与超时解析。

当隧道变成了日常家具

只用一次的反向隧道,手敲就行。但那条承载着你的家庭实验室、演示机和 webhook 端点的隧道,是你每天早上、每次笔记本休眠之后都要重建的状态——到周四你就记不清它们都是什么了。Termalin 的隧道管理器把本地、远程和动态转发都挂在它们所属的主机上:点一下就能启动,一眼就看清哪些在运行,并让它们随连接一起重新建立,而不必从 shell 历史里再敲一遍。整个主机列表——连同密钥、跳板主机、保活和隧道——都会在你的各台机器之间端到端加密同步。而当某台机器长期待在 NAT 之后时,它那条仅出站的 Connector 可以彻底取代手搓的反向隧道——无需入站端口,也没有 autossh 单元要照看。命令行教会你 -R 是什么意思;而一个客户端,让你依赖的那些隧道不再依赖你的记忆。


Termalin 是一款免费、跨平台的 SSH 客户端,内置隧道、SFTP 和密钥管理器——立即下载,或了解它如何安全地处理你的密钥。

先在一台主机上试试。

Termalin 是为你和你的智能体打造的高速 SSH 客户端。

免费版 · Pro 14 天试用 · 价格