主机到虚拟机的nc连接正常(端口9050),但虚拟机上运行的Python服务器在相同端口(9050)上重置了主机到虚拟机的连接[TCP RST]
背景信息
我正在开发一个可以联网的嵌入式设备,目的是让它能和服务器通信。因为这个服务器会运行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 个回答
操作系统发送RST数据包是为了表示这个端口是关闭的——没有任何程序在这个端口上监听。因此,试图连接的客户端会很快收到ECONNREFUSED
(连接被拒绝)的错误。这是完全正常的现象。
你在Python服务器中是如何绑定端口的呢?你绑定的是正确的网络接口吗?如果你不小心只绑定到了回环设备(localhost
或127.0.0.1
),那么你就会遇到你所描述的情况:从本机到本机的连接会成功,但来自外部主机的连接会失败。
在Python中,通常使用''
或'0.0.0.0'
作为地址部分,这表示你想绑定到所有网络接口;这相当于C语言中的常量INADDR_ANY
:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', port))