ping 通了,服务也可能不通
一句话总结
ping 只能证明到 IP 层为止的可达性。它既不能证明上面的端口,也不能证明更上面的应用,甚至不能证明大数据包能否通过。
为什么需要这个
“ping 得通但连不上”不是矛盾,而是正常状态。ping 只是收发 ICMP echo。TCP 8080 是否开放是完全不同的问题,即使端口开放,应用也可能返回 5xx。
反方向也很重要。ping 失败,服务也可能完好无损。 因为很多组织会屏蔽 ICMP echo。所以“ping 不通,服务器挂了”这种判断是危险的。
工作原理
三个工具的作用各不相同。
| 工具 | 看什么 | 本环境中的注意事项 |
|---|---|---|
ping |
到目的地的 IP 往返是否可行 | 可用(ping_group_range 允许) |
traceroute |
能走到哪一跳 | 默认(UDP)和 -I(ICMP)可用,-T(TCP)因权限不足而失败 |
mtr |
持续观察逐跳丢包率和延迟 | 默认(ICMP)和 --tcp 可用,--udp 输出的跳行为空 |
这张表是在本实验 Pod 中实测的结果(2026-11-06)。Pod 没有 CAP_NET_RAW,ICMP 模式却可以运行——如果 net.ipv4.ping_group_range 允许,Linux 的 ICMP 数据报套接字(“ping 套接字”)无需 raw 套接字也能发送 Echo,而本 Pod 中该值为 0 2147483647。同一个工具在不同模式下使用的套接字不同,因此与“没有特权,所以 ICMP 不能用”之类的泛泛之谈相比,在该环境中亲自运行得到的结果才是对的。
traceroute 的原理是把 TTL 从 1 开始逐个增大发送。TTL 变为 0 处的路由器会返回 ICMP time exceeded,其源地址就是那一跳的身份。所以 traceroute 不是“查询路径”的工具,而是“故意让数据包失败来收集应答”的工具。
* * * 不是故障。 只是那一跳的路由器限制或不生成 ICMP 应答而已。判断规则如下。
- 只有中间跳出现丢包,而最终目的地没有丢包,很可能是 ICMP rate limiting
- 从某一跳开始延迟急剧增加,那一段就是瓶颈
- 最后几跳丢包增加,很可能是真正的问题
ping 漏掉的东西:路径 MTU
最棘手的例子是 MTU 黑洞。ping 的默认载荷是 56 字节,总能通过。可是应答稍微变大的 API 就会直接卡住。没有报错,就是卡住。因为只有超过阈值大小的数据包会消失,症状会随大小而不同。
用设置了禁止分片位的 ping 来确认。
ping -M do -s 1472 -c 1 10.20.0.5
# From 10.0.1.1 icmp_seq=1 Frag needed and DF set (mtu = 1420)
-s 的值加上 28(ICMP 8 + IP 20)就是实际 MTU。用二分查找找出能通过的最大值,就得到路径 MTU。
使用隧道时,有效 MTU 会减少相当于开销的大小。
| 封装 | 额外头部 | 有效 MTU | 推荐 MSS 钳制 |
|---|---|---|---|
| PPPoE | 8 | 1492 | 1452 |
| GRE | 24 | 1476 | 1436 |
| VXLAN (IPv4) | 50 | 1450 | 1410 |
| WireGuard (IPv4) | 60 | 1440 | 1400 |
| IPsec ESP + NAT-T | 约 81 | 1419 | 1379 |
在现场遇到的样子
“一开 VPN,只有某些网站打不开。” 这是隧道开销使有效 MTU 减小、却没有 MSS 钳制的典型情况。小页面能打开,大页面卡住。ping 100% 成功。
在云上把 ICMP 全部封掉后运行 traceroute 的情况。 结果全是 * * *,很容易得出“路径断了”的结论。这时用 TCP 模式的 traceroute(-T -p 443)或 nc -zv 直接敲目标端口更准确。不过 -T 要自己构造 SYN,需要 raw 套接字权限——在像本实验 Pod 这样没有 CAP_NET_RAW 的地方会因权限不足而失败(实测),所以要用 nc -zv 或 curl 去敲。
在哪里测量会改变答案
即使用同样的工具测量同样的目标,结论也会因在哪里测量而不同。如果不注意这一点,就会拿着在不同地方测得的数值争论不休。
在我的笔记本上测得的值不是我们服务的值。 办公室线路、VPN、家里的路由器全都夹在路径上。它既不同于用户的体验,也不同于服务器之间的通信。所以第一原则是在与出问题的地方相同的位置测量;做不到时,要把测量位置一起写进结果。
只在一侧测量只能看到一半。 正如前面的课程所见,去程有路而回程没路的情况很常见,这时从一侧看到的 traceroute 是正常的。从两侧互相测量,不对称就会立刻显现。
路径并不每次都一样。 在有多条路径的区段,不同的流会走不同的路,所以 traceroute 跑两次,跳会不一样。只在特定流上出现丢包的问题,一次测量是抓不到的。
测量本身会产生负载。 在已经饱和的链路上挂上 mtr,它本身就会增加丢包。而且正如前面的课程所说,在已经出问题的系统上,诊断命令把故障放大的事确实会发生。
最后,写下测量的时间。 网络问题会随时间出现又消失,没有时间的测量值几天后就毫无依据。提前测好正常时的数值也很有价值,原因相同。没有可比较的东西,就无法判断现在的数值是好是坏。
下一个实验要做的事
确认接口和路由,从 ping 统计中读取丢包率和 RTT,用本环境中可用的模式运行 traceroute 和 mtr。最后亲自比较 ICMP 可以而 TCP 怎么样,并整理成表。