我正在进行 SSH 反向隧道,但无法连接到隧道

我正在进行 SSH 反向隧道,但无法连接到隧道

我有一台 Windows 11 机器,在 127.0.0.1 端口 80 上运行 IIS,它通过 CGNAT 连接到 Internet。我还有一个来自 Linode(VPS 供应商)的 VPS。VPS 的 IP 地址是 139.162.19.185。我想通过我的 VPS 从 Internet 上的任何其他地方连接到我的 Windows 11 机器上的服务器/端口。

我使用 Windows 11 命令提示符在管理员模式下运行了以下命令:

ssh -R 80:localhost:80 [email protected]

当我尝试使用以下方式访问我的 VPS 上的 SSH 隧道时http://139.162.19.185:80,我得到连接被拒绝,但是当我尝试使用访问我的本地主机时http://127.0.0.1,我看到了 IIS 启动主页。

我已经检查了 /etc/ssh/sshd_config 文件,GatewayPorts 和 AllowTcpForwarding 都已启用。

更新:

这是 netstat -tlnp 的结果

root@localhost:~# netstat -tlnp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.1:80            0.0.0.0:*               LISTEN      35027/sshd: root@pt
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      434/sshd: /usr/sbin
tcp6       0      0 ::1:80                  :::*                    LISTEN      35027/sshd: root@pt
tcp6       0      0 :::22                   :::*                    LISTEN      434/sshd: /usr/sbin
root@localhost:~#

curl的结果如下:

root@localhost:~# curl http://127.0.0.1:80
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd">
<HTML><HEAD><TITLE>Bad Request</TITLE>
<META HTTP-EQUIV="Content-Type" Content="text/html; charset=us-ascii"></HEAD>
<BODY><h2>Bad Request - Invalid Hostname</h2>
<hr><p>HTTP Error 400. The request hostname is invalid.</p>
</BODY></HTML>
root@localhost:~#

我需要编辑任何配置文件吗?我尝试了一些调试,以查看 Linode 上是否有防火墙。我安装了 apache2,它在端口 80 上运行良好,因此端口 80 没有被阻止。

答案1

您使用该选项的方式-R意味着您希望远程端仅绑定到环回接口。来自ssh手册页:

     -R [bind_address:]port:host:hostport

     ...

             By default, TCP listening sockets on the server will be bound to the loopback interface only.  This may be overridden by
             specifying a bind_address.  An empty bind_address, or the address ‘*’, indicates that the remote socket should listen on
             all interfaces.  Specifying a remote bind_address will only succeed if the server's GatewayPorts option is enabled (see
             sshd_config(5)).

简化来说就是:

  • -R port:host:hostport将仅绑定到环回
  • -R :port:host:hostport将绑定到所有接口
  • 按照意愿-R *:port:host:hostport-R 0.0.0.0:port:host:hostport

因此,根据您的情况,以下任何一种方法都可以:

ssh -R :80:localhost:80 [email protected]
ssh -R *:80:localhost:80 [email protected]
ssh -R 0.0.0.0:80:localhost:80 [email protected]

*下面是我根据文档文本最初尝试解释这种行为的 - 并进行了一些澄清。

您使用了 PORT:IP:PORT 语法,但未指定 bind_address。

specifying a bind_address上述描述中的文本指的是:在远程端口(PORT:IP:PORT 中的第一个端口)之前有一个。您的示例中没有:,这意味着您没有指定 bind_address,并且根据手册页,远程端将仅绑定到环回接口(默认)。为了绑定到所有接口,您需要指定 bind_address(即在:远程端口前添加一个),即使实际的 bind_address 是一个“空字符串”!在这种情况下,“空字符串”或一个*都可以,但请记住,:必须有一个,这样它才不会仅限于绑定到环回地址!

更新

在@barlop 的评论之后,似乎我的解释不是很清楚,所以我试着在这里逐步澄清一些事情:

  • 该选项定义为-R [bind_address:]port:host:hostport
  • 整个[bind_address:]部分是可选的。如果不存在,则选项具有格式-R port:host:hostport并应用默认行为,这意味着TCP listening sockets on the server will be bound to the loopback interface only
  • 如果[bind_address:]存在该部分,则意味着我们有格式-R bind_address:port:host:hostport,请注意,现在第一个:不再是可选的。从此刻开始,bind_address可以采用多个值,其中一个可能的值确实是空字符串! 因此,在选项中添加冒号意味着我们bind_address这次确实指定了,尽管它是一个空的(根据描述,这意味着)the remote socket should listen to all interfaces

我希望这能让您更清楚一点,基本上not specifying a bind_addressspecifying an empty string as bind_address是两个不同的东西!“空字符串”bind_address 被视为绑定地址,指的是使用:PORT:IP:PORT语法而不在最左边的冒号之前为地址写入任何内容!。

这是我测试的输出(在不同的端口上,但效果相同):

查看它是否正在 SSH 并在远程机器上运行 netstat -an。

gepa@localhost:~$ ssh -R :5555:localhost:5555 cloud1 netstat -an | grep :5555
tcp        0      0 0.0.0.0:5555            0.0.0.0:*               LISTEN     
tcp6       0      0 :::5555                 :::*                    LISTEN     

gepa@localhost:~$ ssh -R 5555:localhost:5555 cloud1 netstat -an | grep :5555
tcp        0      0 127.0.0.1:5555          0.0.0.0:*               LISTEN     
tcp6       0      0 ::1:5555                :::*                    LISTEN     

:请注意,与省略相比,在第一个之前添加5555会使远程主机监听所有接口:

顺便说一句,更清楚的是不要使用空字符串 bind_address 并写入$ ssh -R *:5555:localhost:5555 comp0.0.0.0:80:localhost:80

此外,PORT:IP:PORT 语法绑定到 127.0.0.1 的原因也是出于安全原因。因此,如果您确实希望它非本地绑定,最好将其明确说明,例如使用通配符或指定 0.0.0.0,或者如果仅从 LAN 连接,则指定 LAN 地址。

相关内容