ICMP-Wireshark抓包分析
在Wireshark中配置过滤项ip.addr == 101.42.106.83
,然后开始使用Wireshark抓包,然后ping主机101.42.106.83,可以在Wireshark中看到所抓到的包,如下图。
可以看到,ping 101.42.106.83
所发出的ICMP数据包格式为Ethernet II+IPv4+ICMP,即
下面细说Ethernet II+IPv4+ICMP这三部分。
Ethernet II
从图1可以看到,数据包的Ethernet II部分的14字节为
d0 76 e7 50 ac 99 f0 18 98 30 1e 99 08 00
一般的,Ethernet II的帧格式为
- Preamble:前导码,7字节。由0、1间隔代码组成,用来通知目标站作好接收准备。以太网帧则使用7个字节的0、1间隔代码作为起始符,在线路上帧的这部分的位模式是7个重复的10101010。Wireshark抓不到此前导码,因为在物理层上网卡就已经掉前导码、SFD和FCS。
- SFD (Start Frame Delimiter):帧开始符,1字节。在线路上帧的这部分的位模式是10101011。
- DA (Destination Address):目的 MAC 地址,6字节。目标地址可以是单址,也可以是多点传送或广播地址。
- SA (Source Address):源MAC地址,6字节。
- Type:指定接收数据的高层协议类型,2字节。
- Data:数据载荷,长度应不低于46字节,不超过1500字节,长度过小将会被自动填充Trailer补齐至最短长度。如果数据段长度过大,那么将会把数据段分段后传输
- FCS (Frame Check Sequence):帧校验序列,用于CPC校验。
Wireshark抓不到Preamble、SFD和FCS,我们抓取到的14字节即为DA+SA+Type,其中Ethernet II的Data字段为数据包中的IPv4+ICMP的84字节内容。
从上图可以看到,14字节的Ethernet II部分d0 76 e7 50 ac 99 f0 18 98 30 1e 99 08 00
,目的地址为d0:76:e7:50:ac:99,源地址为f0:18:98:30:1e:99,数据载荷种类为0x0800,为IPv4。所以,一次ICMP的ping请求的数据帧应如下图所示。
下面查看IPv4部分。
IPv4
从图1可以看到,数据包的IPv4部分的20字节为
45 00 00 54 74 8c 00 00 40 01 74 91 c0 a8 01 66 65 2a 6a 53
一般的,IPv4的帧格式如下,其中160位处标红的“选项”部分为可选项,由“首部长度”来确定“选项”部分的长度。
将45 00 00 54 74 8c 00 00 40 01 74 91 c0 a8 01 66 65 2a 6a 53
放进去,如下图:
版本:占4bit,通信双方使用的版本必须一致。对于IPv4,字段的值是4。
首部长度:说明首部有多少32位字(4字节),这个字段的最小值是5(二进制0101),相当于5*4=20字节(RFC 791),最大十进制值是15。
区分服务:最初被定义为服务类型字段,实际上并未使用,但1998年被IETF重定义为区分服务RFC 2474。只有在使用区分服务时,这个字段才起作用,在一般的情况下都不使用这个字段。例如需要实时数据流的技术会应用这个字段,一个例子是VoIP。
显式拥塞通告:允许在不丢弃报文的同时通知对方网络拥塞的发生。ECN是一种可选的功能,仅当两端都支持并希望使用,且底层网络支持时才被使用。
全长:这个16位字段定义了报文的总长,包含首部和数据,单位为字节。这个字段的最小值是20(20字节首部+0字节数据),最大值是2^16-1=65535。
标识符:主要被用来唯一地标识一个报文的所有分片,因为分片不一定按序到达,所以在重组时需要知道分片所属的报文。每产生一个数据报,计数器加1,并赋值给此字段。
标志:与分片有关,用于定义是否被分片,是否还有更多分片。
分片偏移:指明了每个分片相对于原始报文开头的偏移量,以8字节作单位。
存活时间(TTL):这个8位字段避免报文在互联网中永远存在(例如陷入路由环路)。存活时间以秒为单位,但小于一秒的时间均向上取整到一秒。在现实中,这实际上成了一个跳数计数器:报文经过的每个路由器都将此字段减1,当此字段等于0时,报文不再向下一跳传送并被丢弃,最大值是255。常规地,一份ICMP报文被发回报文发送端说明其发送的报文已被丢弃。这也是traceroute的核心原理。如果TTL值为0,“TTL在传输中过期”的消息将会回报给源地址。 每个ICMP消息都是直接封装在一个IP数据包中的,因此,和UDP一样,ICMP是不可靠的。
协议:占8bit,这个字段定义了该报文数据区使用的协议。IANA维护着一份协议列表(最初由RFC 790定义),详细参见IP协议号列表。上图中,0x01对应的就是ICMP的协议号。
首部校验和:这个16位检验和字段只对首部查错,不包括数据部分。在每一跳,路由器都要重新计算出的首部检验和并与此字段进行比对,如果不一致,此报文将会被丢弃。重新计算的必要性是因为每一跳的一些首部字段(如TTL、Flag、Offset等)都有可能发生变化,不检查数据部分是为了减少工作量。数据区的错误留待上层协议处理——用户数据报协议(UDP)和传输控制协议(TCP)都有检验和字段。此处的检验计算方法不使用CRC。
源地址:因为NAT的存在,这个地址并不总是报文的真实发送端,因此发往此地址的报文会被送往NAT设备,并由它被翻译为真实的地址。所以上图中的192.168.1.102是路由器所分配给设备的内网地址,真正的地址会由路由器进行翻译。
目的地址:报文的接收端。
选项:请另查资料。
数据:此字段就是在“协议”字段中指出的协议内容。
**在上图中,由头部“全长”可知,头部+数据共有84字节,而首部有20字节,可以推出数据部分为64字节,便可知数据在何处结束。**所以IP报文并不像上文提到的Ethernet II协议将数据包裹起来。
ICMP
从图1可以看到,数据包的ICMP部分的64字节为
08 00 d6 a5 0d 7c 00 10 62 9e 24 2d 00 0d a1 f2 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37
一般的,ICMP的帧格式如下
- Type:ICMP的类型。标识生成的错误报文。
- Code:进一步划分ICMP的类型。该字段用来查找产生错误的原因。例如,ICMP的目标不可达类型可以把这个位设为1至15等来表示不同的意思。
- Checksum:校验和。用于进行错误检查,该校验和是将该Checksum字段替换为0后,对ICMP头和数据段进行计算得出的。
- Rest of Header:报头的其余部分,四字节字段,内容根据ICMP类型和代码而有所不同。
- Data:填充数据。数据部分紧跟报文头部,根据系统不同,Data长度也不同。如Linux默认情况下还另外填充数据使得“报头+数据”总大小为64字节。而Windows则填充数据使总大小为40字节。
Type和Code的种类很多,代表着不同的意思,请自行查阅资料。
在本文的ICMP报文中,其
- Type:8
- Code:0
- Checksum:0xd6a5
- Rest of Header:0xd7c0010
- Data:可以观察出填充了从00 01 02一直递增至报文总长度到64字节为止。
Type为8,Code为0即为“回显(ping)请求“,也就是我们的ping操作。
请求应答
看一下第二帧,也就是我们上述ping操作的应答帧:
可以看到,IPv4数据包的Source和Destination和ping请求中的进行了互换,且ICMP数据包中的Type和Code都为0,也就是回显应答,表示对方主机已经对我们的请求作出了应答。
拓展 - 死亡之Ping
死亡之Ping,(英文:ping of death, POD),是一种向目标电脑发送错误封包的或恶意的ping指令的攻击方式。通常,一次ping大小为32字节(若考虑IP标头则为84字节)。在当时,大部分电脑无法处理大于IPv4最大封包大小(65,535字节)的ping封包。因此发送这样大小的ping可以令目标电脑崩溃。
在早期TCP/IP的实现中,这攻击方式很容易实现,能影响到众多系统,如Unix、Linux、Mac、Windows、打印机、路由器等。这是一种专门针对一种弱点的非常简单的攻击。在1997-1998年后几乎所有的现代系统都已经修正了这问题。
一般而言,在ICMP规范中,ICMP回送消息在数据包的数据部分只有65,536个字节。送出超过65,536字节ping封包对IP通讯协定而言不是合法的用法,若送出ping封包时分成多个片段,目标电脑必须不断重组封包,期间可能引发缓冲区溢位,而导致系统崩溃。
近年来,出现了另一种更多见的ping的攻击——Ping洪泛攻击(Ping flood)。将过量的ping向目的电脑洪泛以使得正常的访问无法到达目的电脑(一种基本的拒绝服务攻击)。