- 控制报文协议(Internet Control Message Protocol,ICMP)是 TCP/IP 协议族的一个子协议。ICMP 协议用于在 IP 主机和路由器之间传递控制消息,描述网络是否通畅、主机是否可达、路由器是否可用等网络状态。
- 由于IP协议简单,数据传输天然存在不可靠,无连接等特点,为了解决数据传输出现的问题,人们引入了ICMP协议。虽然ICMP协议的数据包并不传输用户数据,但是对于用户数据的传递有着重要的作用
通常使⽤ ping ,来测试远程主机的连通性和延时
# -c3表示发送三次ICMP包后停⽌
$ ping -c3 114.114.114.114
PING 114.114.114.114 (114.114.114.114) 56(84) bytes of data.
64 bytes from 114.114.114.114: icmp_seq=1 ttl=54 time=244 ms
64 bytes from 114.114.114.114: icmp_seq=2 ttl=47 time=244 ms
64 bytes from 114.114.114.114: icmp_seq=3 ttl=67 time=244 ms
--- 114.114.114.114 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2001ms
rtt min/avg/max/mdev = 244.023/244.070/244.105/0.034 ms
ping 的输出,可以分为两部分。
⽐如上⾯的示例显示,发送了 3 个⽹络包,并且接收到 3 个响应,没有丢包发⽣,这说明测试主机到114.114.114.114 是连通的;平均往返延时(RTT)是244ms,也就是从发送 ICMP 开始,到接收到114.114.114.114 回复的确认,总共经历244ms。
ping是基于ICMP
协议工作的,所以要明白ping的工作,就要先学习ICMP协议
ICMP 全称是Internet Control Message Protocol,也就是互联网控制报文协议
里面有个关键词:控制,如何控制呢?
ICMP经常被认为是IP层的一个组成部分。它传递差错报文以及其他需要注意的信息。ICMP报文通常被IP层或者更高层协议(TCP/UDP)使用,一些ICMP报文把差错报文返回给用户进程。
ICMP
主要的功能包括:确认 IP 包是否成功送达目标地址、报告发送过程中 IP 包被废弃的原因和改善网络设置等。
在IP
通信中如果某个IP
包因为某种原因未能达到目标地址,那么这个具体的原因将由ICMP负责通知
A
向主机B
发送了数据包,由于某种原因,途中的路由器2
未能发现主机B
的存在,这时,路由器2
就会向主机B
发送一个ICMP
目标不可达的数据包,说明发往主机B
的包未能成功。IP
进行发送2
返回的ICMP包会按照往常的路由控制先经过路由器1
再转发给主机A
。收到该ICMP包的主机A
则分解ICMP的首部和数据域以后得知具体发生问题的原因。数据包在发送到目标主机的过程中,通常会经过一个或多个路由器。而数据包在通过这些路由进行传输时,可能会遇到各种问题,导致数据包无法发送到目标主机上。为了了解数据包在传输的过程中在哪个环节出现了问题,就需要用到 ICMP 协议。它可以跟踪消息,把问题反馈给源主机。
ICMP报文是封装在IP包里面,它工作在网络层,是IP协议的助手。
ICMP包头的类型字段和代码字段取值如下:
从上面可以看出,ICMP包头的类型,大致可以分为两类:
为什么要对ICPM类型进行区分?
下面各种情况都不会导致产生ICMP差错报文
这些规则是为了防止过去允许ICMP差错报文对广播分组响应所带来的广播风暴。
回送消息 — 类型
0
和8
回送消息用于进行通信的主机或者路由器之间,判断所发送的数据包是否已经成功到达对端的一种消息,ping
命令就是利用这个消息实现的。
可以向对端主机发送回送请求的消息( ICMP Echo Request Message
,类型 8
),也可以接收对端主机发回来的回送应答消息( ICMP Echo Reply Message
,类型 0
)。
相比原生的 ICMP,这里多了两个字段:
ICMP
包,比如用进程PID
作为标识符;0
开始,每发送一次新的回送请求就会加1
, 可以用来确认网络包是否有丢失。ICMP时间戳请求与应答------类型13或者14
ICMP时间戳请求系统向另一个系统查询当前时间。返回的建议值是自午夜开始计算的毫秒数,协调的统一时间UTC。这种ICMP报文的好处是它提供了毫秒级的分辨率,而利用其他方法从别的主机获取的时间(如某些Unix系统提供的rdate命令)只能提供秒级的分辨率。由于返回的时间是从午夜开始计算的,因此调用者必须通过其他方法获知当时的日期,这是它的一个缺陷。
请求端填写发起时间戳,然后发送报文。应答系统收到请求报文时填写接收时间戳,在发送应答时填写发送时间戳。但是,实际上,大多数的实现把后面两个字段都设成相同的值(提供三个字段的原因是可以让发送方分别计算发送请求的时间和发送应答的时间)。
ICMP地址掩码请求与应答-----类型17或者18
ICMP地址掩码请求用于无盘系统在引导过程中获取自己的子网掩码。系统广播它的ICMP请求报文。无盘系统获取子网掩码的另一个方法是BOOTP协议。
ICMP报文中的标识符和序列号字段由发送端任意选择设定,这些值将在应答中被返回。这样,发送端就可以把应答与请求进行匹配。
接下来,说明几个常用的 ICMP 差错报文的例子:
3
IP 路由器无法将 IP 数据包发送给目标地址时,会给发送端主机返回一个目标不可达的 ICMP 消息,并在这个消息中显示不可达的具体原因,原因记录在 ICMP 包头的代码字段。
由此,根据 ICMP 不可达的具体消息,发送端主机也就可以了解此次发送不可达的具体原因。
网络不可达代码为
0
Network Unreachable
)的原因告知主机。主机不可达代码为
1
Host Unreachable
)的原因告知主机。协议不可达代码为
2
端口不可达代码为
3
需要进行分片但设置了不分片位代码为
4
4
的报文,告知发送端主机。4
5
如果路由器发现发送端主机使用了「不是最优」的路径发送数据,那么它会返回一个 ICMP 重定向消息给这个主机。
在这个消息中包含了 最合适的路由信息和源数据。这主要发生在路由器持有更好的路由信息的情况下。路由器会通过这样的 ICMP 消息告知发送端,让它下次发给另外一个路由器。
好比,小林本可以过条马路就能到的地方,但小林不知道,所以绕了一圈才到,后面小林知道后,下次小林就不会那么傻再绕一圈了。
11
TTL
( Time To Live
,生存周期),它的 值随着每经过一次路由器就会减1,直到减到 0 时该 IP 包会被丢弃。
此外,有时可以用 TTL 控制包的到达范围,例如设置一个较小的 TTL 值。
接下来,我们重点来看 ping
的发送和接收过程。
同个子网下的主机A
和 主机 B
,主机 A
执行 ping
主机 B
后,我们来看看其间发送了什么?
ping命令执行的时候,源主机首先会构建一个 ICMP回送请求消息数据包
ICMP数据包中包含多个字段,最重要的是两个:
8
每发出一个请求数据包,序号会自动加1
。为了能够计算往返时间RTT
,它会在报文的数据部分插入发送时间。
然后,由ICMP
协议将这个数据包连同地址 192.168.1.2
一起交给IP 层
。IP 层将以 192.168.1.2 作为目的地址,本机 IP 地址作为源地址,协议字段设置为1
表示是 ICMP
协议,再加上一些其他控制信息,构建一个IP
数据包。
接下来,需要加入MAC
头。如果在本地ARP
映射表中查找出 IP 地址 192.168.1.2 所对应的 MAC地址,则可以直接使用;如果没有,则需要发送 ARP 协议查询 MAC 地址,获得 MAC 地址后,由数据链路层
构建一个数据帧
,目的地址是 IP 层传过来的 MAC 地址,源地址则是本机的 MAC 地址;还要
附加上一些控制信息,依据以太网的介质访问规则,将它们传送出去。
主机 B
收到这个数据帧后,先检查它的目的 MAC
地址,并和本机的 MAC
地址对比,如符合,则接收,否则就丢弃。
接收后检查该数据帧,将IP
数据包从帧中提取出来,交给本机的IP
层。
同样,IP
层检查后,将有用的信息提取后交给ICMP
协议。
主机B
会构建一个 ICMP 回送响应消息数据包,回送响应数据包的类型字段为 0 ,序号为接收到的请求数据包中的序号,然后再发送出去给主机 A。
在规定的时候间内,源主机如果没有接到 ICMP 的应答包,则说明目标主机不可达;如果接收到了ICMP 回送响应消息,则说明目标主机可达。
此时,源主机会检查,用当前时刻减去该数据包最初从源主机上发出的时刻,就是 ICMP 数据包的时间延迟。
针对上面发送的事情,总结成了如下图:
当然这只是最简单的,同一个局域网里面的情况。如果跨网段的话,还会涉及网关的转发、路由器的转发等等。
但是对于 ICMP 的头来讲,是没什么影响的。会影响的是根据目标 IP 地址,选择路由的下一跳,还有每经过一个路由器到达一个新的局域网,需要换 MAC 头里面的 MAC 地址。
说了这么多,可以看出 ping 这个程序是使用了ICMP 里面的 ECHO REQUEST(类型为 8)和ECHO REPLY(类型为 0)。
http://c.biancheng.net/view/6399.html
tcpdump和wireshark
我们可以在linux下使用tcpdump抓包,在windows上使用winshark分析
1、打开终端,因为ping是icmp协议,因此执行下面命令
tcpdump -i ens33 icmp and host 192.168.0.11 -nn
# -i ens33表示抓取ens33网口的数据包
# icmp表示抓取icmp协议的数据包
# host表示主机过滤,抓取对应IP的数据包
# -nn 表示不解析IP地址和端口号的名称
2、打开另一个终端,执行ping命令:
ping -I ens33 -c 3 192.168.0.11
# -I ens33表示指定从ens33网口出去
# -c 3 表示发出3个icmp数据包
这个时候我们可以在第一个终端中看到下面的界面:
可以看到,tcpdump抓取到icmp数据包之后,输出的格式如下:
从数据包中,我们可以很清楚的看到ICMP echo
的交互过程:
ICMP echo request
请求报文,接收方收到之后回了一个ICMP echo reply
响应报文。ICMP
请求对应两个报文,因为我们之前发出了3个ICMP
报文,因此整个过程中有六个报文。我们也可以将tcpdump
抓取到的数据包保存成pcap
后缀的文件,然后用Wireshark
来分析:
tcpdump -i ens33 icmp and host 192.168.0.11 -nn -w ping.pcap
# -i ens33表示抓取ens33网口的数据包
# icmp表示抓取icmp协议的数据包
# host表示主机过滤,抓取对应IP的数据包
# -nn 表示不解析IP地址和端口号的名称
# -w ping.pcap:表示将抓取到的数据包保存到ping.pcap文件中。
接着把 ping.pcap 文件拖到电脑,再用 Wireshark 打开它。打开后,就可以看到下面这个界面:
这里先简单的介绍下Wireshark的控制面板,这个面板包含7个字段,分别是:
在 Wireshark 的页面里,可以更加直观的分析数据包,不仅展示各个网络包的头部信息,还会用不同的颜色来区分不同的协议,由于这次抓包只有 ICMP 协议,所以只有紫色的条目。
前三层基本上都是一样的,第四层开始就可以出现TCP, UDP 协议,第五层就可能有HTTP 应用层协议等等。
接下来我们来分析各个层的具体情况
Frame 1: 98 bytes on wire (784 bits), 98 bytes captured (784 bits)
# 第1帧,线路有98个字节(共784位),实际捕获到98字节
Encapsulation type: Ethernet (1)
# 封装类型: 以太网(1)
Arrival Time: Oct 22, 2020 10:59:36.412790000 中国标准时间
# 到达时间
[Time shift for this packet: 0.000000000 seconds]
# 包偏移时间
Epoch Time: 1603335576.412790000 seconds
[Time delta from previous captured frame: 0.000000000 seconds]
# 两帧之间的时间间隔
[Time delta from previous displayed frame: 0.000000000 seconds]
# 捕获到显示的间隔时间
[Time since reference or first frame: 0.000000000 seconds]
# 此包和第一帧的时间间隔
Frame Number: 1 #帧序号
Frame Length: 98 bytes (784 bits) #帧长度
Capture Length: 98 bytes (784 bits) #捕获长度
[Frame is marked: False] #此帧是否做了标记:否
[Frame is ignored: False] #此帧是否被忽略:否
[Protocols in frame: eth:ethertype:ip:icmp:data] #帧内封装的协议层次结构
[Coloring Rule Name: ICMP] #着色标记的协议名称
[Coloring Rule String: icmp || icmpv6] #着色规则显示的字符串
Ethernet II, Src: VMware_4c:e6:d1 (00:0c:29:4c:e6:d1), Dst: Micro-St_64:86:44 (30:9c:23:64:86:44)
Destination: Micro-St_64:86:44 (30:9c:23:64:86:44) #目的MAC地址
Source: VMware_4c:e6:d1 (00:0c:29:4c:e6:d1) #源MAC地址
Type: IPv4 (0x0800)
Internet Protocol Version 4, Src: 192.168.0.12, Dst: 192.168.0.11
# IPv4 协议 源IP:192.168.0.12, 目的IP:192.168.0.11
0100 .... = Version: 4 # 版本4
.... 0101 = Header Length: 20 bytes (5) # 头长度20字节
Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT) #差分服务区域
Total Length: 84 #总长度
Identification: 0x81d9 (33241) #鉴别
Flags: 0x4000, Don't fragment #标志
Fragment offset: 0 #分的偏移量
Time to live: 64 # 生存期
Protocol: ICMP (1) # 协议名称: ICMP(将协议字段设置为1表示是ICMP协议)
Header checksum: 0x3768 [validation disabled] # 头部校验和
[Header checksum status: Unverified] # 头部校验和检验状态:
Source: 192.168.0.12 # 源IP
Destination: 192.168.0.11 #目的地IP
Internet Control Message Protocol // 因特网控制信息协议
Type: 8 (Echo (ping) request) // 类型,ping 请求
Code: 0
Checksum: 0x4cd3 [correct] // 和校验
[Checksum Status: Good] // 和检验状态
Identifier (BE): 24759 (0x60b7) // 标识符
Identifier (LE): 46944 (0xb760)
Sequence number (BE): 1 (0x0001) // BE 序列号
Sequence number (LE): 256 (0x0100) //LE 序列号
[Response frame: 2]
Timestamp from icmp data: Oct 22, 2020 10:59:36.000000000 中国标准时间
[Timestamp from icmp data (relative): 0.412790000 seconds]
Data (48 bytes) // 数据
Data: 5c4c060000000000101112131415161718191a1b1c1d1e1f…
[Length: 48]
从第4层往上面看,就和 上文【ping —— 查询报文类型的使用】过程是一样的
从 ping 的例子中,我们可以看到网络分层就像有序的分工,每一层都有自己的责任范围和信息,上层协议完成工作后就交给下一层,最终形成一个完整的网络包。
Wireshark抓包深入分析一下Ping的过程
Wireshark 分析ping报文
Wireshark 分析捕获的数据记录