模块四 · 网络层:控制平面
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 字节 | 内容随类型变化 |
| 数据 | 不定 | 差错报告时会带回原始包的一部分 |
常见的类型 / 代码
| 类型 | 名称 | 用途 |
|---|---|---|
| 0 | Echo Reply | ping 的应答 |
| 8 | Echo Request | ping 的请求 |
| 3 | Destination Unreachable | 目标不可达 |
| 3 / 代码 0 | 网络不可达 | 找不到去该网络的路 |
| 3 / 代码 1 | 主机不可达 | 找到了网络,但主机不在 |
| 3 / 代码 3 | 端口不可达 | 主机在,但那个端口没人监听 |
| 3 / 代码 4 | 需要分片但设置了 DF | 包太大,且不允许分片 |
| 11 | Time Exceeded | TTL 减到 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响应;端口连通不是业务可用的充分条件:
Test-NetConnection example.com -Port 443ICMP 的两难:安全与可用性的冲突
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 题 · 先自己答,再展开对照
ping用的是 TCP 还是 UDP?为什么这个问题的答案会影响你对"ping 通"的理解?都不是,ping用的是 ICMP。 ICMP 是网络层的辅助协议,没有端口号。这解释了为什么"ping 通但端口连不上"完全可能 —— 它们走的是不同协议、由不同规则处理,一个通不代表另一个通。tracert是怎么知道路径上每一台路由器的地址的?靠让每一跳的路由器"犯一次错"。 它先发 TTL=1 的包,第一台路由器把 TTL 减到 0、丢弃并回一个 ICMP 超时(类型 11)报文,地址就暴露了;然后发 TTL=2 的包,让第二台路由器做同样的事……如此递增,就把整条路径上的路由器地址逐个套了出来。上一题里,如果某台路由器不回 ICMP,
tracert会显示什么?那一段就一定不通吗?显示* * *(超时)。 但那一段不一定不通 —— 可能只是那台路由器配置了不发送 ICMP 超时报文,包本身仍然被正常转发了。真正可疑的模式是"从某一跳起之后全部是*,而且目标最终不可达",这时才说明那一段可能确实有问题。你在本机执行
tracert 8.8.8.8,看到第 1 跳到第 5 跳的回复地址全都是8.8.8.8。这说明什么?不能单独确定原因。路由环路、隧道、回包选源和代理处理等都可能让地址重复;TUN环境下可怀疑代答,但需退出代理对照或抓包。为什么很多服务器 ping 不通但网页能正常打开?
ICMP策略与TCP/UDP应用不同;应测目标端口,并继续验证TLS与HTTP等应用响应。不能把端口可连接直接等同于服务正常。企业防火墙完全屏蔽外部 ICMP 会带来什么副作用?
会破坏路径 MTU 发现(PMTUD)。 因为 PMTUD 依赖 ICMP 的"需要分片但设置了 DF"(类型 3 代码 4)报文通知发送方把包改小。屏蔽之后发送方收不到通知,就会一直发大包、一直被丢弃,表现为网页能打开但大文件传不完、某些网站打不开 —— 这种故障现象和原因看起来毫不相关,极难排查。"ping 通了"能证明哪些事情?不能证明哪些事情?
能证明:到目标的 ICMP 路径是通的、基本的往返延迟大概是多少。
不能证明:目标端口开着(可能是 ICMP 通但服务挂了)、带宽够用(ping 包只有 32 字节)、延迟稳定(单次测量不代表持续表现)、路径上每台设备的情况。"ping 通"是一个非常弱的信息。
参考资料与适用范围
- RFC 792:IPv4 ICMP Echo与差错类型
- RFC 1812 §4.3、§5.3、§7:ICMP选源、TTL与路由
- RFC 1191:IPv4路径MTU发现
- Microsoft tracert:探测TTL与超时的含义
修订核对日期:2026-10-13。规则按所列协议与实现范围理解;文中的原始命令输出是历史观察,不表示本次重新实测。跨版本、代理/隧道及不同捕获位置需要另行核对。