如何通过反向 SSH 隧道访问 NAT 后面的 Linux 服务器
您在家中运行 Linux 服务器,该服务器位于 NAT 路由器或限制性防火墙后面。现在您想在外出时通过 SSH 连接到家庭服务器。你会如何设置呢? SSH 端口转发肯定是一个选择。但是,如果您正在处理多个嵌套 NAT 环境,端口转发可能会变得很棘手。此外,它可能会在各种 ISP 特定条件下受到干扰,例如阻止转发端口的限制性 ISP 防火墙,或在用户之间共享 IPv4 地址的运营商级 NAT。
什么是反向 SSH 隧道?
SSH 端口转发的一种替代方法是反向 SSH 隧道。反向 SSH 隧道的概念很简单。为此,您需要在受限制的家庭网络之外使用另一台主机(所谓的中继主机),您可以从您所在的位置通过 SSH 连接到该主机。您可以使用具有公共 IP 地址的 VPS 实例设置中继主机。然后您要做的就是设置一条从家庭网络中的服务器到公共中继主机的持久 SSH 隧道。这样,您就可以从中继主机“返回”连接到家庭服务器(这就是为什么它被称为反向隧道)。只要您可以访问中继主机,无论您身在何处,也无论您的家庭网络中的 NAT 或防火墙如何限制,您都可以连接到您的家庭服务器。

在 Linux 上设置反向 SSH 隧道
让我们看看如何创建和使用反向 SSH 隧道。我们假设如下。我们将设置从 homeserver
到 relayserver
的反向 SSH 隧道,以便我们可以从另一台名为 clientcomputer
的计算机通过 relayserver
SSH 到 homeserver
。 relayserver
的公网IP地址是1.1.1.1。
在 homeserver
上,打开与 relayserver
的 SSH 连接,如下所示。
homeserver~$ ssh -fN -R 10022:localhost:22 [email
这里的端口 10022 是您可以选择的任意端口号。只需确保该端口未被 relayserver
上的其他程序使用即可。
-R 10022:localhost:22
选项定义反向隧道。它将 relayserver
端口 10022 上的流量转发到 homeserver
端口 22。
使用 -fN
选项,一旦您成功通过 SSH 服务器进行身份验证,SSH 将直接进入后台。当您不想在远程 SSH 服务器上执行任何命令而只想转发端口时(就像我们的例子一样),此选项非常有用。
运行上述命令后,您将立即回到homeserver
的命令提示符。
登录 relayserver
,并验证 127.0.0.1:10022 是否已绑定到 sshd
。如果是,则说明反向隧道建立正确。
relayserver~$ sudo netstat -nap | grep 10022
tcp 0 0 127.0.0.1:10022 0.0.0.0:* LISTEN 8493/sshd
现在,从任何其他计算机(例如 clientcomputer
)登录到 relayserver
。然后按如下方式访问homeserver
。
relayserver~$ ssh -p 10022 [email
需要注意的一件事是,您为 localhost
输入的 SSH 登录名/密码应该用于 homeserver
,而不是 relayserver
,因为您是通过隧道的本地端点登录到 homeserver
。因此,请勿输入 relayserver
的登录名/密码。成功登录后,您将进入homeserver
。
通过反向 SSH 隧道直接连接到 NATed 服务器
虽然上述方法允许您访问 NAT 后面的 homeserver
,但您需要登录两次:首先登录 relayserver
,然后登录 homeserver
。这是因为 relayserver
上 SSH 隧道的端点绑定到环回地址 (127.0.0.1)。
但事实上,有一种方法可以通过单次登录 relayserver
直接访问 NATed homeserver
。为此,您需要让 relayserver
上的 sshd
不仅从环回地址转发端口,还从外部主机转发端口。这是通过在 relayserver
上运行的 sshd
中指定 GatewayPorts
选项来实现的。
打开 relayserver
处的 /etc/ssh/sshd_conf
并添加以下行。
relayserver~$ vi /etc/ssh/sshd_conf
GatewayPorts clientspecified
重新启动 sshd。
没有 systemd
的基于 Debian 的系统:
relayserver~$ sudo /etc/init.d/ssh restart
基于 Debian 的系统,带有 systemd
:
relayserver~$ sudo systemctl restart ssh
基于红帽的系统:
relayserver~$ sudo systemctl restart sshd
现在让我们从 homeserver
启动反向 SSH 隧道,如下所示。
homeserver~$ ssh -fN -R 1.1.1.1:10022:localhost:22 [email
登录relayserver
并使用netstat
命令确认反向SSH隧道已成功建立。
relayserver~$ sudo netstat -nap | grep 10022
tcp 0 0 1.1.1.1:10022 0.0.0.0:* LISTEN 1538/sshd: dev
与之前的情况不同,隧道的端点现在位于 1.1.1.1:10022(中继服务器
的公共 IP 地址),而不是 127.0.0.1:10022。这意味着可以从外部主机到达隧道的终点。
现在,从任何其他计算机(例如 clientcomputer
),键入以下命令即可访问 NATed homeserver
。
clientcomputer~$ ssh -p 10022 [email
在上述命令中,虽然 1.1.1.1 是 relayserver
的公共 IP 地址,但 homeserver_user
必须是与 homeserver
关联的用户帐户。这是因为您登录的真实主机是 homeserver
,而不是 relayserver
。后者只是将您的 SSH 流量中继到homeserver
。
在 Linux 上设置持久反向 SSH 隧道
现在您已经了解了如何创建反向 SSH 隧道,让我们使隧道持久,以便隧道始终正常运行(无论临时网络拥塞、SSH 超时、中继主机重新启动等)。毕竟,如果隧道并非始终处于运行状态,您将无法可靠地连接到家庭服务器。
对于持久隧道,我将使用一个名为 autossh
的工具。顾名思义,该程序允许您在 SSH 会话因任何原因中断时自动重新启动。因此,保持反向 SSH 隧道处于活动状态非常有用。
第一步,我们设置从 homeserver
到 relayserver
的无密码 SSH 登录。这样,autossh
就可以重新启动损坏的反向 SSH 隧道,而无需用户参与。
接下来,在启动隧道的 homeserver
上安装 autossh
。
从 homeserver
中,使用以下参数运行 autossh
以创建发往 relayserver
的持久 SSH 隧道。
homeserver~$ autossh -M 10900 -fN -o "PubkeyAuthentication=yes" -o "StrictHostKeyChecking=false" -o "PasswordAuthentication=no" -o "ServerAliveInterval 60" -o "ServerAliveCountMax 3" -R 1.1.1.1:10022:localhost:22 [email
-M 10900
选项指定 relayserver
上的监控端口,该端口将用于交换测试数据以监控 SSH 会话。 relayserver
上的任何程序都不应使用此端口。
-fN
选项传递给 ssh
命令,这将使 SSH 隧道在后台运行。
“-o XXXX”选项告诉 ssh:
使用密钥身份验证,而不是密码身份验证。
自动接受(未知)SSH 主机密钥。
每 60 秒交换一次保持活动消息。
最多发送 3 条保持活动消息而不会收到任何回复。
其余与反向 SSH 隧道相关的选项与以前相同。
如果您希望 SSH 隧道在启动时自动启动,您可以在 /etc/rc.local
中添加上述 autossh
命令。
结论
在这篇文章中,我讨论了如何使用反向 SSH 隧道从外部访问限制性防火墙或 NAT 网关后面的 Linux 服务器。虽然我通过公共 VPS 演示了其在家庭网络中的用例,但在将其应用于企业网络时必须小心。此类隧道可被视为违反公司策略,因为它绕过公司防火墙并使公司网络遭受外部攻击。它很有可能被误用或滥用。所以在设置之前一定要记住它的含义。