路由表与网关:数据包是怎么被转发的
default0.0.0.0/0)是兜底路由。当 LPM 找不到任何匹配条目时,数据包走默认网关。默认网关本身必须与本机处于直连可达的网络中(也就是说,本机路由表中必须有一条路由能够到达网关 IP)。# 默认网关的作用位置 # 相当于: ip route add default via 10.0 .0.1 dev eth0 # 所有非直连流量 → 10.0.0.1 → 路由器处理默认网关的配置通常
文章目录
引言
某团队在腾讯云上新部署了一套集群,网段规划为
10.0.1.0/24。上线后发现部分服务之间网络互通正常,部分服务却完全不通。排查了安全组、子网 ACL、弹性网卡配置,均未发现问题。最终定位:10.0.1.0/24子网的路由表里赫然躺着一条10.0.0.0/8的默认路由——另一个团队三个月前申请的 VPN 网关遗留配置,覆盖了整段内网地址,所有发往10.0.1.x的包被路由到了 VPN 隧道而非直连交换机。路由表是数据包转发的决策中枢。理解它不仅仅是背下几个字段,而是搞清楚内核在收到一个包时,是如何从成千上万条路由规则中选出唯一一条来执行转发的。
一、路由表:数据包转发的决策依据
1.1 路由表的结构
Linux 的路由表是一张清单,列出了"发往哪些目标网络,走哪个网关,从哪个网卡出去"。用 ip route show(或废弃的 route -n)查看:
# 查看主路由表
ip route show
ip route show table main
# 输出示例
default via 10.0.0.1 dev eth0 proto dhcp src 10.0.0.100 metric 100
10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.100
192.168.1.0/24 via 10.0.0.254 dev eth0 proto static metric 200
每条路由条目包含以下字段:
| 字段 | 含义 | 示例 |
|---|---|---|
destination |
目标网络(也可为 default,即 0.0.0.0/0) |
10.0.0.0/24 或 default |
via gateway |
下一跳网关 IP(直连网络无需指定) | via 10.0.0.254 |
dev interface |
从哪个网卡发出 | dev eth0 |
proto |
路由来源:kernel=内核自动生成,dhcp=DHCP 学习,static=手动配置 |
proto kernel |
scope |
作用范围:link=仅本链路可达,global=全局可路由 |
scope link |
src |
源 IP 选择:发往该目标时使用哪个源地址发出 | src 10.0.0.100 |
metric |
优先级:数值越小优先级越高 | metric 100 |
直连网络不需要 via 字段。当目标网络与本机某网卡处于同一网段时,内核直接通过 ARP 获取目标 MAC 地址,将包从对应网卡发出,无需经过任何网关。
1.2 最长前缀匹配:内核如何选路
这是路由转发最核心的算法。当内核收到一个数据包,需要决定"走哪条路"时,它在路由表中执行 Longest Prefix Match(LPM)——在所有匹配目标网络的路由条目中,选择前缀最长的那一条。
举例说明:目标 IP 为 10.0.1.150。
0.0.0.0/0(default):匹配 0 位前缀 → 候选10.0.0.0/8:匹配前 8 位(10.) → 候选10.0.1.0/24:匹配前 24 位(10.0.1.) → 候选10.0.1.128/25:匹配前 25 位(10.0.1.1),完全匹配 → 最优
内核选择 /25 这条。如果路由表中没有 /24 和 /25,则选择 /8;如果连 /8 也没有,才 fallback 到 default。
这就是为什么更精确的路由可以覆盖更宽泛的路由。VPN 网关遗留配置中,10.0.0.0/8 的条目会覆盖所有 10.x.x.x 的直连路由,除非有更精确的条目明确指定了不同的下一跳。
1.3 默认网关:最后的兜底路由
default(0.0.0.0/0)是兜底路由。当 LPM 找不到任何匹配条目时,数据包走默认网关。默认网关本身必须与本机处于直连可达的网络中(也就是说,本机路由表中必须有一条路由能够到达网关 IP)。
# 默认网关的作用位置
# 相当于:
ip route add default via 10.0.0.1 dev eth0
# 所有非直连流量 → 10.0.0.1 → 路由器处理
默认网关的配置通常由 DHCP 自动分配,或者在 /etc/sysconfig/network-scripts/ifcfg-eth0(CentOS/RHEL)或 /etc/netplan/01-netcfg.yaml(Ubuntu)中静态指定。
二、策略路由:Linux 的多表路由
标准路由表只能按目标地址做转发决策。但在某些场景下,需要按源地址、入接口或** fwmark(防火墙标记)**选择不同的路由策略。Linux 通过 RPDB(Routing Policy Database) 实现这一能力。
2.1 为什么需要策略路由
典型场景:
- 多出口负载均衡:服务器有两根网卡,分别接入 ISP A 和 ISP B,需要根据目标网络选择不同的出口
- VPN 透明代理:本应访问内网的流量走 VPN 隧道,其余流量走正常网关
- 容器网络隔离:Kubernetes Pod 的流量经 CNI 插件走专用网桥,与主机流量分开
2.2 RPDB 的工作原理
RPDB 由一系列规则(rule)组成,每条规则指向一个路由表。数据包转发时,内核按规则优先级(从小到大)逐一匹配,找到第一条匹配的规则后,使用该规则指向的路由表进行转发:
核心命令:
# 查看所有规则
ip rule show
# 输出示例:
# 0: from 127.0.0.0/8 lookup local
# 100: from 192.168.1.0/24 lookup ISP_A
# 200: from 192.168.2.0/24 lookup ISP_B
# 32766: from all lookup main
# 32767: from all lookup default
# 添加一条基于源地址的策略路由
# 来自 192.168.1.0/24 的流量,走 ISP_A 路由表
ip rule add from 192.168.1.0/24 table ISP_A priority 100
# 添加后立即生效
ip route show table ISP_A
# 需要在 ISP_A 表中定义路由
ip route add default via 203.0.113.1 dev eth0 table ISP_A
# 按 fwmark 标记分流(常用于透明代理)
ip rule add fwmark 0x1 table vpn_table priority 50
# 删除规则
ip rule del from 192.168.1.0/24 table ISP_A priority 100
规则优先级:ip rule 按 priority 数值从小到大依次匹配(数值越小越先匹配)。local 表(优先级 0)包含系统自动生成的本地接口直连路由,永远优先匹配。
2.3 Docker/Kubernetes 中的策略路由
容器网络隔离是策略路由最常见的生产应用。Kubernetes CNI 插件(如 Calico、Flannel)在节点上自动创建策略路由,确保 Pod 流量经由正确的网桥和网卡进出:
# 查看节点的策略路由规则(Kubernetes 节点示例)
ip rule show
# 示例输出:
# 0: from all lookup local
# 32766: from all lookup main
# 32767: from all lookup default
# 9000: from 10.244.1.0/24 lookup cni-plugin # Calico 为 Pod 网段创建的规则
# 对应的 CNI 路由表
ip route show table cni-plugin
# 输出:default via 10.244.1.1 dev cali0
如果不理解这套机制,修改了节点路由表或安全组规则后,Pod 通信异常的根本原因就很难定位。
三、VPC 场景下的路由冲突
云上生产环境的高频故障之一:路由冲突导致的隐性网络分割。
3.1 腾讯云 / 阿里云的路由优先级
云平台 VPC 路由表同样执行 LPM,但平台在用户可见的路由表之上还有系统路由。系统路由的优先级由平台定义,不对用户暴露,当自定义路由与系统路由冲突时,以平台规则为准。
腾讯云路由优先级(从高到低):
- 用户自定义路由(精确匹配)
- 系统路由(含 NAT 网关、VPN 网关、对等连接的下一跳)
- 默认路由(
0.0.0.0/0)
当两个自定义路由条目前缀长度相同时,平台按路由创建时间排序(先创建优先)。这个行为是隐式的,不会主动告警。
3.2 CIDR 重叠:最隐蔽的路由杀手
CIDR 重叠指的是:两个不同业务的 VPC 网段在规划时没有协调,导致地址段交叉或包含。
排查方法:
# 腾讯云 CLI:检查 VPC 路由表中的冲突条目
tccli vpc DescribeRouteTables --VpcId vpc-xxxxxxxx
# 阿里云 CLI:检查 CEN 路由冲突
aliyun cen DescribeCenRouteEntries --CenId cen-xxxxxxxx
# 本地诊断:用 ip route 确认本机实际生效路由
ip route get from 10.0.1.150 to 10.0.2.50
# 如果输出显示走了意外的网关,说明路由匹配有问题
解决方案:
- 事前:VPC 网段规划时建立统一的 CIDR 分配表,新业务申请网段前先查询已有分配
- 事后:缩小冲突子网的掩码(从
/24缩小到/26或/27),将未被使用的地址段腾出来重新分配
3.3 NAT 网关路由陷阱
在腾讯云中,VPC 内实例访问公网时,如果走 NAT 网关(而非公网 IP 直通),需要在路由表中添加一条 0.0.0.0/0 下一跳指向 NAT 网关的路由。
一个常见失误:手动添加 0.0.0.0/0 路由后,没有删除原有的"默认路由通过 DHCP 分配的公网 IP 直通"配置,导致同一条目标网络同时匹配两条路由。此时云平台按内部权重策略选择一条(行为不可预测),表现为"有时通有时不通"的间歇性故障。
# 腾讯云确认 NAT 网关是否生效
# 查看路由表中是否有多条 default 路由
tccli vpc DescribeRouteTables --VpcId vpc-xxxxxxxx --Filters.0.Name=route-table-id --Filters.0.Values=rtb-xxxxxxxx
# 确保只有一个 default 下一跳指向 NAT 网关
四、traceroute 解读:每跳的含义
traceroute 的输出是理解路由路径的最直接工具。traceroute 或 mtr 显示的每一跳代表一个路由器或三层交换机,每跳的 RTT 反映该设备的处理延迟和链路质量。
4.1 traceroute 输出解读
traceroute to 93.184.216.34 (93.184.216.34), 30 hops max, 60 byte packets
1 gateway (10.0.0.1) 0.421 ms 0.385 ms 0.372 ms
2 183.60.83.1 1.203 ms 1.189 ms 1.195 ms
3 10.128.80.1 2.451 ms 2.389 ms 2.510 ms
4 72.14.215.85 5.123 ms 5.089 ms 5.104 ms
5 * * * 5.712 ms 5.698 ms 5.723 ms
6 93.184.216.34 8.234 ms 8.201 ms 8.189 ms
每列含义:
- 第 1 列:TTL 值,即跳数
- 第 2 列:路由器 IP(有些路由器关闭了反向 DNS 解析,显示为 IP)
- 后 3 列:3 次探测的 RTT(毫秒),探测了 3 次取均值
常见模式分析:
- 第 4 跳 RTT 突然从 2ms 跳到 5ms:该路由器或链路开始出现拥塞
- 第 5 跳全是
*:该路由器关闭了 ICMP 回复(traceroute -T -p 80改用 TCP 探测可以绕过部分限制) - 内网 traceroute 全为
*:中间交换机配置了 ACL,屏蔽了 UDP 探测包,改用traceroute -I(ICMP)尝试
4.2 用 ip route get 验证本地路由决策
traceroute 查看的是端到端路径,如果问题出在本机出口,可以用 ip route get 直接验证本机对特定目标的路由决策:
# 查询本机对 93.184.216.34 的路由决策
ip route get 93.184.216.34
# 输出示例:
# 93.184.216.34 via 10.0.0.1 dev eth0 src 10.0.0.100 uid 0
#
# 含义:目标 93.184.216.34
# 下一跳网关 10.0.0.1
# 从 eth0 发出
# 源 IP 10.0.0.100
# 查询内网同网段
ip route get 10.0.1.150
# 10.0.1.150 dev eth0 src 10.0.0.100 uid 0
# 直连网络,不需要网关,直接从 eth0 发出
# 如果返回 "Network is unreachable"
# 说明路由表中没有匹配 10.0.1.150 的条目,也没有默认网关
ip route get 是排查"包从哪个网卡出去、源 IP 是什么"的精确工具,比 ping + route -n 的组合快得多。
五、生产路由故障的排查框架
六、总结:路由是分层的
路由决策不是一个扁平的查表过程,而是一个分层决策体系:
- Linux 主机层:RPDB 按
ip rule优先级 → 选中路由表 → 执行 LPM → 选出转发路径 - VPC 平台层:平台路由表(含系统路由)→ 用户自定义路由 → LPM → 选出下一跳类型(NAT 网关/VPN/对等连接)
- 运营商骨干网层:BGP 路由协议 → AS 路径选择 → 选出 ISP 出口
任何一层出错,包就走不到目的地。理解每层的决策机制,才能在故障发生时准确定位"是哪一层的哪条规则出了问题",而不是对着 traceroute 干瞪眼。
更多推荐
所有评论(0)