小米万兆路由器跑 Mihomo:从 Redir/TProxy 到 Tun 的一次完整排障沉淀
这是一份操作复盘和后续排障线索。涉及到的路由器密码、API Key、SSH 私钥、订阅地址、节点名称和 token 均已刻意省略或泛化。
背景
目标是把原本跑在本机和手机侧的代理能力下沉到小米万兆路由器上,让局域网设备不用单独配置系统代理,也不用每台设备都跑 Clash/Mihomo。期望效果包括:
- 路由器侧透明代理,家里设备连 Wi-Fi 或有线即可按规则分流。
- 使用现有 Mihomo 配置和订阅处理链路。
- 在路由器 U 盘上跑 ShellCrash/Mihomo、Sub-Store、subs-check 等服务。
- 后续尽量减少 MacBook 上长期运行的服务。
- 如果能继续折腾,最终希望搞清楚 TProxy 为什么在这台机器上失败。
硬件和系统环境:
- 设备:小米万兆路由器 RC01。
- 当前固件:
1.1.56。 - 系统:OpenWrt
18.06-SNAPSHOT,kernel5.4.164,aarch64,targetipq95xx/generic。 - 当前 WAN:
eth4 = 192.168.1.2/24 via 192.168.1.1。 - 当前 LAN:
br-lan = 192.168.31.1/24。 - U 盘:挂载在
/mnt/usb-60a54d50,约 28.3G 可用空间。
最终可用状态
最后稳定下来的方案是 ShellCrash + Mihomo Meta + Tun + fake-ip。
核心组件:
- ShellCrash:
/mnt/usb-60a54d50/ShellCrash - ShellCrash 版本:
1.9.4release - Mihomo Meta:
v1.19.24 - 透明模式:
Tun模式 - 防火墙:
iptables - DNS:
fake-ip - IPv6:开启透明劫持,但关闭 IPv6 DNS 返回
当前关键配置:
firewall_mod=iptables
redir_mod=Tun模式
dns_mod=fake-ip
common_ports=OFF
quic_rj=OFF
ipv6_redir=ON
ipv6_dns=OFF
服务入口:
- Mihomo 控制 API / 面板入口:
http://192.168.31.1:9999/ui/ - Mihomo API:
http://192.168.31.1:9999 - subs-check 管理页:
http://192.168.31.1:8199/admin-ui - Sub-Store 前端:
http://192.168.31.1:8298/?api=http://192.168.31.1:8299/sub-store - Sub-Store 后端:
http://192.168.31.1:8299/sub-store
验证结果:
- MacBookAir 作为干净客户端,不设置系统代理,直接访问 Google、GitHub、Baidu 均成功。
- Mihomo
/connectionsAPI 看到客户端连接类型为Tun。 - fake-ip 生效,例如 Google A 记录返回
28.0.0.x,AAAA 不返回,避免普通域名访问走真实 IPv6。 - 路由器重启后,SSH、ShellCrash、Mihomo、subs-check、Sub-Store 均能恢复。
- 路由器内存约 1.8G,扣掉缓存后实际占用约 536M,剩余约 1.28G,当前压力不大。
持久化和守护
ShellCrash 自身有 init 脚本:
/etc/init.d/shellcrash
/etc/rc.d/S99shellcrash -> ../init.d/shellcrash
USB 侧服务通过 /data/router_usb_services.sh 拉起,root crontab 每 2 分钟执行一次。
这个脚本后续做了增强:
- 如果
CrashCore没运行,自动调用/etc/init.d/shellcrash start。 - 如果
CrashCore在但fwmark 0x1ed4策略路由不存在,自动补跑 ShellCrash 的fw_start.sh。 - 自动补充 IPv6 防漏规则。
- 对
FORWARD -o utun和 IPv6 DROP 规则做去重。
最终重启验证中,路由器启动约几十秒后网络可达,随后 ShellCrash/USB 服务在 cron 守护下恢复完整状态。
Redir、TProxy、Tun 的原理差异
Redir
Redir 模式主要靠 NAT REDIRECT 把 LAN 里的 TCP 流量重定向到 Mihomo 的 redir-port,常见端口是 7892。
优点:
- 简单。
- 对 TCP 网页流量比较稳。
缺点:
- 主要覆盖 TCP。
- UDP、QUIC、IPv6、部分直接 IP 场景更容易漏。
- 国内网站如果被劫持进 Redir,也仍然会先进入 Mihomo 再按规则 DIRECT,不是完全绕过 Mihomo。
TProxy
TProxy 理论上是最正统的透明代理方式:iptables mangle 表使用 TPROXY 捕获 TCP/UDP,同时保留原始目标地址,再通过策略路由把包送到本机透明 socket。
理论优点:
- TCP/UDP 都能处理。
- 不需要像 Redir 那样改目标地址。
- 对 UDP/QUIC 更自然。
- 如果内核和固件路径完整,透明度很好。
本次失败点:
- 模块存在。
- iptables TPROXY 规则计数增长。
ip rule fwmark 0x1ed4 table 100存在。- table 100 指向
local default dev lo。 ip route get ... mark 0x1ed4 iif br-lan显示会送本地 lo。- 但 Mihomo 无透明连接,测试客户端超时。
tcpdump能看到 SYN 进入br-lan,但在lo和 WAN 口看不到后续投递。
关键证据是后来编译了一个最小透明 socket probe:
- probe 使用
IP_TRANSPARENT监听测试端口。 - MacBook 直连
http://192.168.31.1:测试端口/hello能返回ok。 - 但把 LAN 流量通过 TProxy 转给这个 probe 时,probe 日志没有任何请求,客户端超时。
- 同时 TProxy 规则计数仍然增加。
因此基本可以排除 Mihomo 配置、节点、订阅、ShellCrash listener 的问题,更像是小米官方固件的桥接/iptables/TPROXY 投递路径问题。
Tun
Tun 模式是当前可用方案。
工作路径:
LAN 设备
-> 路由器 iptables mangle 打 fwmark 0x1ed4
-> policy routing table 100/101
-> utun
-> Mihomo 读取虚拟网卡流量
-> 按规则 DIRECT 或 PROXY
优点:
- TCP/UDP 都覆盖。
- 实测可用。
- 对终端下载、Docker 拉镜像、浏览器、普通 QUIC/UDP 都更完整。
- 配合 fake-ip 可以让局域网设备无需手动配置代理。
缺点:
- 国内直连流量也会先进入 Mihomo 分流,再 DIRECT 出去,比纯硬件转发多一层处理。
- 更依赖
utun + fwmark + policy route + fake-ip状态。 - 理论上比 TProxy 多一点虚拟网卡和包处理开销。
- 对非 TCP/UDP 协议仍不负责,例如 ICMP ping、GRE、ESP/IPsec 等。
IPv6 防漏处理
一开始 ipv6_redir=OFF。MacBookAir 曾拿到过 240e: 全局 IPv6 地址,但当时路由器没有 IPv6 默认路由,且 fake-ip DNS 不返回 AAAA,所以普通域名没有真实 IPv6 泄漏。
为了避免以后 ISP 或路由器恢复 IPv6 默认路由时突然漏流量,最终改成:
ipv6_redir=ON
ipv6_dns=OFF
含义:
- 普通域名仍不返回 AAAA,优先走 fake IPv4。
- 如果某个程序硬连 IPv6 字面量,能被 IPv6 TUN 路径接住。
- 额外加了 LAN IPv6 防漏 DROP:从
br-lan出来的 IPv6 如果不能走utun,就不允许直接转发出去。
守护脚本会补充类似规则:
shellcrashv6_mark -i br-lan -p tcp -j MARK --set-xmark 0x1ed4/0xffffffff
shellcrashv6_mark -i br-lan -p udp -j MARK --set-xmark 0x1ed4/0xffffffff
FORWARD -i br-lan ! -o utun -j DROP
目前还可能漏或不按预期分流的流量
-
不经过这台路由器的流量
例如手机蜂窝、别的网关、设备自己开 VPN/Tailscale 出口。 -
非 TCP/UDP 协议
例如 ICMP ping、GRE、ESP/IPsec、特殊 raw socket 协议。普通上网基本不依赖这些。 -
局域网和私有地址
192.168.x.x、10.x.x.x、172.16-31.x.x、mDNS、组播、NAS、打印机等会绕过代理,这是故意保留,否则内网互访会乱。 -
路由器本机自己的系统流量
当前主要接管 LAN 设备。路由器上的 subs-check 单独设置了HTTP_PROXY/HTTPS_PROXY=127.0.0.1:7890,但系统自己的wget/opkg/ntp不一定自动走 Mihomo。 -
硬编码 DoH/DoT 或直接 IP 的应用
这类流量不会直接从 WAN 漏出去,只要经过路由器仍会被 Tun 接住;但如果没有 DNS 域名信息,Mihomo 的域名规则命中能力会弱一些,可能只能靠 IP、GeoIP、SNI 或嗅探。 -
开机恢复窗口
重启后有几十秒到一两分钟的恢复期。守护脚本会自动补服务和防火墙规则。
性能经验
现在全局 Tun 意味着国内网站也会先经过 Mihomo,再由规则 DIRECT 出去。它不是走代理节点,但会比纯硬件 NAT 转发多一层软件处理。
可能受影响的场景:
- 国内大流量下载。
- 多台设备同时国内视频。
- P2P 或大量连接数。
- 路由器硬件加速无法完全参与被接管流量。
当前实测内存和普通访问都正常。后续如果要优化,更好的方向是做设备级白名单或黑名单:
- 自己的 Mac、手机、Windows 走 Tun。
- 老人设备、电视、IoT 不进 Mihomo。
- 大流量国内下载设备可以排除。
这样比回退 Redir 更可控。
Claude 在这次排障里的作用
Claude 的主要价值不是直接给出最终配置,而是帮助收窄 TProxy 失败边界:
- 建议不要只看 iptables 计数,要写一个最小透明 socket probe 验证 TProxy 包是否真的投递给应用。
- 提醒检查
bridge-nf-call-iptables等桥接转发相关条件。 - 帮助把问题从 Mihomo 配置、节点、订阅、ShellCrash listener 中剥离出来,最终定位到固件/内核投递路径。
也有一些建议不能直接照做,比如清空整张 mangle 表,这在路由器现场环境里风险太大,最终没有执行。
后续如果继续攻 TProxy,建议按这个顺序
-
保留当前 Tun 方案作为可用基线
先不要破坏/data/router_usb_services.sh、ShellCrash 配置和 U 盘目录。 -
在独立测试链里复现 TProxy
不要直接动 ShellCrash 主链。继续用最小透明 socket probe,单独建测试链、测试 mark、测试 table。 -
抓三个点的包
br-lan:确认客户端 SYN 进来。lo:确认 TProxy 是否投递到本地。- WAN 口:确认是否被错误转发或丢弃。
-
继续比对这些内核/固件条件
xt_TPROXYxt_socketnf_tproxy_ipv4nf_socket_ipv4bridge-nf-call-iptablesrp_filterroute_localnetaccept_localip_nonlocal_bind- ECM/SFE/PPE 硬件加速路径
-
尝试 nftables TProxy 或更新 OpenWrt/ImmortalWrt
这次在小米官方固件上,iptables TProxy 的规则命中和策略路由看起来都对,但包没有交给透明 socket。真正解决可能需要换更完整的 OpenWrt 内核/防火墙栈,或者找到小米固件里桥接/硬件转发绕过 TProxy 的具体点。 -
判断是否值得继续
TProxy 理论更漂亮,但当前 Tun 已经覆盖了主要实际需求。继续攻 TProxy 更像是内核/固件研究,不一定带来足够的日常体验收益。
当前结论
这台小米万兆官方固件上,TProxy 的理论路径成立,但实测投递失败。Redir 能用但覆盖面不足。Tun + fake-ip 是当前最可靠、可重启恢复、能覆盖局域网普通 TCP/UDP 流量的方案。
如果未来要继续攻 TProxy,最有价值的不是继续改 Mihomo 配置,而是围绕“TPROXY 命中后为什么没有把包交给透明 socket”做内核和固件路径排查。