在日常工作中,我们经常需要判断网络是否连通,相信大家使用最多的命令就是 ping,traceroute 啦。大家都知道 ping/traceroute 命令是基于 ICMP 协议来实现的,那么什么是 ICMP 协议呢?ping/traceroute 命令又是如何基于 ICMP 实现的呢?
今天这篇文章,我们就来一起搞清楚其中的原理。下面首先我们先来了解一下ICMP 协议。
ICMP协议
ICMP是 Internet Control Message Protocol 的缩写,即互联网控制消息协议。它是互联网协议族的核心协议之一。它用于 TCP/IP 网络中发送控制消息,提供可能发生在通信环境中的各种问题反馈,通过这些信息,使网络管理者可以对所发生的问题作出诊断,然后采取适当的措施解决问题。
虽然 ICMP 是网络层协议,但是它不像 IP 协议和 ARP 协议一样直接传递给数据链路层,而是先封装成 IP 数据包然后再传递给数据链路层。所以在 IP 数据包中如果协议类型字段的值是 1 的话,就表示 IP 数据是 ICMP 报文。IP 数据包就是靠这个协议类型字段来区分不同的数据包的。如下图 WireShark 抓包所示:
<img src="https://pic4.zhimg.com/v2-7614b8422b03023ecfa1bd9150f504bb_b.jpg" data-caption="" data-size="normal" data-rawwidth="1080" data-rawheight="417" class="origin_image zh-lightbox-thumb" width="1080" data-original="https://pic4.zhimg.com/v2-7614b8422b03023ecfa1bd9150f504bb_r.jpg"/>
在 IP 通信中如果某个包因为未知原因没有到达目的地址,那么这个具体的原因就是由 ICMP 负责告知。而 ICMP 协议的类型定义中就清楚的描述了各种报文的含义。
ICMP协议类型
ICMP协议的类型分为两大类,查询报文 和差错报文 。如下表:
<img src="https://pic1.zhimg.com/v2-4f259c166221946c2ef40960d360053c_b.jpg" data-caption="" data-size="normal" data-rawwidth="1366" data-rawheight="1306" class="origin_image zh-lightbox-thumb" width="1366" data-original="https://pic1.zhimg.com/v2-4f259c166221946c2ef40960d360053c_r.jpg"/>
<img src="https://pic4.zhimg.com/v2-621f5a7f9898466bb1ec4d097b3c141f_b.jpg" data-caption="" data-size="normal" data-rawwidth="1378" data-rawheight="870" class="origin_image zh-lightbox-thumb" width="1378" data-original="https://pic4.zhimg.com/v2-621f5a7f9898466bb1ec4d097b3c141f_r.jpg"/>
是不是看起来有点多啊?计算机网络真的是博大精深啊。而平时我们经常使用的少之又少。
ICMP报文格式
从 ICMP 的报文格式来说,ICMP 是 IP 的上层协议。但是 ICMP 是分担了 IP 的一部分功能。所以,他也被认为是与 IP 同层的协议。下面一起来看一下 ICMP 数据包格式和报文内容吧。具体参考下图:
<img src="https://pic1.zhimg.com/v2-ef5b42aff92acc5a8873d946d48177e4_b.jpg" data-caption="" data-size="normal" data-rawwidth="696" data-rawheight="941" class="origin_image zh-lightbox-thumb" width="696" data-original="https://pic1.zhimg.com/v2-ef5b42aff92acc5a8873d946d48177e4_r.jpg"/>
可以看到,我们一层层剥开 ICMP 的外壳,查看其本质。方便我们更好的理解 ICMP 协议。
ICMP协议实现--Ping命令
通过上面的叙述,我们初步了解了 ICMP 协议的内容,那么下面我们来看一下ICMP 的具体实现与应用吧,首先我们来了解查询报文 的应用--ping,下面我们通过 ping 同一个子网的主机,来看一下整个过程是怎么样的。
那么比较完整的流程是:
1. 向目的服务器发送回显请求 首先,向目的服务器上执行ping命令,主机会构建一个 ICMP 回显请求消息数据包(类型是8,代码是0),在这个回显请求数据包中,除了类型和代码字段,还被追加了标识符和序号字段。标识符和序号字段分别是 16 位的字段。ping 命令在发送回显请求数据包时,会将进程号填写在标识符里。对于序号,每送出一个数据包数值就增加1。而且,回显请求的选项数据部分用来装任意数据。这个任意数据用来调整 ping 的交互数据包的大小。如下图在 192.168.1.10上执行 ping 192.168.1.1的命令:
ping 命令执行的时候,他的进程号是 43991:
<img src="https://pic1.zhimg.com/v2-d8a328032435c1713659ae37411afdcc_b.jpg" data-caption="" data-size="normal" data-rawwidth="1080" data-rawheight="193" class="origin_image zh-lightbox-thumb" width="1080" data-original="https://pic1.zhimg.com/v2-d8a328032435c1713659ae37411afdcc_r.jpg"/>
通过 WireShark 抓包可以看出,上图中的 192.168.1.10 主机会构建一个 ICMP 回显请求消息数据包。
<img src="https://pic3.zhimg.com/v2-d2161822052e99cd7e545a14dc965386_b.jpg" data-caption="" data-size="normal" data-rawwidth="1080" data-rawheight="557" class="origin_image zh-lightbox-thumb" width="1080" data-original="https://pic3.zhimg.com/v2-d2161822052e99cd7e545a14dc965386_r.jpg"/>
上图中我们可以看到 ICMP 的 Type(协议类型)是 8,Code(代码)是 0,Identifier(ping进程号) 是 43991,同时还有 Sequence Number 发送序号11,以及发送时间 。
2. 目的服务器发送回显应答
当192.168.1.10送到 回显请求数据包后,192.168.1.1就会向发送方192.168.1.10发送回显应答(类型是0,代码是0),这个 ICMP 回显应答数据包在 IP 层来看,与被送来的回显请求数据包基本上一样。不同的只有源、目标 IP 地址字段被交换了,Type类型字段里填入了表示回显应答的0。通过 WireShark 抓包可以看出,如下图:
<img src="https://pic4.zhimg.com/v2-6ac347e9fecb1feba27f11929f463fd7_b.jpg" data-caption="" data-size="normal" data-rawwidth="1080" data-rawheight="538" class="origin_image zh-lightbox-thumb" width="1080" data-original="https://pic4.zhimg.com/v2-6ac347e9fecb1feba27f11929f463fd7_r.jpg"/>
3. 源服务器显示相关数据
如果源服务器可以接收到回显应答数据包,那我们就认为192.168.1.1是正常工作着的。进一步,记住发送回显请求数据包的时间,与接收到回显应答数据包的时间差,就能计算出数据包一去一回所需要的时间。这个时候ping命令就会将目的服务器的 IP 地址,数据大小,往返花费的时间打印到屏幕上。如下图:
<img src="https://pic1.zhimg.com/v2-b4d74f52d89436bc6e7fbcf9165e9ef8_b.jpg" data-caption="" data-size="normal" data-rawwidth="1018" data-rawheight="314" class="origin_image zh-lightbox-thumb" width="1018" data-original="https://pic1.zhimg.com/v2-b4d74f52d89436bc6e7fbcf9165e9ef8_r.jpg"/>
ICMP协议实现--traceroute命令
traceroute命令是一款充分利用 ICMP 差错报文 类型的应用,其主要用作追踪路由信息,下面我们来逐个查看一下其工作原理。
我们通过执行 traceroute 192.168.1.1,来分析一下他的原理,它的原理就是利用 IP 包的 TTL 从 1 开始按照顺序递增的同时发送 UDP 包,强制接收 ICMP 超时消息的方法。
首先 traceroute 会将 IP 包的 TTL 设置 为 1,然后发送 UDP 包,他会填入一个端口号作为 UDP 目标端口号(默认是:33434-33534)。如下图:
<img src="https://pic3.zhimg.com/v2-b94339a7a5f98df9a54e2c57a8e0335e_b.jpg" data-caption="" data-size="normal" data-rawwidth="1080" data-rawheight="526" class="origin_image zh-lightbox-thumb" width="1080" data-original="https://pic3.zhimg.com/v2-b94339a7a5f98df9a54e2c57a8e0335e_r.jpg"/>
当目的主机收到 UDP 包后,会返回 ICMP 差错报文消息(类型 3,代码 3)。参照上面的表,该错报文类型是端口不可达,说明发送方发出的 UDP 包到达了目的主机。如下图:
<img src="https://pic3.zhimg.com/v2-fe105808fa75759d2bcbf902b95583b2_b.jpg" data-caption="" data-size="normal" data-rawwidth="1080" data-rawheight="400" class="origin_image zh-lightbox-thumb" width="1080" data-original="https://pic3.zhimg.com/v2-fe105808fa75759d2bcbf902b95583b2_r.jpg"/>
这样的过程,traceroute 就可以拿到了所有的路由器 IP,这样子就可以看到从源主机到目的主机过程中的所有路由信息。
当然实际情况有的路由器禁用 ICMP ,那么他就根本不会返回这个 ICMP 差错报文,所以是看不到中间经过的路由IP的。
Tips:traceroute 在类 Unix/Linux 系统中默认使用的是 UDP 协议,也可以通过参数修改为使用 ICMP 协议;Windows 操作系统中只使用 ICMP 协议。
说了这么多,我们还是直接来看一张图吧,基本可以描述清楚 traceroute 的整个过程。如下图:
<img src="https://pic1.zhimg.com/v2-1835f72b05f39288dd909bd059a55944_b.jpg" data-caption="" data-size="normal" data-rawwidth="1080" data-rawheight="230" class="origin_image zh-lightbox-thumb" width="1080" data-original="https://pic1.zhimg.com/v2-1835f72b05f39288dd909bd059a55944_r.jpg"/>
总结
以上内容就是关于ICMP协议的全部内容啦,相信你看完本篇文章就可以深入理解每一次ping,traceroute背后的工作原理啦。好了,当我们深入学习完以上内容,当我们面对面试官的各种***钻问题时,是不是游刃有余了呢?那么面试官一般都问些什么问题呢?这就给推荐牛客网,各种面试经历,还有在线面试模拟。
<img src="https://pic4.zhimg.com/v2-7393ad246801c6a39f9e67b531fac477_b.jpg" data-caption="" data-size="small" data-rawwidth="258" data-rawheight="258" class="content_image" width="258"