ICMP 运行机制
ICMP(Internet Control Message Protocol,因特网控制报文协议)被主机和路由器用来彼此沟通网络层的信息。ICMP 最典型的用途是差错报告。
ICMP 报文有一个类型字段和一个编码字段,并且包含引起该 ICMP 首次生成的 IP 数据报的首部和前 8 个字节(以便发送方能确定引发该差错的数据报)。下表是相关的 ICMP 报文类型:
ICMP 类型 | 编码 | 描述 |
---|---|---|
0 | 0 | 回显回答(对 ping 的回答) |
3 | 0 | 目的网络不可达 |
3 | 1 | 目的主机不可达 |
3 | 2 | 目的协议不可达 |
3 | 3 | 目的端口不可达 |
3 | 6 | 目的网络未知 |
3 | 7 | 目的主机未知 |
4 | 0 | 源抑制(拥塞控制) |
8 | 0 | 回显请求 |
9 | 0 | 路由器通告 |
10 | 0 | 路由器发现 |
11 | 0 | TTL 过期 |
12 | 0 | IP 首部损坏 |
注意到 ICMP 报文并不仅是用于通知差错情况。
ping
ping
程序发送一个 ICMP 类型 8 编码 0 的报文到指定主机。看到回显(echo)请求,目的主机发回一个类型 0 编码 0 的 ICMP 回显回答。
当 ping
一个不存在的 IP 时,会收到目的主机不可达(类型 3 编码 1)的响应。
Traceroute
Traceroute 在 Linux 中一般为 tracepath
,在 Windows 中一般为 tracert
。该程序允许我们跟踪从一台主机到世界上任意一台主机之间的路由。其用 ICMP 报文来实现。
为了判断源和目的地之间所有路由器的名字和地址,源主机中的 Traceroute 向目的地主机发送一系列普通的 IP 数据报。这些数据报的每个携带了一个具有不可达 UDP 端口号的 UDP 报文段。第一个数据报的 TTL 为 1,第二个的 TTL 为 2,第三个的 TTL 为 3,依此类推。该源主机也为每个数据报启动定时器。当第 n 个数据报到达第 n 台路由器时,第 n 台路由器观察到这个数据报的 TTL 正好过期。根据 IP 协议规则,路由器丢弃该数据报并发送一个 ICMP 告警报文给源主机(类型 11 编码 0)。该告警报文包含了路由器的名字和它的 IP 地址。当该 ICMP 报文返回源主机时,源主机从定时器得到往返时延,从 ICMP 报文中得到第 n 台路由器的名字与 IP 地址。
这些数据报之一将最终沿着这条路到达目的主机。因为该数据报包含了一个具有不可达端口号的 UDP 报文段,该目的主机将向源发送一个端口不可达的 ICMP 报文(类型 3 编码 3)。当源主机收到这个特别的 ICMP 报文时,知道它不需要再发送另外的探测分组。
标准的 Traceroute 程序实际上用相同的 TTL 发送 3 个一组的分组,因此 Traceroute 输出对每个 TTL 提供了 3 个结果。
一个 Traceroute 运行示例如下:
1 | tracert 185.199.109.153 |
可以看到输出有 6 列:
- 第一列:前面描述的 n 值,即路径上的路由器编号
- 第二、三、四列:3 次实验的往返时延
- 第五列:路由器的名字
- 第六列:路由器地址
如果源从任何给定路由器接收到的报文少于 3 条(由于网络中的丢包),Traceroute 在该路由器号码后面放一个星号,并向那台路由器报告少于 3 次往返时间。
其他
ICMP 通常被认为是 IP 的一部分,但从体系结构上讲它位于 IP 之上,因为 ICMP 报文是承载在 IP 分组中的。这就是说,ICMP 报文是作为 IP 有效载荷承载的,就像 TCP 与 UDP 报文段作为 IP 有效载荷被承载那样。