☰
Ubuntu双网卡优先级配置:路由表与metric实战指南
2026/10/16 4:24:28 网站建设 项目流程

你有没有遇到过这种尴尬:Ubuntu 笔记本明明插着千兆有线网口,却在用 Wi-Fi 传一个 200MB 的文件,慢到让人怀疑人生;或者服务器上两个网口分别接了办公网和业务网,业务流量偏偏从办公网口出去,被防火墙拦得死死地。网上搜这个问题,大家通常管它叫“Ubuntu 双网卡配置优先级”,但严格来说,Linux 系统里并不存在一个叫“网卡优先级”的开关,真正决定出口的是路由表里的条目顺序和一个叫 metric 的数值。这篇文章我会从路由原理开始讲,再给出手动切换、永久配置、策略路由和排错方法,把我在这类问题上踩过的坑一并记录下来。无论你是笔记本用户,还是要维护多网口服务器的人,应该都能从中找到可用的操作。

1. 双网卡优先级不是“网卡顺序”,而是路由表排序

1.1 数据包先查路由表,再决定走哪张网卡

很多人直觉上认为,系统会按照网卡的物理顺序或者接口名去选出口,比如eth0一定比eth1“高级”。这个理解在 Ubuntu 里并不成立。

Linux 转发一个数据包时,先查的是路由表。路由表里存放着很多“目标网段 + 下一跳 + 出口网卡”的记录。比如你访问192.168.1.22,而eno1上配置了192.168.1.0/24,系统会直接通过eno1发送,根本不会去问“是不是应该用eno2”。如果访问的是一个互联网地址,不在任何局域网段里,那么系统会在路由表里找default,也就是默认路由。

所以“双网卡优先级”这个问题,真正要处理的是:当两张网卡都往路由表里塞了一条默认路由时,系统以哪一条为准。你调整的重点也应该是这些默认路由条目,而不是接口的物理顺序。

1.2 metric 是决定同一条路由谁先谁后的关键数值

假设你的 Ubuntu 同时开启了有线网卡eno1和无线网卡wlan0,两张网卡都通过 DHCP 拿到了 IP、网关和默认路由。这时用ip route show多半会看到类似这样的内容:

default via 192.168.1.1 dev eno1 proto dhcp metric 100 default via 192.168.2.1 dev wlan0 proto dhcp metric 600 192.168.1.0/24 dev eno1 proto kernel scope link src 192.168.1.20 192.168.2.0/24 dev wlan0 proto kernel scope link src 192.168.2.50

两条default路由的目标都是整个互联网,这时 Linux 会看一个数值:metric。metric 越小,优先级越高。上面这个输出里,eno1的 metric 是 100,wlan0是 600,所以当前默认出口是eno1,也就是有线网卡。这个行为在大多数情况下符合直觉:有线的带宽更高、延迟更稳。

但问题恰恰出在这:DHCP 分配的 metric 并不总是符合你的真实意图。比如某个场合里有线网卡被分到了 metric 600,无线反而只有 100,那系统就会默认从无线出去。你想调整优先级,本质上就是调整这些默认路由的 metric。

1.3 路由选择的基本规则:最长前缀匹配优先

在深入操作前,还有一条基础规则需要记住:目标地址能匹配到越具体的路由,就越优先,哪怕这条具体路由没有 metric 优势。

举个例子,你的路由表里同时存在default via 192.168.1.1和192.168.1.0/24 dev eno1。你访问192.168.1.5时,/24 路由比 default 更具体,所以系统一定走eno1。只有当目标地址不在任何具体网段内时,默认路由才会被拿出来比较。

这条规则解释了一个很常见的困惑:为什么明明把默认路由切到了wlan0,可访问某个内网 IP 还是从eno1出去?因为那个 IP 被更具体的网段路由匹配了,默认路由管不到它。所以在动手改优先级之前,先确认你要控制的流量到底匹配的是哪个路由范围。

2. 临时切换默认出口:ip route 命令的实操与验证

2.1 动手前先看懂当前路由表

临时调整适合用在“先验证一下效果”的场景,比如你想确认切到某个网卡后,业务访问是否正常。第一步永远是看当前路由表,而不是凭感觉敲命令。

ip route show ip route

两个命令输出一致,后者是前者简写。重点找所有default开头的行。如果只有一条default,那你的问题其实不是默认路由优先级,而是缺一条有利于新网卡的路由,或者你根本就没让另一张网卡参与默认出口的竞选。如果有两条以上default,才需要做 metric 调整。

我通常还会配合ip -br address看接口状态和 IP 是否正常。接口是DOWN或者没有拿到地址时,谈优先级没有意义。

2.2 用 ip route replace 控制默认路由的 metric

临时切换默认出口最直接的办法是给某条 default 路由设定一个更小的 metric。比如我想让wlan0成为默认出口,原来的 gateway 是192.168.2.1,可以执行:

sudo ip route replace default via 192.168.2.1 dev wlan0 metric 100

这里用replace而不是add,是为了避免目标格式相同的默认路由已存在时,系统报RTNETLINK answers: File exists。如果两条 default 的via或dev不一样,replace 不一定能精准替换掉你心里想的那条,所以有时更稳妥的方式是“先加新路由,再删旧路由”:

sudo ip route add default via 192.168.2.1 dev wlan0 metric 50 sudo ip route del default via 192.168.1.1 dev eno1

顺序是先让新出口以更小的 metric 顶上,再删除旧出口的默认路由,尽量缩短没有任何默认路由的窗口期。在远程通过 SSH 操作服务器时,这一步能帮你降低断连风险。

2.3 验证出口的三个实用方法

改完之后,不能只看ip route show里 default 顺序变了就以为完成,要实际验证流量走向。我常用的方法有三个。

第一个是ip route get。命令会模拟内核选路过程,直接告诉你某个目标 IP 应该从哪张网卡、哪个源地址出去:

ip route get 203.0.113.10

输出里会出现dev wlan0等字段,这就是当前路由逻辑给出的答案。第二步是做真实连通性测试,比如固定从某张网卡 ping 一个公网地址。第三步是访问一个能显示来访 IP 的页面,看出口地址有没有变成目标网卡的地址。我在命令行里一般用curl --interface wlan0 http://example.com来指定出口进行测试,也可以用浏览器配合排查。注意,如果只ping一个内网地址,很可能会被更具体的网段路由截走,测不出默认路由的真实效果。

3. 让优先级永久生效:netplan 与 NetworkManager 该选哪个

3.1 先确认系统里到底是谁在管理网卡

手动ip route命令只是临时的,重启或者 DHCP 续租后大概率被打回原形。要想永久生效,得把配置写进网络管理工具。

Ubuntu 上的网络配置历史上经历过多次更迭,现在最常见的是两套体系:netplan 和 NetworkManager。netplan 通常负责/etc/netplan/下的 YAML 文件,根据配置再渲染给 systemd-networkd 或 NetworkManager。桌面版 Ubuntu 通常默认预装 Netplan,但实际管理连接的往往是 NetworkManager;服务器场景里则常见 netplan 渲染到 systemd-networkd。

动手改配置前,先确认这个接口到底归谁管:

systemctl is-active systemd-networkd NetworkManager nmcli device status

如果NetworkManager是 active,并且nmcli device status里能看到你的网卡被显示为connected,那大概率是 NetworkManager 在管连接。如果systemd-networkd在管,那 netplan 配置会生效更快。两者同时存在时千万不要在两个文件里反复横跳,否则优先级会被搞得更乱。

3.2 服务器场景:netplan 写入 metric 的完整示例

如果你的服务器采用 netplan 渲染到 systemd-networkd,配置默认路由优先级的方法非常直接。比如eno1做业务出口,eno2做管理出口,业务网卡希望绝对优先,可以在/etc/netplan/下的 YAML 里写:

network: version: 2 renderer: networkd ethernets: eno1: dhcp4: true dhcp4-overrides: route-metric: 50 eno2: dhcp4: true dhcp4-overrides: route-metric: 200

关键点在于dhcp4-overrides的route-metric。这个字段会覆盖 DHCP 默认分配的 metric 值,而且 DHCP 租约续租时也不会再把它改回去。静态 IP 场景下则要在routes段手写 default 路由并指定 metric:

eno1: addresses: - 192.168.1.20/24 routes: - to: default via: 192.168.1.1 metric: 50

这里要注意一个坑:如果你同时开着dhcp4: true又手动写 default 路由,DHCP 也可能下发自己的默认路由,出现重复条目。要么关闭dhcp4,要么用dhcp4-overrides统一管理从一个来源来的路由。

改完后执行:

sudo netplan generate sudo netplan apply

先generate是为了检查 YAML 语法和字段是否合法,再apply应用。务必明白netplan apply会重新加载网络配置,对 SSH 远程会话可能造成瞬断。我一般在物理终端或带外管理控制台里操作,不敢在生产环境直接远程 apply。

3.3 桌面场景:用 nmcli 修改连接级 route-metric

笔记本这类桌面环境,我倾向于把网络管理交给 NetworkManager。它给每个连接都维护了独立的配置,视觉效果上“哪个连接优先”更直观。

先看当前的连接列表:

nmcli connection show

假设有线连接的名字叫“Wired connection 1”,要让它的默认路由优先,执行:

nmcli connection modify "Wired connection 1" ipv4.route-metric 50 nmcli connection up "Wired connection 1"

同样地,把 Wi-Fi 连接的ipv4.route-metric调高,比如 600,这样有线连接在默认路由竞争里就占据绝对优势。NetworkManager 在图形界面里也提供了“路由优先级”的配置项,原理一样,只是在命令行里写脚本更方便。

有一点经验值得说明:NetworkManager 本身会给不同类型连接一个默认 metric 倾向,通常有线比无线更优先,这是比较贴心的设计。但 DHCP 服务器有可能下发自己的 metric,或者你在 netplan 里也配了一份,最终状态以ip route show为准,不要只看某个管理工具的面板显示。

4. 进阶:按目标网段或来源地址做策略路由

4.1 最简单的场景:一条更长的前缀路由就够了

很多时候你不需要调整全局默认路由,只想让某个网段固定走某个网卡。比如服务器上有eno1接办公网,eno2接某资源池网段10.10.0.0/16,希望访问资源池时一定走eno2,其他流量走办公网。

最直接的办法是加一条指向该网段的静态路由:

sudo ip route add 10.10.0.0/16 via 192.168.2.1 dev eno2

由于 10.10.0.0/16 比 default 更具体,内核会优先匹配它,不需要动默认路由。这类简单的“目标网段分流”,用普通静态路由就能解决,别一开始就上策略路由。

4.2 多出口分流:独立路由表 + ip rule 的组合

当你的分流条件不只是目标网段,而是“来自某个 IP 的流量必须走某张网卡”时,普通静态路由就不够用了。这种场景常见于一台双网口设备同时给几个网段做网关,不同网段要求分别走不同上游出口。

这时需要用策略路由。思路很简单:为某个出口专门建一张独立路由表,再用ip rule规则把符合条件的流量导入那张表。

先给路由表起个名字:

echo "100 mgmt" | sudo tee -a /etc/iproute2/rt_tables

在表 100 里放一条默认路由:

sudo ip route add default via 10.0.1.1 dev eno2 table 100

然后添加规则,让来自10.10.10.0/24的流量查询表 100:

sudo ip rule add from 10.10.10.0/24 lookup 100

这时可以分别查看:

ip route show table 100 ip rule show

这种方案的可扩展性很强。你可以为每个出口建一张独立路由表,再配合多条ip rule实现按来源、目标、二层优先级等条件分流。

持久化方面,新版 netplan 支持routing-policy字段:

network: version: 2 renderer: networkd ethernets: eno2: addresses: - 10.0.1.2/24 routing-policy: - from: 10.10.10.0/24 table: 100 routes: - to: default via: 10.0.1.1 table: 100

如果你的 netplan 版本较老,或者使用 NetworkManager,就需要注意版本差异。NetworkManager 的ipv4.routing-rules语法在不同版本之间变化很大,老版本往往只支持非常基本的格式。我在一个老版本环境里就遇到过nmcli提示命令不支持的情况,最后还是在/etc/network或者 netplan 层面手工落地的。所以我的经验是:策略路由这种复杂配置,优先走 netplan + systemd-networkd 的组合,别在 NetworkManager 里硬凹。

4.3 慎用双线负载均衡:连接跟踪与 SNAT 的现实约束

有些朋友看到有两张网卡,就想着把默认路由设置成“一半流量走这张、一半流量走那张”,实现负载均衡。在 Ubuntu 里确实可以写多路径路由,但我个人非常不建议在普通场景下这么做。

原因在于网络连接不是只看一个方向。TCP 连接有源地址、目标地址、序列号,很多环境还做了 NAT。如果同一个 TCP 连接的前几个包从网卡 A 出去,后面的包从网卡 B 出去,回包可能会走到完全不同的路径,连接会被拆得七零八落。即使使用ip route add default nexthop ...这类多路径写法,实际效果也严重依赖内核的连接跟踪和外部路由器的反路径过滤规则。

更稳妥的做法是“主备”而不是“负载均衡”。保留两条默认路由,但把业务网卡的 metric 调低,让它成为主出口;管理网卡保留较高的 metric,只在主出口故障时启用。这样既能实现链路冗余,又不会因为出口切换导致业务不稳定。

5. 改完不生效?我的排查链路与真实坑点

5.1 首个坑:配置归属不明,netplan 和 NetworkManager 打架

有次 A 同学在一台 Ubuntu 服务器上修改了/etc/netplan/,设置了两张网卡的 metric,然后执行netplan apply,结果ip route show完全没变化。奇怪的是netplan apply也没有报错。

当时排查的第一步是看接口到底被哪个服务管理。执行nmcli device status后发现两个接口都被 NetworkManager 接管了,而 netplan 配置里的renderer是networkd,两份配置互相没有交集。也就是说,netplan 生成的配置被 systemd-networkd 接收了,但接口却被 NetworkManager 抢先绑定。

解决办法是在 netplan 里统一指定renderer: NetworkManager,或者反过来,禁用 NetworkManager 对接口的管理,让 systemd-networkd 独享这些设备。从此以后我养成了一个习惯:在 Ubuntu 上排查网络问题,第一个问题永远是“谁在管这张网卡”,而不是急着改配置。

5.2 第二个坑:两条 default 路由存在,但路由选择仍走旧接口

另一个常见现象是:路由表里明明有两条 default,metric 也设好了,新网卡的 metric 更小,但实际流量还是从旧网卡出去。

先用ip route get看目标地址匹配到哪条路由。很多时候你会发现,目标地址其实被旧网卡的某个具体网段路由匹配了,比如访问的是一个与旧网卡同网段的内网资源,根本轮不到默认路由来决定出口。这时调整 default 的 metric 当然没用,你要么修改旧网卡的网段路由范围,要么把目标流量分流到另一张网卡。

还有一种情况是旧网关仍然可达,而新网卡的网关虽然存在,但实际链路是不通的。Linux 对 default 网关默认不会做实时健康探测,所以路由表里它仍然是可用状态,系统就会持续尝试往一个并不存在的下一跳发包。遇到这种“路由看起来对,流量却不通”的问题,我会逐一向新网卡的网关做连通性测试:

ping -I eno2 10.0.1.1

如果 ping 不通,说明问题根本不在 metric,而在物理链路、交换端口或者 IP 配置。

5.3 第三个坑:DNS 没跟着换,域名解析还是走旧出口

路由切换成功后,ping 公网 IP 能通,但访问域名解析不出来,这是很多人在调完双网卡优先级后遇到的第二个坎。

原因是 DNS 查询出口由 systemd-resolved 管理,它跟路由表是两个层面的东西。你只改了默认路由,systemd-resolved仍可能把 DNS 查询优先发给旧网卡收到的 DNS 服务器。查询请求发去旧链路,自然解析很慢或者失败。

排查时用:

resolvectl status

查看当前每个接口的 DNS 配置,以及默认 DNS 路由指向哪个接口。如果 DNS 还绑在旧网卡上,可以用:

sudo resolvectl dns eno2 10.0.1.1 sudo resolvectl default-route eno2 yes

在 netplan 层面,更持久化的做法是给网卡固定nameservers,并且通过dhcp4-overrides里的use-dns: false阻止 DHCP 写入 DNS 配置,确保 DNS 只从你指定的接口获取。这个坑提醒我:讲“双网卡优先级”不能只盯着路由表,DNS 服务的优先级也要同步处理。

5.4 第四个坑:DHCP 租约续租后,手动 metric 被覆盖

有时候你明明用ip route replace手动调整好了 metric,运行一段时间后却发现又变回了原来的优先顺序。重启后变回去大家都能理解,但没重启就变回去,多半是 DHCP 续租搞的鬼。

DHCP 客户端在租约续租时可能重新应用服务器下发的路由和 metric 信息,把你在命令行里做的临时修改覆盖掉。想要长期保留优先级,就不能只依赖手工命令,必须把配置写进网络管理工具的持久化文件里。对于 DHCP 接口,使用 netplan 的dhcp4-overrides是最干净的方案;如果走 NetworkManager,使用连接配置里的ipv4.route-metric而不是临时命令。

我整理了一个简易对照表,方便按现象定位问题:

现象大概率原因处理思路
ip route show有两条 default,但流量仍走旧口目标地址命中更长前缀路由用ip route get确认匹配规则
改了默认路由,域名解析仍然失败DNS 出口由 resolved 管理,未同步切换调整resolvectlDNS 或 netplanuse-dns
netplan apply 后路由没变化接口被 NetworkManager 接管统一 renderer 或禁用 NM 对接口的管理
临时设置 metric 很快失效DHCP 续租覆盖手工配置使用 netplan 或 NM 持久化配置

6. 最后:一份可以直接照抄的双网卡优先级自查清单

无论问题多复杂,我通常都会按下面这份清单一步步走,很少会漏掉关键信息:

ip -br address # 看接口状态和 IP ip route show # 看所有路由,重点是 default 条目 ip rule show # 看有没有策略路由在参与选路 resolvectl status # 看 DNS 出口与各接口 DNS 配置

第一步,确认问题到底是默认出口选错,还是某些目标网段走了不期望的网卡。第二步,查路由表里 default 条目数量和 metric;如果只有一条 default,那问题就变成“另一张网卡没参与默认出口竞选”,要从 DHCP 配置或静态路由入手。第三步,查策略路由。有时主表看起来正常,但高优先级的ip rule会提前把流量导走,主表规则根本轮不到执行。第四步,查 DNS。

配置层面我的原则很简单:服务器上用 netplan 统一收口所有网卡,桌面机上完全交给 NetworkManager,不要混用。metric 数值要拉开差距,比如一个 50,一个 200,避免数值接近导致后续加新路由时不好判断。DNS 也要尽量固定到同一个出口,否则路由切了 DNS 没切,等于白切。

最后分享一个小技巧:在修改网络配置时,别急着关终端,先在后台跑一个持续的连通性测试任务,再执行netplan apply。如果配置错误导致断流,你还能在断开的终端里来不及操作之前,通过另一条通路快速回滚。这套方法陪着我处理了很多次双网卡配置事故,到现在还在用。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询