先确定部署拓扑:主路由还是旁路由

在 OpenWrt 上运行 Clash 系内核,当前通常是部署 mihomo。mihomo 延续 Clash Meta 的配置格式与规则能力,可以直接读取 YAML 配置,并提供 mixed-port、DNS、TUN、规则集和外部控制接口。路由器场景与桌面客户端不同:桌面端只处理本机流量,路由器还要识别来自局域网设备的转发流量,并处理 DNS、策略路由、IPv4 与 IPv6 的返回路径。

部署前先确定设备在网络中的角色。主路由方案由 OpenWrt 负责拨号、DHCP、DNS 和默认网关,数据路径清晰,透明代理规则也最容易统一管理。旁路由方案保留现有主路由,OpenWrt 作为同一局域网中的第二个三层设备,只接管指定终端或由 DHCP 分配过来的流量。旁路由改动较少,但网关、DNS 和回程路径必须逐项核对。

主路由拓扑

  • 光猫桥接时,由 OpenWrt 的 WAN 口拨号;光猫路由模式下,OpenWrt WAN 口从上级网络获取地址。
  • 局域网终端默认网关指向 OpenWrt,例如 192.168.10.1
  • DHCP 和 DNS 都由 OpenWrt 提供,终端无需单独设置代理地址。
  • TUN 或 TProxy 规则可以覆盖整个 LAN,也可以按源地址、MAC 对应的固定租约或目标网段绕过。

旁路由拓扑

  • 主路由可使用 192.168.1.1,旁路由设置为同网段固定地址 192.168.1.2
  • 旁路由的默认网关和上游 DNS 先指向主路由,避免自身更新订阅时失去出口。
  • 需要代理的终端将网关和 DNS 指向 192.168.1.2;其他终端继续使用主路由。
  • 若主路由 DHCP 支持下发自定义网关,可统一下发旁路由地址。否则应在终端手动设置,或谨慎调整 DHCP 服务边界。

硬件、架构与存储空间

内核能否启动只取决于架构和运行库是否匹配,实际吞吐则受到 CPU 单核性能、加密算法、规则规模、连接数和网络驱动共同影响。仅用于两三台终端、100 Mbps 左右带宽时,双核 ARM64 与 256 MB 内存可以完成基础规则代理。若目标是 500 Mbps 以上、同时启用 TUN、DNS fake-ip 和较大的规则集,建议从四核 ARM64、512 MB 内存起步。千兆线路还要检查设备的 NAT、网卡中断和 CPU 软中断占用。

一份包含数万条规则和多个 rule-provider 的配置,mihomo 常见常驻内存约为 80 至 180 MB;启用大量域名规则、连接追踪和面板查询后还会继续上升。OpenWrt 自身及 dnsmasq、firewall4、日志服务也需要内存,因此 128 MB 设备通常只适合精简配置。闪存方面,内核文件、GeoIP、GeoSite、规则集和临时下载文件合计预留 100 MB 以上更稳妥。

确认 CPU 架构

通过 SSH 登录 OpenWrt,先读取系统报告,不要仅凭路由器商品名称选择二进制文件。

uname -m
ubus call system board
cat /etc/openwrt_release

x86_64 对应 AMD64,aarch64 对应 ARM64。部分旧设备会返回 armv7lmipsmipsel。MIPS 还区分大小端和浮点实现,下载前必须与发布文件的架构标记逐项对应。二进制架构错误时,执行通常直接返回 Exec format error

检查 TUN 与透明代理模块

ls -l /dev/net/tun
opkg list-installed | grep -E 'kmod-tun|firewall4|nftables'
nft list ruleset | head

TUN 模式至少需要内核 TUN 支持,OpenWrt 常用软件包为 kmod-tun。基于 nftables 的 TProxy 方案还需要当前固件提供相应透明代理模块,例如 kmod-nft-tproxy。软件包名称会随 OpenWrt 分支和目标平台变化,应以当前设备的软件源为准,不要混装其他版本仓库中的内核模块。

放置 mihomo 内核与最小配置

独立部署建议把可执行文件放在 /usr/bin/mihomo,配置和运行数据放在 /etc/mihomo。对于闪存紧张的设备,也可以把规则集目录放到挂载的 USB 存储中,但启动脚本必须等待挂载完成。以下命令假设二进制文件已经通过 SCP 上传到 /tmp/mihomo

mkdir -p /etc/mihomo
install -m 0755 /tmp/mihomo /usr/bin/mihomo
/usr/bin/mihomo -v

先建立一份能够启动的 /etc/mihomo/config.yaml。代理节点和策略组应来自实际服务配置,下面只展示路由器相关的监听、控制接口和 DNS 结构。

mixed-port: 7890
redir-port: 7892
tproxy-port: 7893
allow-lan: true
bind-address: "*"
mode: rule
log-level: info
ipv6: false

external-controller: 127.0.0.1:9090
secret: "change-this-controller-secret"

profile:
  store-selected: true
  store-fake-ip: true

dns:
  enable: true
  listen: 0.0.0.0:1053
  ipv6: false
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  fake-ip-filter:
    - "*.lan"
    - "localhost.ptlogin2.qq.com"
  nameserver:
    - https://1.1.1.1/dns-query
    - https://8.8.8.8/dns-query

proxies: []
proxy-groups:
  - name: PROXY
    type: select
    proxies:
      - DIRECT

rules:
  - GEOIP,CN,DIRECT
  - MATCH,PROXY

allow-lan: true 允许局域网终端访问代理监听端口,因此 OpenWrt 防火墙应只允许可信 LAN 区域访问 7890、7892、7893 和 DNS 监听端口。外部控制接口示例仅绑定到 127.0.0.1:9090;如果面板部署在另一台设备上,需要改为局域网监听地址,并设置强随机 secret 与明确的防火墙来源限制。

保存后先进行语法验证,再以前台方式启动。-d 指定运行目录,mihomo 会从该目录读取 config.yaml 并存放缓存数据。

/usr/bin/mihomo -t -d /etc/mihomo
/usr/bin/mihomo -d /etc/mihomo

看到配置加载完成后,在另一个 SSH 会话中检查端口:

ss -lntup | grep -E '7890|7892|7893|9090|1053'
logread -f

TUN 与 TProxy 的取舍

TUN 和 TProxy 都能实现终端无感接入,但处理路径不同。TUN 由 mihomo 创建虚拟网卡,把进入虚拟接口的 IP 流量交给用户态协议栈。TProxy 依靠防火墙标记、策略路由和透明套接字,把 TCP 或 UDP 流量送到指定监听端口,同时保留原始目标地址。两者都不是简单打开一个配置开关;路由器还需要匹配当前 OpenWrt 的转发和防火墙结构。

TUN:部署路径较集中

mihomo 的 TUN 配置可直接写入 YAML。OpenWrt 上通常使用 system 栈,配合自动路由和自动识别出口接口:

tun:
  enable: true
  stack: system
  device: mihomo
  auto-route: true
  auto-detect-interface: true
  strict-route: true
  dns-hijack:
    - any:53
  mtu: 1500

TUN 的优势是规则主要集中在内核配置中,TCP 与 UDP 处理方式一致,对游戏机、电视和不支持手动代理的应用更友好。代价是数据进入用户态虚拟网卡,低性能路由器上的 CPU 占用可能高于针对性配置的 TProxy。若部分网站超时而小数据包正常,可把 MTU 从 1500 逐步降到 1480、1460 或 1400 测试,但最终值应结合 PPPoE、隧道和上游网络确定。

TProxy:控制粒度较细

TProxy 更适合已经熟悉 nftables、策略路由和 OpenWrt firewall4 的维护者。典型数据路径包括:在 prerouting 链筛选 LAN 流量、跳过局域网和保留地址、为目标连接设置防火墙标记、用 ip rule 把带标记流量送入本地路由表,再转到 mihomo 的 tproxy-port: 7893。UDP 也要单独纳入规则。

OpenWrt 22.03 之后默认使用 firewall4 与 nftables。旧教程中的 iptables 命令、链名称和启动时机不能直接套到 nftables 环境。手写 TProxy 规则时还要避免重复处理路由器自身发起的订阅下载、NTP、软件包更新和节点连接,否则可能形成代理回环。实际部署更适合使用与当前 OpenWrt 版本匹配的管理组件生成规则,再通过 nft list ruleset 检查结果。

选择依据

  • 需要快速覆盖 TCP、UDP 与多数局域网设备:优先评估 TUN。
  • 设备 CPU 较弱,但维护者能精确管理 nftables:可评估 TProxy。
  • 只代理浏览器和少量电脑:先使用 mixed-port: 7890,不必立即增加透明代理复杂度。
  • 需要按终端分流:两种方案都可按源 IP 控制,前提是 DHCP 为终端分配固定地址。
  • 网络启用了 IPv6:必须同步设计 IPv6 DNS、路由和防火墙策略,不能只处理 IPv4 后假定所有连接都会经过代理。

订阅更新:下载、校验配置语法、原子替换

路由器上的订阅不是把 URL 填入图形界面就结束。更新过程至少应包含下载到临时文件、测试 YAML、替换正式配置和重载服务四步。直接覆盖正在使用的 config.yaml,一旦下载中断或服务端返回 HTML 错误页,下一次重启就可能无法加载配置。

下面的脚本使用 uclient-fetch 下载完整配置。订阅地址应写入仅 root 可读的文件或脚本,不应输出到公开日志。把脚本保存为 /usr/bin/update-mihomo,并执行 chmod 700 /usr/bin/update-mihomo

#!/bin/sh
set -eu

CONFIG_DIR="/etc/mihomo"
TEMP_FILE="/tmp/mihomo-config.yaml"
SUB_URL="https://subscription.example/path"

uclient-fetch -q -O "$TEMP_FILE" "$SUB_URL"

/usr/bin/mihomo -t -f "$TEMP_FILE"

cp "$CONFIG_DIR/config.yaml" "$CONFIG_DIR/config.yaml.bak"
mv "$TEMP_FILE" "$CONFIG_DIR/config.yaml"

/etc/init.d/mihomo reload || /etc/init.d/mihomo restart

mihomo -t -f 会解析指定配置文件,可以拦截 YAML 缩进、字段结构和部分规则错误。它不能确认所有远端节点都可连接,因此更新后仍要查看服务日志和策略组状态。若订阅依赖特定 User-Agent 或重定向,可根据服务提供方要求调整下载命令。

确认手动更新稳定后,再写入 cron。例如每天 04:17 更新一次:

17 4 * * * /usr/bin/update-mihomo >> /tmp/mihomo-update.log 2>&1

OpenWrt 的 /tmp 位于内存文件系统,更新日志重启后会清空,适合避免长期写闪存。排障阶段要限制日志大小;长期运行不宜让调试级日志持续写入闪存。

使用 procd 设置开机自启

OpenWrt 服务应交给 procd 管理,而不是把后台命令直接追加到 /etc/rc.local。procd 可以跟踪进程、在异常退出后重启,并统一处理启动、停止和重载。创建 /etc/init.d/mihomo

#!/bin/sh /etc/rc.common

START=99
STOP=10
USE_PROCD=1

start_service() {
  procd_open_instance
  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_set_param limits nofile="65535 65535"
  procd_close_instance
}

reload_service() {
  procd_send_signal mihomo HUP
}

service_triggers() {
  procd_add_reload_trigger "network"
}

赋予执行权限并启用服务:

chmod 755 /etc/init.d/mihomo
/etc/init.d/mihomo enable
/etc/init.d/mihomo start
/etc/init.d/mihomo status
logread -e mihomo

respawn 3600 5 5 表示在观察窗口内处理异常退出并延迟重启,避免进程高频崩溃时形成紧密循环。若配置中的远端规则集必须联网下载,首次启动可能受 WAN 尚未就绪影响。可以把必要规则文件预先放入本地,或让更新任务在网络连通后单独执行,不要依赖每次启动都即时取得所有远端资源。

分流、安全边界与常见故障

保留地址必须直连

透明代理规则应跳过本机回环、局域网、组播和保留地址,例如 127.0.0.0/810.0.0.0/8172.16.0.0/12192.168.0.0/16224.0.0.0/4。如果家庭网络使用多个私有网段,还要明确哪些网段通过静态路由互访。盲目代理 NAS、打印机和管理页面会造成访问绕路,甚至让路由器后台无法打开。

控制接口只开放给管理网络

9090 控制接口可以切换策略、读取连接和修改运行状态,应默认绑定回环地址。需要从 LAN 使用面板时,可绑定到路由器 LAN 地址,例如 192.168.10.1:9090,同时设置 secret,再由防火墙限制来源。代理端口也只应在 LAN 防火墙区域开放,不应从 WAN 接受连接。

内核启动后终端仍无法上网

  1. 在路由器上执行 ip route,确认默认路由指向实际 WAN。
  2. 执行 nslookup openwrt.org 127.0.0.1,确认基础 DNS 正常。
  3. 让电脑手动连接路由器的 7890 端口,排除节点和订阅问题。
  4. 执行 nft list ruleset,确认透明代理链确实存在且计数器增长。
  5. 检查终端网关和 DNS 是否都指向计划中的主路由或旁路由地址。

访问国内站点正常,部分境外站点超时

先检查策略组是否选择了可用节点,再比较域名解析结果与规则命中。若只有大页面、上传或视频连接失败,测试 MTU。PPPoE 链路通常比以太网少 8 字节,叠加其他隧道后还会下降。可以使用逐步减小包长的方式观察,但不要把所有故障都归因于 MTU。

路由器能访问,局域网终端不能访问

这种情况通常说明 mihomo 自身出站正常,但 LAN 转发路径没有进入透明代理。主路由检查 LAN 到 WAN 转发与透明代理规则;旁路由检查 net.ipv4.ip_forward、防火墙区域和终端网关。如果终端仍把主路由作为网关,流量自然不会经过旁路由。

重启后服务存在但规则未生效

服务启动和防火墙加载存在顺序差异。若 TProxy 规则由独立脚本生成,应接入 firewall4 的 include 或热插拔机制,并保证重复执行不会创建重复链。若使用 TUN 的自动路由,检查启动日志中是否存在接口创建、路由表或权限错误,同时确认 /dev/net/tun 在启动时已经可用。

部署验收清单

路由器直跑内核的重点不是让进程显示为“运行中”,而是让整个数据路径可预测、可恢复。正式接管家庭网络前,可以按以下清单逐项验收:

  • 内核架构与设备一致,mihomo -v 能正常返回版本信息。
  • mihomo -t 能通过配置检查,订阅更新失败时不会覆盖现有配置。
  • 7890 普通代理端口已单独验证,节点和策略组可以建立连接。
  • 主路由或旁路由的网关、DHCP、DNS 职责明确,没有两个 DHCP 服务冲突。
  • TUN 或 TProxy 只启用一种主要接管路径,避免重复重定向同一连接。
  • 局域网、路由器管理地址、组播和必要的保留网段已绕过代理。
  • 控制接口设置访问密钥,并由防火墙限制到可信管理网络。
  • 重启设备后,WAN、时间、DNS、mihomo、透明代理规则按顺序恢复。
  • 分别测试网页、视频、UDP 应用、局域网 NAS 和打印机访问。
  • 测速时记录 CPU、内存、软中断和温度,而不是只看单次带宽结果。

对于首次部署,建议先从普通 mixed-port 和单台测试终端开始,再扩展到 TUN 或 TProxy。主路由方案路径更直接,适合统一接管;旁路由方案便于渐进迁移,适合先覆盖少量设备。无论选择哪种拓扑,配置语法、DNS 路径、防火墙规则和开机恢复都应能够分别验证。