tcpdump 结果


IP数据报格式

抓包举例

        0x0000:  4500 003c 34c1 4000 4006 4351 ac13 0009  E..<4.@[email protected]....
        0x0010:  dcb5 39d8 b80e 0050 fdfc 6acc 0000 0000  ..9....P..j.....
        0x0020:  a002 7210 c2d8 0000 0204 05b4 0402 080a  ..r.............
        0x0030:  bd3f 5e0d 0000 0000 0103 0307            .?^.........
0x0000:  4500 003c 34c1 4000 4006 4351 ac13 0009  E..<4.@[email protected]....

最外层是IP数据包,最开始的一个字节(8bit)中,前4bit用来标识IP协议的版本,最常见的就是4和6,分别代表IPv4和IPv6;后4bit所能表示的最大数值是15,而IP数据报标准规定,“首部长度”的单位是4字节(32bit),此处的数字是5,因此可以计算得出这个IP包的首部长度是固定的20字节。如果出现首部长度不是4字节的整数倍时,需要在最后一个字段加以填充,务必保证首部长度是4字节的整数倍。这样,我们的数据部分就总是从4字节的整数倍处开始。如下蓝色部分都是IP数据包的首部部分:

0x0000:  4500 003c 34c1 4000 4006 4351 ac13 0009  E..<4.@[email protected]....
0x0010:  dcb5 39d8 b80e 0050 fdfc 6acc 0000 0000  ..9....P..j.....

如下所示,在IP版本和首部长度之后,接下来的一个字节(8bit)是“00”,此域常被称为TOS(Type Of Service),其中前3bit代表本数据报的优先级;D表示要求更低的时延;T表示要求更高的吞吐;R表示要求更高的可靠性;C表示要求选择代价更小的路由;第8个bit目前没有被使用。
上面这种分类方式,其实已很少应用,因为有时候这些要求的组合会使得调度策略产生矛盾,比如一条路由是高吞吐但不可靠,另一条是低吞吐但可靠,那么当用户同时要求T和R时,就会产生矛盾。因此,IETF组织将TOS重新进行了定义,称为DS(Differentiated Service),由于此标准只在特定环境特定设备中才有应用。
P:IP包的优先级;
D:0--一般延迟,1--低迟延
T:0--一般传输量,1--高传输量
R:0--一般可靠度,1--高可靠度
UU:保留

0x0000:  4500 003c 34c1 4000 4006 4351 ac13 0009  E..<4.@[email protected]....

如下所示,后面的2字节表示整个IP包的总长度(首部长度+数据长度), (16bit)可以表示的最大值为65535,所以IP数据报的最大长度可以到达65535字节。但由于以太网的MTU(Maximum Transmission Unit)最大为1500字节,所以如果IP协议是运行在以太网的话,就会遇到需要分片的情况。这里“003c”,因此可以知道这个请求包的总长度是60字节。

0x0000:  4500 003c 34c1 4000 4006 4351 ac13 0009  E..<4.@[email protected]....

再向下的2字节(16bit)是“标识域”,如果IP包的大小超过了数据链路层的MTU限制,就需要对IP包进行分拆,此时就要用这个域来表示哪些包在分拆前是同一组的。此处的标识域值为0x34c1。

0x0000:  4500 003c 34c1 4000 4006 4351 ac13 0009  E..<4.@[email protected]....

接下3bit的标志位,最高位为保留位,中间一位为DF(don’t fragment),最低位为MF(more fragments)
DF等于1的话,表示此IP数据报“不能分片”。只有在DF等于0时,才允许对其进行分片。
MF等于1的话,表示此IP数据报后面还有分片的数据报,而MF等于0时,则表示当前的IP数据报是这一组中最后一个数据报。

0x0000:  4500 003c 34c1 4000 4006 4351 ac13 0009  E..<4.@[email protected]....

接下13bit 表示当IP数据报超过MTU而被分拆成多片后,每一片在原IP数据报中的位置。此偏移量的参照起点是原数据报的数据部分的起点。
要注意的是,片偏移的单位是“8字节”,也就是说,每个分片的长度必须是8字节的整数倍。
D:0--可以分段,1--不可分段
M:0--最后分段,1--非最后分段
这里为4000,转成二进制的前三位为010,为不可以分段,是最后分段

0x0000:  4500 003c 34c1 4000 4006 4351 ac13 0009  E..<4.@[email protected]....

紧接着是8bit的TTL(Time To Live,即生存周期),此包的值为0×40,换算成十进制是64,这表明这个网络包,如果经过了超过64个中间路由节点,则认为目的地不可达,中间路由器会将此包抛弃掉。
默认情况下Linux的TTL为255,windowsXP为128,windows98为32,UNIX为255。更全的TTL统计,可以参考[这里]

0x0000:  4500 003c 34c1 4000 4006 4351 ac13 0009  E..<4.@[email protected]....

继续的8bit为协议域,用于指代上一层协议类型。
1--ICMP
2--IGMP
3--GGP
4--IP
6--TCP
8--EGP
17--UDP
06表示TCP协议

0x0000:  4500 003c 34c1 4000 4006 4351 ac13 0009  E..<4.@[email protected]....

接下来的2个字节表示IP首部校验和,此处计算出来的结果是4351

0x0000:  4500 003c 34c1 4000 4006 4351 ac13 0009  E..<4.@[email protected]....

接下来4字节为源ip地址,和后面4字节为目标ip地址

0x0000:  4500 003c 34c1 4000 4006 4351 ac13 0009  E..<4.@[email protected]....
0x0010:  dcb5 39d8 b80e 0050 fdfc 6acc 0000 0000  ..9....P..j.....

至此,网络层IP协议的首部20字节已经分析完了。

        0x0000:  4500 003c 34c1 4000 4006 4351 ac13 0009  E..<4.@[email protected]....
        0x0010:  dcb5 39d8 b80e 0050 fdfc 6acc 0000 0000  ..9....P..j.....
        0x0020:  a002 7210 c2d8 0000 0204 05b4 0402 080a  ..r.............
        0x0030:  bd3f 5e0d 0000 0000 0103 0307            .?^.........

接下来部分分别为请求方端口和目标端口 b80e 为 47118, 0050为 80端口, 所以tcp udp 理论的端口范围为 0~ffff 即 0~65535

        0x0000:  4500 003c 34c1 4000 4006 4351 ac13 0009  E..<4.@[email protected]....
        0x0010:  dcb5 39d8 b80e 0050 fdfc 6acc 0000 0000  ..9....P..j.....
        0x0020:  a002 7210 c2d8 0000 0204 05b4 0402 080a  ..r.............
        0x0030:  bd3f 5e0d 0000 0000 0103 0307            .?^.........

接下来 如果是UDP包则为 包的总长度(报头+数据部分),
TCP此处为包序号, 蓝色部分为确认序号,0,因为这是tcp三次握手的第一次,所以ack number为0
a002 TCP包头长度,标志位。(1010 000000 000010)前4bitTCP长度10个32BIT,中间6bit保留,后6bit为标志位(URG, ACK,PSH, RST, SYN, FIN),可以看出设置了倒数第二位,SYN位。
7210 - 窗口大小,十进制为29200
c2d8 - 校验和,覆盖了整个的TCP报文段: TCP首部和TCP数据
0000 - 紧急指针, 只有当URG标志置1时紧急指针才有效
0204 05b4 0101 0402 - 选项字段,8个字节


以下相关字段解释
【源端口】- 16bit

来源处的端口号;

【目的端口】- 16bit

目的处的端口号;

【序号】- 32bit

每一个TCP报文段都会有一个序号,序号字段的值其实是本报文段所发送的数据的第一个字节的序号。这是因为TCP是面向连接的可靠服务,其每一个字节都会对应一个序号,通过序号来确保服务的可靠性和有序性。

【确认号】- 32bit

确认号,是期望收到对方的下一个报文段的数据的第一个字节的序号。(这句话有些拗口,但是在后面我们讲解三次握手和四次挥手时,大家会更深刻的理解这句话的含义)

【数据偏移】- 4bit

其实它本质上就是“首部长度”,因为“数据偏移”是指TCP报文段的数据部分的起始处距离TCP报文段的起始处的距离。(仍然很拗口,但相信你能明白)。

数据偏移总共占4bit,因此最大能表示的数值为15。而数据偏移的单位是“4字节”,此处的设计和IP数据报的设计是完全相同的,所以说TCP报文段首部的长度最长为15×4=60字节,且首部长度必须为4字节的整数倍。

【保留字段】- 6bit

这6bit在标准中是保留字段,我猜测,有两个目的,第一个是预留除URG/ACK/PSH/RST/SYN/FIN/之外的冗余功能位;第二个是为了对其字节位。

【紧急字段URG】- 1bit

此字段告诉系统此报文段中有紧急数据,应尽快传送。当URG=1时,

【确认字段ACK】- 1bit

当ACK=1时,表示确认,且确认号有效;当ACK=0时,确认号字段无效。

【推送字段PSH】- 1bit

当PSH=1时,则报文段会被尽快地交付给目的方,不会对这样的报文段使用缓存策略。

【复位字段RST】- 1bit

当RST为1时,表明TCP连接中出现了严重的差错,必须释放连接,然后再重新建立连接。

【同步字段SYN】- 1bit

当SYN=1时,表示发起一个连接请求。

【终止字段FIN】- 1bit

用来释放连接。当FIN=1时,表明此报文段的发送端的数据已发送完成,并要求释放连接。

【窗口字段】- 16bit

此字段用来控制对方发送的数据量,单位为字节。

一般TCP连接的其中一端会根据自身的缓存空间大小来确定自己的接收窗口大小,然后告知另一端以确定另一端的发送窗口大小。

【校验和字段】- 16bit

这个校验和是针对首部和数据两部分的。

【紧急指针字段】- 16bit

紧急指针指出在本报文段中的紧急数据的最后一个字节的序号。

UDP数据报长度一般设置为多少比较合适

TCP/IP通常被认为是一个四层协议系统,包括链路层,网络层,运输层,应用层.
UDP属于运输层,下面我们由下至上一步一步来看:
以太网(Ethernet)数据帧的长度必须在46-1500字节之间,这是由以太网的物理特性决定的.
这个1500字节被称为链路层的MTU(最大传输单元).
但这并不是指链路层的长度被限制在1500字节,其实这这个MTU指的是链路层的数据区.
并不包括链路层的首部和尾部的18个字节.
所以,事实上,这个1500字节就是网络层IP数据报的长度限制.
因为IP数据报的首部为20字节,所以IP数据报的数据区长度最大为1480字节.
而这个1480字节就是用来放TCP传来的TCP报文段或UDP传来的UDP数据报的.
又因为UDP数据报的首部8字节,所以UDP数据报的数据区最大长度为1472字节.
这个1472字节就是我们可以使用的字节数。

当我们发送的UDP数据大于1472的时候会怎样呢?
这也就是说IP数据报大于1500字节,大于MTU.这个时候发送方IP层就需要分片(fragmentation).
把数据报分成若干片,使每一片都小于MTU.而接收方IP层则需要进行数据报的重组.
这样就会多做许多事情,而更严重的是,由于UDP的特性,当某一片数据传送中丢失时,接收方便
无法重组数据报.将导致丢弃整个UDP数据报。

因此,在普通的局域网环境下,我建议将UDP的数据控制在1472字节以下为好.

进行Internet编程时则不同,因为Internet上的路由器可能会将MTU设为不同的值.
如果我们假定MTU为1500来发送数据的,而途经的某个网络的MTU值小于1500字节,那么系统将会使用一系列的机
制来调整MTU值,使数据报能够顺利到达目的地,这样就会做许多不必要的操作.

鉴于Internet上的标准MTU值为576字节,所以我建议在进行Internet的UDP编程时.
最好将UDP的数据长度控件在548字节(576-8-20)以内.

Reference
[1] http://roclinux.cn/?p=2520
[2] http://roclinux.cn/?p=2523
[3] http://roclinux.cn/?p=2797