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

ICMP 用「类型 + 代码」两个数字区分几十种消息,类型说大类、代码说细分。 排查时最常遇到的是 3(不可达)、11(超时)、8/0(回显)。

📝 本节和前面几节的关系

5.4.1 讲了它的定位,这一节讲它的「词汇表」。 4.5.3 的 PMTU 用的是类型 3 的代码 4,这里会再遇到。

一、类型和代码的分工

两个字段,八位加八位:类型决定「哪一类消息」,代码决定「这一类里的第几种」。

类型 名称 典型代码
0 回显应答 0
3 目标不可达 0 网络、1 主机、3 端口、4 需分片
8 回显请求 0
11 超时 0 TTL 归零、1 重组超时

第二行那四个代码值得背下来:因为「不可达」是最常见的错误, 而「哪一种不可达」直接决定你去查什么。 「网络不可达」多半是路由问题(没有去那个网段的路); 「主机不可达」多半是对方关机或 ARP 失败;「端口不可达」说明机器活着但服务没起。

二、排障时怎么用

把「症状」和「类型代码」对上,能省很多时间:

症状 ICMP 说什么 往哪儿查
立刻报不可达 3 的 0 或 1 路由、对方在线
一直超时 没有 ICMP 中间被丢或被拦
能通但服务连不上 3 的 3 端口、防火墙
小包通大包不通 3 的 4 被拦 PMTU 黑洞

第二行那格「没有 ICMP」才是最常见的:因为大部分防火墙的策略是「静默丢弃」, 所以你「什么都收不到」。 这也是「超时」比「不可达」更常见的原因。 第三行那个「端口不可达」很有用: 它证明「网络通、机器活着」,只是「服务没起」——一下子把排查范围缩到应用层。

三、为什么不建议全禁

「为了安全把 ICMP 全禁掉」是个常见做法,但它有代价:

禁掉什么 连带废掉什么 后果
全部 ICMP PMTUD、traceroute 大包不通、路径查不到
只禁 8(请求) 只是不能 ping 你 影响最小

第二行是「折中方案」:禁掉「别人 ping 我」,但保留「我报告错误」的能力, 这样既不暴露「我在线」,也不破坏 PMTUD。 这是大多数规范的推荐做法。 第一行的后果在 IPv6 里更严重:因为 IPv6 不允许中间路由器分片, ICMPv6 的「包太大」是唯一的调整机制——禁了它,大包直接不通,连「偷偷分片」的退路都没有。

四、动手 Demo:ICMP 的主要类型

把六种主要类型列出来,看它们各自解决什么问题。 注意类型 3 的四个代码,它们对应四种完全不同的故障。

types = {0: '回显应答', 3: '目标不可达', 5: '重定向',
         8: '回显请求', 11: '超时', 12: '参数问题'}
for k in sorted(types):
    print(k, types[k])

实跑输出:

--------------------------------------------------------------------
ICMP 的主要类型
--------------------------------------------------------------------
**ICMP 靠「类型 + 代码」两个数字区分几十种消息**:**类型说大类,代码说细分。**

  类型       名称               典型用途
  -------------------------------------------------
  **0**      **回显应答**       **ping 的回复**
  **3**      **目标不可达**     **细分 15 种代码**
  **5**      **重定向**         **告诉你换个网关**
  **8**      **回显请求**       **ping 的发问**
  **11**     **超时**           **TTL 归零**
  **12**     **参数问题**       **首部有错**

**第二行那个「细分 15 种代码」值得展开**:
**代码 0 是网络不可达、1 是主机不可达、3 是端口不可达、4 是「需要分片」。**
**4.5.3 讲的 PMTU 发现,靠的就是代码 4。**

**第五行「超时」是 `traceroute` 的原理**:
**故意发 TTL=1 的包,第一台路由器减到 0 就回一个超时**——**于是它的地址就暴露了。**
**再发 TTL=2,就暴露第二台。**
**所以 traceroute 不是「探测」,是「骗设备自己报地址」。**

**这张表还有一个用法**:
**看防火墙日志时,先看类型再看代码**——
**「type 3 code 3」是「端口不通」(服务没起),「type 3 code 1」是「主机不通」(机器不在)。**
**这两种故障的处理方式完全不同。**

类型号和「谁发的」没有关系:0 和 8 是主机发的,3 和 11 主要是路由器发的, 但协议上谁都能发(这也是 ICMP 可以被伪造的原因)。 「参数问题(12)」很少见,但出现就很严重:它表示「首部有字段不合法」, 通常意味着「设备不兼容」或者「包被中间设备改坏了」。 记住这张表最实用的方式是「按排查顺序记」: 先看有没有 3(不可达)→ 再看有没有 11(超时)→ 都没有就说明「被静默丢弃」。 三种情况的处理方式完全不同。

30 秒实验

  1. 想一下:为什么「超时」比「不可达」更常见?
  2. 想一下:类型 3 的代码 3 说明什么?
  3. 想一下:只禁 ping 请求和全禁 ICMP 有什么区别?

常见误区

  1. 以为「ICMP 只有 ping 用」。 错误报告全靠它,PMTUD、traceroute 都依赖它。
  2. 以为「收到不可达就是对方关机」。 还有四种可能,要看代码。
  3. 以为「禁 ICMP 一定更安全」。 会破坏 PMTUD,造成「大包不通」。
自测三问(点开对答案) 1. ICMP 用什么区分不同的消息? —— **类型(大类)加代码(细分)**,各占 8 位。 2. 类型 3 的代码 4 表示什么? —— **需要分片但 DF 被置位**,PMTU 发现就靠它。 3. 为什么「超时」比「不可达」更常见? —— **因为很多设备静默丢弃,不回任何 ICMP**。

下一节看几条「已经没人用」的 ICMP 消息。

相关笔记