Linux 路由表:默认网关、转发与回程实战

现有命令速查里的 ip route 只能展示路由。本篇通过一次应用访问另一网段后端的故障排查,理解主机如何选择下一跳、为什么有路由仍不通。实验仅操作隔离的网络命名空间,不改宿主机默认网关。

学习顺序与验收#

这是一组从基础到日常生产排障的实践文档;先完成每篇实验,再做综合考核。阅读不等于掌握,以能独立定位、修复、验证和回退为准。

顺序 文档 验收目标
1 本页基础实验 去程、转发、回程和最长前缀
2 多网卡与策略路由 根据源地址选择出口
3 反向路径检查 修好非对称回程后恢复严格检查
4 防火墙与 NAT 区分路由、FORWARD 和地址转换
5 IPv6 与 MTU 双栈及报文大小相关故障
6 持久化与安全回退 目标发行版重启与恢复验收
7 综合故障考核 七类随机故障与取证记录

1. 先看懂一张路由表#

default via 10.10.0.1 dev eth0 metric 100
10.10.0.0/24 dev eth0 proto kernel scope link src 10.10.0.10
10.20.0.0/24 via 10.10.0.1 dev eth0 metric 200
字段 含义
10.10.0.0/24 直连网段,直接通过 eth0 找到邻居
via 10.10.0.1 下一跳网关的地址,不是最终目标地址
dev eth0 从哪个接口发送
src 10.10.0.10 未指定源地址时,路由建议使用的源地址;不是源地址匹配条件
default IPv4 的 0.0.0.0/0,没有更具体匹配时才使用
metric 在同一表、相同前缀等可比路由中通常优先较小值;不能盖过更具体的前缀
proto kernel / scope link 由内核生成;目的网段直接在链路上

普通目标路由先比前缀长度:/32 > /24 > /0。下一跳通常必须在当前接口可直接到达的链路内;设置网关不会自动把它变成能转发流量的路由器。ip route get 计算本机选路,不发送探测包,也不证明对端可达。ip-route 手册

# 以下只读命令可以在普通 Linux 主机执行。
ip -br address
ip -4 route show
ip -4 route get 10.20.0.10
ip -4 rule show
ip -4 route show table all

ip route 默认显示 main 表;Linux 实际先按 ip rule 的优先级选择查表规则。默认常见顺序为 local → main → default;数字越小越先匹配。策略路由可按源地址、流量标记等选表,出现多网卡/VPN 时不要只检查 main。ip-rule 手册

2. 实验环境:三台逻辑主机#

使用一台可丢弃的 Ubuntu 24.04 Linux VM(虚拟机),具备 sudo 权限。macOS 不能直接执行 ip netns,需进入 Linux VM。Namespace(命名空间)各自拥有接口、路由及网络栈;veth 是成对的虚拟网卡。

lr-app                       lr-router                      lr-db
eth0:10.10.0.10/24 ── app0:10.10.0.1/24
                             db0:10.20.0.1/24 ── eth0:10.20.0.10/24
                                                            HTTP :8080

lr-db 用 HTTP(超文本传输协议)健康端点模拟私网后端,重点验收实际 TCP(传输控制协议)连接,不以 ping 成功代替服务可达。这是 Linux 路由实验,不是模拟 AWS VPC 的内部实现,也不部署生产数据库。

sudo apt-get update
sudo apt-get install -y iproute2 curl python3 tcpdump
# 下载本页配套 lab.sh 到当前目录,检查内容后执行。
sudo bash lab.sh setup
sudo ip -n lr-app route
sudo ip -n lr-router route
sudo ip -n lr-db route

下载 lab.sh。脚本创建两个直连网段和后端,故意不加跨网段路由,且关闭实验路由器的转发。名称已存在则拒绝覆盖;失败会清理本次已创建资源。ip-netns 手册

3. 修复三处问题,逐步打通#

第一处:应用不知道如何去后端网段。 初始 ip route get 应报不可达。

sudo ip -n lr-app route get 10.20.0.10
sudo ip -n lr-app route add 10.20.0.0/24 via 10.10.0.1 dev eth0
sudo ip -n lr-app route get 10.20.0.10
sudo ip netns exec lr-app curl --noproxy '*' --connect-timeout 2 --max-time 3 http://10.20.0.10:8080/health

选路已正确,但请求仍失败:路由器没有开启转发。 --noproxy '*' 避免环境代理绕开实验路径。

sudo ip netns exec lr-router sysctl -w net.ipv4.ip_forward=1
sudo ip netns exec lr-app curl --noproxy '*' --connect-timeout 2 --max-time 3 http://10.20.0.10:8080/health

仍应失败:后端没有回到 10.10.0.0/24 的路由。 中间路由器已直连两个网段,无需额外静态路由;两个端点却分别需要远端路由。

sudo ip -n lr-db route add 10.10.0.0/24 via 10.20.0.1 dev eth0
sudo ip netns exec lr-app curl --noproxy '*' --fail --max-time 3 http://10.20.0.10:8080/health

预期返回 backend-ready。整个路径没有 NAT(网络地址转换),后端看到的来源仍是 10.10.0.10。转发开关只控制主机是否转发跨接口报文;不是访问控制授权。内核 ip_forward

4. 默认路由不能覆盖更具体的路由#

sudo ip -n lr-app route add default via 10.10.0.1 metric 100
sudo ip -n lr-app route get 203.0.113.10
# 仅证明默认路由选向 10.10.0.1;该地址用于文档,本实验没有互联网出口。
sudo ip -n lr-app route add blackhole 10.20.0.10/32 metric 999
sudo ip netns exec lr-app curl --noproxy '*' --connect-timeout 2 --max-time 3 http://10.20.0.10:8080/health
# 请求应失败:/32 比 /24 和 default 更具体,即使 metric=999。
sudo ip -n lr-app route del blackhole 10.20.0.10/32 metric 999
sudo ip netns exec lr-app curl --noproxy '*' --fail --max-time 3 http://10.20.0.10:8080/health

删除后恢复成功。路由命中 blackhole 时不会因为失败自动尝试默认路由;默认网关也不一定通向互联网,它只代表未知目的的下一跳。

5. 实际排障怎么查#

两个终端配合:终端 A 抓后端接口,终端 B 重复第 3 节请求。还可删除 lr-db 的回程路由重现超时,再原样恢复。

# 终端 A:仅抓本实验的合成流量,Ctrl-C 结束。
sudo ip netns exec lr-router tcpdump -ni db0 'tcp port 8080'
# 终端 B:核对目标监听、回程选路与下一跳邻居。
sudo ip netns exec lr-db ss -lnt
sudo ip -n lr-db route get 10.10.0.10
sudo ip -n lr-app neigh show
现象 优先检查
Network is unreachable 本端路由与策略表;不要先改服务端防火墙
下一跳邻居长期 INCOMPLETE/FAILED 接口状态、网关地址和二层可达性
本机可访问,远端超时 去程、回程、路由器转发、防火墙、服务绑定地址
路由都正确仍失败 nftables/iptables 的 INPUT、OUTPUT、FORWARD 链;云上还需检查 SG/NACL
多网卡下单向通 ip rule、源地址选择、非对称回程,以及 rp_filter(反向路径检查);不要直接全局关闭

6. 与 AWS 路由表的区别,以及清理#

EC2 的 Linux 路由表先决定把包从哪块网卡发给哪个下一跳;AWS 子网路由表再决定 VPC 内如何转发到 local、NAT、Peering 等目标。Linux 的 local 表用于本机地址,并不等于 AWS 的“整个 VPC CIDR → local”路由。

上述 ip route add 是运行时变更,重启或网络管理器重载可能消失。正式主机应由其实际使用的 NetworkManager、systemd-networkd 或 Netplan 持久化;不要混用多个管理器,更不要在 SSH 会话里直接删除主机默认路由试验。

sudo bash lab.sh cleanup

清理只删除脚本记录的三个命名空间及其中的测试进程。宿主机路由、网卡和转发开关保持原样。继续对照 AWS 三层子网 与 请求路径,即可区分“主机选路”和“云网络转发”。

搜索文档

输入关键词,搜索所有文档。

↑ ↓ 选择 · Enter 打开 · Esc 关闭