Scapy官方文档已经给出了IPv4的UDP校验和的计算方式
- 自动计算IPV4 UDP校验和
# 构建数据包
packet = IP(dst="10.11.12.13", src="10.11.12.14")/UDP()/DNS()
# 把数据包转换成byte,这时候会自动计算校验和
packet = IP(raw(packet))
# 查看校验和
checksum_scapy = packet[UDP].chksum
- 手动计算IPv4 UDP校验和
# 构建数据包,将校验和设置为0
packet = IP(dst="10.11.12.13", src="10.11.12.14")/UDP(chksum=0)/DNS()
# 校验和转化为byte
packet_raw = raw(packet)
# 得到udp部分的byte,也就是IP负载(payload),20是IPv4包头的长度
udp_raw = packet_raw[20:]
# 计算校验和,socket.IPPROTO_UDP是协议号,UDP是17,可以直接写17
chksum = in4_chksum(socket.IPPROTO_UDP, packet[IP], udp_raw)
# 将校验和写回数据包
packet.chksum = chksum
# 下面就可以发包了
两种方式得到的校验和是一样的
3. 手动计算IPv6 UDP 校验和
通过实践发现IPv6 UDP 校验和只能手动计算,按照自动计算IPv4校验和的方式校验和还是不变。手动计算IPv6 UDP 校验和与计算 IPv4 UDP 校验和一致。
# 构建数据包,将校验和设置为0,构建数据包完才能计算校验和,dst,src,sport,dport这些都会影响校验和的计算
packet = IPv6(dst="2001:4860:4860::8888")/UDP(chksum=0, dport = 33434)
# 校验和转化为byte
packet_raw = raw(packet)
# 得到udp部分的byte,也就是IPv6负载(payload),40是IPv6包头的长度
udp_raw = packet_raw[40:]
# 计算校验和
chksum = in6_chksum(socket.IPPROTO_UDP, packet[IP], udp_raw)
# 将校验和写回数据包
packet.chksum = chksum