ICMP协议,全称Internet Control Message Protocol,也叫互联网控制报文协议。
0x00 简介
ICMP 常用的有两种类型的报文,一种是查询类型的,另一种是差错类型的。
查询类型的报文,它可以用来主动查询网络数据包是否可以到达目标主机;至于差错类型的报文,你可以把它理解成是报信的,它可以用来通报源主机,你发送的数据包出错了,到不了你指定的网络、主机或者端口,等等。
0x01 展开
查询类型报文
我们常用的 ping 程序,使用的就是查询类型的 ICMP 报文,它是一种主动请求,并且获得主动应答的 ICMP 协议。
对于主动请求的报文,称为 ICMP ECHO REQUEST,而主动请求的回复,称为ICMP ECHO REPLY。对 ping 程序的网络数据进行抓包,你就会看到这两个类型的数据包了。
ICPM 查询类型报文:
22:43:14.678840 IP 192.168.1.5 > blog.chenishr.com: ICMP echo request, id 59234, seq 0, length 64
22:43:14.689983 IP blog.chenishr.com > 192.168.1.5: ICMP echo reply, id 59234, seq 0, length 64
差错类型报文
前面说过,差错类型的报文是用来给源主机报信的,当互联网协议在传输过程中发生错误时,会给源主机发送一个ICMP的差错报文。常见的差错报文有以下几种:
第一种是终点不可达。很明显就是说数据包到达不了它指定的目标,如到达不了网络、主机等等。
具体的有以下几种场景:
- 网络不可达
- 主机不可达
- 协议不可达
- 端口不可达
- 需要进行分片但设置了不分片位
那些不可达的目标很好理解,就是到达不了具体的网络、主机、端口等等。需要进行分片但设置了不分片位,这一点可能不好理解。这个场景的意思是这样子的,当数据包在传输路径中碰到一个 MTU 比较小的网卡,而且数据包的大小比那个 MTU 大时,必须要对数据进行分片,但是数据包设置了不可分片位,这时就会返回一个这样的差错报文。
第二种是源站抑制。源主机发送数据包的速度太快了,目标主机处理不过来,也就是让源主机放慢发送速度。
第三种是时间超时。IP数据报有个 TTL 的生存时间,每次经过一个路由节点就会减一,点到零还没到目标主机的话,就会发送一个时间超时的差错报文。
第四种是路由重定向。也就是让下次发给另一个路由器。
0x02 运用
ping 程序
ICMP 协议查询报文类型的典型运用是 ping 程序。ping 是我们日常工作中经常用到的,想要知道某个主机的网络通不通,ping 一下就知道了。
ping 程序执行的输出:
PING blog.chenishr.com (120.77.213.253) 56(84) bytes of data.
64 bytes from 120.77.213.253: icmp_seq=1 ttl=51 time=6.55 ms
64 bytes from 120.77.213.253: icmp_seq=2 ttl=51 time=65.9 ms
64 bytes from 120.77.213.253: icmp_seq=3 ttl=51 time=7.93 ms
64 bytes from 120.77.213.253: icmp_seq=4 ttl=51 time=30.4 ms
^C
--- blog.chenishr.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3003ms
rtt min/avg/max/mdev = 6.552/27.717/65.967/24.030 ms
从输出可以看出,ping 程序发送了四个报文,都能正常收到回复,没有丢包,而且最后还有相应的统计信息。
工作原理
源主机首先会构建一个 ICMP 请求数据包,ICMP 数据包内包含三个重要的内容。第一个是类型字段,对于请求数据包而言该字段为 8;另外一个是顺序号,主要用于区分连续 ping 的时候发出的多个数据包,每发出一个请求数据包,顺序号会自动加 1;最后是发送时间,它被添加到报文的数据部分,为了能够计算往返时间 RTT。
目标主机收到请求后会构建一个 ICMP 应答包,应答数据包的类型字段为 0,顺序号为接收到的请求数据包中的顺序号,然后再发送出去给源主机。需要注意的是,目标主机可能会关闭响应 ICMP 请求。
源主机如果在规定的时候间内没有接到 ICMP 的应答包,则说明目标主机不可达;如果接收到了ICMP 应答包,则说明目标主机可达。此时,源主机会检查,用当前时刻减去该数据包最初从源主机上发出的时刻,就是 ICMP 数据包的时间延迟。
Traceroute 程序
Traceroute 程序是对 ICMP 差错报文类型的一个经典运用。我们主要用它来追踪网络数据包的路由途径。
Traceroute 程序执行输出:
traceroute to blog.chenishr.com (120.77.213.253), 30 hops max, 60 byte packets
1 172.17.0.1 (172.17.0.1) 1.168 ms 1.091 ms 1.033 ms
2 192.168.5.1 (192.168.5.1) 15.025 ms 15.352 ms 15.948 ms
3 192.168.0.2 (192.168.0.2) 14.760 ms 14.683 ms 14.621 ms
4 * * *
5 113.106.40.50 (113.106.40.50) 208.131 ms 202.105.155.205 (202.105.155.205) 208.044 ms 61.146.241.233 (61.146.241.233) 208.000 ms
6 183.56.65.6 (183.56.65.6) 208.619 ms 183.56.65.14 (183.56.65.14) 91.293 ms 183.56.65.86 (183.56.65.86) 91.100 ms
7 119.147.223.110 (119.147.223.110) 90.981 ms 92.300 ms *
8 183.2.182.130 (183.2.182.130) 92.160 ms 58.61.162.134 (58.61.162.134) 92.146 ms 92.076 ms
9 183.61.45.10 (183.61.45.10) 92.041 ms 183.2.184.134 (183.2.184.134) 91.943 ms 183.61.45.10 (183.61.45.10) 91.948 ms
10 116.251.113.142 (116.251.113.142) 91.867 ms * 42.120.242.218 (42.120.242.218) 91.772 ms
11 42.120.253.2 (42.120.253.2) 91.730 ms 42.120.253.6 (42.120.253.6) 91.687 ms 116.251.117.153 (116.251.117.153) 103.880 ms
12 * * *
13 * * *
14 120.77.213.253 (120.77.213.253) 103.499 ms 103.443 ms 103.401 ms
其中前面的序号表示经过的第几个路由,序号后面是一个 IP 地址,即该路由的 IP。接下来是三个时间,Traceroute默认会向每个网关发送三个探测数据包,那三个数值是网关响应后返回的时间。还有出现星号的情况,那表示网关没有返回数据。
工作原理
程序使用了 IP 首部中的 TTL (生存周期)字段和 ICMP 的差错类型报文。
首先将 TTL 设为 1 ,当它到达第一个路由时就超时了,这样它就可以收到该路由返回的 ICMP 的时间超时差错报文;然后程序再将 TTL 设为 2,这样就可以拿到第二个路由的信息;以此类推,直到到达目标主机。
Traceroute 程序给目的主机发送的是一份 UDP 数据报,但它选择一个不可能的值作为 UDP 端口号(大于30000),使目的主机的任何一个应用程序都不可能使用该端口。这样目的主机就会给程序返回一个端口不可达的差错报文,程序就知道数据包已经到达目的主机了,不用再发送探测包了。
有了以上收集的信息,Traceroute 程序既可以将网络数据包的路由途径绘制出来了。
0x03 最后
本文主要介绍了 ICMP 协议查询类型和差错类型的报文,然后介绍了 ping 和 traceroute 程序是如果利用 ICMP 协议的功能来工作。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。