一. 前言
计算网络数据包的校验和是机器自动完成,不需要手动计算。但是正因为如此,我们往往不会去深究校验和到底是怎么计算的,留下这一块盲区。虽然书上有大致介绍计算的方法,但是,“纸上得来终觉浅,绝知此事要躬行”,本文将详细演示IP、ICMP、TCP、UDP的校验和的计算步骤。
二. IP数据包头部校验和
我们知道,IP数据包头部的校验和只是计算头部的数据,所以,计算只需要关注IP头部,抓包示例如下:
如上图可知,IP头部的校验和是0xF89A,计算过程如下:
1. 取IP头部数据
45 04 00 34 f7 6a 40 00 33 06 f8 9a 6a 0b 2b 9e c0 a8 01 69
2. 将校验和部分先置为00 00
45 04 00 34 f7 6a 40 00 33 06 00 00 6a 0b 2b 9e c0 a8 01 69
3. 将数据合并为16位一组并相加
4504+0034+f76a+4000+3306+0000+6a0b+2b9e+c0a8+0169=30762
4. 将结果的高16位与低16位相加
762 + 3 = 765
5. 将0xFFFF减上一步结果得到校验和
0xFFFF - 0x765 = 0xF89A
6. 与抓包的校验和比较是一致的
三. ICMP数据包校验和
ICMP的校验和是包括:ICMP头部和ICMP数据的,也就是ICMP的全部数据的校验和,抓包示例如下:
如上图可知,ICMP的校验和是0x2B7D,计算过程如下:
1. 取ICMP全部数据
08 00 2b 7d 08 83 00 00 f3 f2 d0 0c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
2. 将校验和部分置为00 00
08 00 00 00 08 83 00 00 f3 f2 d0 0c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
3. 将数据合并为16位一组并相加,后面的00忽略
0800+0000+0883+0000+f3f2+d00c=1d481
4. 将结果的高16位与低16位相加
d481 + 1 = d482
5. 将0xFFFF减上一步结果得到校验和
0xFFFF - 0xD482 = 0x2B7D
6. 与抓包的校验和比较是一致的
四. TCP数据包校验和
TCP的数据包的校验和计算的数据来源包括三部分:TCP伪首部和TCP首部和TCP数据。TCP计算校验和引入了伪首部,包括后面介绍的UDP。如下图所示,TCP伪首部包括:源地址(32 bit),目标地址(32 bit),Zeros(8 bit),Protocol(8 bit),TCP Length(16 bit)。
TCP的伪首部的提取需要查看IP头部数据,例如,源地址,目标地址,TCP协议号(6),TCP数据长度,抓包示例如下:
由上图可知,源地址是106.11.43.158(6a 0b 2b 9e), 目标地址192.168.1.105(c0 a8 01 69),TCP的协议号是6,TCP数据长度是IP数据总长度减去IP头部52-20=32(0x20)。接下来是TCP头部和数据部分抓包示例:
由上图可知,TCP的校验和是0x755E,计算过程如下:
1. 取伪首部的数据
Source Address Destination Address Zeros Protocol TCP Length
6a 0b 2b 9e c0 a8 01 69 00 06 00 20
2. 将伪首部数据合并为16位一组并相加
6a0b+2b9e+c0a8+0169+0006+0020=157E0
3. 取TCP数据
01 bb de c0 d3 86 24 c6 0e 5f 8d 90 80 10 00 0e 75 5e 00 00 01 01 05 0a 0e 5f 8d 8f 0e 5f 8d 90
4. 将校验和部分置为00 00
01 bb de c0 d3 86 24 c6 0e 5f 8d 90 80 10 00 0e 00 00 00 00 01 01 05 0a 0e 5f 8d 8f 0e 5f 8d 90
5. 将TCP数据合并为16位一组并相加
01bb+dec0+d386+24c6+0e5f+8d90+8010+000e
+0000+0000+0101+050a+0e5f+8d8f+0e5f+8d90=432BC
6. 将伪首部和TCP数据的相加结果相加
157E0 + 432BC = 58A9C
7. 将上一步结果的高16位和低16位相加
8A9C + 5 = 8AA1
8. 将0xFFFF减8AA1得到校验和
0xFFFF - 0x8AA1 = 755E
9. 与抓包的校验和比较是一致的
五. UDP数据包校验和
UDP数据校验和和TCP数据的校验和计算的方法是一致的,包括:UDP伪首部,UDP头部和UDP数据。
UDP的伪首部的提取需要查看IP头部数据,例如,源地址,目标地址,UDP协议号(17),UDP数据长度,抓包示例如下:
由上图可知,源地址是192.168.1.40(c0 a8 01 28), 目标地址111.230.189.174(6f e6 bd ae),UDP的协议号是17 (0x11),UDP数据长度是IP数据总长度减去IP头部76-20=56(0x38)。接下来是UDP头部和数据部分抓包示例:
由上图可知,UDP的校验和是0x3AF9,计算过程如下:
1. 取伪首部的数据
Source Address Destination Address Zeros Protocol TCP Length
c0 a8 01 28 6f e6 bd ae 00 11 00 38
2. 将伪首部数据合并为16位一组并相加
c0a8+0128+6fe6+bdae+0011+0038=1EFAD
3. 取UDP头部和数据部分
89 34 00 7b 00 38 3a f9 23 00 08 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 76 0c e9 2c 37 38 89 de
4. 将校验和部分置为00 00
89 34 00 7b 00 38 00 00 23 00 08 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 76 0c e9 2c 37 38 89 de
5. 将UDP数据合并为16位一组并相加
8934+007b+0038+0000+2300+0820+0000+0000+0000+0000+0000+0000+0000
+0000+0000+0000+0000+0000+0000+0000+0000+0000+0000+0000+760c+e92c
+3738+89de = 2D555
6. 将伪首部和UDP数据的相加结果相加
1EFAD + 2D555 = 4C502
7. 将上一步结果的高16位和低16位相加
C502 + 4 = C506
8. 将0xFFFF减C506得到校验和
0xFFFF - 0xC506 = 3AF9
9. 与抓包的校验和比较是一致的
六. 总结
本文主要介绍了IP、ICMP、TCP和UDP的计算方式,并附带介绍了TCP和UDP的伪头部的概念和组成。