我一直在使用发送大量 TCP/IP 流量的设备。
我正在尝试使用 Python 编程语言在我的 Linux 机器(Ubuntu 22.04.2 LTS)中捕获这些数据包。
但是,大多数情况下,无法从操作系统正确接收发送的数据包。
我可以看到其中一些数据包已由操作系统正确重新组装,但大多数数据包并非如此。
我可以清楚地看到 Wireshark 的内容。
以下是意外行为:
我主要看到的是碎片化的 IP 协议数据包,之后,我看到超出了生存时间(超出了碎片重组时间)。
以下是预期的行为:
有没有办法纠正这种行为(放宽导致无法重组数据包的条件)以捕获所有数据包?
我在 Windows 10 中从未遇到过此问题。
在同一台客户端计算机上,当注销 Ubuntu 并登录 Win10 时,我看不到丢弃的数据包,并且所有传输的块都重新组合并发送到相应的端口。看起来,Linux 上有一些系统参数会影响丢包。
我在下面附上了 Wireshark 捕获文件:
https://drive.google.com/file/d/1GFtlHnKF619HE02JfuSUQpIGqSxRt6Yf/view?usp=sharing
这是输出sudo sysctl -a | grep ipfrag
net.ipv4.ipfrag_high_thresh = 4194304
net.ipv4.ipfrag_low_thresh = 3145728
net.ipv4.ipfrag_max_dist = 64
net.ipv4.ipfrag_secret_interval = 0
net.ipv4.ipfrag_time = 30
我也尝试执行以下操作(上述设置的 10 倍):
sudo sysctl -w net.ipv4.ipfrag_time=300
sudo sysctl -w net.ipv4.ipfrag_high_thresh=41943040
sudo sysctl -w net.ipv4.ipfrag_low_thresh=31457280
sudo sysctl -w net.ipv4.ipfrag_max_dist=640
还是没有运气。
谢谢。
答案1
一些碎片由于某种原因丢失了。
这不是重新组装问题,无论如何调整超时都无法解决它。
您在 Wireshark(或任何基于 pcap 的工具)中看到的是在将其移交给操作系统网络堆栈之前传入和传出 NIC 的原始通信。因此,只要捕获中缺少某些内容,就意味着 NIC 从未收到过它(或者它被硬件直接丢弃)。
您的第一个屏幕截图显示转储至少缺少一个片段(偏移量为 17760 的片段)。因此,操作系统会等待一段时间,等待该片段可能到达(以防它在传输中重新排序或在较低层上重新传输),如果它从未到达,则会出现 ICMP 重组超时错误。
除非有充分的理由预期数据包会被底层网络延迟很长时间,否则摆弄超时是没有意义的。碎片只是丢失了,永远不会出现,等待更长的时间也无济于事。
这正是基于不可靠传输的 UDP 的现实。如果介质有明显损耗并且存在大量碎片,则许多数据包将无法重新组装。
您需要首先调查导致数据包丢失的原因。检查 NIC 的错误计数器可能是一个好的第一步。如果在具有相同硬件的不同操作系统上没有发生这种情况,则可能是网卡配置不同(例如禁用卸载,导致 CPU 无法处理流量,或者网卡以不同的数据速率运行)例如一个操作系统上的自动协商快速以太网与另一个操作系统上的强制千兆位)。