首页 / 内容指南 / 当前文章

Linux ip rule 的 priority、from、to、fwmark、iif、oif、lookup、suppress 和 goto 有什么区别?

发布于 2026-08-26 · routecfg.com 编辑部

Linux 普通路由通常只根据目标地址在 main 表中做最长前缀匹配;策略路由则先由 Routing Policy Database(RPDB)逐条检查 ip rule,再决定查询哪张路由表或执行何种动作。多出口、透明代理、源地址分流、VRF 和按进程路由都依赖这层机制。

本文目录(22 节)

快速对照

↔ 表格可左右滑动查看完整内容
字段所在层作用常见误解
priorityRule决定 RPDB 扫描先后,数字小优先与 Route metric 相同
fromRule selector匹配源地址前缀修改源地址
toRule selector匹配目标地址前缀等同路由表内最长匹配
fwmarkRule selector匹配内核包标记及可选掩码匹配 DSCP 或防火墙规则编号
iifRule selector匹配入接口匹配最终出接口
oifRule selector匹配本地且绑定设备的套接字出接口对所有转发包都有效
lookup/tableRule action查询指定路由表无路由时必然立即丢包
suppress_prefixlengthRule suppressor拒绝前缀长度小于等于阈值的查表结果删除该表的路由
gotoRule action跳到指定规则优先级继续 RPDB跳到路由表编号

RPDB 与路由表是两层决策

一条 Rule 由 selector 和 action 组成。selector 判断数据包是否匹配,例如源地址属于某网段、包标记为某值;action 通常执行 lookup TABLE。进入路由表后,内核再根据目标地址、TOS、scope、metric、nexthop 等选择具体路由。

因此:

ip rule add priority 1000 from 192.0.2.0/24 lookup isp_a

只表示来源于该网段的包优先查询 isp_a。如果表里没有匹配目标的路由,不等于自动走某个网关;RPDB 可以继续扫描后续规则。若表内有 unreachable、prohibit 或 blackhole 等终止性路由,结果则与“没有路由”不同。

Rule priority 解决“先查哪张表”,同一张表里的 Route metric 解决候选路由偏好,目标前缀长度仍决定表内最长前缀匹配。三者不能互换。

默认的 local、main 和 default 规则

Linux 启动时通常建立三条默认 RPDB 规则:

0:      from all lookup local
32766:  from all lookup main
32767:  from all lookup default

priority 0 先查询 local 表(ID 255),其中包含本机地址、广播等由内核维护的高优先级控制路由。main 表(ID 254)保存未显式指定其他表的大多数普通路由。default 表(ID 253)默认通常为空,为前面规则没有给出结果后的后处理预留。

不要为了让自定义规则“绝对优先”随意删除 local 规则。否则发往本机地址的数据可能被送到外部网关,破坏本机服务和回环语义。自定义规则通常放在 0 与 32766 之间,并给每条规则分配显式、唯一的 priority。

priority:数字越小越早执行

priority、preference 和 order 在 ip rule 语法中是同义表达。内核按数值递增顺序扫描,即 100 先于 1000,1000 先于 32766。这里“高优先级”对应更小的数字。

不要省略 priority 依赖工具自动分配,也不要给多条规则重复数字。重复 priority 虽可能被内核接受,但同优先级的显示和处理顺序不适合作为稳定配置契约,自动化删除时也容易误删。

建议预留区段,例如 100–199 给本机特殊流量,1000–1999 给源地址策略,10000–10999 给 mark 策略,并在配置仓库登记所有者。插入新规则时无需整体重编号。

from:按源地址选择路由策略

from PREFIX 匹配包的源 IPv4 或 IPv6 地址,典型用途是多宿主机让不同源地址从对应 ISP 返回:

ip rule add priority 1000 from 192.0.2.10/32 lookup isp_a
ip rule add priority 1010 from 198.51.100.10/32 lookup isp_b

它只做匹配,不执行 SNAT,也不强制应用一定使用该源地址。本地连接的源地址选择可能在路由查找过程中发生,应用显式 bind、Route 的 src 属性和地址作用域都会影响结果。

多出口设计还要考虑回程对称、NAT、连接跟踪和反向路径过滤。只添加 from rule 而不给专用表配置直连网段及默认路由,可能连本地网关都无法解析。

to:在 RPDB 层匹配目标前缀

to PREFIX 匹配目标地址,可让特定目的网段先查询专用表。例如将内部网段固定走内网接口,其余保持 main 表。

它与路由表里的目标前缀不同:Rule 的 to 决定“是否执行这条规则”,表内 Route prefix 决定“该表选哪一条路由”。策略复杂时可用一条较宽的 Rule 选择表,再让表中的多个前缀完成细分,避免为每个网段创建 Rule。

DNS 域名不能直接作为稳定内核 Rule selector。域名先解析成 IP,且 CDN 地址会变化。需要按域名分流时通常由代理、nftables 动态集合或应用层完成,再转换成 mark 或地址集合。

fwmark:匹配包的内核元数据

fwmark VALUE[/MASK] 匹配 skb mark。这个 mark 通常由 nftables、iptables、tc、cgroup/BPF 或套接字选项设置,不会作为普通 IP 头字段传到远端。它与 DSCP、conntrack mark、路由表 ID 和防火墙规则 handle 都不是同一个概念。

带掩码可以只匹配某些位:

ip rule add priority 1100 fwmark 0x100/0xff00 lookup proxy

标记规划应给不同子系统分配位域,避免透明代理、QoS、容器网络和多 WAN 互相覆盖。写 mark 时采用按位保留规则,而不是无意把其他模块设置的位清零。

Packet mark 默认不会自动跟随整个连接。需要请求与回包对称时,可在 conntrack mark 与 packet mark 之间保存/恢复,并验证 NAT 前后 Hook 顺序。内核生成但不属于已有 socket 的回复包是否继承 mark,还受 fwmark_reflect 等 sysctl 影响。

iif:包从哪里进入

iif NAME 匹配 incoming interface,主要用于转发流量。例如从 LAN 接口进入的包查访客网络表,从 VPN 接口进入的包查隧道路由表。

当 iif lo 时,ip-rule 手册说明它只匹配本机产生的包,因此可以把本地流量与转发流量分开治理。但容器 veth、bridge、VRF 和 TUN 场景中的实际 iif 可能不是应用直觉中的物理网卡,需要使用 tcpdump -i any、nft trace 或内核事件观察真实路径。

iif 不表示最终出接口。想“从 eth0 进就从 eth1 出”,仍需 action 选择一张最终包含 eth1 nexthop 的路由表。

oif:仅适用于特定本地套接字场景

oif NAME 匹配 outgoing interface,但手册明确指出,它只对本地产生、且 socket 绑定到某设备的流量可用。内核在一般路由查找前往往还不知道最终出接口,不能把 oif 当成所有包的通用选择条件。

对于转发流量按出口分类,通常先用其他 selector 选表,或在 nftables/tc 阶段基于已有路由结果处理。若应用未使用 SO_BINDTODEVICE 等方式绑定设备,oif Rule 可能始终不匹配。

排障时用 ip route get 模拟时显式给 oif 并不等同真实应用已绑定接口,应结合 socket 状态和应用代码确认。

uidrange、ipproto、sport 和 dport

Linux RPDB 还可按 uidrange、IP protocol、源端口和目标端口匹配。uidrange 适合让某个本地服务账户走专用出口;端口 selector 可区分 TCP/UDP 服务,但应同时指定 ipproto,避免数字在不同协议下产生歧义。

这些字段更适合本地流量或内核能取得相应报头的场景。分片、加密隧道、封装层和转发路径会影响端口可见性。复杂应用分类通常先由 nftables/cgroup 设置 fwmark,再由 RPDB 查表,可降低 Rule 数量并集中匹配逻辑。

lookup/table:查询指定路由表

lookup TABLE 与 table TABLE 同义。表可以使用数字,也可使用 /etc/iproute2/rt_tables 或 /usr/lib/iproute2/rt_tables 中定义的名称。名称只提高可读性,内核实际使用表 ID。

专用表至少要包含到 nexthop 的直连可达路由和业务需要的目标路由。仅添加:

ip route add default via 192.0.2.1 table isp_a

若该表没有 192.0.2.0/24 dev eth0 等链路路由,网关可能被判定不可达。不要依赖 main 表自动补齐,因为一次 table lookup 不会把多张表隐式合并为一张。

没有路由、throw 与 blackhole 的区别

Rule 查表后若没有匹配路由,RPDB 可以继续下一规则。throw Route 显式终止当前表查找,并表现得像该表没有找到路由,适合让特定前缀回退到后续 Rule。

blackhole 会静默丢包;unreachable 丢包并返回不可达;prohibit 表示管理上禁止。它们是明确终止结果,不应与“表为空所以继续”混淆。若希望某类流量绝不回落 main 表,可用合适终止 Route 或 Rule type 明确失败,而不是假设没有默认路由就一定丢弃。

suppress_prefixlength:忽略过宽的查表结果

suppress_prefixlength N 会拒绝该次 table lookup 中前缀长度小于等于 N 的路由结果,然后让 RPDB 有机会继续。最常见的是:

ip rule add priority 1000 lookup main suppress_prefixlength 0

它允许 main 表中的具体路由生效,但忽略 /0 默认路由。若没有更具体结果,后续规则可把流量送往 VPN 或另一张表。

该选项不会删除 main 表的默认路由,也不改变其他查询看到的内容。它只抑制通过这条 Rule 得到的结果。N 越大,受抑制的宽前缀越多;配置前应列出表内所有前缀并验证边界。

suppress_ifgroup 类似地拒绝使用指定接口组的路由结果,适合更复杂的接口治理,但需要明确接口组配置。

goto:跳转到另一条 Rule priority

goto NUMBER 把 RPDB 执行跳到目标 priority,用于复用规则尾部或构建分段策略。目标是 Rule priority,不是路由表 ID,也不是数组下标。

goto 能减少重复 action,但会让控制流不再线性。运维人员查看 ip rule show 时必须跟踪跳转,自动化删除目标规则还可能留下无效路径。大多数简单多 WAN 配置用有序 lookup 已足够,只有重复规则集明显时才值得引入 goto。

l3mdev 与 VRF

VRF 设备会关联独立路由表,Linux 可使用 l3mdev Rule 把属于 L3 master 设备的流量导向相应表。内核 VRF 文档说明,更高优先级的 PBR Rule 仍可优先于 VRF 规则,实现例外分流。

不要同时为每个 VRF 手工堆叠 iif/oif Rule,又保留自动 l3mdev 规则而不检查顺序。升级旧配置时应比较内核版本、VRF 规则 priority 与应用 socket 绑定方式,防止同一流量被两套机制处理。

rp_filter 为什么会让正确 Rule 看起来失效

多出口和非对称路由中,包可能按策略从一个接口进入、从另一个接口返回。严格 reverse path filtering 会检查源地址的反向路由,路径不符合预期时提前丢包,使 ip rule 和路由表看似完全正确却没有回包。

内核文档建议复杂或非对称路由考虑 loose 模式。使用 fwmark 做双向路由时,src_valid_mark 决定反向路径查找是否把 mark 纳入。不同发行版可能在启动脚本中改变默认 rp_filter,应检查 all 与具体接口最终生效的最大值。

不应为了快速恢复直接全局关闭源验证。先确认业务确实需要非对称路径,再按接口调整并补充反欺骗防火墙规则。

用 ip route get 验证真实决策

单看 ip rule show 和 ip route show table X 只能证明配置存在。应使用与真实包相同的源、目标、mark、入接口和协议模拟:

ip route get 203.0.113.8 from 192.0.2.10 mark 0x100

转发场景可提供 iif,本地绑定场景可测试适用 oif。fibmatch 可显示匹配的 FIB 路由。再用 nftables trace、ip monitor route rule、conntrack 和抓包确认 mark 写入时机、NAT 与真实出接口。

IPv4 与 IPv6 RPDB 分开管理,验证时分别使用 ip -4 rule、ip -6 rule 与对应路由表。只配置 IPv4 策略而应用优先 IPv6,会造成部分请求绕过预期出口。

一个双出口示例

ip route add 192.0.2.0/24 dev eth0 table isp_a
ip route add default via 192.0.2.1 dev eth0 table isp_a
ip route add 198.51.100.0/24 dev eth1 table isp_b
ip route add default via 198.51.100.1 dev eth1 table isp_b

ip rule add priority 1000 from 192.0.2.10/32 lookup isp_a
ip rule add priority 1010 from 198.51.100.10/32 lookup isp_b

这只是内核运行时示例,不包含发行版持久化、DNS、NAT、rp_filter、故障切换和远端路由。正式上线前应使用 NetworkManager、systemd-networkd、Netplan 或发行版支持机制持久化,并在重启后复验。

变更与回滚清单

  1. 保存 ip -4/-6 rule show 和所有相关 table;
  2. 为新规则设置唯一显式 priority;
  3. 先补齐专用表的直连与默认路由;
  4. 用 ip route get 离线推演多个源、目标和 mark;
  5. 小范围加入 Rule,保持现有管理连接不受影响;
  6. 检查 nftables、conntrack mark 和 Hook 顺序;
  7. 验证转发、本地流量、回包与 IPv6;
  8. 检查 rp_filter、src_valid_mark 和 fwmark_reflect;
  9. 将配置写入发行版持久化系统;
  10. 重启网络服务或主机后重新验证,不只看命令退出码。

常见误区

priority 数字越大越先执行

错误。数字越小优先级越高,RPDB 按数值递增扫描。

Rule 命中就一定从该表出站

错误。还要在表内找到有效 Route;未找到时可能继续下一条 Rule。

fwmark 会随数据包传到互联网

错误。它是内核 skb 元数据,通常不在线路上传输,也不会自动跨连接方向保留。

iif 和 oif 是一对普通入出口匹配

错误。iif 面向进入接口;oif 仅适用于本地且 socket 绑定设备的特定流量。

suppress_prefixlength 0 会删除默认路由

错误。它只在该 Rule 的查表结果中抑制 /0,路由表本身不变。

FAQ

1. ip rule priority 与 ip route metric 有什么区别?

priority 决定先执行哪条 RPDB Rule;metric 在同一张路由表的候选 Route 中参与偏好选择。

2. 为什么默认有 priority 0 的 local Rule?

它优先处理本机和广播地址等内核维护路由,保证发往本机的包正确本地交付,通常不应删除。

3. lookup 表里没有目标路由会怎样?

通常视为该 Rule 未给出成功路由,RPDB 继续后续规则;若匹配到 blackhole、unreachable 或 prohibit,则产生明确终止结果。

4. fwmark 和 connmark 是同一个值吗?

不是。fwmark 属于当前 packet;connmark 属于连接跟踪项。可以通过防火墙规则在二者之间保存和恢复。

5. suppress_prefixlength 0 最常见用途是什么?

让某张表的具体前缀继续生效,但忽略其默认路由,再由后续 Rule 选择 VPN、代理或另一出口。

6. 能否按域名写 ip rule?

不能直接可靠匹配域名。内核 Rule 使用地址、mark、接口、协议和端口等字段;域名策略需先转化为 IP 集合或 mark。

7. 为什么手工 ip rule 重启后消失?

ip 命令修改运行时内核状态,不自动持久化。应写入发行版支持的网络配置系统并测试重启恢复。

8. 怎样判断某个真实包最终命中了哪条策略?

先用 ip route get 按真实字段模拟,再结合 nft trace、conntrack、ip monitor 和抓包验证 mark、Rule、Route 与出接口。

参考来源