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

Linux ip rule 怎么按来源地址选择路由表

来源:17golang原创

时间:2026-09-28 02:14:23 347浏览 收藏

要让 Linux 按来源地址选择路由表,需要同时配置两层:先在独立路由表中写好直连路由和默认路由,再用 ip rule add from 来源前缀 lookup 表号 priority 优先级 把匹配流量送进该表。只添加 rule、没有填充目标表,或者表里缺少到网关的直连路由,都不会得到预期出口。

参考手册:https://man7.org/linux/man-pages/man8/ip-rule.8.html

下面用文档保留地址演示:主机的 eth1 地址为 198.51.100.10/24,网关为 198.51.100.1,希望所有源地址为 198.51.100.10 的流量查询路由表 200。

问题现场:第二个源地址仍然走 main 表

多网卡主机常见的现象是:两张网卡都已配置地址,但系统只有一条主默认路由。服务绑定第二张网卡的地址后,回包仍可能按 main 表选择出口,导致从错误网卡发出,或在上游被丢弃。

先收集当前状态,不要急着添加规则。需要确认地址确实在接口上、RPDB 中是否已有冲突规则,以及 main 表现在把默认流量送到哪里。

# 查看 IPv4 地址,确认源地址属于哪张接口
ip -4 address show

# 查看策略规则;数值越小,匹配优先级越高
ip -4 rule show

# 查看主路由表,确认现有默认出口
ip -4 route show table main

如果 198.51.100.10 在 eth1 上,而 main 表默认路由指向另一张网卡,那么“地址已配置”并不代表系统会自动为该源地址选择另一张路由表。

初步判断:规则负责选表,路由表负责选出口

ip rule 管理的是路由策略数据库 RPDB。规则包含选择器和动作:from 选择源前缀,lookup 200 表示匹配后查询表 200。真正决定下一跳和出口设备的,仍是表 200 里的路由项。

RPDB 通常自带三条基础规则:优先级 0 查询 local 表,32766 查询 main 表,32767 查询 default 表。优先级是数值越小越先处理,因此自定义来源规则一般放在 0 和 32766 之间,并显式使用一个唯一值,例如 1000。

Linux 来源地址通过 RPDB 的 priority 1000 规则进入 table 200,并由直连路由和默认网关选择 eth1 的说明图
图1:来源策略路由关系说明图,规则只负责选表,具体出口由表内路由决定。
对象本例值作用
来源地址198.51.100.10/32决定规则是否匹配
规则优先级1000决定 RPDB 检查顺序
路由表200保存该来源使用的路由
直连网段198.51.100.0/24 dev eth1让网关地址可达
默认路由via 198.51.100.1 dev eth1决定外部目的地址的下一跳

动手验证:先查询尚未配置时的选路结果

ip route get 可以让内核按给定目的地址和源地址执行一次路由查询。它不会发送测试包,适合在变更前后对比选中的网关、设备和源地址。

# 模拟目的地址为 203.0.113.8、源地址为 198.51.100.10 的查询
ip -4 route get 203.0.113.8 from 198.51.100.10

此时如果结果仍指向 main 表的默认网卡,就能确认问题在策略选路,而不是应用根本没有绑定目标源地址。若命令直接提示源地址无效,则先修正接口地址或命名空间,再继续配置。

定位原因:为什么只加 ip rule 仍然不通

一个常见误操作是先执行 ip rule add from ... table 200,却忘了表 200 最初是空的。规则匹配成功不等于路由成功;内核进入该表后仍要找到与目的地址匹配的路由。

另一个误区是只往表 200 添加默认路由。默认路由的下一跳 198.51.100.1 本身也需要可达,因此表里通常还要有对应直连网段。否则添加默认路由时可能得到“网络不可达”类错误,或查询无法解析下一跳。

Linux 策略路由中 source、priority、table routes 和 route get 共同决定预期出口的排查说明图
图2:策略路由排查关系图,四个检查对象共同决定最终出口。

修复方案:创建表 200 并添加来源规则

先写自定义表,再添加规则,便于逐层核对。下面命令只改变当前运行状态;接口名、地址、网关和表号必须替换成机器的真实值。

# 先加入直连网段,让表 200 能解析网关 198.51.100.1
sudo ip -4 route add 198.51.100.0/24 \
  dev eth1 src 198.51.100.10 table 200

# 再加入该来源使用的默认路由
sudo ip -4 route add default \
  via 198.51.100.1 dev eth1 table 200

# 最后添加来源选择规则;1000 小于 main 表规则的 32766
sudo ip -4 rule add from 198.51.100.10/32 \
  lookup 200 priority 1000

from 198.51.100.10/32 只匹配这个单独地址。如果希望整个来源网段使用相同表,可以改成相应前缀,但要确认这不会把其他主机或转发流量意外纳入。表名不是必须的,直接使用数字表号可以避免不同发行版上 rt_tables 配置路径差异。

验证结果:分别检查规则、表和组合查询

不要只看到 ip rule show 有一行就判定成功。需要依次确认规则存在、表内两条关键路由存在,以及组合查询最终命中预期网关和接口。

# 检查来源规则及其优先级
ip -4 rule show

# 检查表 200 是否同时包含直连网段和默认路由
ip -4 route show table 200

# 验证指定源地址的最终选路结果
ip -4 route get 203.0.113.8 from 198.51.100.10

组合查询的预期特征是:下一跳为 198.51.100.1,设备为 eth1,源地址为 198.51.100.10。如果目的地址位于直连网段,结果应直接使用 eth1,而不是经过默认网关。

规则存在却不生效的六个检查点

源地址和规则前缀不匹配

from 匹配的是数据包实际源地址,不是“希望使用的接口地址”。本机程序如果没有绑定该源地址,内核可能先按其他路由决定源地址,导致这条规则根本不匹配。测试时在 ip route get 中明确给出 from,应用层则确认套接字绑定或服务监听行为。

自定义表里只有默认路由

检查表内是否有到网关所在网段的直连路由。多网卡、点对点链路或需要 onlink 的特殊拓扑不能机械套用本例,必须依据真实链路补齐可达性。

优先级被更早的规则截获

规则按优先级数值从小到大检查。若已有更小数值且会匹配同一流量的规则,它可能先返回路由结果。给每条规则明确且唯一的优先级,并结合 ip rule show 判断顺序。

把 route 的 src 当成 rule 的 from

路由项中的 src 是该路由建议使用的首选源地址;规则中的 from 是匹配条件。二者作用不同。配置来源策略路由时,不能只在 route 上写 src 而省略 rule。

只验证了连通性,没有验证回程

多出口通信还取决于上游是否能把响应送回该地址、防火墙和 NAT 是否允许这条路径,以及主机的反向路径过滤策略是否与非对称路由兼容。ip route get 只证明本机当前的选路结果,不替代端到端检查。

重启后配置消失

ip route add 和 ip rule add 通常只修改运行时网络状态。持久化方式取决于发行版和网络管理器,应把同样的表号、来源前缀、优先级、直连路由和默认路由写入当前系统实际使用的网络配置,并在维护窗口内验证重载和重启行为。

回退:按唯一优先级精确删除

测试完成后,如果不保留这组策略,先删除规则,再清空专用表。用明确优先级删除,能降低误删其他相似来源规则的风险。

# 先删除优先级 1000 的来源规则
sudo ip -4 rule del priority 1000

# 再清空本例专用的表 200
sudo ip -4 route flush table 200

如果表 200 与其他服务共享,不要直接清空;应按完整前缀、网关和设备逐条删除本次新增路由。生产环境变更前也应先保存现状,确保能恢复原有规则顺序。

总结:判断是否配置完整的速查表

检查项正确状态典型错误
源地址实际数据包源地址命中 from只看接口地址,应用未绑定
优先级唯一,且在 main 规则之前被更早规则截获
自定义表有直连路由和默认路由只有 rule,没有 route
下一跳网关在该表中可达缺少网关所在直连网段
验证ip route get ... from ... 命中预期出口只看 rule 列表
持久化写入实际网络管理器配置重启后运行时规则丢失

相关问题

table 和 lookup 有什么区别?

在 ip rule 的这个用法中,二者都可指定匹配后查询的路由表,可以按团队规范选择一种写法。

为什么 priority 数字越小反而越优先?

RPDB 按优先级数值递增顺序扫描,因此较小的数先执行。为避免顺序不清,手工添加规则时应显式指定唯一值。

能按整个来源网段选择表吗?

可以,把 /32 改为需要的来源前缀即可。但前缀越宽,影响流量越多,配置前应确认本机流量与转发流量的范围。

有了来源规则后还需要 main 表吗?

通常仍需要。没有命中自定义规则的流量会继续按后续 RPDB 规则处理,main 表仍承担普通路由。不要为了来源策略路由随意删除默认基础规则。

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