使用Scapy接收分片数据包时出现延迟的问题排查
Scapy抓包时TCP分片包延迟触发回调的问题分析
问题背景
使用Scapy 2.5.0 + Python 3.11.5抓取特定应用数据包,简化复现代码如下:
from scapy.all import * def callback(packet): load: bytes = bytes(packet[TCP].payload) ip_layer = packet.getlayer(IP) ip_id = int(ip_layer.id) print(ip_id, len(load)) sniff(filter='ip and src host xx.xx.xx.xx',prn=callback)
异常现象
源端发送大体积数据时会拆分为多个分片包,第一个包能正常接收并打印,但第二个包需等到第三个包到达时才会被一同打印:
packet_1 received: load: b"a lot of data that needs to b" ip_id: 1 ... ... some time elapsed ... ... packet_2 received: load: b"e split in several packets\x00" ip_id: 2 packet_3 received: load: b"data that has no connection with the two previous packets\x00" ip_id: 3
目标应用可正常接收并拼接分片数据(推测通过\x00结束符处理),但Scapy的回调触发存在明显延迟。
问题分析与解决
- 与第一个包无
\x00无关:Scapy的回调触发逻辑不依赖应用层的结束符,它仅负责捕获底层网络包并传递给回调函数。 - 核心原因:Scapy默认TCP重组机制:Scapy默认启用TCP分片重组(
conf.TCP_segment_reassemble默认值为True),收到第一个分片后会等待后续分片完成重组,才会将完整TCP流数据传递给回调。第二个分片虽携带\x00,但Scapy仍可能等待更多数据,直到第三个包(新TCP流)到来时,才触发之前缓存分片的处理。 - 这是默认行为而非已知问题:TCP重组是Scapy为方便用户获取完整应用层数据设计的默认逻辑,并非bug。
- 解决方法:
- 在代码开头添加
conf.TCP_segment_reassemble = False,关闭TCP重组功能。 - 关闭后,每个TCP分片都会立即触发回调,可实时打印ip_id=1、2、3的数据包,不会出现延迟。
- 在代码开头添加
内容的提问来源于stack exchange,提问作者NicoTine
相关产品推荐
相关产品推荐

