如何使用反向 SSH 隧道绕过防火墙和 NAT

Posted

技术标签:

【中文标题】如何使用反向 SSH 隧道绕过防火墙和 NAT【英文标题】:How to bypass firewall and NAT with reverse SSH Tunnel 【发布时间】:2013-10-16 15:44:31 【问题描述】:

我正在尝试在路由器后面的机器中生成 SSH 服务器。

首先我尝试将 SSH 绑定到我的公共 IP 地址:

ssh -R 10002:localhost:22 <ip_address>

然后提示我输入密码,但我的用户名密码似乎不起作用。

显然我知道我的用户名密码,所以在我看来它正在尝试在同一网络下的另一台计算机上进行身份验证。

有什么建议可以解决这个问题吗?

当您无权访问路由器时,它还可以帮助我了解如何在路由器后面创建 SSH 服务器。

iptables中的端口都是开放的。

更新

正如Thomas Oster 回答所建议的那样,我尝试了以下方法。

在路由器后面的机器中,我执行了以下命令:

$ ssh -R10002:localhost:22 &lt;remote_public_ip_address&gt; -l &lt;my_remote_server_username&gt;

&lt;remote_ip_address&gt; 是具有公共 IP 和 SSH 服务器的服务器的 remote_ip_address,我可以完全控制它。

&lt;my_remote_server_username&gt; 是远程服务器用户名。

之后,我尝试从远程服务器连接到路由器后面的服务器,如下所示:

$ ssh -p 10002 &lt;remote_public_ip_address&gt;

但是此命令显示以下输出:

ssh: connect to host <remote_public_ip_address> port 10002: Connection refused

于是我在 iptables 防火墙中使用以下命令打开了 10002 端口:

sudo iptables -A INPUT -p tcp --dport 10002 -j ACCEPT

之后我再次执行该命令,但它显示相同的错误消息。

在路由器后面的机器中,我在 iptables 中打开了所有端口。

更新 2

您必须在 /etc/ssh/sshd_config 的 /etc/ssh/sshd_config 中允许端口转发 remove_public_ip_address 服务器

我已尝试在 sshd_config 文件中添加此命令来允许端口转发:

LocalForward 10002 <my_remote_public_server_ip>:22

但它给了我这个错误信息:

Bad configuration option: LocalForward

在“ssh -R....”之后,您是否让窗口保持打开状态?

执行该命令后,它连接到远程公共机器,是的,我没有打开窗口。

你可以在公共服务器上使用 ssh -p 10002 localhost 吗? 隧道创建了吗?

是的,如果我在公共服务器中执行该命令,它会在向我询问凭据后连接。

请在路由器后面的机器上尝试“ssh localhost”以检查 sshd 是否正在运行。

这也有效。

更新 3

我终于可以让它工作了(再次感谢Thomas Oster)

我们将使用三台机器:

目标机器:我们要连接的机器。

中间机:充当连接中介的服务器(在我的例子中是 Linode)

家用计算机:我们将访问目标计算机的位置。

这些是我遵循的步骤

第 1 步:

[destination computer]$ vi /etc/ssh/sshd_config

添加 GatewayPorts 选项:

网关端口是

重启 ssh。

第 2 步:

[destination computer]$ ssh -R 4040:localhost:22 middle-machine-user@middle-machine-public-ip

这将通过端口 4040 将您的公共计算机与您的目标计算机链接

它将连接到中间机器并提示终端,您必须保持此选项卡处于打开状态。

第 3 步:

在家连接:

ssh destination-user@destination-ip -p4040

或者从中间机连接:

[home computer]$ ssh middle-machine-user@middle-machine-ip

[middle computer]$ ssh destination-user@localhost -p4040

Source

【问题讨论】:

必须在 remove_public_ip_address 服务器的 /etc/ssh/sshd_config 中允许端口转发 在“ssh -R....”之后,您是否让窗口保持打开状态?隧道仅在连接打开时才处于活动状态。它是否显示任何错误消息,例如“无法绑定到 10002”?建立隧道后可以在公共服务器上使用 ssh -p 10002 localhost 吗? 请在路由器后面的机器上尝试“ssh localhost”以检查sshd是否正在运行和工作。 如果你不想要HTTP或HTTPS,你也可以试试burrow.io,免费账户可以让你打开1个HTTP反向隧道,你要做的就是在上面运行一个curl命令正在侦听端口 4040 的机器。您在网站上设置隧道。这很酷。 我认为在第 3 步中您的意思是 ssh destination-user@middle-ip -p4040 【参考方案1】:

在公共“ip_address”上是否有运行 ssh 服务器?您要做的是“打开到“ip_address”的 ssh 连接,然后将端口 10002 上的任何传入请求隧道传输到 localhost:22”。

如果“ip-address”是您的 dsl 路由器的公共 IP 地址,您必须在路由器的配置中创建一个端口转发到您的主机:22。

如果您无法访问路由器,唯一可能的情况是您可以访问互联网上运行 ssh 的另一台服务器,您可以从该服务器进行隧道传输。

# open a session to the public available machine and create a tunnel from port 10002 back  to your local sshd (22)
ssh -R 10002:localhost:22 ip_of_public_server
# as long as this session is open, all calls to the public available machine on port 10002 will be tunneled to your local machine (make sure sshd is running on port 22)
ssh -p 10002 ip_of_public_server

【讨论】:

不知道公网ip上运行的是哪个SSH服务器。但我确实有另一台服务器运行具有公共 IP 的 SSH 服务器,并在另一个网络中完全控制它。但是我不知道如何在那里创建一个隧道,该隧道将与路由器后面的这台计算机链接。这意味着我可以从路由器后面的计算机连接到另一个 SSH 服务器,但我不知道如何反过来。 好的。假设您的公共计算机具有 IP 地址 public_ip。然后转到路由器后面的机器并执行“ssh -R10002:localhost:22 public_ip”。如果可行,您可以使用“ssh -p 10002 public_ip”从任何地方连接到路由器后面的机器 如果对您有用,请接受答案,或描述您的问题所在。 我已经用你的建议的答案更新了帖子。谢谢!【参考方案2】:

正如你所说,我们有“目标机器”(我们想使用 ssh 连接的地方)、“中间机器”(作为转发器的公共服务器)、“其他计算机”(网络上的任何其他计算机)

正如@thomas-oster 所说,你必须使用

[destination computer] $ ssh -R 2222:localhost:22 ip_of_public_server

但是,为了让隧道绑定到 0.0.0.0 而不是 localhost,您必须在“中间机”(公共服务器)上的 /etc/ssh/sshd_config 中使用 GatewayPorts:

GatewayPorts yes

当然你必须在添加这个选项后重新启动sshd。

阅读http://www.snailbook.com/faq/gatewayports.auto.html 以获得解释: "默认情况下 SSH 只监听环回地址上转发端口的连接"

这将允许您使用中间机器(公共服务器)的 ip 从网络上的任何计算机连接到目标计算机:

[any computer on the net] $ ssh -p 2222 ip_of_public_server

确保公共服务器上的防火墙允许连接到端口 2222/tcp。

【讨论】:

【参考方案3】:

我最近偶然发现了同样的问题,但在 SSH 服务器上没有 root 权限。

如上所述,GatewayPorts yes 是必需的,因此来自网络的客户端也能够连接到 SSH 服务器上的远程转发端口。默认情况下,它设置为no。因此,如果您没有 root 权限,则无法更改 SSHD 设置以将 GatewayPorts 选项设置为 true。但在这种情况下,您可以使用以下解决方法:

ssh -R 4041:localhost:22 myserver.com 'socat TCP-LISTEN:4040,fork TCP:127.0.0.1:4041'

socat 是一个很棒的网络实用程序,它在接口 0.0.0.0 上绑定 TCP 端口 4040,因此它可以从网络中看到,并将所有流量重定向到 127.0.0.1:4041,其中 SSHD 正在侦听并将其重定向到您客户端的端口22.

因此,如果有人想按照您(在客户端)描述的那样在端口 22 上连接您的本地 SSH,他会这样做:

ssh -p 4040 myserver.com 

它的工作原理是这样的:

SSH client --&gt; myserver.com:4040 (socat) --&gt; 127.0.0.1:4041 (myserver.com, SSHD) --&gt; SSH client port 22

socat 可以从源代码构建或已安装在系统上。它存在于 RHEL/CentOS 的 RPMForge 存储库中(但是,如果您没有 root 权限,则无法安装它)。

【讨论】:

以上是关于如何使用反向 SSH 隧道绕过防火墙和 NAT的主要内容,如果未能解决你的问题,请参考以下文章

通过反向 SSH 隧道访问 NAT 后面的 Linux 服务器

反向 ssh 隧道不暴露 ec2 上的端口

C# 反向代理(绕过 NAT/防火墙)

将 ssh 隧道反向访问公司防火墙后面的系统的最佳方法是啥?

反向 SSH 隧道监控

如何配置系统通过 ssh 反向隧道/代理使用 git?