Python Scapy中IP与UDP的chksum值计算方法问询
IP与UDP校验和的含义及Scapy计算原理
一、IP头校验和(chksum=0x95d3)的含义
IP头部的校验和是验证IP头部数据完整性的16位校验值,核心逻辑是「16位补码和的补码」:
- 计算时,将IP头部按16位(2字节)为一组拆分,对所有组的数值求和,再对求和结果取反(补码运算),最终得到的就是校验和。
- 接收方收到IP包后,会重新对IP头部执行相同的求和+取反操作,若计算结果与头部携带的0x95d3相加后为全1(即补码和为0),则说明IP头部在传输过程中未被篡改或损坏;反之则判定头部出错,直接丢弃该包。
- 0x95d3就是当前IP头部经过上述计算后得到的16进制校验结果,用于标识该头部的完整性状态。
二、UDP头校验和(chksum=0x1a77)的含义
UDP校验和的校验范围比IP更广泛,它不仅校验UDP头部和载荷,还会包含一个伪头部(由源IP、目的IP、协议类型、UDP总长度组成),目的是防止UDP数据被错误交付到其他主机或协议。其计算逻辑与IP校验和一致:
- 把伪头部、UDP头部、UDP载荷按16位分组求和,再取反得到校验和。
- 接收方验证时,若重新计算的结果与0x1a77不匹配,会直接丢弃该UDP报文;匹配则认为数据完整且交付正确。
- 0x1a77是针对当前UDP报文(含伪头部)计算出的16进制校验值。
三、Scapy中的校验和计算方式
Scapy默认会自动处理校验和的计算与填充,无需手动设置,以下是具体逻辑和手动计算方法:
IP校验和
- 自动计算:构造IP包时,若不手动指定
chksum字段,Scapy在发送包或调用bytes()/build()方法时,会自动计算并填充校验和。 - 手动计算:可调用
scapy.utils.checksum()函数,传入IP头部的字节流即可得到结果。示例代码:
from scapy.layers.inet import IP from scapy.utils import checksum # 构造IP头部 ip_pkt = IP(src="192.168.1.1", dst="192.168.1.2", ttl=64) # 自动生成的校验和 print(f"自动计算IP校验和: 0x{ip_pkt.chksum:04x}") # 手动计算:提取IP头部字节流后计算 ip_bytes = bytes(ip_pkt) manual_chksum = checksum(ip_bytes) print(f"手动计算IP校验和: 0x{manual_chksum:04x}")
UDP校验和
- 自动计算:当UDP包绑定到IP包时(即
IP()/UDP()),Scapy会自动构造伪头部并计算校验和,无需手动设置chksum。 - 手动计算:需要手动构造伪头部,将其与UDP报文(需先把UDP的
chksum设为0)拼接后,再调用checksum()函数。示例代码:
from scapy.layers.inet import IP, UDP from scapy.utils import checksum # 构造完整的IP+UDP包 ip_pkt = IP(src="192.168.1.1", dst="192.168.1.2") udp_pkt = UDP(sport=1234, dport=5678, payload=b"test data") full_pkt = ip_pkt / udp_pkt # 自动生成的UDP校验和 print(f"自动计算UDP校验和: 0x{full_pkt[UDP].chksum:04x}") # 手动计算:构造伪头部并拼接UDP报文 # 伪头部由IP头的前12字节(源IP、目的IP)+ 协议号(0x11) + UDP长度组成 pseudo_header = bytes(ip_pkt)[:12] + b'\x00\x11' + bytes(udp_pkt)[2:4] # 计算前需将UDP的chksum置0 udp_pkt.chksum = 0 udp_with_pseudo = pseudo_header + bytes(udp_pkt) manual_udp_chksum = checksum(udp_with_pseudo) print(f"手动计算UDP校验和: 0x{manual_udp_chksum:04x}")
注意:如果手动指定了
chksum字段的值,Scapy会保留该值,不会自动覆盖。
内容的提问来源于stack exchange,提问作者user20486964
相关产品推荐
相关产品推荐

