bigywater.tech
网络协议 · 97

SSH 端口转发:本地、远程与动态转发

SSH 不只是远程登录:它还能当隧道。-L 把本地端口变成远处的服务,-R 把近处的服务暴露到远处。这篇在本机实现一个会转发的 SSH 服务器,验证两个方向的转发、多个连接怎么共用一条 SSH 连接,以及隧道的代价。

432 字节
一次本地转发连接期间 SSH 服务器端口上的流量,里面找不到明文和目标端口
20 / 20
同一个隧道并发 20 个转发连接,各自收到自己的回显
1015~1163 vs 615~803 ms
2% 丢包下经隧道与直连传 2 MB 的耗时(各 2 次)

-L 本地转发

实测 · 本机执行输出
  客户端连本地 19172,发 b"hello through the tunnel",收到 b'ECHO:hello through the tunnel'——服务器端的目标回显服务器加了 "ECHO:" 前缀,说明数据真的到了目标并回来了
  同时抓 SSH 服务器端口 19116 上的流量(lo0):共 432 字节;其中能找到明文 "hello through the tunnel" 吗?找不到;能找到目标端口号 19639 的十进制文字吗?找不到(目标地址和端口在加密的通道请求里)
  从线路上看只是一条 SSH 连接;目标 127.0.0.1:19639 是 SSH 服务器“看到”的,不是在你的机器上直接可达的路径(本实验里恰好都在本机)

客户端监听本地端口,每个连接变成一个 direct-tcpip 通道,由服务器去连目标。目标地址只出现在加密的通道请求里。

-R 远程转发

实测 · 本机执行输出
  请求服务器在 19518 上监听(tcpip-forward 全局请求);之后外部连 19518 发 b"knock knock",收到 b'CLIENT-SIDE:knock knock'——连接经 SSH 回到了客户端这一侧的目标 19585

客户端发 tcpip-forward 请求,服务器监听并把每个进来的连接通过 forwarded-tcpip 通道送回客户端。

多路复用

实测 · 本机执行输出
  20 个并发连接各自收到自己的回显:20 / 20 正确;它们全部复用同一条到 SSH 服务器的 TCP 连接(从 SSH 客户端 Transport 看:通道数是 SSH 的概念,TCP 连接数 1)

所有转发连接是同一条 SSH 连接里的不同通道。

代价

实测 · 本机执行输出
  直连 2 MB:[2, 1, 1] ms,中位 1 ms(≈ 1415 MB/s)
  经隧道 2 MB:[11, 12, 12] ms,中位 12 ms(≈ 173.3 MB/s;paramiko 在纯 Python 里加密 + 解密,比直连慢很多,不代表 OpenSSH 的速度)
  netlab 每方向 25 ms、丢包 0%:直连(目标端口在受损范围里)2 MB [252, 305] ms;经隧道(只有 SSH 那条 TCP 受损,内层连接不受损)2 MB [211, 157] ms
  netlab 每方向 25 ms、丢包 2%:直连(目标端口在受损范围里)2 MB [615, 803] ms;经隧道(只有 SSH 那条 TCP 受损,内层连接不受损)2 MB [1015, 1163] ms

多一层加解密和窗口控制;受损的链路上隧道约慢 1.5 倍;0% 丢包的延迟链路上没有更慢。

分步演示

SSH 端口转发
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64(Apple 芯片)/ Python 3.14.8 / tcpdump(libpcap)/ scapy 2.8 / dpkt / dnspython / h2 / aioquic / OpenSSL / curl 8.7.1;抓包在 lo0(环回)上做,少数实验用真实网卡 en0(这台机器上 en0 是 Wi-Fi,tcpdump 看到的是系统转成以太网格式的帧,所以文中的“以太网头”都指这个 14 字节的头)或访问公网(会在文章里注明);需要丢包 / 延迟 / 限速时,用一个只作用于 lo0 端口 9400-9499 的 dummynet 辅助脚本(netlab);所有服务端都是本机自己起的进程;时间戳取自 tcpdump 的 -tt,数字每次运行会有小幅抖动。转发功能是我用 paramiko 5.0.0 自己实现的服务器端和客户端(没有用 OpenSSH),全在本机;密钥临时生成;第四节每个条件只测 2 次,只有 SSH 那一条 TCP 在 netlab 范围内(其余端口刻意放在范围外),所以不是严格的 TCP 套 TCP;吞吐数字是 paramiko 的,不代表 OpenSSH
    • 没有验证:动态转发 -D(SOCKS 代理,下一部分讲 SOCKS5);ProxyJump 和多跳;OpenSSH 的 ControlMaster 复用;GatewayPorts 与绑定地址的安全影响;通道窗口大小对吞吐的影响;真正的 TCP 套 TCP(内外层都受损)
    京ICP备2026067502号-1京公网安备11010502063487号