路由综合排障:证据链、随机故障与掌握标准
验证:未记录
- 适用版本
- 未记录
- 验证范围
- 尚未登记验证记录。
目标不是记住命令,而是能回答:谁发给谁、选了哪条路径、在哪个位置丢失、为何回不来、怎样最小变更恢复。配合 Linux Troubleshooting 使用。
1. 固定排障顺序#
| 步骤 | 证据 | 要排除的问题 |
|---|---|---|
| 明确流量 | 源/目的 IP、协议、端口、命名空间、IPv4/IPv6、时间 | 查错主机、查错 namespace、DNS/代理改变目的 |
| 本端接口 | ip -br address、ip -s link |
地址、链路、丢包、MTU(最大传输单元)错误 |
| 本端选路 | ip route get TARGET from SOURCE、ip rule、ip route show table all |
错表、错网卡、错网关、黑洞路由 |
| 下一跳 | ip neigh;必要时抓 ARP/NDP |
邻居失败;不能把静态错误邻居当路由错误 |
| 中间转发 | ip_forward、路由器 FORWARD 规则和计数 |
路由器未转发、过滤规则拦截 |
| 目标服务 | ss -lntp、目标本机请求、应用日志 |
没监听、仅 loopback、应用鉴权或负载问题 |
| 回程 | 从响应源地址执行反向 route get |
多网卡、源地址策略、rp_filter(反向路径检查) |
| 连接/报文大小 | conntrack -L、包长与重传、IPv6 对照 |
NAT 旧映射、PMTUD 黑洞、双栈差异 |
ARP = IPv4 地址解析;NDP = IPv6 邻居发现;PMTUD = 路径 MTU 发现。DNS(域名系统)失败时先对照 getent ahosts 与指定 IP;HTTPS 使用 curl --resolve 保留证书主机名,不用 -k 掩盖另一类故障。
# 在故障主机只读执行;填实际已批准的源/目的与网卡。
export SOURCE_IP='REPLACE_SOURCE_IP'
export TARGET_IP='REPLACE_TARGET_IP'
export INTERFACE='REPLACE_INTERFACE'
ip -4 route get "$TARGET_IP" from "$SOURCE_IP"
ip -4 rule
ip -4 route show table all
ip neigh show dev "$INTERFACE"
sudo tcpdump -ni "$INTERFACE" "host $TARGET_IP and tcp port 443"tcpdump 某处抓到 SYN 只证明到达该抓包点;内核后续检查仍可丢弃。客户端没有 SYN-ACK 时,沿路径向后找最后能看到包的点,再反向检查回包,而不是一次放宽所有防火墙。
2. 随机故障考核#
下载 lab.sh、fault.sh,安装 iproute2、Python 3、curl、nftables、iputils-ping、tcpdump。只用本实验独立环境,不叠加前几篇的额外规则。
sudo bash lab.sh connected
sudo bash fault.sh inject
# 每次都测三个维度;某些故障仍允许小 HTTP 请求。
sudo ip netns exec lr-app curl --noproxy '*' --connect-timeout 2 --max-time 3 http://10.20.0.10:8080/health
sudo ip netns exec lr-app ping -c 1 -W 2 -s 56 10.20.0.10
sudo ip netns exec lr-app ping -c 1 -W 2 -M do -s 1400 10.20.0.10脚本随机选择:去程缺失、回程缺失、转发关闭、FORWARD 丢弃、/32 黑洞、错误邻居、MTU 黑洞。先不要看答案,也不要立即运行 restore。 自己检查三端接口、路由、规则、邻居和抓包,写出下列记录:
故障流:source → destination:port / namespace / 时间
现象:HTTP、小 ping、大 DF ping 各自结果
定位:在哪一跳/哪一层,以及两项独立证据
修复:应执行的最小变更及其影响范围
验收:原故障请求恢复,其他既有路径没有退化完成诊断后核对答案,由脚本按原始故障精确恢复,再执行三个验收请求:
sudo bash fault.sh show
sudo bash fault.sh restore
sudo ip netns exec lr-app curl --noproxy '*' --fail --max-time 3 http://10.20.0.10:8080/health
sudo ip netns exec lr-app ping -c 1 -W 2 -M do -s 1400 10.20.0.10
sudo bash lab.sh cleanup重复直到七类均完成并保存记录。若你已手工修复部分项目,restore 可能因规则不存在而报错;直接清理并重建实验基线,不去改宿主机“凑成功”。
3. 容器、云网络与隧道的分界#
- 容器有独立网络命名空间,宿主机
ip route不等于容器路由;在容器及宿主机分别取证。Kubernetes 还要检查 CNI(容器网络接口)、Service 转发和 NetworkPolicy。 - EC2 主机选路之后才进入 AWS 子网转发路径;Linux main 表正确,不证明 VPC 路由、SG/NACL 或云源/目标检查正确。参见 VPC 流量路径。
- VPN/隧道还需区分封装外层下一跳与内层业务路由;确认对端路由、允许的网段、加密协商和封装开销。
- 路由表正确却逐渐出现大量连接失败,应检查端口、conntrack 容量与应用连接池;不要直接增大内核参数替代容量定位。
4. 达标标准与进阶边界#
完成以下事项,才能认为掌握了日常 Linux 主机路由与静态/策略路由排障:
- 不看答案定位七类随机故障,并解释为什么失败。
- 独立建立双网卡源地址策略;在 strict rp_filter 下请求和响应仍走预期路径。
- 能解释 SNAT/DNAT 前后的地址、端口、FORWARD 匹配及 conntrack 状态。
- 单独验证 IPv4/IPv6,复现小包通、大包失败并恢复。
- 在自己的目标发行版完成持久化、重启和回退,保留前后证据。
动态路由 BGP/OSPF、VRF(虚拟路由隔离)、ECMP(等价多路径)、复杂隧道及运营商网络属于进一步专项:它们可能改变路由来源或查表环境。知道当前处于哪个表/VRF、路由由谁下发,是排障起点;不能把本系列通过等同于掌握所有网络架构。