抱歉,我的问题有点难以在标题中概括。这是我能想到的最好的答案。
TL;DR 版本:当数据包到达操作系统但未到达目标进程时,如何调试?
解释:我有两个进程,运行在两台设备中,并通过 TCP/IP 进行通信。第一台设备仅通过以太网电缆直接连接到第二台设备。第二台设备连接到网络。两台设备连接并开始相互通信,没有任何问题。然后我尝试物理断开第一台设备的连接,然后在片刻后重新连接电缆。使用 Wireshark,我看到设备接收到了数据包。我看到数据包具有正确的目标端口号。我看到我的进程正在使用正确的端口号监听 [0.0.0.0:port]。但由于某种原因,该进程没有接收到数据包。
不过,奇怪的是,这种情况只发生在第一台设备直接连接到第二台设备时。如果我将两台设备都连接到交换机并重复此测试,则数据包在重新连接电缆后可以顺利到达该过程。
在这两种情况下,我都是静态设置 IP。而问题中的进程使用 ZMQ 堆栈来接收数据包。最让我困惑的是,为什么我的网络拓扑会影响 Linux 操作系统中发生的路由(如果是这样的话)。
我该如何调试这种情况?我应该从哪里开始查找?我可以进行测试以缩小问题范围吗?如果您希望我进一步澄清任何内容,请告诉我。
PS:我已在两个系统上禁用防火墙。
答案1
这需要很多猜测,但到目前为止,我在实际系统中看到过以下几个原因:(我会几乎打赌它是校验和。)
- 防火墙(netfilter)。检查
nft list ruleset
以及iptables-save -c
。 - 校验和错误,无论是 IP 标头还是 TCP/UDP 数据包。(硬件校验和卸载多次导致虚拟机上 UDP 数据包被神秘地忽略。)检查
netstat -s
接收端的统计信息,查找“InCsumErrors:”。 - 严格的rp_过滤器丢弃数据包,因为反向路由将指向不同的接口。运行
sysctl net.ipv4.conf.all.rp_filter=0
以禁用此功能。 - 特定的 {dstaddr:dstport} 与绑定到特定 IP 地址的另一个监听套接字匹配,该套接字的优先级高于通配符 {0.0.0.0:dstport} 套接字。
- {srcaddr:srcport → dstaddr:dstport} 的特定组合匹配连接的套接字,因此不会传送到任何侦听套接字。这甚至适用于 UDP – 尽管线路上没有连接,但您仍然可以拥有与特定远程端点关联的“已连接”UDP 套接字。
- (特定于 IPv6:)在目标系统上,由于 DAD(重复地址检测)失败,分配的 IP 地址处于非活动状态。它将在 中显示为“dadfailed”
ip -6 addr
。
答案2
您也可以尝试滴滴手表查看内核是否因为某种原因丢弃了数据包。