ICMP 是用来给主机与路由器间沟通网络层信息的协议,用来弥补 IP 协议本身并未提供能诊断发送失败的功能这一缺陷,是网络层三个重要组件之一。
最常见的用途是差错报告,例如在传输数据时在某一个结点发生了问题,此时该结点路由器就可以返回一个 ICMP 差错报文,发送方收到该报文时就可以针对该错误作出相应处理。
封装
ICMP 报文封装于 IP 数据包中。
通过 IP 数据报中协议字段来标识 ICMP 协议。ICMP 头部中类型和代码是用来表示信息的核心,在之后详述。校验和字段覆盖整个 ICMP 数据段。
ICMP 与 TCP 一样是封装于 IP 数据报中,将其作为载荷传输数据,但是同时被认为是 IP 层的一部分,必须在所有 IP 的实现中存在,所以通常认为 ICMP 位于网络层与传输层之间,而非属于二者其一。
报文类型
ICMP 报文被分为两类:
- 差错报文(error message):有关数据包传递的报文
- 信息类报文(informational message):有关信息采集和配置的报文
利用头部中的类型(Type)字段表示报文类型,代码(Code)字段用于确定具体的信息。例如下表中 ICMPv4 的部分常见信息。
类型 | 正式名称 | E / I |
---|---|---|
0 | 回显应答 | I |
3 | 目的不可达 | E |
5 | 重定向 | E |
8 | 回显请求 | I |
11 | 超时 | E |
12 | 参数问题 | E |
类型 | 代码 | 描述 |
---|---|---|
0 | 0 | 回显(ping) |
3 | 0 | 目的网络不可达 |
3 | 1 | 目的主机不可达 |
3 | 2 | 目的协议不可达 |
3 | 3 | 目的端口不可达 |
3 | 13 | 管理禁止通信 |
11 | 0 | TTL 过期 |
12 | 0 | IP 首部损坏 |
通常来说,传入的信息类报文请求会被操作系统自动处理,差错报文就会传递给上层处理。
应用
Ping
Ping 用到了 ICMP 中的回显请求和回显应答(ICMPv4 类型 0/8,ICMPv6 类型 129/128)。ICMP 的回显报文分为三部分:
- 标识符(4 字节):ICMP 中不存在端口号,所以回显时需要用该字段确定是谁发出的信息。
- 序列号(4 字节):从 0 开始,用于与回显的数据报对应。
- 数据(可选):回显的数据。在 ping 的程序中存放发送时的本地时间,这样在收到回显时再与本地时间对比,就可以得到一个 RTT 估计值。
traceroute
traceroute 工具用于确定发送者到目的地路径上的路由器。在 IP 报文中 TTL 字段降至 0 时会返回一个超时报文,有了这一前提,那么只要向目的地依次发送 TTL 为 1、2、3…… 的数据报,通过返回的 ICMP 报文就能确定过期时所抵达的路由器,直到抵达了目的地,就能得到整个路径上所经过的路由器。