← 网络基础学习第 32 / 55 章基础40 分钟

模块四 · 网络层:控制平面

ICMP:ping 与 tracert 的原理

ping 和 tracert 是最常用的两个网络命令,但很多人不知道它们靠的是同一个协议 —— ICMP。本章会拆开它们的原理,并且给出一个反面案例:本机的 tracert 结果是坏的,而且坏得很有教育意义。

本章要解决的问题:ping 和 tracert 是最常用的两个网络命令,但很多人不知道它们靠的是同一个协议 —— ICMP。本章会拆开它们的原理,并且给出一个反面案例:本机的 tracert 结果是坏的,而且坏得很有教育意义。

本章的证据来源:历史实测记录(ping、tracert 对多个目标的实际输出)。报文类型定义出自 RFC 792。

先从一个例子理解概念

你想知道某个地址能不能回应,或者包在哪一步没继续走。先分清工具发了什么,以及无回复到底能说明什么。

通知与诊断:ICMP

ICMP是IP层使用的控制消息,能传差错通知和诊断探测。它与网页服务不是同一个协议,所以ICMP被拒绝不等于网页必然打不开。

问一下再等回答:ping

ping通常发送Echo Request,即“请回应”,等待Echo Reply。超时只表示限定时间没等到所需回复,原因可能不止一种。

一个来回用了多久:RTT

RTT(往返时间)是探测发出到回复返回所用的时间,包含两个方向和处理、排队等。不能把它直接当单程传播时间。

逐步试出路径:tracert

tracert是Windows的路径探测工具,逐步增加探测包的TTL,尝试让沿途路由器通知其位置。星号表示那次没收到预期回复,不自动证明那台设备不转发。

下面再用这些概念看原理、命令和结果。规范与官方资料列在本章末尾,类比只帮助理解,不代替协议规则。

为什么需要 ICMP

IP 协议本身有一个很大的缺陷:它不保证送达,也不报告失败。

一个包发出去之后,可能遇到这些情况:

  • 目的主机不存在
  • 目的端口没人监听(TCP通常回RST;UDP可触发ICMP端口不可达)
  • 中间某台路由器找不到去目的地的路
  • TTL 减到 0 被丢弃
  • 包太大但设置了禁止分片

IP 层自己不负责通知发送方。 那么发送方怎么知道出了问题?

答案是另设一个协议专门做这件事:ICMP(Internet Control Message Protocol,互联网控制报文协议)。

ICMP 有两个用途:

用途说明例子
差错报告告诉发送方"你的包出问题了"目标不可达、TTL 超时、需要分片
网络诊断主动发探测包,测量连通性和路径ping、tracert

注意 ICMP 不是传输层协议。 它没有端口号,不承载应用数据。它装在 IP 包里(IP 头里的协议字段 = 1),本身是"网络层的辅助协议"。

ICMP 报文长什么样

ICMP 报文头只有 8 字节(《全景与基础》模块实测的那个 28 字节里,8 就是它):

字段长度作用
类型1 字节主要看这个
代码1 字节同一类型下的细分
校验和2 字节校验 ICMP 报文本身
类型相关字段4 字节内容随类型变化
数据不定差错报告时会带回原始包的一部分

常见的类型 / 代码

类型名称用途
0Echo Replyping 的应答
8Echo Requestping 的请求
3Destination Unreachable目标不可达
3 / 代码 0网络不可达找不到去该网络的路
3 / 代码 1主机不可达找到了网络,但主机不在
3 / 代码 3端口不可达主机在,但那个端口没人监听
3 / 代码 4需要分片但设置了 DF包太大,且不允许分片
11Time ExceededTTL 减到 0(tracert 靠它工作)

ping 的原理

ping 做的事情非常简单:发一个 ICMP Echo Request(类型 8),等一个 Echo Reply(类型 0)。

你的电脑                          目标
   |--- ICMP 类型 8 (Echo Request) -->|
   |<-- ICMP 类型 0 (Echo Reply) -----|

因为顺序是"发—收",所以能测出往返时间(RTT,Round-Trip Time),也就是 ping 输出里的 time= 那个数字。

实测:《全景与基础》模块那个报错的真身

IPv4路由器遇到超过出口MTU且DF=1的包,通常丢弃并按规则发送ICMP类型3代码4。Windows的本地协议栈也可在包尚未发出时检查到出口限制并向ping返回错误。

所以 Packet needs to be fragmented but DF set 这行文本不能单独证明收到了远端ICMP。需要抓包区分本地失败与收到ICMP;ICMP又受过滤、限速和不得对某些报文产生差错等规则影响。RFC 1191 §4、RFC 1812 §4.3.2

tracert 的原理:用 TTL 逼路由器暴露自己

tracert(Linux 上叫 traceroute)要做的事是:画出从你到目标经过的每一台路由器。

它用了一个很巧妙的办法,而这个办法的根基正是上一章的 TTL:

第 1 步:发一个 TTL = 1 的包
         → 第一台路由器收到,TTL 减 1 变成 0
         → 丢弃,并回一个 ICMP 类型 11(超时)
         → 你就知道了第 1 跳的地址

第 2 步:发一个 TTL = 2 的包
         → 第一台路由器减到 1,转发
         → 第二台路由器减到 0,回 ICMP 类型 11
         → 你就知道了第 2 跳的地址

第 3 步:TTL = 3 …… 以此类推

支持并允许发送ICMP超时的路由器可返回通知(可能被过滤或限速),这个报错恰好泄露了它的地址。这就是 tracert 能显示路径的原因。

如果某个路由器不回了呢? 输出里就会出现 * * *(超时)—— 可能由回包过滤、限速、探测丢失或设备策略造成,但包可能仍然被正常转发了。

实测:本机的 tracert 是坏的

原教程记录:对223.5.5.5探测时只显示一跳;对8.8.8.8的多个跳数探测显示相同地址;另一个目标连续超时。这些是历史输出,不能直接认定“真实网络不可能”。

公网地址可以属于邻接设备;同一回复地址重复可能与路由环路、隧道、回包源地址选择或代理处理有关。*仅表示该次探测未收到预期回复,不证明设备停止转发。

本机当时存在TUN代理,代理代答是合理怀疑,尚需对照或抓包确认。ping看到的响应TTL属于返回包,tracert递增的是请求TTL;两者并不是同一条已知方向、已知初始TTL的路径,不应直接比较成矛盾。

复现时可在可恢复的环境中退出代理再比较,并记录接口、路由和两端抓包。保留结果,分别列出可能原因,避免先宣布工具结果“全错”。Microsoft tracert、RFC 1812 §4.3.2.4

为什么 ping 不通不代表服务不可用

这是《全景与基础》模块埋下的伏笔,现在可以完整回答了。

原因一:很多服务器主动屏蔽 ICMP。

出于安全和减少负载的考虑,大量服务器和防火墙会直接丢弃 ICMP 报文。所以:

ping example.com      →  超时(ICMP 被丢弃)
curl https://example.com  →  正常返回网页(TCP 没被屏蔽)

同一个目标,一个通一个不通,因为用的是两个不同的协议。

原因二:CDN 和云服务的行为不一致。

大型网站通常有一堆服务器,有的响应 ping、有的不响应。所以 ping 一个域名 得到的结果可能时好时坏 —— 因为你每次 ping 到的可能不是同一台机器。

正确的判断方式:先测对应端口,再验证应用协议,例如TLS握手与HTTP响应;端口连通不是业务可用的充分条件:

示例powershell
Test-NetConnection example.com -Port 443

ICMP 的两难:安全与可用性的冲突

ICMP 因为太好用,也被滥用:

滥用方式原理
ping 扫描快速 ping 一个网段,找出哪些主机在线
ICMP 隧道把数据藏在 Echo Request 的"数据"字段里,绕过只检查 TCP/UDP 的防火墙
放大攻击伪造源地址向广播地址发 ping,让大量主机把回应发给受害者

所以很多企业防火墙的策略是:屏蔽外部进来的 ICMP。

但这会引发《全景与基础》模块讲过的那个问题:

防火墙屏蔽了 ICMP
  → 发送方收不到「需要分片但设置了 DF」的通知(那是 ICMP 类型 3 代码 4)
  → 发送方一直发大包、一直被丢弃
  → 表现:网页能开,但大文件传不完、某些网站打不开

这是一个真实的两难:屏蔽 ICMP 提升了安全性,却破坏了路径 MTU 发现(PMTUD)机制。

实践中的折中做法:屏蔽大部分 ICMP 类型,但放行类型 3 和类型 11(也就是"不可达"和"超时"这两类差错报告)。这样既不让外部用 ping 扫描你,又不会破坏 PMTUD。《抓包与排错》模块讲排错时会再提到这个配置问题。

常见误解

误解一:"ping 是 TCP 或 UDP 的一种"

都不是。ping 用的是 ICMP,它是网络层的辅助协议,没有端口号。这也是为什么"ping 通了但端口连不上"完全可能发生。

误解二:"tracert 显示超时说明那一段不通"

不一定。中间路由器可能只是配置了不回应 ICMP,包本身照样正常转发。后续全部超时也只是线索;结合最终目标服务是否可用、协议与回程策略检查,不能由星号直接定位故障。

误解三:"ping 通了说明网络正常"

只能说明ICMP 这条路径通。它不说明:

  • 目标端口开着(可能是 ICMP 通但服务挂了)
  • 带宽够(ping 包只有 32 字节,测不出带宽)
  • 延迟稳定(单次 ping 的延迟不能代表持续表现)

误解四:"屏蔽 ICMP 是纯粹的好事"

它会破坏路径 MTU 发现,导致前面说的那种"网页能开、大文件传不完"的诡异故障,而且极难排查(因为现象和原因看起来毫不相关)。安全和可用性在这里是要权衡的,不是单向取舍。

本章小结

结论性质
IPv4 ICMP包含差错报告与Echo诊断,无TCP/UDP端口RFC 792
ping显示本次往返耗时和收到回复时的TTL工具观察
tracert递增探测TTL,未回复可由过滤或限速造成工具规则
重复地址或短路径不能单独证明代理代答推断限制
本地MTU错误与远端ICMP通知需抓包区分证据限制
PMTUD依赖相应差错通知,安全策略需按类型和协议版本设计协议机制
TCP端口成功之后仍需检查TLS/应用响应诊断层次

自测题

7 题 · 先自己答,再展开对照

  1. ping 用的是 TCP 还是 UDP?为什么这个问题的答案会影响你对"ping 通"的理解?
    都不是,ping 用的是 ICMP。 ICMP 是网络层的辅助协议,没有端口号。这解释了为什么"ping 通但端口连不上"完全可能 —— 它们走的是不同协议、由不同规则处理,一个通不代表另一个通。
  2. tracert 是怎么知道路径上每一台路由器的地址的?
    靠让每一跳的路由器"犯一次错"。 它先发 TTL=1 的包,第一台路由器把 TTL 减到 0、丢弃并回一个 ICMP 超时(类型 11)报文,地址就暴露了;然后发 TTL=2 的包,让第二台路由器做同样的事……如此递增,就把整条路径上的路由器地址逐个套了出来。
  3. 上一题里,如果某台路由器不回 ICMP,tracert 会显示什么?那一段就一定不通吗?
    显示 * * *(超时)。 但那一段不一定不通 —— 可能只是那台路由器配置了不发送 ICMP 超时报文,包本身仍然被正常转发了。真正可疑的模式是"从某一跳起之后全部是 *,而且目标最终不可达",这时才说明那一段可能确实有问题。
  4. 你在本机执行 tracert 8.8.8.8,看到第 1 跳到第 5 跳的回复地址全都是 8.8.8.8。这说明什么?
    不能单独确定原因。路由环路、隧道、回包选源和代理处理等都可能让地址重复;TUN环境下可怀疑代答,但需退出代理对照或抓包。
  5. 为什么很多服务器 ping 不通但网页能正常打开?
    ICMP策略与TCP/UDP应用不同;应测目标端口,并继续验证TLS与HTTP等应用响应。不能把端口可连接直接等同于服务正常。
  6. 企业防火墙完全屏蔽外部 ICMP 会带来什么副作用?
    会破坏路径 MTU 发现(PMTUD)。 因为 PMTUD 依赖 ICMP 的"需要分片但设置了 DF"(类型 3 代码 4)报文通知发送方把包改小。屏蔽之后发送方收不到通知,就会一直发大包、一直被丢弃,表现为网页能打开但大文件传不完、某些网站打不开 —— 这种故障现象和原因看起来毫不相关,极难排查。
  7. "ping 通了"能证明哪些事情?不能证明哪些事情?
    能证明:到目标的 ICMP 路径是通的、基本的往返延迟大概是多少。
    不能证明:目标端口开着(可能是 ICMP 通但服务挂了)、带宽够用(ping 包只有 32 字节)、延迟稳定(单次测量不代表持续表现)、路径上每台设备的情况。"ping 通"是一个非常弱的信息。

参考资料与适用范围

修订核对日期:2026-10-13。规则按所列协议与实现范围理解;文中的原始命令输出是历史观察,不表示本次重新实测。跨版本、代理/隧道及不同捕获位置需要另行核对。

正文源自 m4-03-ICMP与ping.md · 共 12 节 · 7 道自测题