默认路由(0.0.0.0/0)和自定义路由同时存在时,转发优先级遵循“先看前缀,再看成本”的规则:目标IP匹配到更长的子网掩码就先走自定义路由,匹配不到任何精确路由时才轮到默认路由兜底;如果两条路由掩码完全相同,则比较 metric(路由成本),数值小的优先。
默认路由和自定义路由优先级:先看掩码还是先看成本?
路由转发的第一原则是最长前缀匹配,行业共识认为,这条规则优先于路由来源、配置顺序、管理距离等一切因素,也就是说,哪怕默认路由是系统自动生成的,自定义路由是你手动加进去的,只要目标地址落在自定义路由的网段范围内,系统就只认自定义路由。
举个例子,一台 Ubuntu 服务器有两块网卡:eth0 接办公网,eth1 接 IDC 专线,开机后内核自动生成一条默认路由 default via 10.0.0.1 dev eth0,你为了访问 IDC 的资产,手动加了一条自定义路由:
ip route add 172.16.0.0/12 via 10.0.0.2 dev eth1
此时服务器访问 16.3.50,系统会同时匹配到两条路由:16.0.0/12 和 0.0.0/0,因为前者掩码长度是 12,后者是 0,系统选择掩码更长的 /12,数据包直接从 eth1 出去。
如果自定义路由是 /32 的主机路由,比如访问某个独立 IP,精确匹配优先级更高,默认路由更是完全没有机会。
那 metric 什么时候起作用?答案是当掩码长度完全相同时,最常见的场景就是两条默认路由并存,或者两条指向同一个网段的自定义路由并存,这时候系统才比较 metric,metric 越小越优先。
| 场景 | 匹配路由 | 掩码长度 | 选择结果 |
|---|---|---|---|
| 目标在自定义网段内 | 默认路由 /0 + 自定义路由 /24 | /24 更长 | 自定义路由 |
| 目标是普通公网 IP | 默认路由 /0 + 自定义路由 /24 | /24 不匹配目标 | 默认路由 |
| 两条默认路由 | 默认路由 A(metric 5)+ 默认路由 B(metric 50) | 均为 /0 | metric 小的 A |
| 两条等价默认路由 | metric 完全一致 | 均为 /0 | 多数情况下逐流或逐包分担 |
路由转发中自定义路由先走,默认路由兜底:完整流程拆解
Linux 内核实际查路由表的顺序,不是简简单单从上往下扫一遍,它按以下层级递进:
- 先查 local 表,匹配本机地址、广播地址、NAT 地址。
- 再查 main 表,按前缀长度从长到短排序,优先匹配最精确的路由。
- 若存在多条相同前缀的路由,比较 metric,小者胜出。
- 若所有精确路由都没匹配上,才轮到
/0默认路由兜底。 - 整张表都找不到路径,返回
Network is unreachable。
这里有一个容易忽略的环节:策略路由(ip rule)可以改变查表顺序,即使 main 表里自定义路由前缀更长,如果用户为某个来源 IP 指定了 lookup 100,该来源的数据包会先查 table 100,而不是 main 表,结果就是 main 表里的自定义路由再精确,也可能被跳过。
这正是“路由转发中自定义路由先走,默认路由兜底”这句话的适用范围边界:它默认所有路由都在同一张 main 表里,一旦引入多路由表,优先级由 ip rule 的列表顺序决定,前缀长度反而要靠后。
实际操作中,验证当前系统到底会选哪条路由,用这个命令最直接:
ip route get 172.16.3.50
输出结果里会明确告诉你 via 网关和 dev 出口网卡,改完路由后先跑一下这个命令,比看路由表更可靠。
Linux路由优先级怎么设置?双默认路由实测还原
双 WAN 软路由或双线服务器上,两条默认路由并存是常态,很多人会遇到“多条默认路由怎么选”的困惑:明明加了新路由,流量却还是走老出口。
问题通常出在 metric 没有显式设置上,推荐做法是动手前先规划好主备关系,再执行:
ip route add default via 192.168.1.1 dev eth0 metric 10 ip route add default via 192.168.2.1 dev eth1 metric 100
执行后查看 ip route show,会看到两条 default 条目,metric 分别为 10 和 100,此时用 ip route get 223.5.5.5,系统返回的一定是 via 192.168.1.1 dev eth0,而 eth1 的默认路由只会在 eth0 断开或 metric 被调大后才被激活。
如果想直接改一条已有默认路由的 metric,用 ip route replace:
ip route replace default via 192.168.2.1 dev eth1 metric 200
如果用的是 NetworkManager 管理网络,持久化配置比临时命令更稳:
nmcli connection modify eth0 ipv4.route-metric 10 nmcli connection up eth0
如果走 /etc/sysconfig/network-scripts/ifcfg-eth0 风格配置,加一行 METRIC=10 即可,Debian/Ubuntu 系统使用 /etc/network/interfaces 时,可以在 up ip route add 行里显式带上 metric。
业内专家指出,生产环境里手动加默认路由时不指定 metric,是多数路由漂移问题的根源,内核自动分配的 metric 值在不同发行版上规则并不相同,依赖默认值等于把选路结果交给运气。
验证真实出接口的命令组合
ip route get 目的IP:查看内核按当前路由表计算出的实际路径。tcpdump -i eth0 icmp:在对应网卡抓包,确认数据包真实出口。ip rule show:查看策略路由优先级,确认 main 表是否被前置或后置。
路由优先级改动后不生效,先查这三个位置
很多时候路由表看起来已经改对了,但流量就是不按预期走,排障时按顺序查下面三处。
第一,查 ip rule 策略路由顺序。
ip rule show
如果看到类似 from 192.168.1.100 lookup 100 的规则排在 main 表前面,那么来自 192.168.1.100 的流量会优先查 table 100,而不是 main 表,即使 main 表里有更精确的自定义路由,也不会被使用。

第二,查反向路径过滤 rp_filter。
Linux 默认可能开启反向路径校验,当数据包源地址方向与路由表不一致时,内核直接丢弃,表现是路由看着通,但 ping 或业务流量完全没有回应。
临时关闭方法:
sysctl -w net.ipv4.conf.all.rp_filter=0
生产环境不建议全局关闭,可以针对单个网卡设置,或在防火墙中做精细化控制。
第三,查自定义路由是否写进了正确的表。
ip route show table all
这条命令会列出所有路由表,如果你用 ip route add ... table 100 添加了路由,但没有配置 ip rule,这条路由永远不会生效,因为系统默认不会去查 table 100。
默认路由和自定义路由优先级常见的3个问题
Q1:默认路由和自定义路由的掩码一样,优先级怎么算?
掩码相同时比较 metric,metric 小者胜出,metric 也相同,Linux 会启用等价多路径路由,流量在两条链路上分担;Windows 则使用接口跃点数决定,生产环境建议显式设置不同 metric,避免行为不确定。
Q2:ip route add 和默认路由冲突时会报错吗?
Linux 不报错,它允许同一路由表里存在多条默认路由,但如果不设置 metric,转发路径不可控,必须用 ip route get 验证实际出口,Windows 上执行 route add 0.0.0.0 且目标已存在时,系统会提示“The object already exists”,需要先删除旧路由。
Q3:多条默认路由怎么选才稳定?
多数情况下设置不同 metric 做主备最稳妥,如果需要负载均衡,把 metric 设为一致,并用 ip route add default nexthop via 192.168.1.1 dev eth0 weight 1 nexthop via 192.168.2.1 dev eth1 weight 1 创建等价多路径路由,让内核按权重分配流量。
默认路由和自定义路由的选择,从来不是看谁先配置、谁后配置,而是看前缀长度、metric 和策略路由顺序的完整配合,记住这个核心逻辑,路由优先级的排查和调优就不再是玄学。

