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。

| 对象 | 本例值 | 作用 |
|---|---|---|
| 来源地址 | 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 本身也需要可达,因此表里通常还要有对应直连网段。否则添加默认路由时可能得到“网络不可达”类错误,或查询无法解析下一跳。

修复方案:创建表 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 表仍承担普通路由。不要为了来源策略路由随意删除默认基础规则。
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
116 收藏
-
150 收藏
-
464 收藏
-
108 收藏
-
481 收藏
-
228 收藏
-
442 收藏
-
279 收藏
-
273 收藏
-
128 收藏
-
308 收藏
-
132 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习