Linux 路由规则
1. 流量分拣的三级流程
当一个 IP 包准备发出(或进入)时,内核会按照以下顺序进行“三审制”:
第一级:分拣员 (ip rule)
这是最高层。内核会查阅规则列表(从优先级 0 开始往后查)。
- 它问: “这个包是谁发的?发给谁的?带了什么标记(fwmark)?”
- 它做: “根据规则,你应该去查 Table X。”
- 排查重点:
ip rule list。看你的包是否命中了一个特定的lookup动作。
第二级:地图 (ip route table)
一旦 ip rule 指向了一个 Table(比如 netbird 或 main),内核就会进入这个特定的表里查地图。
- 它问: “这个表里有比
0.0.0.0/0更具体的路径(比如192.168.3.0/24)吗?” - 它做: * 如果找到了精确匹配:直接发出,流程结束。
- 如果没找到(或被
suppress抑制):退回第一级,继续看下一条ip rule。
- 如果没找到(或被
- 排查重点:
ip route show table <name>。
第三级:出口 (Device/Interface)
地图指出了出口(如 dev wt0 或 dev ens33)。
- 它问: “这个网卡现在状态是对的吗?网关能通吗?”
- 排查重点:
ip addr和ping <gateway_ip>。
2. 故障排查的“标准套路”
当你发现一个 IP(比如 192.168.3.6)走得不对,或者不通时,请按以下步骤“逆向侦破”:
第一步:询问内核的最终判决
不要自己去人肉查表,直接问内核:
ip route get 192.168.3.6
这条命令会直接告诉你:内核打算从哪个 Table 出发、从哪个接口出去、源 IP 是哪个。
- 如果这里显示的网卡不对,说明路由表或规则有问题。
第二步:追踪路由表来源
如果 ip route get 显示它走了一个你没听过的 Table(比如 table 110),去查它的名字:
cat /etc/iproute2/rt_tables | grep 110
# 然后看这个表的所有内容
ip route show table 110
第三步:确认规则拦截 (Rule Check)
查看 ip rule list,重点寻找那些带 not、fwmark 或者 suppress 关键字的规则。
- 常见坑点: 像 NetBird 这种工具会用
suppress_prefixlength 0来故意跳过主路由表的默认网关,强制流量滑落到后面的自定义表里。
第四步:物理链路与抓包
如果路由查出来没问题,但就是 Ping 不通:
# 看看包到底从哪个网卡飞出去了
tcpdump -i <网卡名> host 192.168.3.6
- 如果 tcpdump 有包发出但没回包:对端路由器没写回程路由,或者防火墙拦了。
- _如果 tcpdump 压根没包:流量在更底层的 iptables/nftables 被拦截了。
3. 核心关系图解
netbird 配置后 ip rule 关系。
ip rule list
0: from all lookup local
105: from all lookup main suppress_prefixlength 0
110: not from all fwmark 0x1bd00 lookup netbird
32766: from all lookup main
32767: from all lookup default
graph TD
Start((数据包产生)) --> R0[<b>ip rule 0</b><br/>lookup local]
R0 -->|未命中/非本地| R105[<b>ip rule 105</b><br/>lookup main]
subgraph Table_Main [Routing Table: main]
M1[是否有精确路由?<br/>例如: 192.168.1.0/24]
M2[是否有默认路由?<br/>0.0.0.0/0]
end
R105 --> M1
M1 -->|是| Exit1([从 ens35/ens33 发出])
M1 -->|否| M2
M2 -->|命中默认路由| Suppress{是否存在<br/>suppress_prefixlength 0?}
Suppress -->|是: 抑制并回溯| R110[<b>ip rule 110</b><br/>lookup netbird]
subgraph Table_Netbird [Routing Table: netbird]
N1[是否有 VPN 路由?<br/>例如: 192.168.3.0/24]
end
R110 --> N1
N1 -->|是| Exit2([封装入 wt0 隧道])
N1 -->|否| R32766[<b>ip rule 32766</b><br/>lookup main]
R32766 --> M2
M2 -->|无抑制再次查找| Exit3([从默认网关 192.168.1.1 发出])
style R105 fill:#f9f,stroke:#333,stroke-width:2px
style R110 fill:#bbf,stroke:#333,stroke-width:2px
style Suppress fill:#fff4dd,stroke:#d4a017,stroke-width:2px
总结建议
在你的场景中(NetBird + 多网卡):
- 优先用
ip route get <IP>定位 Table。 - 用
ip route show table <TABLE_NAME>确认路径。 - 用
ip rule list理解流量为什么会被导向那个 Table。
Read other posts