通过公共EC2实例访问内部VPC终端点。
在主机的浏览器中打开来自开发VM的本地主机端口。
将来自家庭/私有网络的任何本地服务器暴露给外部世界。等等

但尽管我每天都在使用SSH隧道,但我总是需要一段时间来找到正确的命令。它应该是本地隧道还是远程隧道?有哪些标志?是local_port:remote_port还是相反?因此,我决定最终理解它,并制作了一系列实验

先决条件

SSH隧道涉及通过网络连接主机,因此以下每个实验都涉及多个“机器”。但是,我懒得启动完整的实例,特别是可以使用容器时。这就是为什么我最终使用了一个只有一个VagrantVM和Docker的解决方案。

理论上,任何安装了DockerEngine的Linux系统都可以。但是,如果在DockerDesktop上运行以下示例,将无法访问机器容器的IP。

或者,可以使用Lima(QEMU+nerdctl+containerd+BuildKit)完成实验,但不要忘记首先执行limactlshellbash。

每个示例都需要在主机上拥有有效的无需密码的密钥对,然后将其挂载到容器中以简化访问管理。如果没有,请在主机上生成它非常简单,只需运行ssh-keygen即可。

重要提示:这里容器中的SSH守护进程仅用于教育目的-本文中的容器旨在表示具有SSH客户端和服务器的完整“机器”。请注意,在现实世界中,在容器中使用SSH是个好主意!

本地端口转发

通常情况下,可能会有一个服务在本地主机或一台机器的私有接口上监听,而我只能通过其公共IP进行SSH访问。我迫切需要从外部访问此端口。几个典型的例子:

    使用精美的UI工具从您的笔记本电脑访问数据库(MySQL,Postgres,Redis等)。 使用浏览器访问仅暴露给私有网络的Web应用程序。 从您的笔记本电脑访问容器的端口,而不将其发布在服务器的公共接口上。
    所有上述用例都可以通过单个ssh命令解决:

    ssh-L[local_addr:]local_port:remote_addr:remote_port[user@]sshd_addr

-L标志表示我们正在启动本地端口转发。其实际含义是:

在您的计算机上,SSH客户端将开始侦听local_port。

该端口的任何流量都将被转发到您SSH到的远程机器的remote_private_addr:remote_port。

以下是它在图表上的样子:

提示:使用ssh-f-N-L命令可以在后台运行端口转发会话。

使用跳板主机的本地端口转发

一开始可能不太明显,但是ssh-L命令允许将本地端口转发到任何机器上的远程端口,不仅仅是SSH服务器本身。请注意,remote_addr和sshd_addr可能具有相同或不同的值:

ssh-L[local_addr:]local_port:remote_addr:remote_port[user@]sshd_addr

不确定在这里使用“堡垒主机”这个术语是否合适,但这就是我自己想象的场景:

我经常使用上述技巧来调用从跳板主机可访问但从我的笔记本电脑无法访问的端点(例如,使用具有私有和公共接口的EC2实例连接到完全部署在VPC中的OpenSearch集群)。

远程端口转发

另一个常见(但相反的)场景是当您想要暂时将本地服务暴露到外部世界时。当然,为此,您需要一个面向公众的入口网关服务器。但是不要担心!任何具有SSH守护进程的面向公众的服务器都可以用作这样的网关:

ssh-R[remote_addr:]remote_port:local_addr:local_port[user@]gateway_addr

上述命令看起来并不比其ssh-L对应命令更复杂。但是有一个陷阱...

默认情况下,上述SSH隧道将仅允许使用网关的localhost作为远程地址。换句话说,您的本地端口仅从网关服务器本身内部可访问,这很可能不是您实际需要的。例如,我通常希望使用网关的公共地址作为远程地址,以将我的本地服务暴露给公共互联网。为此,需要使用GatewayPortsyes设置配置SSH服务器。

以下是远程端口转发的用途:

将笔记本电脑上的开发服务暴露到公共互联网上进行演示。

以下是远程端口转发的图示:

从家庭/私有网络进行远程端口转发

与本地端口转发类似,远程端口转发也有其自己的堡垒主机模式。但是这次,具有SSH客户端的机器(例如您的开发笔记本电脑)扮演堡垒的角色。特别地,它可以通过入口网关将您的笔记本电脑可以访问的家庭(或私有)网络中的端口暴露给外部世界:

ssh-R[remote_addr:]remote_port:local_addr:local_port[user@]gateway_addr

看起来几乎与简单的远程SSH隧道相同,但是local_addr:local_port对变成了家庭网络中设备的地址。以下是如何在图表上表示它:

由于我通常将我的笔记本电脑作为轻量级客户端,而实际的开发是在家庭服务器上进行的,因此当我需要将家庭服务器上的开发服务暴露给公共互联网时,只有我的轻量级笔记本电脑可以访问网关,因此我会依靠这种远程端口转发。

总结

    “local”一词既可以指SSH客户端计算机,也可以指从该计算机可访问的上游主机。 “remote”一词既可以指SSH服务器计算机(sshd),也可以指从它可访问的上游主机。 本地端口转发(ssh-L)意味着是SSH客户端开始侦听新端口。 远程端口转发(ssh-R)意味着是sshd服务器开始侦听额外的端口。 助记符是“ssh-Llocal:remote”和“ssh-Rremote:local”,而始终是左侧打开新端口。