主机到虚拟机的nc连接正常(端口9050),但虚拟机上运行的Python服务器在相同端口(9050)上重置了主机到虚拟机的连接[TCP RST]

1 投票
1 回答
613 浏览
提问于 2025-04-18 09:43

背景信息

我正在开发一个可以联网的嵌入式设备,目的是让它能和服务器通信。因为这个服务器会运行Linux系统(但我需要Windows工具来开发),所以我在虚拟机上运行Ubuntu Server 14.04来进行开发。

嵌入式的部分对这个问题不重要,我只是想简化测试环境(只让主机连接到虚拟机上的服务器,以查看TCP连接是否建立)来进行故障排查。

网络设置

  • 使用DD-WRT的D-Link DIR-615路由器 [v24-sp2 (03/25/13) std (SVN revision 21061)],通过MAC过滤器为主机和虚拟机分配静态IP,启用了DNS功能

  • 开发机器(192.168.5.117,dev.test.lan)

  • Ubuntu虚拟机(192.168.5.118,vm.test.lan) - 使用桥接连接(NAT不工作,因为客户端会主动连接虚拟机)

  • 路由器没有连接到任何广域网,只是有线连接,Wi-Fi已禁用

已进行的基本检查

  • 从虚拟机ping主机成功(使用IP或DNS名称)

  • 从主机ping虚拟机成功(使用IP或DNS名称)

  • 主机和虚拟机之间的nc测试(可以从任一方监听/连接)[监听端口9050]

  • 在虚拟机内,可以通过nc连接到运行在虚拟机上的服务器应用程序,成功建立连接[到端口9050]

  • Windows防火墙已为端口9050的进出TCP连接打开

问题分析

通过wireshark,我可以看到在进行nc基本测试时(主机与虚拟机之间),TCP连接正常工作。

当我在虚拟机上运行用Python编写的服务器(使用asyncio),并尝试从主机通过nc连接时,服务器没有看到任何连接进来(但我们知道从nc到服务器的连接在虚拟机内部是成功的)。

从wireshark中,我看到主机向虚拟机发送了一个SYN包,之后虚拟机回应了[RST, ACK]。主机在放弃之前重试了两次。

问题

  • 桥接连接是虚拟机的合适设置吗?

  • 找出RST来源的最佳方法是什么?(是路由器、虚拟机的TCP/IP协议栈,还是Python的某个部分导致的?)


更新: 在虚拟机内尝试了nc 192.168.5.118 9050,观察到的连接被拒绝的行为与从主机尝试时相同。根据Adam所说的,看来我们离解决问题更近了。我会尝试Adam的建议,并发布更新。

1 个回答

1

操作系统发送RST数据包是为了表示这个端口是关闭的——没有任何程序在这个端口上监听。因此,试图连接的客户端会很快收到ECONNREFUSED(连接被拒绝)的错误。这是完全正常的现象。

你在Python服务器中是如何绑定端口的呢?你绑定的是正确的网络接口吗?如果你不小心只绑定到了回环设备(localhost127.0.0.1),那么你就会遇到你所描述的情况:从本机到本机的连接会成功,但来自外部主机的连接会失败。

在Python中,通常使用'''0.0.0.0'作为地址部分,这表示你想绑定到所有网络接口;这相当于C语言中的常量INADDR_ANY

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', port))

撰写回答