从 Mihomo TUN 模式看策略路由的艺术
0. 诡异的“现状”
当我第一次开启 Mihomo (Clash Meta) 的 TUN 模式并成功科学上网后,作为一个有好奇心的 Linux 用户,我习惯性地敲下 ip route 想看看默认网关变成了什么。
然而,看到的结果可能会让我大吃一惊:
1 | |
一切看起来太“正常”了。
默认网关(default)依然指向家里的路由器(192.168.3.1),并没有像传统的 VPN 那样被修改为虚拟网卡。
既然路由表没变,流量是怎么“凭空”跑进 Mihomo 的 Meta 网卡的?
实际上,真正的 Magic 并没有发生在大家熟悉的 ip route(路由表)里,而是发生在其上层——**ip rule(路由策略)** 中。
让我们看看 ip rule 的输出:
1 | |
1. 地图与分拣员
在 Linux 网络世界里,管理流量主要靠两个层级:
- **
ip route(路由表 - 地图)**:它只负责回答”去哪里怎么走”。比如:去局域网走 Wi-Fi 网卡,去互联网走网关。 ip rule(路由策略 - 分拣员):它是路由表的”经理”。它决定了谁有资格看哪张地图。
为什么不只用一张地图?
因为需求太复杂。比如:代理软件自身的流量必须走”普通地图”发出去,而浏览器的流量必须看”代理地图”进 TUN 网卡。如果大家看同一张图,就会陷入”无限套娃”的死循环。
2. Mihomo 的 TUN 模式是如何工作的?
通过观察 ip rule 的输出,我们可以将数据包的处理流程分为三个阶段:
第一阶段:特殊车辆避让(防环路)
1 | |
- 原理:Mihomo 给自己发出的加密数据包打上了”防火墙标记”(
fwmark 0x80000)。 - 逻辑:分拣员看到这种标记,会命令它直接查
main表(物理网卡出口)。这保证了代理后的流量能正常发出,而不会被再次拦截,完美避免了环路。
第二阶段:精妙的分流(劫持核心)
1 | |
这是最精彩的部分:
- 黑科技
suppress_prefixlength 0:内核先尝试查main表。如果你访问的是局域网(掩码长度 > 0),就直接查表走人;如果你访问的是互联网(只能匹配到默认路由,掩码长度为 0),这条规则就会失效,继续往下走。 - 强制入表:没被
main表接纳的上网流量,在9002规则处被统统扔进了 **table 2022**。 - 进入 TUN:
table 2022是一张 Mihomo 专门画的地图,上面只有一条路:default dev Meta。于是,流量顺着管道进入了 Mihomo 进程。
第三阶段:兜底与放行
1 | |
- 对于那些从 TUN 网卡处理完出来、准备发往互联网的包,Mihomo 通过
goto 9010让它们跳过拦截区,最终从32766处的main表正常发出。
3. 流量的一生:以访问 Google 为例
- 应用发起请求:目标
8.8.8.8。 - 分拣员判断:
- 不是本地包?跳过
local。 - 没有标记?跳过
5210。 - 查
main表发现只有默认路由?被suppress_prefixlength 0踢出。 - **匹配
9002**:滚去查table 2022!
- 不是本地包?跳过
- 进入虚拟网卡:
table 2022说走Meta设备,Mihomo 收到数据包。 - 代理加密:Mihomo 处理后,给新包打上
0x80000标记。 - 二次出发:
- 匹配
5210规则。 - 直接查
main表。 - 顺利通过 Wi-Fi 网卡发出。
- 匹配
4. ip 命令家族速查
ip 命令是现代 Linux 运维的标配:
| 命令 | 职责 | 场景举例 |
|---|---|---|
ip link |
网卡开关/物理属性 | 修改 MTU、开启/关闭网卡 |
ip addr |
IP 地址管理 | 给网卡添加多个 IP |
ip route |
管理地图 | 手动添加静态路由 |
ip rule |
决策引擎 | 实现多线接入、流量劫持 |
ip neigh |
邻居发现 | 查看局域网内的 MAC 地址 |
ip netns |
网络多重宇宙 | Docker 容器的网络隔离原理 |
从 Mihomo TUN 模式看策略路由的艺术
https://20040702.xyz/2026/01/01/linux-route/