登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  linux

ip rule 与多路由表实现策略路由

来源:17golang原创

时间:2026-10-10 17:48:06 406浏览 收藏

Linux 主机有两条上行链路时,只在 main 表里放两条默认路由,通常无法保证“从哪个源地址发出,就从对应网关返回”。ip rule 的作用是先按源地址、目标地址、入口接口或标记匹配规则,再选择指定路由表;每张表内部仍按普通路由的最长前缀规则选下一跳。

官方手册:https://github.com/iproute2/iproute2/blob/main/man/man8/ip-rule.8.in

最小可用方案是:每条上行链路一张自定义路由表,表内同时放直连网段和默认路由,再用带唯一 priority 的 from 规则把源地址映射到对应表。

出现这些信号时才需要策略路由

  • 主机有两个公网地址,响应包总从 main 表默认网关出去。
  • 同一目标需要按业务源地址、容器网段或 fwmark 选择不同出口。
  • 抓包能看到请求从 eth1 进入,响应却从 eth0 发出。
  • 切换默认路由能暂时恢复一条业务,却会让另一条链路失败。

如果只是多个等价下一跳、链路负载均衡或单一路由表里的优先级问题,先评估 ECMP、metric 或路由协议;不要为了“看起来更灵活”无条件增加 RPDB 规则。

先看清 RPDB、规则优先级和路由表

报文选择条件、ip rule、priority、local、main、自定义表和路由条目的静态关系图
图1:RPDB 静态结构说明图,规则先选择路由表,路由表再按目标前缀给出路由。

策略路由数据库称为 RPDB。每条 rule 由选择器和动作组成,系统按 priority 数字从小到大检查,也就是数字越小优先级越高。命中后常见动作是 lookup TABLE_ID;如果该表给出成功路由,查找结束,否则可以继续后面的规则。

系统默认通常包含三条规则:priority 0 查询 local 表,32766 查询 main 表,32767 查询 default 表。自定义规则应明确写唯一 priority,并放在 main 规则之前,但通常不要覆盖 priority 0 的 local 规则。

双网卡示例的地址边界

下面使用文档专用地址,不可直接复制到生产:

接口源地址直连网段网关路由表
eth0192.0.2.10192.0.2.0/24192.0.2.1100
eth1198.51.100.10198.51.100.0/24198.51.100.1200

在远程服务器上操作前,先保留带外控制台或第二个会话,并记录当前规则和路由。策略路由配置错误可能立刻切断 SSH 回程。

# 记录当前 RPDB 和所有路由表,便于异常时对照。
ip rule show
ip route show table all

# 只查看接口与地址,不对系统做任何修改。
ip -br address show

每张自定义表先补直连路由

只在 table 100 里添加默认路由并不总是够用。内核还要知道网关本身如何到达,因此每张自定义表应包含对应直连网段,再放默认路由。

# 表 100 对应 eth0:先声明网关所在直连网段,再添加默认路由。
ip route add 192.0.2.0/24 dev eth0 src 192.0.2.10 table 100
ip route add default via 192.0.2.1 dev eth0 table 100

# 表 200 对应 eth1:保持源地址、接口和网关属于同一链路。
ip route add 198.51.100.0/24 dev eth1 src 198.51.100.10 table 200
ip route add default via 198.51.100.1 dev eth1 table 200

# 分别查看两张表,确认直连网段和默认路由都存在。
ip route show table 100
ip route show table 200

如果地址由 DHCP、PPP 或云平台动态下发,网关和接口可能变化,不能把这组命令静态写死。应让网络管理器或链路事件脚本在地址就绪后维护对应表。

用 from 规则把源地址映射到路由表

两个源地址、两条 ip rule、两张路由表和两个网关的静态对应关系图
图2:双上行策略路由说明图,每个源地址由独立规则绑定到自己的路由表与网关。
# 源地址 192.0.2.10 使用表 100;较小数字代表更高优先级。
ip rule add from 192.0.2.10/32 lookup 100 priority 10000

# 源地址 198.51.100.10 使用表 200,并使用不同的唯一优先级。
ip rule add from 198.51.100.10/32 lookup 200 priority 10010

# 列出规则,确认它们位于 local 与 main 默认规则之间。
ip rule show

规则顺序不是备注信息,而是行为的一部分。不要省略 priority 让不同工具自行分配,也不要让两条规则使用相同优先级。后续自动化、排错和删除都会更困难。

不要用 ping 代替路由决策验证

ip route get 会按给定条件解析实际路由,但不会真正发送数据包。它比只看 ip route show 更适合确认 RPDB 最终选择了哪张表、哪个源地址、哪个设备和下一跳。

# 模拟源地址 192.0.2.10 访问外部目标,期望经 eth0 和 192.0.2.1。
ip route get 203.0.113.80 from 192.0.2.10

# 模拟源地址 198.51.100.10 访问同一目标,期望经 eth1 和 198.51.100.1。
ip route get 203.0.113.80 from 198.51.100.10

# 显示匹配到的 FIB 条目,辅助区分最终解析结果与原始表项。
ip route get fibmatch 203.0.113.80 from 192.0.2.10

检查结果时关注 via、dev、src。如果仍走 main 表,先看 rule priority 是否排在 32766 之前;如果报网关不可达,检查自定义表内是否缺少直连路由。

按标记分流时要保证 mark 真正存在

除了源地址,ip rule 也能按 fwmark 匹配。它适合代理、容器或防火墙先给报文打标,再由 RPDB 选表。规则本身不会产生 mark;如果 nftables、iptables 或应用没有设置对应标记,这条规则永远不会命中。

# 让 mark 0x64 的报文查询表 100;掩码限制参与匹配的位。
ip rule add fwmark 0x64/0xff lookup 100 priority 10100

# 用 route get 的 mark 参数模拟查找,确认策略表选择是否符合预期。
ip route get 203.0.113.80 mark 0x64

如果只需要源地址分流,不要同时叠加 fwmark、iif 和端口选择器。选择条件越多,线上报文与测试命令不一致的概率越高。

回滚必须精确删除规则再清空表

验证失败时先删除自定义规则,让流量恢复 main 表路径,再清空自定义表。不要直接执行无选择器的 ip rule flush,它可能删除不属于本次变更的规则。

# 先按唯一优先级删除本次新增规则,停止进入自定义表。
ip rule del priority 10000
ip rule del priority 10010
ip rule del priority 10100

# 再清空本次专用表,不影响 main 和 local 表。
ip route flush table 100
ip route flush table 200

# 重新解析两种源地址,确认已经回到变更前的路由策略。
ip route get 203.0.113.80 from 192.0.2.10
ip route get 203.0.113.80 from 198.51.100.10

若某条可选规则从未添加,删除命令会返回找不到对象。生产脚本应记录哪些步骤实际成功,回滚时只撤销已生效项。

重启后消失是临时配置的正常表现

ip rule add 和 ip route add 直接修改当前内核状态,通常不会自动持久化。验证完成后,应把规则和表写入当前发行版实际使用的网络管理体系,例如 NetworkManager、systemd-networkd 或 Netplan。不要同时让多个管理器维护同一接口。

持久化前再确认三点:接口名是否稳定;地址和网关是否静态;网络服务重载时规则与路由表的创建顺序是否正确。建议先在维护窗口重载网络配置,再执行同样的 ip rule show 和 ip route get 检查。

值班检查清单

  • 规则是否显式设置唯一 priority,且数字顺序符合预期。
  • 自定义表是否同时包含网关直连路由和默认路由。
  • ip route get ... from ... 是否返回正确的 via、dev 和 src。
  • fwmark 规则上游是否真的设置了同一个 mark 和掩码。
  • 远程变更是否有带外通道、精确回滚命令和变更前记录。
  • 临时命令是否已转换为唯一网络管理器的持久化配置。

常见问题

为什么 priority 数字越小越先匹配?

RPDB 按 priority 数值递增检查规则,因此较小数值代表更高优先级。

只添加 ip rule 不建自定义表可以吗?

规则可以添加,但目标表没有合适路由时无法产生预期下一跳,查找可能继续后续规则或失败。

多路由表会自动做 NAT 吗?

不会。策略路由解决查表和下一跳选择,源地址转换仍由 nftables、iptables 或其他网络组件负责。

ip route show 为什么看不出策略结果?

它只展示表项。用带 from、mark 等条件的 ip route get 才能解析最终选择。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>