TT Lab
博客 开始
学习 学习路径 课程

Linux 网络诊断

把「连不上」这条报障拆成四层

在 TT Lab 中继续学习

一句话总结

网络故障诊断的 90%,先确定“卡在哪一层” 就解决了。不先确定层就打开工具,只会白白浪费时间。

为什么需要这个

接到“API 连不上”的报告时,人们通常会这样做:ping 一下,打开防火墙规则看看,检查 DNS,翻应用日志。没有顺序。结果同一个地方看了两遍,没看过的地方一直没看。

熟练的人做法不同。先锁定层,然后只用适合那一层的一个工具。

工作原理

实际工作中用到的层不必是 OSI 七层,四层就足够了。

层 问题 检查工具 失败时的样子
名称 这个名称解析成哪个 IP getent hosts, dig, resolvectl query Name or service not known
可达 数据包能否到达那个 IP ping, traceroute -U, ip route Network is unreachable、无响应
端口 那个 IP 的那个端口是否开放 nc -zv, ss -ltn, curl --connect-timeout Connection refused / timed out
响应 端口开着,但回答不对劲 curl -v, curl -w、应用日志 5xx、缓慢、响应体错误

关键在于:每一层的失败都有各自不同的样子。 只要准确读出这个样子,层就确定了。

记住下面这张按 errno 区分的判别表,光看报告里的那句话就能分出层。

消息 errno 实际发生了什么 先看哪里
Name or service not known EAI_NONAME 名称解析失败,连套接字都没打开 nsswitch.conf、resolv.conf、/etc/hosts
Network is unreachable ENETUNREACH 路由表中没有路径 ip route,尤其是 IPv6 路由
No route to host EHOSTUNREACH 收到 ICMP unreachable 或 ARP 无响应 目标主机电源、ARP、REJECT 规则
Connection refused ECONNREFUSED 目标返回了 RST 目标主机上的进程及其绑定地址
Connection timed out ETIMEDOUT SYN 重传全部用完仍无响应 防火墙 DROP、安全组、accept 队列

这里最常见的错误是把 refused 归咎于防火墙。refused 表示收到了 RST;既然收到了 RST,就证明数据包已经通过了路由、安全组、NAT 和网络策略。实际环境中的防火墙几乎总是 DROP 策略,被拦的端口会表现为 timeout。看到 refused 却去翻防火墙,等于重新检查一道已经通过的关卡。

时间也是证据。在 Linux 默认值(net.ipv4.tcp_syn_retries=6)下,无响应的连接会在 1+2+4+8+16+32+64 = 127 秒后放弃。如果应用的超时写的是 30 秒,实际却在 127 秒后才失败,就说明这个超时设置没有生效。

在现场遇到的样子

“本地可以,只有远程不行。” 十有八九是绑定地址的问题。如果 ss -ltnp 显示在 127.0.0.1:8080 上监听,那么发往 Pod IP 的连接会被内核用 RST 拒绝——也就是 refused。反过来,如果连 Pod IP 也是 timeout,这时才开始查网络策略。这一次分岔就能把排查范围缩小一半。

下一步要做的事

从最底层的名称解析开始。亲手确认 /etc/hosts 和 nsswitch.conf 为什么优先于 dig,以及为什么 dig 完全不看这两者。