ICMP协议概述

天将降大任于是人也,必先苦其心志,劳其筋骨,饿其体肤,空乏其身,行拂乱其所为,所以动心忍性,曾益其所不能。

—— 战国·孟子·《生于忧患,死于安乐》

网络通信过程中可能出现各种各样的差错,因此需要具备 差错传送 机制。开始介绍解决方案前,我们先考察一下问题的背景:

这是我们在网络规划一节讨论的某公司网络拓扑图,法务部同事 aliceIP 地址是 192.168.170.194/26 ,她准备向研发部的 bruce 发送一些数据,bruceIP 地址是 192.168.171.3/25

由于 bruce 今天刚好休假,电脑没开机,这时会发生什么事情呢?

alice 发出来的 IP 包,可以顺利到达研发部路由器。路由器接到包后,一看目标网络就在网卡 eth1 上,它可以直接通过以太网帧将包发送至目的地。

为了封装以太网帧,路由器需要先找到 192.168.171.3MAC 地址——向研发部网络广播 ARP 地址解析请求。但由于 bruce 的电脑已经关机,它无法应答路由器的 ARP 请求。

由于久久得不到 ARP 应答,路由器便认为 192.168.171.3 这个地址 不可达 。接下来,路由器需要将这个情况反馈给 alice ,即 192.168.170.194 。具体怎么做呢?

解决方案很简单,路由器可以封装一个 IP 包,将差错信息作为数据发给 alice

整个网络所有参与方需要对差错信息的组织格式达成一致,这就是 ICMP 协议负责的范畴。

ICMP 报文结构

互联网控制消息协议 ( Internet Control Message Protocol )简称 ICMP ,是 IP 的辅助协议,同样位于网络层,负责网际通信中 控制信息差错信息 的传送。

ICMP 有赖 IP 提供的网际通信能力,它的报文作为数据承载在 IP 包中进行传输:

注意到,IP 包头部中的 protocol 字段,用于标识数据部分所属的协议,可以当做数据类型来理解。如果 protocol 字段的值为 1 ,说明 IP 包的数据部分是一个 ICMP 报文。

那么,ICMP 报文的格式又长啥样呢?

ICMP 报文同样分为 头部数据 两部分,其中头部字段如下:

  • 类型type ),顾名思义用来标识 ICMP 报文的类型,例如 目的不可达destination unreachable )差错报文;
  • 代码code ),进一步划分 ICMP 报文的类型,标识错误的原因,例如目的不可达可以进一步分成网络不可达、主机不可达以及端口不可达等等;
  • 校验和checksum ),用于差错校验,由 ICMP 头部计算得出;

常见的 ICMP 报文类型列举如下表:

类型 描述 状态 查询 差错
0 回显响应 ✔️
1 保留 未分配
2 保留 未分配
3 目的不可达 ✔️
4 源端关闭 弃用 ✔️
5 重定向 ✔️
6 备用主机地址 弃用
7 保留 未分配
8 回显请求 ✔️
9 路由通告 ✔️
10 路由请求 ✔️
11 超时错误 ✔️
12 参数错误(IP头部错误) ✔️
13 时间戳请求 ✔️
14 时间戳应答 ✔️

注意到,ICMP 报文类型分为两种,一种是差错传送,一种是信息查询。举个例子,类型 13 用于向一台主机查询时间戳。下一小节,我们将研究 ping 命令,它是利用 请求回显 实现的,这也是一种查询类型。

主机不可达差错

回到前面的场景,研发部路由器发现 192.168.171.3bruce )不可达后,将向 192.168.170.194alice )传送主机不可达差错。差错消息用 ICMP 报文封装,其中类型为 3 ,代表目的地不可达;代码为 1 ,代表主机不可达。

由于 192.168.170.194alice )可能同时与多方通信,因此 ICMP 报文必须提供更多上下文,表明是 192.168.171.3bruce )不可达。

问题不难解决,将产生差错的 IP 包,作为 ICMP 报文的数据,一并发给 192.168.170.194alice )不就好了吗?实际上,不用将整个 IP 包都附上,只需附上 IP 包头部以及数据的前 8 字节即可。

最终,ICMP 包被封装成 IP 包,由研发部路由器发给 alice ,其中源地址是路由器的地址,即 192.168.170.5 ;目的地址为 alice 的地址,即 192.168.170.194 ;协议类型为 1 ,代表 ICMP 协议。详情如下:

192.168.170.194alice )收到 ICMP 报文后,检查类型和代码字段,就知道这是一个主机不可达错误。它继续检查附在 ICMP 报文数据中的差错包头部,就知道是发数据给 bruce 时产生的。

顺便提一下,额外附上差错包数据的前 8 字节的原因在于:IP 报文数据经常承载传输层的协议分组,前 8 个字节刚好是分组的头部。有了差错包的传输层分组头部,则可以进一步确定差错是访问目标主机的什么端口产生的。

扩展阅读

小菜学网络】系列文章首发于公众号【小菜学编程】,敬请关注:

【小菜学网络】系列文章首发于公众号【小菜学编程】,敬请关注: