一、部署形态:主路由直装还是旁路由
在路由器上运行代理内核,先要做一道选择题:内核装在哪台设备上。两种形态各有清晰的使用边界,选错形态是新手翻车的第一个原因。
主路由直装
内核直接运行在出口网关上,局域网所有流量天然经过它,客户端零配置。代价是耦合过深:内核崩溃、规则写错、内存耗尽,任何一处出问题都是全家断网;同时 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 |
| mipsel | MT7621 等 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 未装好或未加载,重装后重启。
客户端网关指向
旁路由本身不与任何设备直连,流量要靠「指路」过来。三种做法按推荐度排列:
- 主路由 DHCP 下发:在主路由的 DHCP 选项里,把网关(option 3)与 DNS(option 6)改为旁路由 IP,全屋设备无感切换,新接入设备自动生效。
- 单设备手动指定:只让需要的设备改网关与 DNS,其余设备直连主路由——这是旁路由独有的精细度,适合先拿一台设备试跑验证。
- 旁路由自建 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 的任务,节点列表即可保持新鲜。
六、验证与排障清单
部署完成不等于分流正确,按下面的顺序逐项验证,每一步都有明确判据:
进程存活
pgrep mihomo有输出,/etc/init.d/mihomo status显示 running。首次启动会自动下载 GeoIP 数据库到 /etc/mihomo,确认该目录可写且剩余空间充足。日志干净
logread -e mihomo无反复报错。持续刷同一行错误通常是配置或网络问题,按错误信息定位。面板可达
浏览器打开 http://旁路由IP:9090/ui,输入 secret 后能看到实时连接。external-ui 指向的 ui 目录,需要先把 metacubexd 或 zashboard 的构建产物解压进去。
DNS 已接管
在客户端执行
nslookup www.google.com 旁路由IP,fake-ip 模式下返回 198.18.x.x 段地址,说明查询进入了内核而非旁路泄漏。出口正确
客户端打开任一 IP 查询站点,显示的应是节点出口地址;再访问一个国内站点,确认其走直连且速度正常,分流即告成立。
高频故障与对策:
- Illegal instruction / Exec format error:架构包选错,回第二节对照表换包。
- 节点全部超时但面板能打开:路由器系统时间偏差过大导致 TLS 校验失败,先确认 NTP 校时完成;旁路由自身也要能正常解析订阅域名。
- 客户端能连旁路由但全网不通:utun 未加入防火墙 lan 区域,或客户端到旁路由的网关指向未生效,逐项复查第四节。
- 国内站点莫名变慢:DNS 分流未生效,检查 dns 段是否启用、fake-ip-filter 是否覆盖国内域名;必要时把客户端 DNS 也指向旁路由,避免绕过内核直接问上游。
至此,一台可自愈、可回退、按需接管的旁路由就部署完成了。后续维护只剩两件事:关注 mihomo 的版本更新节奏,以及定期备份 /etc/mihomo 目录——里面躺着全部配置与数据库,换机迁移时整个目录拷走即可。