📚 第五章 IP协议相关技术
📄 一句话概括

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 秒实验

  1. 想一下:ICMP 为什么不叫传输层协议?
  2. 想一下:traceroute 是怎么「骗」出路径的?
  3. 算一下:ping 3 次全通,丢包率是多少?

常见误区

  1. 以为「ICMP 能保证送达」。 不能,它只报告问题,不修问题。
  2. 以为「ICMP 是传输层」。 不是,它没有端口,装在 IP 里。
  3. 以为「禁用 ICMP 更安全」。 会连带废掉 PMTUD,导致「小包通、大包不通」。
自测三问(点开对答案) 1. ICMP 的作用是什么? —— **在 IP 层报告错误和异常**:不可达、超时、包太大等。 2. ICMP 为什么不算传输层协议? —— **它没有端口,也不承载应用数据**,只是 IP 的附带功能。 3. ping 和 traceroute 分别用哪个 ICMP 类型? —— **ping 用 8 和 0(请求与应答),traceroute 用 11(超时)。**

下一节把 ICMP 的主要消息列一遍。

相关笔记