如何在Linux使用Nmcli为多网卡设置路由权重以实现流量管理分离?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1038个文字,预计阅读时间需要5分钟。
nmcli 本身不支持路由权重这种说法——它没有类似BGP中的local-preference或metric权重的调整机制。所谓管理流与数据流分离,本质上是指让不同业务流走不同的网卡,这依赖于策略路由(Policy-Based Routing,PBR),而非简单的权限选择。nmcli的作用仅是将策略路由规则持久化到NetworkManager配置中,避免因重启而失效。
常见误解是以为 nmcli connection modify 加个 ipv4.route-metric 就能分流,其实那只影响**同一目标网络的多条直连/默认路由之间的优先级比较**,对跨网段、跨业务的定向分流完全无效。真要分离管理流(比如 SSH 到 192.168.10.0/24)和数据流(比如备份到 10.0.100.0/24),必须用 ip rule + 自定义路由表。
先配好自定义路由表和规则,再让 nmcli 持久化
假设 eth0 连管理网(192.168.10.0/24),eth1 连数据网(10.0.100.0/24),目标是:所有源地址为 192.168.10.50 的出向流量走 eth0;所有源地址为 10.0.100.50 的出向流量走 eth1。
- 编辑
/etc/iproute2/rt_tables,追加两行:100 mgmt和200 data - 为 mgmt 表加路由:
ip route add default via 192.168.10.1 dev eth0 table mgmt - 为 data 表加路由:
ip route add default via 10.0.100.1 dev eth1 table data - 添加策略规则:
ip rule add from 192.168.10.50/32 table mgmt priority 100和ip rule add from 10.0.100.50/32 table data priority 101
此时规则已生效,但重启即丢。接下来交给 nmcli:
- 在 eth0 对应连接配置中(如
nmcli connection show "System eth0"),执行:nmcli connection modify "System eth0" +ipv4.routes "192.168.10.0/24 192.168.10.1"(确保直连路由存在) - 关键一步:用
nmcli connection modify "System eth0" ipv4.post-up-command "ip rule add from 192.168.10.50/32 table mgmt priority 100; ip route add default via 192.168.10.1 dev eth0 table mgmt" - 同理为 eth1 配
post-up-command,注意替换 IP、表名和网关 - 最后
nmcli connection reload && nmcli connection down "System eth0" && nmcli connection up "System eth0"
为什么不用 ipv4.routing-rules?
NetworkManager 从 1.32+ 开始支持 ipv4.routing-rules,但 Rocky Linux 9 / RHEL 9 默认的 NM 版本(1.40+)虽有该字段,实际解析时**只认 from/to + table,不支持 priority 和 iif/oif 等高级匹配项**。你写 ipv4.routing-rules "from 192.168.10.50/32 table mgmt priority 100",nmcli 会静默忽略 priority,导致规则插入顺序错乱,可能被主表 default 规则覆盖。
更稳妥的做法是坚持用 post-up-command,它原样执行 shell 命令,兼容性无死角。注意命令里别漏分号,且所有路径、命令必须绝对完整(比如用 /usr/sbin/ip 而非仅 ip,避免 PATH 不一致)。
rp_filter 是个隐藏杀手,必须关
即使规则和路由全对,管理流或数据流仍可能间歇性不通——八成是内核反向路径校验(rp_filter)在作祟。当响应包从非原路返回(比如 SSH 请求从 eth0 进、响应却从 eth1 出),rp_filter=1 会直接丢包。
- 查当前值:
sysctl net.ipv4.conf.all.rp_filter - 临时关闭:
sysctl -w net.ipv4.conf.all.rp_filter=0 - 永久生效:在
/etc/sysctl.conf加一行net.ipv4.conf.all.rp_filter = 0,然后sysctl -p
别只关 all,如果某块网卡还跑服务,顺手也关对应接口的:sysctl -w net.ipv4.conf.eth0.rp_filter=0。这个点极容易被跳过,但一旦触发,排查起来毫无头绪。
本文共计1038个文字,预计阅读时间需要5分钟。
nmcli 本身不支持路由权重这种说法——它没有类似BGP中的local-preference或metric权重的调整机制。所谓管理流与数据流分离,本质上是指让不同业务流走不同的网卡,这依赖于策略路由(Policy-Based Routing,PBR),而非简单的权限选择。nmcli的作用仅是将策略路由规则持久化到NetworkManager配置中,避免因重启而失效。
常见误解是以为 nmcli connection modify 加个 ipv4.route-metric 就能分流,其实那只影响**同一目标网络的多条直连/默认路由之间的优先级比较**,对跨网段、跨业务的定向分流完全无效。真要分离管理流(比如 SSH 到 192.168.10.0/24)和数据流(比如备份到 10.0.100.0/24),必须用 ip rule + 自定义路由表。
先配好自定义路由表和规则,再让 nmcli 持久化
假设 eth0 连管理网(192.168.10.0/24),eth1 连数据网(10.0.100.0/24),目标是:所有源地址为 192.168.10.50 的出向流量走 eth0;所有源地址为 10.0.100.50 的出向流量走 eth1。
- 编辑
/etc/iproute2/rt_tables,追加两行:100 mgmt和200 data - 为 mgmt 表加路由:
ip route add default via 192.168.10.1 dev eth0 table mgmt - 为 data 表加路由:
ip route add default via 10.0.100.1 dev eth1 table data - 添加策略规则:
ip rule add from 192.168.10.50/32 table mgmt priority 100和ip rule add from 10.0.100.50/32 table data priority 101
此时规则已生效,但重启即丢。接下来交给 nmcli:
- 在 eth0 对应连接配置中(如
nmcli connection show "System eth0"),执行:nmcli connection modify "System eth0" +ipv4.routes "192.168.10.0/24 192.168.10.1"(确保直连路由存在) - 关键一步:用
nmcli connection modify "System eth0" ipv4.post-up-command "ip rule add from 192.168.10.50/32 table mgmt priority 100; ip route add default via 192.168.10.1 dev eth0 table mgmt" - 同理为 eth1 配
post-up-command,注意替换 IP、表名和网关 - 最后
nmcli connection reload && nmcli connection down "System eth0" && nmcli connection up "System eth0"
为什么不用 ipv4.routing-rules?
NetworkManager 从 1.32+ 开始支持 ipv4.routing-rules,但 Rocky Linux 9 / RHEL 9 默认的 NM 版本(1.40+)虽有该字段,实际解析时**只认 from/to + table,不支持 priority 和 iif/oif 等高级匹配项**。你写 ipv4.routing-rules "from 192.168.10.50/32 table mgmt priority 100",nmcli 会静默忽略 priority,导致规则插入顺序错乱,可能被主表 default 规则覆盖。
更稳妥的做法是坚持用 post-up-command,它原样执行 shell 命令,兼容性无死角。注意命令里别漏分号,且所有路径、命令必须绝对完整(比如用 /usr/sbin/ip 而非仅 ip,避免 PATH 不一致)。
rp_filter 是个隐藏杀手,必须关
即使规则和路由全对,管理流或数据流仍可能间歇性不通——八成是内核反向路径校验(rp_filter)在作祟。当响应包从非原路返回(比如 SSH 请求从 eth0 进、响应却从 eth1 出),rp_filter=1 会直接丢包。
- 查当前值:
sysctl net.ipv4.conf.all.rp_filter - 临时关闭:
sysctl -w net.ipv4.conf.all.rp_filter=0 - 永久生效:在
/etc/sysctl.conf加一行net.ipv4.conf.all.rp_filter = 0,然后sysctl -p
别只关 all,如果某块网卡还跑服务,顺手也关对应接口的:sysctl -w net.ipv4.conf.eth0.rp_filter=0。这个点极容易被跳过,但一旦触发,排查起来毫无头绪。

