ICMP 是 IP 的「通讯员」:包丢了、到不了、太大了,都由它回来报告。 它装在 IP 包里,但不是传输层协议——它没有端口。
4.5.3 的 PMTU 发现靠的就是 ICMP,这一节讲它的全貌。 5.1 的「五个配套协议」里,它是第三个要讲的。
一、它补的是哪个洞
IP 是「尽力而为」:发出去就不管了,成没成功它不说。 这个设计让转发变简单,但让排查变困难——包丢了,你完全不知道丢在哪儿、为什么丢。
| 情况 | 没有 ICMP 会怎样 | 有 ICMP 之后 |
|---|---|---|
| 目的地没人 | 静默超时 | 回「主机不可达」 |
| 包太大 | 静默丢弃 | 回「需要分片」 |
| TTL 用完 | 静默丢弃 | 回「超时」 |
三行都是「静默」变「有声」:这是 ICMP 唯一的价值——它不修问题,只报告问题。 所以「ICMP 通畅」本身也是排查手段: 如果连错误报告都收不到,你就只能在「猜」和「抓包」之间二选一。
二、它为什么不叫传输层
因为它没有端口,也不承载应用数据。 它只是「IP 的一个附带功能」,报文格式由 IP 首部里的「协议号 1」标识。
| 项 | ICMP | TCP/UDP |
|---|---|---|
| 有没有端口 | 没有 | 有 |
| 承载应用数据吗 | 不承载 | 承载 |
| 可靠吗 | 不保证 | TCP 可靠、UDP 不可靠 |
第一行「没有端口」带来一个实际后果: NAT 设备没法用端口号把 ICMP 映射回内网某台机器—— 所以「内网 ping 不通外网」经常是 NAT 的锅。 第二行更关键: ICMP 不承载数据,所以它不能「替你传文件」—— 虽然历史上有过用 ICMP 隧道偷偷传数据的工具,但那是滥用。
三、三个最常用的场景
排查时真正用得上的就三个:
| 工具 | 用的 ICMP 类型 | 能测什么 |
|---|---|---|
| ping | 8 和 0 | 通不通、往返多久 |
| traceroute | 11(超时) | 路径上有哪些设备 |
| PMTUD | 3 的代码 4 | 路径能过多大的包 |
第二行那个「超时」是「故意制造」的:发 TTL=1 的包,第一台路由器减到 0 就回一个超时, 它的地址就暴露了。 所以 traceroute 不是「探测」,是「骗设备自己报地址」。 第三行是最容易被忽略的:它不产生「用户可见的结果」,但决定了「大包能不能过」。 所以「ICMP 全禁」的防火墙会顺手把 PMTUD 也废掉——这就是 PMTU 黑洞的成因。
四、动手 Demo:ICMP 是 IP 的「通讯员」
跑三次 ping,看每一行回复和最后那行统计。 每条「回复」就是一个 ICMP 回显应答,对应我们发出去的请求。
import subprocess
out = subprocess.run('ping -n 3 127.0.0.1', shell=True,
capture_output=True).stdout.decode('gbk')
print(out)
实跑输出:
--------------------------------------------------------------------
ICMP 是 IP 的「通讯员」
--------------------------------------------------------------------
**IP 只负责发,不负责报告结果**:**包丢了它不管,包到了它也不说。**
**ICMP 就是那个「出事了回来告诉你」的角色。**
**实测一次往返**:
**来自 127.0.0.1 的回复: 字节=32 时间<1ms TTL=128**
**来自 127.0.0.1 的回复: 字节=32 时间<1ms TTL=128**
**来自 127.0.0.1 的回复: 字节=32 时间<1ms TTL=128**
**数据包: 已发送 = 3,已接收 = 3,丢失 = 0 (0% 丢失),**
**每一条「回复」就是一个 ICMP 回显应答(type 0)**,**对应我们发出去的「回显请求」(type 8)。**
**所以 ping 不是「测带宽」,是「测往返时间」**——**它只证明「包能来回」,不证明「带宽够」。**
**ICMP 有个特点容易被忽略**:**它装在 IP 包里,但它不是传输层协议。**
**所以它「没有端口」,也「不能被 NAT 简单地映射」**——
**这正是「ping 不通但网页能开」的原因之一:有人把 ICMP 全拦了。**
**排查时最有用的三个 ICMP 消息**:
**目标不可达(type 3)说明「路到了但没人接」**;**超时(type 11)说明「TTL 用完了,可能成环」**;
**重定向(type 5)说明「网关觉得你走错了门」。**
「往返时间」是 ping 唯一有价值的输出:它证明包能来回,而且告诉你「来回花了多久」。 但它不证明带宽——一条 1 Mbps 的链路也能 ping 出 1 毫秒。 「丢失 = 0」这一项要特别看:它同时证明「去程通」和「回程通」。 如果「已发送 3、已接收 0」,就分不清是去不了还是回不来——这时要换一台机器反向 ping 一次。 为什么先 ping 127.0.0.1:这个地址不出网卡,只走协议栈。 所以它通了说明「系统本身没问题」,接下来才需要怀疑网线、网关、DNS。 排查的次序就是这么一层层排除出来的。
30 秒实验
- 想一下:ICMP 为什么不叫传输层协议?
- 想一下:traceroute 是怎么「骗」出路径的?
- 算一下:ping 3 次全通,丢包率是多少?
常见误区
- 以为「ICMP 能保证送达」。 不能,它只报告问题,不修问题。
- 以为「ICMP 是传输层」。 不是,它没有端口,装在 IP 里。
- 以为「禁用 ICMP 更安全」。 会连带废掉 PMTUD,导致「小包通、大包不通」。
自测三问(点开对答案)
1. ICMP 的作用是什么? —— **在 IP 层报告错误和异常**:不可达、超时、包太大等。 2. ICMP 为什么不算传输层协议? —— **它没有端口,也不承载应用数据**,只是 IP 的附带功能。 3. ping 和 traceroute 分别用哪个 ICMP 类型? —— **ping 用 8 和 0(请求与应答),traceroute 用 11(超时)。**下一节把 ICMP 的主要消息列一遍。
- ☐ (本节完,下一节 5.4.2 主要的ICMP消息)