SSH隧道原理及其使用方法

SSH 隧道(SSH Tunnel)原理

A Secure Shell (SSH) tunnel consists of an encrypted tunnel created through an SSH protocol connection. Users may set up SSH tunnels to transfer unencrypted traffic over a network through an encrypted channel. It is a software-based approach to network security and the result is transparent encryption.

SSH 隧道(SSH Tunneling),又称为 SSH 端口转发(SSH Port Forwarding),是一种利用SSH协议为其他协议或网络链接加密的方法。通过SSH隧道,用户可以安全地传输未加密的网络流量,通过远程服务器转发到目标目的地,保证了数据传输的私密性和安全性。

SSH 隧道并不是真的建立了一条物理线路,而是在应用层重新包装了数据包。简单来说,它就像是在原本互不相通或不安全的两个点之间,拉了一根加密的“隐形管道”。你把原本要发送的数据包塞进这个管道,数据包在传输过程中会被 SSH 协议严密包裹并加密,等到了管道另一头再由 SSH 拆包发送给最终目标。

1. 协议封装(Protocol Encapsulation)

  • 原始数据:假设你通过隧道访问数据库,原始包是 TCP [Target_IP:3306]
  • 隧道封装:SSH 客户端拦截该 TCP 流,提取其 Payload(负载),然后将其作为 SSH 报文的数据部分。
  • 外层包裹:这个数据部分会被加上 SSH 的加密头、序列号和 MAC 校验码。
  • 最终传输:最终在互联网上传输的包,其目标 IP 是 SSH 服务器,端口是 22。对于中间的路由器和防火墙来说,它们只能看到合法的 SSH 加密流量,完全不知道里面“藏”着数据库请求。

2. 频道多路复用(Channels)

一个 SSH 连接(Connection)内部可以并行跑很多个隧道,这得益于 Channel 机制。

  • 在一个物理的 TCP 连接(SSH 会话)中,SSH 协议可以创建多个逻辑上的 Channel。
  • 每个 -L-R 转发请求都会开启一个独立的 Channel。
  • SSH 协议栈负责将不同 Channel 的流量进行编号和解复用,确保发往本地 8080 端口的数据不会错乱到其他端口去。

3. SSH 隧道转发模式(Port Forwarding)

SSH 隧道转发(SSH Port Forwarding)主要有以下三个方式,它们通过在加密的 SSH 连接中建立数据通道,实现网络请求的跨网络传输。

3.1 本地转发

将发送到本地机器特定端口的请求,通过 SSH 隧道转发到远程目标主机的指定端口。请求由本地发起,SSH 客户端充当“中转站”。具体命令如下:

1
ssh -f -N -L $LocalIP:$LocalPort:$TargetIP:$TargetPort $Username@$SSHServer
  • -f:让 SSH 客户端在后台运行,即使命令行关闭也能保持 SSH 隧道建立
  • -N:只建立连接,不执行远程命令
  • -L:以本地转发模式建立 SSH 隧道
  • $LocalIP:本地 IP,可以是127.0.0.1,也可以是 DHCP 分配的 IP,区别在于前者只供本机访问,后者可供局域网内其他设备访问。也可以为空,为空时,除了代表允许任何设备都可以访问到这个端口,还可以支持 IPv6 访问。
  • $LocalPort:本地用于接收请求的端口,要求端口号之前不能被占用,建议选择1024以上且未被占用的端口。
  • $TargetIP:可以是 SSH 服务器的 IP,也可以是局域网内能与 SSH 服务器相通的其他服务器 IP。如果是后者的话,需要开启 SSH 服务器的转发权限,即编辑/etc/ssh/sshd_config,修改AllowTcpForwardingyes(默认通常开启)
  • $TargetPort:目标服务器上提供服务的端口
  • $Username:SSH 服务器上的登录时的用户名
  • $SSHServer: SSH 服务器 IP

3.2 远程转发

将发送到远程 SSH 服务器特定端口的请求,通过 SSH 隧道转发到本地机器或其可达的其他主机的指定端口。命令在本地执行,但请求由远程发起,通常用于将内网服务临时暴露给外网。具体命令如下:

1
ssh -f -N -R $RemoteIP:$RemotePort:$TargetIP:$TargetPort $Username@$SSHServer
  • -f:让 SSH 客户端在后台运行,即使命令行关闭也能保持 SSH 隧道建立
  • -N:只建立连接,不执行远程命令
  • -R:以远程转发模式建立 SSH 隧道
  • $RemoteIP:SSH 服务器 IP,可填本地回环地址或者SSH 服务器的局域网地址,区别在于前者只转发 SSH 服务器本地访问请求,后者可转发局域网内其他设备访问请求,但需要开启 SSH 服务器的网关端口,即编辑/etc/ssh/sshd_config,修改GatewayPortsyes(默认通常关闭)。也可以为空,为空时,可转发该端口的所有访问请求。
  • $RemotePort:SSH 服务器用于转发请求的端口,要求端口号之前不能被占用,建议选择1024以上且未被占用的端口。
  • $TargetIP:本机 IP,可填本地回环地址或者本机的局域网地址,区别在于前者只供本机访问,后者可供本机局域网内其他设备访问。
  • $TargetPort:本机上的端口,要求端口号之前不能被占用,建议选择1024以上且未被占用的端口。
  • $Username:SSH 服务器上的登录时的用户名
  • $SSHServer: SSH 服务器 IP

3.3 动态转发

在本地机器上建立一个 SOCKS 代理服务器。它不会绑定固定的目标端口,而是根据应用请求动态决定去向。

1
ssh -f -N -D $LocalIP:$LocalPort 用户名@SSH服务器
  • -f:让 SSH 客户端在后台运行,即使命令行关闭也能保持 SSH 隧道建立
  • -N:只建立连接,不执行远程命令
  • -D:以本地转发模式建立 SSH 隧道
  • $LocalIP:本地 IP,可以是127.0.0.1,也可以是 DHCP 分配的 IP,区别在于前者只供本机访问,后者可供局域网内其他设备访问。也可以为空,为空时,除了代表允许任何设备都可以访问到这个端口,还可以支持 IPv6 访问。
  • $LocalPort:本地用于接收请求的端口,要求端口号之前不能被占用,建议选择1024以上且未被占用的端口。
  • $Username:SSH 服务器上的登录时的用户名
  • $SSHServer: SSH 服务器 IP

3.4 转发模式对比

转发方式 核心参数 流量方向 主要用途
本地转发 -L 本地 -> 远程 访问远程内网资源
远程转发 -R 远程 -> 本地 内网穿透/反向代理
动态转发 -D 本地 -> 动态目标 SOCKS5 代理/加密上网

SSH隧道适用场景

1. 访问远程内网资源

  • 本地 PC(Local PC)
  • SSH 服务器(SSH Server)
  • MySQL 服务器(MySQL Server)

通过 SSH 隧道本地转发模式将远程 MySQL 服务器3306端口映射本地的3306端口。

本地转发模式场景密码登录

1
ssh -N -L 3306:10.0.1.102:3306 -p 22 [email protected]

本地转发模式场景密钥登录

1
ssh -N -L -i "$PrivateKeyPath" 3306:172.17.0.2:3306 -p 22 [email protected]
  • $PrivateKeyPath:是 SSH 的私钥文件路径,示例路径为$HOME\.ssh\id_rsa,使用$HOME是为了避免中文路径乱码。

2. 内网穿透/反向代理

  • 家用 PC(Home PC)
  • 家用监控(Home Camera)
  • 公司 Laptop(Company Laptop)
  • SSH 服务器(SSH Server)

家用 PC上通过 SSH 隧道远程转发模式将本地局域网中的家用监控服务 8080 端口映射给SSH 服务器8080 端口,然后在公司 Laptop上通过 SSH 隧道本地转发模式将SSH 服务器8080 端口映射到本地 8080 端口。

远程转发模式场景密码登录

Home PC上执行:

1
ssh -N -R 127.0.0.1:8080:192.168.1.101:8080 -p 22 [email protected]

Company Laptop上执行:

1
ssh -N -L 127.0.0.1:8080:127.0.0.1:8080 -p 22 [email protected]

执行完后,在Company Laptop上的浏览器输入http://127.0.0.1:8080 即可看到监控。

3. SOCKS5代理/加密上网

  • 本地 PC(Local PC)
  • SSH 服务器(SSH Server)
  • MySQL 服务器(MySQL Server)
  • Web 服务器(Web Server)

通过 SSH 隧道动态转发模式将SSH 服务器变成代理服务器,同时将本地 IP 和端口作为代理入口。这样可以在本地 PC 或者其所在局域网内其他设备配置应用或系统代理,以此来访问SSH 服务器所在局域网中MySQL 服务器Web 服务器

动态转发模式场景密码登录

本地 PC上执行:

1
ssh -N -D 192.168.1.100:1080 -p 22 [email protected]

本地 PC或者局域网内其他设备的浏览器上配置代理:

  • IP:192.168.1.100
  • Port:1080

在浏览器上输入http://10.0.1.103:8080即可访问Web Server上的网页

Tabby上SSH隧道使用方法

打开Tabby终端,点击右上设置图标 ,然后点击左侧目录中的Profiles & connections,然后选择+ New profile, 填入如下信息:

  • Name:ssh-tunnel
  • Host:10.0.1.101
  • Port:22
  • Username:root

创建SSH会话配置界面

然后点击PORTS,此时可按照LocalRemoteDynamic这三种类型进行配置,配置好后,可点击Save新建并保存 SSH 会话配置。只要该会话被打开,端口转发配置将自动生效,当与 SSH 服务器会话完全关闭后,端口转发配置也将自动失效。

访问远程内网资源
内网穿透/反向代理-Home PC
内网穿透/反向代理-Company Laptop
SOCKS5 代理/加密上网

故障排查

1. 后台运行的SSH隧道建立命令如何彻底关闭

使用了-f参数来建立 SSH 隧道,关闭命令行后,端口仍然被占用,该如何彻底关闭 SSH 隧道,释放端口?

powershell中执行命令找到占用端口的进程 PID,然后将该进程强制杀掉。

1
netstat -ano | findstr :$Port

$Port是被占用的端口,输出结果中的最后一行数字就是PID

1
taskkill /F /PID $PID

$PID就是输出结果中的PID

2. SSH隧道建立后,为什么无法访问MySQL的3306端口

直连MySQL Server3306端口可以成功,为什么连接映射到本地的3306端口,却显示连接被拒绝?

这一般是因为 MySQL 的监听配置所限制,当连接映射本地的 3306 端口时,一般使用的IP地址为localhost或者127.0.0.1,需要在MySQL bind-address中查看是否已监听这些地址。同时 MySQL 的权限是绑定用户名+主机名的,而localhost127.0.0.1并不完全等价,如果你的用户权限只授予了'user'@'localhost',使用 127.0.0.1连接可能会被拒绝。

3. SSH隧道建立后,为什么无法转发UDP请求

原生SSH 隧道本身不支持UDP 协议。SSH 的-L-R参数设计的初衷是建立TCP级的加密隧道。因为UDP是无连接状态的,而SSH 协议是运行在TCP之上,所以它无法直接封装和转发UDP数据包。

4. Tabby配置了SSH会话PORTS,为什么打开会话没有效果

在 Tabby 上配置了PORTS 的 SSH 会话,保存后再打开会话,为什么 SSH 隧道还是未成功建立?

这个一般是因为本地还与 SSH 服务器还存在会话连接,此时需要关闭所有与目标 SSH 服务器的会话连接,然后再次打开配置了PORTS的 SSH 会话,才会顺利建立 SSH 隧道。

5. SSH隧道常常因为网络波动等问题而自动关闭

SSH 隧道极易受不稳定通信线路所影响,当网络高峰时期,延迟太高或者丢包率太高,可能会造成 SSH 隧道自动关闭。

针对 SSH 隧道因网络波动(如 Wi-Fi 切换、短暂掉线、长连接被防火墙切断)而自动关闭的问题,目前业界公认的最优解是 Autossh。

powershell中安装autossh

1
winget install autossh

然后通过autossh来建立隧道:

1
autossh -M $MonitorPort -N -L $LocalIP:$LocalPort:$TargetIP:$TargetPort $Username@$SSHServer

$MonitorPort:这是autossh特有的参数。它会启动一个本地端口(比如 7277 )来监听连接状态。它会不断通过这个端口发送测试数据。如果发现数据不通,autossh就认为隧道已断开,并立即自动重启 SSH 进程。

如果是在Tabby中,则可以在ADVANCED界面调高如下配置:

ADVANCED配置界面

  • Keep Alive Interval(Milliseconds):每5000 ms向服务器发一次心跳包。
  • Max Keep Alive Count:如果连续10次没收到服务器回应,就主动断开重连。

参考信息

1. Tabby github开源项目

https://github.com/Eugeny/tabby

2. SSH Tunneling官方说明

https://www.ssh.com/academy/ssh/tunneling

https://www.ssh.com/academy/ssh/tunneling-example

3. A Visual Guide to SSH Tunnels

https://iximiuz.com/en/posts/ssh-tunnels/

4. SSH Port Forwarding

https://www.digitalocean.com/community/tutorials/ssh-port-forwarding

5. 网络拓扑示意图drawio绘制工具

https://github.com/jgraph/drawio

https://app.diagrams.net/


SSH隧道原理及其使用方法
https://blog.commentsdebugger.com/2026/04/01/SSH隧道原理及其使用方法/
作者
Debugger
发布于
2026年4月1日
许可协议