策略路由不生效主因是规则优先级或匹配条件错误;linux按pref数值从小到大匹配,非添加顺序;需确认源ip真实、对应路由表存在有效路由,并用ip route get验证。

为什么 ip rule 加了却没走新路由?
策略路由不生效,八成是规则优先级(pref)或匹配条件写错了。Linux 按 pref 数值从小到大匹配规则,而不是按添加顺序;如果已有 pref 0 的默认规则挡在前面,你加的 pref 100 规则根本不会被看到。
- 用
ip rule show看实际生效顺序,别只信自己 add 的顺序 - 匹配源地址时,确保数据包真实源 IP 是你写的那个——NAT 后、DNAT 前、容器网络里常不是你以为的那个 IP
- 加规则后必须确认对应路由表存在且有有效路由:比如
ip rule add from 192.168.1.100 table 100,就得有ip route show table 100并含至少一条可用路由 - 测试时用
ip route get <code>1.1.1.1from192.168.1.100iif eth0,比 ping 更直接暴露路由决策过程
ip route add ... via 和 via dev 有什么区别?
选错下一跳类型会导致路由“看起来对”,但实际发不出包。核心区别在于:是否经过内核路由查找环节。
-
via <code>192.168.2.1:走标准三层转发,需要该网关可达(即本机有直连或能到达它的路由),且会触发反向路径检查(rp_filter) -
via dev eth1:强制二层发送,跳过路由查找,适合点对点链路(如 PPPoE、某些光纤终端),但不能用于普通以太网网关 - 多 ISP 场景下,若 ISP 分配的是 /30 或 /31 点对点子网,用
via dev更稳妥;若给的是带网关的 /29,必须用via <code>gw_ip - 误用
via dev对非点对点接口,会导致 ARP 请求发向错误 MAC,抓包可见大量 unanswered ARP
负载均衡不是轮询,ip route balance 不存在
Linux 内核原生不支持基于流的自动负载分担。所谓“多路径”(multipath)仅限同一张路由表内的等价路径(nexthop),且默认策略是 per-flow hash,不是 per-packet。
- 想让不同连接走不同 ISP,得靠策略路由分流:例如按源 IP 段、目标端口、甚至 conntrack 标记做规则分发
- 不要试图用
ip route add default scope global nexthop via <code>10.0.1.1dev eth0 weight 1 nexthop via10.0.2.1dev eth1 weight 1 实现“双线负载”——它只在目标完全相同时才起作用,对出站默认路由基本无效 - 真要动态负载,得配合
iptables + CONNMARK标记连接,再用ip rule查标记查表,否则每个新 TCP 握手都可能随机选线,导致回程路径不一致被丢弃 - UDP 流量更敏感,无连接状态,必须靠五元组哈希或固定规则分流,否则 DNS、VoIP 很容易断
ISP 切换时连接中断的根本原因
不是配置没生效,而是连接状态和路由变更不同步。TCP 连接绑定的是四元组+路由输出接口,一旦接口 down 或路由表刷新,已有连接无法自动迁移到新路径。
- 用
ip link set eth0 down或拔网线,已建立的 SSH、下载连接会卡住或超时,不会“自动切到 eth1” -
ip rule和ip route只影响新连接的路由决策,不影响 conntrack 表项的输出接口缓存 - 若需平滑切换,得提前用
conntrack -D清旧连接,或上层应用支持重连(如 curl 的--retry),或用 TPROXY+iptables 做透明代理层兜底 - 最易忽略的一点:很多家用光猫在 WAN 口切换时会重置 ARP 表,导致即使路由正确,首包仍因 MAC 不可达而丢,需加
arping -U主动刷新










