Scapy计算UDP校验和错误:是库问题还是操作失误?
问题
在Ubuntu系统中拦截了一个UDP数据包,删除其校验和后使用Scapy重新计算,发现生成的校验值错误。原UDP校验和为0x81fe,但重新计算后得到0x8f92。请问这是Scapy库的问题,还是操作有误?若为操作问题,请告知正确的计算方法。
拦截数据包的代码
from scapy.all import * s=conf.L2listen(iface="wlo1",filter="tcp or udp") pkt = s.sniff(count=1)[0] pkt
原始数据包内容
<Ether dst=a0:9f:7a:0b:83:4e src=44:e5:17:5d:42:b5 type=IPv4 |<IP version=4 ihl=5 tos=0x0 len=74 id=3847 flags= frag=0 ttl=64 proto=udp chksum=0xe9e5 src=192.168.0.101 dst=192.168.0.1 |<UDP sport=35375 dport=domain len=54 chksum=0x81fe |<DNS id=8493 qr=0 opcode=QUERY aa=0 tc=0 rd=1 ra=0 z=0 ad=0 cd=0 rcode=ok qdcount=1 ancount=0 nscount=0 arcount=1 qd=<DNSQR qname='i.sstatic.net.' qtype=A qclass=IN |> an=None ns=None ar=<DNSRROPT rrname='.' type=OPT rclass=1472 extrcode=0 version=0 z=0 rdlen=None |> |>>>>
重新计算校验和的操作及结果
pkt[UDP].chksum = None pkt.show2()
输出结果:
###[ Ethernet ]### dst = a0:9f:7a:0b:83:4e src = 44:e5:17:5d:42:b5 type = IPv4 ###[ IP ]### version = 4 ihl = 5 tos = 0x0 len = 74 id = 3847 flags = frag = 0 ttl = 64 proto = udp chksum = 0xe9e5 src = 192.168.0.101 dst = 192.168.0.1 \options \ ###[ UDP ]### sport = 35375 dport = domain len = 54 chksum = 0x8f92 ...
原因分析与解决方法
这不是Scapy的问题,是操作时忽略了UDP校验和的计算依赖项导致的:
UDP校验和的计算需要依赖IP伪头部(包含IP层的源IP、目的IP、协议号、UDP长度等字段),Scapy在计算UDP校验和时会基于当前IP层的字段生成伪头部。如果仅重置UDP的校验和而不处理IP层的状态,可能会因为内部字段不一致导致计算结果偏差。
正确的操作步骤如下:
- 捕获数据包后,先将其转换为字节流再重新解析,确保数据包内部状态一致:
pkt = IP(bytes(pkt))
- 同时重置IP层和UDP层的校验和为
None,让Scapy重新计算所有校验值:
pkt[IP].chksum = None pkt[UDP].chksum = None
- 调用
pkt.show2()查看重新计算后的结果,此时UDP校验和应该与原始值一致。
补充说明:如果仍然存在差异,可能是系统开启了校验和硬件卸载——系统发送数据包时由网卡硬件计算校验和,而捕获到的数据包中校验和是硬件填充的,但标准校验和计算逻辑是统一的,按上述步骤操作后应该能得到正确结果。
内容的提问来源于stack exchange,提问作者Aztec N
相关产品推荐
相关产品推荐

