RouterOS 升级到 7.22 之后,容器里的 sing-box 和 mihomo 突然不能用了 —— 流量根本进不了容器。折腾了半天才发现,问题不在代理配置,在 RouterOS 自己身上。
这个坑我踩过,也把完整的定位过程和修复脚本整理出来了,写在这里给同样卡住的人省点时间。
[image: 封面]
问题现象
升级到 RouterOS 7.22 之后出现这些症状:
容器里的 TUN 网关停止工作
流量不会进入容器
把容器设置为网关没有任何效果
在 7.20.8 / 7.21 上一切正常,从 7.22 开始失效。
如果你的 TUN 网关在 7.22+ 上不工作,不要先去调代理配置 —— 先检查 ip rule。
根因:容器内 ip rule 优先级被改了
RouterOS 7.22 修改了容器内默认的 ip rule 优先级,变成了这样:
1: from all lookup local
2: from all lookup main
3: from all lookup default
这个改动会直接破坏:
策略路由(policy routing)
fwmark 路由
基于 TUN 的代理核心
为什么 1/2/3 就会坏?
在 7.20.x 里,容器的默认规则是:
200: from all lookup local
2147483646: from all lookup main
2147483647: from all lookup default
关键在 200 和 2147483646 之间留出了巨大的数字空间,sing-box、mihomo 这类代理核心会把自己的路由规则插到这两条之间,策略路由才能正常工作。
而 7.22+ 改成 1 / 2 / 3 之后,留给第三方插入的空间几乎没有了。代理核心添加的规则只能排到表的最底部,优先级低于默认规则,于是完全失效。
修复方法
思路很简单:在启动代理核心之前,把 ip rule 的顺序规范化,恢复成 7.21 那种留有充足插入空间的布局。
基础命令:
ip rule del pref 1
ip rule del pref 2
ip rule del pref 3
ip rule add pref 200 from all lookup local
ip rule add pref 2147483646 from all lookup main
ip rule add pref 2147483647 from all lookup default
推荐用带健壮性检查的版本 —— 直接删可能因为规则不存在而报错,下面这个可以安全地重复执行:
ensure_ip_rule_priorities() {
while ip rule show | grep -Eq '^1:\s+from all lookup local(\s|$)'; do
ip rule del pref 1 >/dev/null 2>&1 || break
done
while ip rule show | grep -Eq '^2:\s+from all lookup main(\s|$)'; do
ip rule del pref 2 >/dev/null 2>&1 || break
done
while ip rule show | grep -Eq '^3:\s+from all lookup default(\s|$)'; do
ip rule del pref 3 >/dev/null 2>&1 || break
done
if ! ip rule show | grep -Eq '^200:\s+from all lookup local(\s|$)'; then
ip rule add pref 200 from all lookup local >/dev/null 2>&1 || true
fi
if ! ip rule show | grep -Eq '^2147483646:\s+from all lookup main(\s|$)'; then
ip rule add pref 2147483646 from all lookup main >/dev/null 2>&1 || true
fi
if ! ip rule show | grep -Eq '^2147483647:\s+from all lookup default(\s|$)'; then
ip rule add pref 2147483647 from all lookup default >/dev/null 2>&1 || true
fi
}
ensure_ip_rule_priorities
实测在 7.22.1 上同样有效。
关于 fake-ip:如果启用了 fake-ip,还需要补一条路由 ip route add 198.18.0.0/15 dev tun0。也可以在容器启动命令里加一段延迟执行:
-c "sleep 3 && ip route add 198.18.0.0/15 dev tun0"
️ mihomo 的 TUN 配置
用 mihomo 的 TUN 模式时,需要额外加一段 tun 配置。把下面这段粘贴到配置文件的 DNS 段之后:
tun:
enable: true
device: tun0
stack: system
auto-route: true
auto-detect-interface: true
strict-route: true
dns-hijack:
- any:53
容器入口保持 entrypoint=/entrypoint.sh,不需要其他额外设置。
节点配置可以用转换工具生成,比如 sublink.works。
🧩 官方的修复
容器内的路由规则优先级已经在 7.23rc2 中由官方修正。
MikroTik 在 7.23rc2 的发布说明里写道:
route - revert to old routing rule priorities for containers
(introduced in v7.22);
也就是说,官方回退了 7.22 引入的这次改动,恢复到旧行为。
完整文档
上面只是要点。完整的分析过程、社区讨论记录(包括 MikroTik 官方是如何被说服去修的)、以及可以直接用的完整 entrypoint.sh 脚本,我整理成了一份 PDF:
RouterOS 7.22+ 容器 TUN 网关失效 — 根因分析与修复
内容包括封面、目录、问题现象、根因定位、修复方案、mihomo 配置要点、社区讨论全文、官方修复跟进、附录脚本,共 12 页。
下载地址(Google Drive)
预构建容器(sing-box / mihomo,已修复)—— 可直接导入使用。
网盘内附容器说明,这些容器在最新版本的 RouterOS 中同样可以正常使用。
https://drive.google.com/drive/folders/1YTVe9rqMn2YzbFZPkyYn6zjeUQKpf-uT
详细流程文档(PDF):
https://drive.google.com/file/d/14fn8Llyzc28fwrHptqLZr7Nx9gYXbniq/view
️ 一句话总结
这不是 sing-box 的问题,不是 mihomo 的问题,也不是配置问题 ——
这是 RouterOS 容器路由的一次回归,只在 7.22 ~ 7.23rc1 之间出现,7.23rc2 已修复。
如果你的设备还在这个版本区间,要么用上面的脚本兜住,要么就停在能用的版本别升。