我有一台 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_address
和specifying 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 comp
或0.0.0.0:80:localhost:80
此外,PORT:IP:PORT 语法绑定到 127.0.0.1 的原因也是出于安全原因。因此,如果您确实希望它非本地绑定,最好将其明确说明,例如使用通配符或指定 0.0.0.0,或者如果仅从 LAN 连接,则指定 LAN 地址。