我正在尝试调试端口转发的一个问题,即“为什么我不能限制要连接的端口?”但这不是这里的问题。这里的问题是“为什么 nc 不会通过转发端口发送任何数据?”
在本地机器上简单开始:
- 我已经在 Windows 8.1 下安装了 OpenSSH。很简单。
将这些行添加到 sshd_config 文件的开头:
许可证TTY 号 最大会话数 1
我使用命令启动 sshd
net start sshd
。- 我启动了一个 cygwin bash shell(也尝试使用 git-bash)并输入命令:
ssh -N -L 1234:localhost:5678 adrian@localhost
,然后输入密码。 - 我启动另一个 cygwin bash shell 并输入命令
nc -l 5678
。 - 我启动另一个 cygwin bash shell 并输入命令
nc -v localhost 1234
。
此时,我希望看到连接成功,现在可以在第二个 cygwin bash shell 中输入内容,并让其显示在第一个 cygwin bash shell 中。但是,我收到的是连接成功的消息,然后它又回到了 bash 提示符。为什么?
例子
然后它将我引导到命令行的成功消息是:
$ nc -v localhost 1234 Connection to localhost 1234 port [tcp/*] succeeded! $
如果我没有
nc
运行侦听器并尝试通过转发端口进行连接,也会发生这种情况。我可以直接连接到端口并收到一条错误消息,然后收到一条成功消息,最后我可以在一个 shell 中输入,它会显示在另一个 shell 中:
$ nc -v localhost 5678 nc: connect to localhost port 5678 (tcp) failed: Connection refused Connection to localhost 5678 port [tcp/*] succeeded!
如果我要连接未转发的端口,并且无论 sshd 是否正在运行,这都是一致的。
如果没有端口转发,如果我没有
nc
运行侦听器并尝试通过先前转发的端口进行连接,则会失败:$ nc -v localhost 1234 nc: connect to localhost port 1234 (tcp) failed: Connection refused nc: connect to localhost port 1234 (tcp) failed: Connection refused
编辑
因此,根据答案,失败的原因似乎是nc -l 5678
将连接到传入的 IP4 数据包。 nc localhost 5678
将首先尝试发送 IP6 数据包,如果失败,则再次尝试发送 IP4 数据包。 通过从 接收到的任何数据包类型sshd
与 进行通信。由于这是 IP4 数据包,因此它会失败,关闭隧道,然后关闭 ,然后关闭发送方,然后再重试发送 IP6 数据包。nc -l 5678
ssh
ssh
nc
要修复它,请使用命令让监听器仅接受 IP6 数据包nc -6l 5678
,然后一切就可以正常工作。
答案1
SSH“端口转发”与路由器执行的端口转发略有不同。路由器会单独且不加改变地转发每个 IP 数据包,而 SSH 会处理“连接已打开”等通用信号,并且根本不转发实际的 TCP 操作。
也就是说,SSH 充当两个完全独立的 TCP 连接(“nc→ssh”和“sshd→nc-l”)之间的管道,而不像路由器那样从一端到另一端承载相同的连接。
因此,使用 SSH 实际上是您的本地系统它接受来自的 TCP 握手nc
,而 SSH 客户端只知道这一点后它已经被接受了。然后 SSH 客户端向服务器发送“隧道打开”请求,服务器尝试建立到最终目的地的全新 TCP 连接。如果没有成功,它会向客户端发送“隧道打开失败”的回复。
此时,您的本地系统nc
以通常的方式通知错误已经太晚了——请记住它已经接受了连接;它可以立即关闭它,但无法及时返回并完全拒绝它。
(您收到的“拒绝”消息做localhost
see 与转换为 IPv4 127.0.0.1 和 IPv6 ::1相关– nc 尝试访问两者,但 ssh 客户端被告知只监听其中一个。)
因此,根据答案,失败的原因似乎是 nc -l 5678 将连接到传入的 IP4 数据包。nc localhost 5678 将首先尝试发送 IP6 数据包,如果失败,则再次尝试发送 IP4 数据包。sshd 通过从 ssh 收到的任何数据包类型与 nc -l 5678 进行通信。由于这是 IP4 数据包,因此它会失败,关闭隧道,然后关闭 ssh,然后关闭 nc 发送方,然后再重试发送 IP6 数据包。
不。有点像,但是——再说一遍——实际的 IP 数据包根本就不会穿过隧道。有两个独立的连接(如果算上实际的 SSH 会话,可能是三个)和本地nc
客户端尝试的 IP 版本能与远程侦听器收到的 IP 版本不同nc -l
。
更具体地说,这是两个客户端-服务器对:
本地系统:
nc localhost 5678
作为客户端⇆ssh -L ...
作为监听器;远程系统:
sshd
作为客户端⇆nc -l 5678
作为监听器。
第一次出现连接拒绝是因为ssh-L 密码不期望 IP 版本nc 本地主机正在尝试。此尝试未到达远程系统(既未sshd也不数控知道这一点)。