docker路由冲突

default via 172.22.97.1 dev bond0.3097 proto static metric 400
blackhole 10.42.42.128/26 proto bird
10.42.42.135 dev cali675e68d37c2 scope link
10.42.42.136 dev cali450e5f9b4e9 scope link
10.42.42.137 dev calic517c05a73b scope link
10.42.42.138 dev cali9589f1a924c scope link
10.42.42.139 dev calieda3ec6e12b scope link
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown
172.21.0.0/16 dev br-21db2d2d3b4c proto kernel scope link src 172.21.0.1
172.22.97.0/24 dev bond0.3097 proto kernel scope link src 172.22.97.39 metric 400
172.22.99.0/24 dev bond0.3099 proto kernel scope link src 172.22.99.39 metric 401
172.22.100.0/24 dev bond0.3100 proto kernel scope link src 172.22.100.39 metric 402
172.22.101.0/24 dev bond0.3101 proto kernel scope link src 172.22.101.39 metric 403
192.168.0.0/16 via 192.168.140.1 dev ens13f0 proto static metric 102
192.168.140.0/24 dev ens13f0 proto kernel scope link src 192.168.140.39 metric 102

Linux 策略路由 + 源地址验证与 RP 过滤解析

这是Linux 策略路由 + 源地址验证 / 反向路径过滤最典型的现象,我用最直白的运维逻辑给你讲透:

核心一句话

你删掉这条路由之前: 外界访问 172.22 段 → 服务器回包时,错误地把回包扔进了 172.21 网桥里 → 包丢了,不通。

删掉之后: 回包终于走对了:从 bond0.3097 网关出去 → 正常回程 → 通了。


完整过程(你一定能看懂)

1. 外界访问你的流程

  • 外面机器:公网IP / 其他机房IP

  • 访问你:172.22.97.39

  • 包正常进来:bond0.3097

2. 关键在:服务器怎么回包

服务器要回复这个包,它会查路由表: 目标 IP = 外面那台机器的 IP

但问题来了: 你这台机器上 同时存在两条超大网段路由

  1. 172.21.0.0/16 dev br-xxx scope link

  2. default via 172.22.97.1 dev bond0.3097

重点:Linux 路由匹配规则

更长掩码 / 更精确的网段优先匹配 /16 优先级 远大于 默认路由


3. 为什么删之前不通?

外界 IP 假设是:114.114.114.114

服务器查路由:

  1. 先看 172.21.0.0/16 → 不匹配

  2. 再看 172.22.x.0/24 → 不匹配

  3. 然后看 默认路由 → 匹配,应该走网关出去


但!你这里有个隐藏坑:rp_filter 反向路径过滤

Linux 默认会做 严格反向路径检查

从哪个网卡进来的包,回包必须从同一张网卡回去,否则直接丢包。

真实情况是:

  • 包从 bond0.3097 进来

  • 系统检查:回去的路由是不是也走 bond0.3097

  • 结果发现: 本机有一条 [172.21.0.0/16](172.21.0.0/16) 超大直连路由 系统会错误判断

    这台主机的主路由出口是网桥 br-xxx,不是物理网卡 路径不对称 → 直接丢弃回包

所以表现就是: 能抓到进来的包,抓不到回去的包 → ping 不通、访问超时


4. 为什么删掉 [172.21.0.0/16](172.21.0.0/16) 就好了?

删掉之后:

  • 系统再也没有那条超大直连网桥路由干扰

  • 回程路由只剩下:default via 172.22.97.1 dev bond0.3097

  • 系统检查:

    进:bond0.3097 出:bond0.3097 路径完全对称 → 放行

于是: 包正常回去 → 外界可以访问 172.22 段了


5. 极简总结(最关键的两点)

  1. [172.21.0.0/16](172.21.0.0/16) 是一条 /16 超大路由 优先级极高,会干扰 Linux 对 “出口网卡” 的判断。

  2. rp_filter(反向路径过滤) 因为路由混乱,导致系统认为进出网卡不一致,直接丢弃回包。

  3. 删掉它 = 清除干扰路由 = 回程走正确物理网卡 = 通了


额外小知识(对你很有用)

如果你不想删路由,也能解决:

net.ipv4.conf.all.rp_filter = 2
net.ipv4.conf.bond0.rp_filter = 2

设为 2(松散模式),就不会严格检查进出网卡是否一致。

你现在的现象,就是标准的 rp_filter 导致的回程丢包

防火墙 2026-03-10

评论区