OpenWrt 路由器部署 mihomo 内核:旁路由分流实战记录

把代理内核从电脑搬到路由器上,是不少家庭网络的终局形态:电视、游戏机这类不便安装客户端的设备也能被一并接管。本文记录在 OpenWrt 旁路由上部署 mihomo(Clash Meta)内核的完整过程——从部署形态抉择、二进制安装、订阅配置落地,到 TUN 接管、procd 守护与分流验证,每一步都给出可直接照抄的命令与明确的检查点。

mihomo 内核·TUN 接管模式·procd 开机守护·OpenWrt 23.05 演示环境

一、部署形态:主路由直装还是旁路由

在路由器上运行代理内核,先要做一道选择题:内核装在哪台设备上。两种形态各有清晰的使用边界,选错形态是新手翻车的第一个原因。

主路由直装

内核直接运行在出口网关上,局域网所有流量天然经过它,客户端零配置。代价是耦合过深:内核崩溃、规则写错、内存耗尽,任何一处出问题都是全家断网;同时 NAT 与加解密叠加在同一颗芯片上,对算力要求最高,百兆以上带宽的低端 MIPS 机型基本无法胜任。

旁路由(单臂网关)

另备一台设备——淘汰的电视盒子、树莓派、x86 小主机均可——刷入 OpenWrt,网口接入主路由所在的局域网,固定一个同网段 IP。需要走代理的设备,把默认网关与 DNS 服务器指向这台旁路由即可;不想被接管的设备保持原样,互不干扰。旁路由死机时,把网关改回主路由,十秒内恢复上网,风险被完全隔离。

本文以旁路由为主线展开。两种形态在内核安装与配置部分完全相同,差异只在流量入口,选择主路由直装的读者可跳过第四节中「网关指向」小节。

批注

旁路由的最大价值不是性能,而是可回退:任何配置失误都有一条十秒钟的退路。这是把代理内核放进生产网络之前,先铺好的一层安全垫。

二、内核选型与安装

mihomo 是 Clash 原版内核归档后由社区延续维护的分支(原 Clash.Meta),以单文件二进制发布,无额外依赖、可直接在 OpenWrt 上运行,是当前在路由器上部署的首选内核。它的 release 产物是 gzip 压缩的裸二进制,按 CPU 架构分包,因此第一步是认清自己设备的架构。

SSH 登录路由器,执行 uname -m,按下表对照选择下载包:

uname -m 输出典型设备release 文件名关键词
aarch64树莓派 4/5、NanoPi R4S、多数 ARM 盒子linux-arm64
armv7l树莓派 2/3(32 位系统)、老款开发板linux-armv7
mipselMT7621 等 MIPS 路由(K2P、新三)linux-mipsle-softfloat
x86_64软路由小主机、虚拟机linux-amd64-compatible

两个容易踩的坑:其一,x86 软路由请选带 compatible 后缀的包,OpenWrt 的 x86 构建面向较老指令集,普通 amd64 包在部分 CPU 上会直接报 Illegal instruction;其二,MT7621 这类 MIPS 设备是 little-endian 且多数没有硬浮点单元,必须选 mipsle-softfloat。

以 arm64 设备为例,完整安装命令如下:

opkg update
opkg install curl ca-bundle kmod-tun
curl -L -o /tmp/mihomo.gz https://github.com/MetaCubeX/mihomo/releases/download/v1.19.5/mihomo-linux-arm64-v1.19.5.gz
gunzip /tmp/mihomo.gz
mv /tmp/mihomo /usr/bin/mihomo
chmod +x /usr/bin/mihomo
mihomo -v

最后一行 mihomo -v 能打印出版本号,说明架构选对了;若提示 Illegal instruction 或 Exec format error,回到上表换包重试。命令中的版本号仅为示例,下载前请到 mihomo 的 releases 页面核对当前稳定版与确切文件名。kmod-tun 一并在此装好,第四节会用到。

批注

/tmp 在 OpenWrt 上是内存盘,重启即清空,只适合中转;内核与配置必须落进闪存,如 /usr/bin 与 /etc/mihomo。闪存不足 32MB 的机型请先做 extroot 或改用外置存储,否则连 GeoIP 数据库都放不下。

三、配置落地:订阅下载与关键字段

约定配置目录为 /etc/mihomo,内核以 -d /etc/mihomo 参数启动,目录下会依次出现 config.yaml、GeoIP 数据库与缓存文件。先建目录,再把订阅拉下来:

mkdir -p /etc/mihomo
curl -L -o /etc/mihomo/config.yaml "你的订阅地址"

多数机场的订阅链接在被 Clash 系客户端请求时会直接返回 YAML 配置,保存为 config.yaml 即可使用。如果下载到的是 base64 编码的节点列表,说明服务端返回的是通用订阅,需要在请求里带上 Clash 的 User-Agent,或者先在电脑上完成转换再 scp 上传到路由器——不建议在路由器上跑订阅转换程序,徒增维护面。

拿到订阅后,按旁路由的角色修改以下关键字段,其余保持订阅原样:

mixed-port: 7890            # HTTP 与 SOCKS 混合入口
allow-lan: true             # 允许局域网设备连接,旁路由必须开启
bind-address: "*"
log-level: warning
external-controller: 0.0.0.0:9090   # 外部控制接口
external-ui: ui             # 面板静态文件目录
secret: "请改成自定义口令"
dns:
  enable: true
  listen: 0.0.0.0:1053
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  nameserver:
    - 223.5.5.5
    - 119.29.29.29
  fallback:
    - https://1.1.1.1/dns-query
    - https://dns.google/dns-query
tun:
  enable: true
  stack: system
  auto-route: true
  auto-detect-interface: true
  dns-hijack:
    - any:53

三个字段决定旁路由能否工作:allow-lan 不开,局域网设备根本连不上 7890 端口;external-controller 绑定 0.0.0.0,电脑上的浏览器才能访问面板;tun 段则是下一节接管流量的核心。修改完成后,用内核自带的检查功能验证语法:

mihomo -t -d /etc/mihomo

输出提示 configuration file test is successful 即通过;若报错,信息里会给出具体行号,按行号回去修。

批注

external-controller 暴露在局域网时务必设置 secret,且切勿把它映射到公网。9090 端口持有切换节点、查看连接、修改配置的全部权限,裸奔等于把网络出口交给同网段的任何人。

四、接管流量:TUN 模式与网关指向

接管方式选 TUN,理由是它把路由维护收进内核内部:启用后 mihomo 创建名为 utun 的虚拟网卡,auto-route 自动写入路由规则,把本机发出的与被转发来的 TCP、UDP 流量全部收入内核,无需手写一条 iptables REDIRECT 规则,也不必为 UDP 单独做处理。stack 选 system 兼容性最好;追求吞吐可换 gvisor 对比测试。

TUN 的前提是内核态支持,第二节安装的 kmod-tun 即为此准备。确认设备节点存在:

ls /dev/net/tun

输出 /dev/net/tun 即正常;提示不存在则说明 kmod-tun 未装好或未加载,重装后重启。

客户端网关指向

旁路由本身不与任何设备直连,流量要靠「指路」过来。三种做法按推荐度排列:

  1. 主路由 DHCP 下发:在主路由的 DHCP 选项里,把网关(option 3)与 DNS(option 6)改为旁路由 IP,全屋设备无感切换,新接入设备自动生效。
  2. 单设备手动指定:只让需要的设备改网关与 DNS,其余设备直连主路由——这是旁路由独有的精细度,适合先拿一台设备试跑验证。
  3. 旁路由自建 DHCP:关掉主路由的 DHCP 由旁路由接管,控制最彻底,但旁路由故障时全屋拿不到地址,新手不建议。

两个系统层确认:OpenWrt 默认开启 IP 转发,可用 sysctl net.ipv4.ip_forward 复核返回值为 1;防火墙方面,进入「网络 → 防火墙 → 区域」,把 utun 设备加入 lan 区域的设备列表,否则被转发进来的流量会在 netfilter 层被丢弃,表现为客户端能连上旁路由,却打不开任何网页。

五、开机自启:交给 procd 守护

OpenWrt 的服务管理器是 procd,写一个 init 脚本即可获得开机自启与崩溃拉起。新建 /etc/init.d/mihomo,内容如下:

#!/bin/sh /etc/rc.common
# mihomo 内核守护脚本
START=99
STOP=10
USE_PROCD=1

start_service() {
    procd_open_instance mihomo
    procd_set_param command /usr/bin/mihomo -d /etc/mihomo
    procd_set_param respawn 3600 5 5
    procd_set_param stdout 1
    procd_set_param stderr 1
    procd_close_instance
}

respawn 一行的三个数字依次是阈值、间隔与重试次数,含义是进程退出后 5 秒拉起,一小时内反复崩溃超过 5 次则放弃;stdout 与 stderr 重定向到 syslog,之后用 logread 就能翻内核日志。赋予执行权限并启用:

chmod +x /etc/init.d/mihomo
/etc/init.d/mihomo enable
service mihomo start

enable 会在 /etc/rc.d 下建立 S99 开头的软链,重启路由器后内核自动起来。订阅更新也可以顺手自动化:在 crontab 里加一条每周凌晨重新下载 config.yaml 再执行 service mihomo restart 的任务,节点列表即可保持新鲜。

六、验证与排障清单

部署完成不等于分流正确,按下面的顺序逐项验证,每一步都有明确判据:

  1. 进程存活

    pgrep mihomo 有输出,/etc/init.d/mihomo status 显示 running。首次启动会自动下载 GeoIP 数据库到 /etc/mihomo,确认该目录可写且剩余空间充足。

  2. 日志干净

    logread -e mihomo 无反复报错。持续刷同一行错误通常是配置或网络问题,按错误信息定位。

  3. 面板可达

    浏览器打开 http://旁路由IP:9090/ui,输入 secret 后能看到实时连接。external-ui 指向的 ui 目录,需要先把 metacubexd 或 zashboard 的构建产物解压进去。

  4. DNS 已接管

    在客户端执行 nslookup www.google.com 旁路由IP,fake-ip 模式下返回 198.18.x.x 段地址,说明查询进入了内核而非旁路泄漏。

  5. 出口正确

    客户端打开任一 IP 查询站点,显示的应是节点出口地址;再访问一个国内站点,确认其走直连且速度正常,分流即告成立。

高频故障与对策:

至此,一台可自愈、可回退、按需接管的旁路由就部署完成了。后续维护只剩两件事:关注 mihomo 的版本更新节奏,以及定期备份 /etc/mihomo 目录——里面躺着全部配置与数据库,换机迁移时整个目录拷走即可。

下载Clash