本文目录
先确认是域名模式校验失败
本文只处理一组明确症状:同一份配置在 Mihomo v1.19.29 或更早版本可以启动,升级到 v1.19.30 后却出现 Parse config error: invalid domain,内核在加载配置阶段直接退出。
官方 issue #3116 在 Linux Docker 环境记录了该变化,最终定位到 sniffer.skip-domain 与 dns.fake-ip-filter 里的域名模式。v1.19.30 收录了更严格的 Clash 风格域名通配符校验;这不是节点失效,也不是把代理模式切成 Direct 就能绕开的连接问题。
如果日志是 Invalid YAML、unsupported field、proxy not found,或内核已经启动但网页打不开,故障发生在其他阶段,应先按对应错误排查,不能把所有配置失败都改成本文的通配符写法。
先按第一条错误分流
| 日志或现象 | 更可能的阶段 | 本文是否适用 |
|---|---|---|
| Parse config error: invalid domain | 域名模式校验 | 升级到 v1.19.30 后出现时适用 |
| Invalid YAML 或缩进错误 | YAML 文本结构 | 不适用,先修语法 |
| proxy / group not found | 策略组或规则引用 | 不适用,先补齐引用 |
| 内核已启动,只有某个域名失败 | DNS、规则或网络 | 不适用,先看连接记录 |
先保存可用配置和生成来源
动手搜索星号前,先分别保存当前最终配置、客户端的 Profile、Merge 或覆写,以及订阅转换模板。只备份运行目录里的 config.yaml 不够:客户端下一次更新订阅时,来源中的错误模式还会把修复覆盖回去。
如果旧内核仍在转发,不要先重启服务或连续刷新订阅。先保留当前可用状态,再复制错误日志、客户端版本和实际 Mihomo 版本;截图与配置副本要移除订阅 token、节点密码、控制器 secret 和私人域名。
准备一条可回退路径
记录实际内核版本
从客户端关于页、启动日志或 mihomo -v 确认运行的是 v1.19.30,不用“最新版”代替版本号。
导出最终配置
保存内核实际加载的 YAML,并另存 Profile、Merge、覆写或转换模板。
保留上一版内核
只保留来自官方 Release、且本机曾验证可用的 v1.19.29 文件作为临时回退。
固定其他变量
排查期间不同时换订阅、节点、DNS 模式或 TUN 设置,避免新增第二个故障。
定位第一条无效域名模式
先用实际要运行的 v1.19.30 测试最终配置。官方 issue 使用的命令是 mihomo -t -f;测试模式成功只代表配置可以被当前内核解析和初始化,不会启动代理,也不能证明节点可用。
v1.19.30 稳定版可能只返回笼统的 invalid domain。此时在最终 YAML 和它引用的本地文件中搜索星号,优先检查 issue 已确认出现问题的 sniffer.skip-domain 与 dns.fake-ip-filter。每修正一项就重新测试,让内核继续指出下一条错误。
mihomo -v
mihomo -t -f /path/to/config.yamlgrep -R -n '\*' /path/to/config.yaml /path/to/rules 2>/dev/nullrrn-sw-*、a*.example.com 或 *a.example.com
星号混在同一个标签里,属于 v1.19.30 明确拒绝的模式。
*.example.com 或 time.*.com
星号独占完整标签,形式本身合法;继续找下一项。
example.com.、a..example.com 或首尾带空格
尾点、空标签和首尾空白也会被严格校验拒绝。
完全找不到星号
检查加号、尾点、空标签和客户端生成的最终配置,不要只搜索订阅原文。
先分清三种合法域名通配符
Mihomo 文档把这里的写法称为 Clash 风格域名通配符,并特别说明它与路由规则里的 DOMAIN-WILDCARD 不是同一种语法。不能从规则教程复制一个看似相同的星号表达式,直接放进 fake-ip-filter 或 skip-domain。
关键不是星号写在前面还是后面,而是星号必须独占由点分隔的完整标签。time.*.com 合法,因为中间一段只有星号;rrn-sw-* 不合法,因为星号和 rrn-sw- 混在同一个标签里。
按真实匹配范围选择写法
| 合法写法 | 匹配范围 | 不会匹配 |
|---|---|---|
| *.example.com | 恰好一级子域,如 a.example.com | example.com、b.a.example.com |
| +.example.com | 根域和任意层级子域 | 其他后缀 |
| .example.com | 任意层级子域 | example.com 根域 |
| time.*.com | 中间恰好一个完整标签 | time.com、time.a.b.com |
| * | 不含点的单标签主机名 | 带点的完整域名 |
rrn-sw-*
a*.example.com
*a.example.com
a*b.example.com按真实意图改写,不做机械替换
如果意图是匹配某个固定根域下的一级或多级子域,可以在星号、加号和点前缀之间选择。若原意是匹配 rrn-sw- 开头的一批局域网主机,Clash 风格域名列表没有与 rrn-sw-* 等价的部分标签通配符;最稳妥的方法是枚举实际主机名。
不要把 rrn-sw-* 机械改成 *.rrn-sw、rrn-sw.* 或 +.rrn-sw。它们表达的是不同的标签结构,可能通过校验,却不会命中原来想要的主机。先列出真实查询名称,再让每条配置都能解释其覆盖范围。
sniffer:
skip-domain:
- "rrn-sw-01"
- "rrn-sw-02"
dns:
fake-ip-filter:
- "+.example.com"
- "time.*.com"错误写法与可执行处理
| 原始意图 | 不要这样改 | 可执行处理 |
|---|---|---|
| 匹配 rrn-sw- 开头的短主机名 | 继续使用 rrn-sw-* | 枚举 rrn-sw-01、rrn-sw-02 等真实主机名 |
| 匹配 example.com 的一级子域 | a*.example.com | 使用 *.example.com |
| 匹配根域与全部子域 | *example.com | 使用 +.example.com |
| 只匹配全部子域,不含根域 | *.example.com 并误以为含多级 | 使用 .example.com |
用同一 v1.19.30 验证修复
保存候选副本后,再用同一份 v1.19.30 执行配置测试。若仍报 invalid domain,继续处理下一条,不要因为第一条消失就直接覆盖唯一可用配置。所有错误清零后,才让客户端加载候选并重启内核。
内核启动只是第一层验收。分别访问一条应该命中 fake-ip-filter 的域名、一条应该被 sniffer 跳过的域名和一个普通公网域名,再查看 DNS 结果与连接记录。写法通过校验但匹配范围错误,仍然不是完成修复。
按可回退顺序上线候选
测试候选副本
运行 mihomo -t -f,直到 v1.19.30 明确返回配置测试成功。
保存原件再替换
保留上一份可用 YAML,不在客户端运行中覆盖唯一原件。
重载或重启内核
确认日志显示 v1.19.30 已启动,没有继续读取旧进程或旧配置。
复测真实匹配
用确定的域名请求检查 DNS、嗅探、规则命中和最终页面访问。
修复完成标准
- v1.19.30 对最终配置的测试模式通过
- 内核能启动并保持运行,没有新的配置解析错误
- 枚举的局域网主机按预期跳过嗅探或 Fake-IP
- 一级、任意层级与根域的匹配范围符合所选语法
- 普通公网域名和节点连接没有被扩大后的规则误伤
- 原配置、生成来源和旧内核回退文件仍可找到
更新后复发要修生成来源
如果手工修改后可以启动,但刷新订阅、切换 Profile 或重启客户端又报同样错误,说明无效模式来自转换模板、远程配置、Merge 或覆写。此时不要反复编辑临时运行文件,先比较修复前后的最终 YAML,找到是哪一层重新写回了旧值。
能控制订阅或转换器时,直接修模板并重新生成;只能控制客户端时,在受控 Merge 或覆写中替换完整列表,并确认更新后最终配置仍然合法。不要把含 token 的订阅上传到陌生转换站,也不要用一条过宽后缀覆盖所有未知情况。
每次更新订阅后复发
修订订阅转换模板或上游配置,再生成候选。
切换 Profile 后复发
分别检查每个 Profile 的 Merge、Script 和本地覆写。
磁盘文件已改,内核仍报旧值
确认实际加载路径、进程和客户端生成的最终配置。
只能靠宽泛后缀才能启动
先枚举必要主机并记录缺口,不把扩大范围当长期答案。
无法立即修正时先安全回退
若配置由不可控来源持续生成、短时间内无法完成修订,可以先关闭 TUN 或系统代理,恢复系统直连,再还原备份配置。确有业务依赖时,可临时回到本机已验证的 v1.19.29,等待生成源修正后重新测试 v1.19.30。
回退只用于恢复服务,不能证明旧写法正确。v1.19.30 的严格校验提交已经进入当前稳定版,而更详细的错误路径提交在其后出现;不要把“旧版不报错”和“新 Alpha 更容易定位”混成长期版本策略。
恢复已知可用状态
停止失败的内核重试
先关闭客户端接管,避免系统流量持续指向没有运行的本地端口。
恢复配置备份
还原 Profile、最终 YAML 与必要覆写,不导入来源不明的完整目录。
必要时临时回退内核
只使用官方 v1.19.29 和本机已验证架构,记录回退原因与日期。
安排同版本复测
生成源修正后回到 v1.19.30,重复配置测试、启动和真实域名验证。
