@iximiuz: https://x.com/iximiuz/status/2069036148077293614
摘要
SSH本地和远程端口转发的可视化指南,解释如何通过SSH隧道访问私有服务以及暴露本地端口,包含实用示例和配置技巧。
查看缓存全文
缓存时间: 2026/06/22 19:51
SSH 隧道实用指南:本地与远程端口转发
以清晰直观的方式解释 SSH 端口转发。如何使用本地和远程端口转发。可能需要调整哪些 sshd 设置。如何记住正确的标志。
SSH 是古老技术至今仍在广泛使用的又一个例子。长远来看,学习几个 SSH 技巧可能比掌握十几个注定在下个季度被废弃的云原生工具或 AI 代理框架更有价值。
这项技术我最喜欢的一部分是 SSH 隧道。仅使用标准工具,通常只需一条命令,你就能实现以下功能:
- 通过面向公网的 EC2 实例访问内部 VPC 端点。
- 在本地浏览器中打开远程开发虚拟机的 localhost 端口。
- 将家庭/私有网络中的任何本地服务器暴露到外部世界。
- 将浏览器的调试端口隧道传输到远程沙盒化编码代理。
- 还有更多 😍
但尽管我每天都使用 SSH 隧道,我总是需要花点时间才能想起正确的命令。应该是本地隧道还是远程隧道?标志是什么?是 local_port:remote_port 还是反过来?所以,我决定彻底搞清楚它,于是就有了这一系列实验和一张可视化速查表。
SSH 隧道速查表
SSH 隧道速查表
本地端口转发
从我最常用的那个开始。很多时候,可能存在一个服务监听在远程机器的 localhost 或私有接口上,而我只能通过其公网 IP 进行 SSH 连接。我迫切需要从本地机器访问这个端口。几个典型例子:
- 使用你喜欢的 UI 工具从笔记本电脑访问私有远程数据库(MySQL、Postgres、Redis 等)。
- 使用浏览器访问仅暴露给私有网络的 Web 应用程序。
- 从笔记本电脑访问容器的端口,而不将其发布到服务器的公共接口上。
以上所有用例都可以通过一条 ssh 命令解决:
bash ssh -L [local_addr:]local_port:remote_addr:remote_port [user@]sshd_addr
-L 标志表示我们要启动本地端口转发。它实际的意思是:
- 在你的本地机器上,SSH 客户端将开始在 local_port 上监听(很可能在 localhost 上,但取决于 GatewayPorts 设置)。
- 任何发送到此端口的流量都将被转发到 remote_addr:remote_port,从你 SSH 连接的远程机器访问。
以下是图示:
使用堡垒主机的本地端口转发
一开始可能不太明显,但 ssh -L 命令允许将本地端口转发到任何机器上的远程端口,而不仅仅是 SSH 服务器本身。注意 remote_addr 和 sshd_addr 可能相同也可能不同:
bash ssh -L [local_addr:]local_port:remote_addr:remote_port [user@]sshd_addr
用于访问私有目的地的远程 SSH 服务器通常称为堡垒机或跳板机。这是我脑海中的可视化场景:
我经常使用上述技巧来调用从堡垒机可访问但从我的笔记本电脑无法访问的端点(例如,使用具有私有和公共接口的 EC2 实例连接到完全部署在 VPC 内的 OpenSearch 集群或任何其他服务)。
远程端口转发
另一种流行(但相当反向)的场景是,你想暂时将本地服务暴露给外部世界。当然,为此你需要一个面向公网的入口网关服务器。好消息是,任何带有 SSH 守护进程的面向公网服务器都可以用作这样的网关:
bash ssh -R [remote_addr:]remote_port:local_addr:local_port [user@]gateway_addr
上面的命令看起来并不比它的 ssh -L 对应命令更复杂。但有一个陷阱……
默认情况下,上述 SSH 隧道只允许使用网关的 localhost 作为远程地址。 换句话说,你的本地端口只能从网关服务器内部访问,这很可能不是你真正想要的。例如,我通常希望使用网关的公网地址作为远程地址,将我的本地服务暴露给公共互联网。为此,SSH 服务器需要配置 GatewayPorts yes 设置。
以下是远程端口转发可能的用途:
- 将笔记本电脑上的开发服务暴露给公共互联网,用于快速演示。
- 将你的家庭实验室暴露给公共互联网(用于任意目的)。
- 将本地浏览器的调试端口隧道传输到远程和/或沙盒化的编码代理。
以下是远程端口转发的可视化:
远程端口转发到家庭或私有网络
与本地端口转发类似,远程端口转发也有自己的堡垒机或跳板机模式。但这次,SSH 客户端机器(例如你的开发笔记本电脑)扮演跳板机的角色。具体来说,它允许将从笔记本电脑可访问的家庭(或私有)网络端口,通过充当入口网关的远程 SSH 服务器暴露给外部世界:
ssh -R [remote_addr:]remote_port:local_addr:local_port [user@]gateway_addr
看起来与简单的远程 SSH 隧道几乎相同,但 local_addr:local_port 对变成了家庭网络中设备的地址。以下是图示:
我通常将笔记本电脑用作瘦客户端,实际开发在远程服务器上进行。有时,这样的远程服务器可能位于我的家庭网络中,并且没有或受限制的互联网访问(为了额外隔离)。这时我可能想要依赖远程端口转发,使用我的笔记本电脑(它可以同时访问内部开发服务器和远程 SSH 服务器(入口网关))作为跳板机,将家庭服务器上的服务暴露给公共互联网。
动态本地端口转发
这种转发模式对客户端来说不太透明,但也比常规的本地端口转发灵活得多。动态(本地)端口转发不是将本地端口连接到单个远程目标(如 ssh -L 所做),而是将 SSH 客户端转换为本地 SOCKS 代理。任何支持 SOCKS 的应用程序都可以通过它发送流量,并且每个连接可以选择实际的目标主机和端口——这些信息将被发送到 SSH 服务器,由它解析目标并建立连接:
ssh -D [local_addr:]local_port [user@]sshd_addr
当使用 -D 标志时,你机器上的 SSH 客户端会启动一个 SOCKS 代理,在 local_port 上监听(默认在 localhost 上)。通过代理建立的每个连接都会被转发到 SOCKS 客户端请求的任何地址,从 sshd_addr 机器访问。
换句话说,这类似于 ssh -L,但你不需要预先指定单一的 remote_addr:remote_port,因为 SOCKS 协议允许在每个连接开始时指定目标(通过在有效载荷之前发送几个额外字节)。一个(本地)代理端口让你能够访问从(远程)SSH 服务器可达的所有主机和端口。
以下是动态端口转发可能的用途:
- 通过堡垒机调用私有网络中的 API,无需为每个服务单独建隧道。
- 通过单个跳板机浏览远程网络中的内部 Web 应用。
- 通过一个 EC2 实例从笔记本电脑访问 VPC 中的多个端点。
动态远程端口转发
就像 ssh -L 有对应的动态版本 ssh -D 一样,ssh -R 命令也有自己的动态模式。如果你从 -R 中省略固定目标,只传递一个端口,OpenSSH 会将 SSH 服务器本身转变为 SOCKS 代理。这与 -D 完全对称:这次代理位于网关上,通过它建立的每个连接都会被隧道传回 SSH 客户端,并从客户端视角解析:
ssh -R [bind_address:]port [user@]gateway_addr
不带目标的 -R 标志 意味着:
- 在远程网关上,SSH 服务器启动一个 SOCKS 代理,在 port 上监听(默认在网关的 localhost 上,如果 GatewayPorts yes 则在所有接口上)。
- 通过代理建立的每个连接都会被隧道传回 SSH 客户端,并转发到 SOCKS 客户端请求的任何地址,从客户端侧访问。
这类似于常规的 ssh -R,但你不需要预先选择单一的 local_addr:local_port。网关上的一个代理暴露了从 SSH 客户端可达的所有主机和端口——例如,整个家庭网络。
总结
这里是一个快速回顾和几个帮助你记忆 SSH 隧道命令的记忆技巧:
- 本地端口转发(ssh -L)使远程服务在本地端口上可用。
- 远程端口转发(ssh -R)使本地服务在远程端口上可用。
- 动态本地端口转发(ssh -D)将本地 SSH 客户端转变为 SOCKS 代理。
- 动态远程端口转发(不带目标的 ssh -R)将 sshd 服务器转变为 SOCKS 代理。
- 本地端口转发(ssh -L)意味着是 SSH 客户端开始监听新端口。
- 远程端口转发(ssh -R)意味着是 sshd 服务器开始监听额外端口。
- local 一词可以指 SSH 客户端机器 或从它可访问的内部主机。
- remote 一词可以指 SSH 服务器机器(sshd) 或从它可访问的任何主机。
- 记忆技巧:ssh -L 表示 local:remote,ssh -R 表示 remote:local,而且总是左侧打开新端口。
希望以上内容能帮助你成为 SSH 隧道大师 🧙
在 iximiuz Labs 找到包含动手练习的完整教程版本:https://labs.iximiuz.com/tutorials/ssh-tunnels
相似文章
SSH 隧道实用指南:本地和远程端口转发
一份实用教程,通过图表和实验讲解 SSH 本地和远程端口转发,用于安全访问内部网络服务。
@levelsio: 这是我最近的设置。每个网站我都在Termius中设置了一个配置文件,比如 > hoodmaps.com,点击后立即进入…
Pieter Levels分享了他的服务器工作流程:使用Termius配置文件和一个自定义的tmux函数,自动连接到每个网站的会话,实现设备间无缝切换和一致的工作会话。
mikeroyal/Self-Hosting-Guide
全面指南,介绍如何在本地自托管软件应用程序,涵盖云服务、LLM、WireGuard、自动化、Home Assistant 和网络。
@elonmusk:使用Grok Build的技巧
由Yun-Ta Tsai分享的关于使用Grok Build通过SSH和tmux会话管理多台机器的技巧。
imthenachoman/如何保障 Linux 服务器安全
这是一份全面的开源指南与工具集,旨在保障 Linux 服务器的安全,涵盖使用 Ansible、Fail2Ban 和 Lynis 等工具进行 SSH 加固、防火墙配置以及入侵检测。