TCP/IP 与 UDP 报文协议抓包浅析
2020-04-15
关键字:以太网协议、网络抓包分析
这篇文章结合实际网络通信过程来简单了解一下 以太网协议、TCP报文格式、IP报文格式与UDP报文格式。
在这之前,我们必须要知道:所有的数据,不管什么网络数据、网络包、视频、音频、图片等等,在网线中都是一组“有序的串行数据”。这一长串数据中就包含了各种协议与各种数据。
1、TCP/IP报文格式
我们首先来看一下在实际通信应用中的 TCP/IP 报文格式。
这里笔者通过 tcpdump 工具来抓取,并通过 wireshark 来分析两个设备通过 Socket 发送 "Hello world" 文本的交互过程来分析。
1.1、分析环境
这里先贴上笔者的这个原始网络包,有兴趣的可以下载查看:
链接:https://pan.baidu.com/s/1QHXq88yiqTWISRMd-8-Q2g
提取码:nd5u
在 wireshark 中按IP过滤即可: ip.addr == 192.168.77.104
先介绍一下两个设备的基本信息:
服务端设备:
IP: 192.168.77.104
MAC: A8:BD:3A:37:54:AB
客户端设备:
IP: 192.168.77.103
MAC: A8:BD:3A:37:54:FF
TCP在通信前是要先经“三次握手”建立连接的,如下图所示:
同时,一方在接收到另一方的消息以后,也要作出“回复”以告知发送方“我已接收到”。
如此一来,我们通过Socket进行的"Hello world"文本通信过程,就至少需要 5 个通信过程,即 5 个网络包。当然,如果要算上断开连接时的“四次挥手”的话,又还得再加多 4 个网络包,总计达到 9 个网络包。但在这里,我们不考虑断开连接的情况,因此只有 5 个网络包需要我们考虑。
在 wireshark 中可以过滤出这一过程的 5 个网络包,如下图所示:
1.2、以太网头
第 1 个网络包的内容如下:
这里我们只看中间的“串行数据”部分。两侧的内容是 wireshark 自己添加用以辅助观看使用的。
首先,前 14 个字节是属于以太网头。它的组成结构如下:
目的端MAC地址(6个字节) + 源端MAC地址(6个字节) + IP协议版本号(2个字节)
我们可以很轻松地发现,前6个字节确实是服务端设备的MAC地址 A8:BD:3A:37:54:AB,中间6个字节是客户端的MAC地址 A8:BD:3A:37:54:FF。而最后两个字节 0x0800 就表示该网络包使用的是 IPV4 通信协议。
以太网头的结构就是这么简单。
1.3、IP报文格式
接下来就是 IP 协议了。
在看IP报文格式之前,有必要参照着标准的格式组成结构图来看,如下图所示:
IP报文格式
默认情况下,IP报文的长度就是 20 个字节,如上图所示。就拿我们上面抓到的网络包来看,它的 IP 报文部分如下图所示:
将实际通信网络包结合着上面的IP报文格式组成图示来看,IP报文第 1 个字节里就包含了两部分的内容:协议版本 与 IP报文长度,这两部分各占 4 位。
版本+首部长度:
在我们这个网络包中第1个字节是 0x45。高 4 位的值是十进制下的数字 4 ,表示当前 IP 协议的版本号是 4,就是 IPV4。如果是 IPV6 高4位的值就是数字6。
低 4 位的值是十进制的数字 5。这个值稍微特殊一点,它并不是说这个 IP 报文只有 5 个字节长度,而是要将这个值乘以 4bytes,即 5 * 4bytes = 20bytes。 这个网络包中IP报文数据占20个字节长度。不包含可选字段与填充字段。
区分服务:
在我们这个网络包中,它的值是 0x00。一般不用理会这个值。
总长度:
占 2 个字节,值为 0x003c,即十进制的 60。表示这整个网络包中 IP报文+数据报文 的总长度,即这个网络包中除去前面 14 个字节以太网头后的总长度。可以认为这个值就是描述整个网络包的总长度的了。
标识:
占两个字节。0x500a。可以认为是这个网络包的身份证号。这个数通常是顺序递增的,每发送一个网络包值就加1。但当同一个网络包的数据过长(超过 MTU 大小)时,这个网络包会被“拆分”成短包逐个发送(即分片)。每一个分片中的标识都是相同的,这样才可保证接收端可以将零散的网络包重组为一个完整的网络包。
标志+片偏移:
共占 2 个字节,标志占高3位,片偏移占低13位。
标志:
3位从高到低依次为:
1、保留位
2、禁止分片位
为0表示该网络包有分片。为1表示不分片。(取决于该网络包的数据大小是否超过 MTU)
3、更多分片位
为0表示该分片是最后一片。为1表示这个网络包只是其中一片,后面还有更多的分片。
在本篇文章示例的网络包中,标志段的值为 0x4 --> 010。 表示这个网络包不分片。
片偏移:
13位的值,值范围为 0 ~ 8191。表示这个分片在原数据报文中相对于首位的偏移位数。这个值要再乘以8才是真正的偏移位置。说白了就是在网络包数据太长要拆分发送时用于给接收端散包重组用的参考系。
生存时间:
即 TTL,占 1 个字节。在本例中值为 0x40,即十进制的60。它表示这个IP报文所允许通过的最大路由跳数。IP报文每经过一个路由器,这个值就减1,当值减到0时仍未到达目的端,就丢弃这个网络包。其实这个 TTL 还真的蛮重要的。如果没有它,我们的互联网可能就完全被垃圾信息堵死了。
协议:
占 1 个字节。表示该IP报文携带的数据所使用的协议类型。常见的可选值有如下几种:
1、0x06 -- TCP
2、0x11 -- UDP
3、0x01 -- ICMP
4、0x02 -- IGMP
首部检验和:
2个字节的IP报文校验码。
源地址+目标地址:
各占 4 个字节。c0a84d67 --> 192.168.77.103; c0a84d68 --> 192.168.77.104
到这里已经分析了有 20 个字节了,由于我们这个 IP报文 没有可选字段与填充字段,因此整个IP报文协议到这也就结束了。再接下来的就是数据字段部分了。
1.4、TCP报文格式
这里我们的数据部分使用的是 TCP 协议通信的。因此接下来分析的就是 TCP报文格式。
TCP报文协议的标准格式如下图所示:
在本例分析所使用到的网络包中,TCP部分的内容如下图所示:
源端口+目的端口:
首当其冲的四个字节就是IP地址的源端口和目的端口。0xe785 是客户端设备的IP通信端口。0x4315是服务端设备的IP通信端口。
序列号+确认号:
各占 4 个字节。序列号在本例中为 0xaca2b4fd。序列号与确认号可谓是TCP会话中的时间流。一般情况下这两个号都是顺序递增的。序列号是表示自己这个网络包所对应的序号,简单理解成我是在某一个时刻说出的这句话。而确认号则表示我我期望接收端在回复我这个网络包时所使用的序列号。即,接收方在回复我们的这个网络包时所使用的序列号号应该要是我们这个网络包的确认号。
一般而言,确认号是依据上一个来自接收方的序列号递增的一个数值。在本例中确认号是0,这是因为这个网络包是发起TCP会话时的第一个包,没有前一个包的序列号可参考,因此就只能填上0。
这里贴上本例中5个网络包所使用到的序列号与确认号示意图以便加深理解,同学们仔细体会几个连续的网络包中这两个号的差别:
头部长度:
又称为“数据偏移”。占4位。它表示TCP报文头部数据所占的字节长度。这个值在本例中是 0xa --> 即十进制的10。 它要在这个数的基础上再乘以4bytes,所以TCP头部长度为10 * 4bytes=40bytes。说白了就是TCP报文除数据以外的长度。
12位标志位:
紧跟着上一段“头部长度”后面的12位是一系列的标志位。其中,高6位是保留位,低6位用于设置一些东西。这些位设置的含义笔者不想细纠,直接贴上 wireshark 的辅助与某网友文章中的解释供大家参考。
窗口大小:
占2个字节。与TCP的流量控制有关。可用于指示接收缓冲区的创建大小。
TCP校验和:
占2个字节。
紧急指针:
占2个字节。用于指示在本报文中紧急数据的字节长度。紧急数据会在数据段的首部。
额外选项:
略。
TCP报文除额外选项外的数据固定有 20 个字节,与IP报文头部的长度一致。
以下是一个携带了数据的完整TCP/IP网络包拆解与注释:
000c296b8577000c296b8577 【双方MAC地址】 0800 【IPV4标志】 45 【版本和IP报文的首部长度,这里是5*4=20个字节】 00 【区分服务】 003a 【总长度】 fe10 【标识】 4000 【标志与片偏移】 40 【TTL】 06 【协议,06表示TCP】 dd58 【校验码】 c0a86f01c0a86f02 【双方IP地址】 【从这里开始就是TCP的报文协议格式了】 aa384316 【源端口和目标端口】 56f4b30f 【序列号】 e4c60050 【确认号】 8018 【头部长度与标志位】 00e5 【窗口】 0807 【校验和】 0000 【紧急指针】 0101080a00145223ffff9bf1 【Options,12个字节。】 68656c6c6f0a 【数据】
2、UDP报文格式
通过前面 TCP/IP 的网络包分析,我们已经知道整个网络包的构成按顺序排列无非就三个部分:
1、以太网信息
2、IP报文信息
3、TCP或UDP或ICMP或IGMP报文信息
UDP报文格式相较于TCP而言就简单的多了。
UDP报文协议标准格式如下图所示:
源端口+目的端口:
略。
长度:
占2个字节。UDP报文头部+数据的总长度。
校验值:
略。
数据:
略。
由于UDP通信不像TCP要握手连接挥手告别,它直接简单粗暴地将数据往网络中广播就行了,因此,分析它的格式也不必像前面分析TCP那样繁琐。而且UDP通信网络包前面的以太网信息和IP报文信息都已经在前面介绍过了。因此就直接在以下贴出一个完整的UDP发送数据的网络包并给出相应注释供大家参考学习就是了:
完整的UDP通信网络包:
000c296b8577000c296b8577080045000022cf40400040110c36c0a86f01c0a86f028ebf4316000e8acb68656c6c6f0a
释义:
000c296b8577000c296b8577 【双方的MAC地址】 0800 【IP版本号,此处是IPV4】 【以下开始是IP报文】 45 【版本号+首部长度。IPV4 + 20bytes】 00 【区分服务】 0022 【除14字节以太网头以外的总长度,34个字节】 cf40 【标识,即会话序号】 4000 【标志+片偏移。不分片。】 40 【TTL】 11 【IP报文携带数据的协议,此处是UDP】 0c36 【IP报文头部校验和】 c0a86f01c0a86f02 【双方IP地址】 【以下开始是UDP报文】 8ebf4316 【双方的端口号。源端口+目的端口】 000e 【长度,UDP报文的总长度,UDP头+数据共14个字节】 8acb 【校验码】 68656c6c6f0a 【数据】
参考资料:
https://blog.csdn.net/bobozai86/article/details/87518617
https://blog.csdn.net/a7980718/article/details/82316880
https://blog.csdn.net/a4230787/article/details/80301048