一. 前言

        计算网络数据包的校验和是机器自动完成,不需要手动计算。但是正因为如此,我们往往不会去深究校验和到底是怎么计算的,留下这一块盲区。虽然书上有大致介绍计算的方法,但是,“纸上得来终觉浅,绝知此事要躬行”,本文将详细演示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 - 0xC5063AF9

9. 与抓包的校验和比较是一致的 

六. 总结

        本文主要介绍了IP、ICMP、TCP和UDP的计算方式,并附带介绍了TCP和UDP的伪头部的概念和组成。

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐