排查顺序
模块装上了但没效果,按这个顺序查:
- 模块在列表里开着吗?客户端不在「直连」或「全局」模式吗?这两个模式下所有模块规则整体失效。
- 规则命中了吗?—— 换成
REJECT试一次。如果目标彻底连不上,说明规则命中了,问题在出口;如果照常能连,说明规则没命中。 - 匹配值有没有写成大写?域名类的值必须自己写小写,大写永远不命中。
- 有没有把注释写在规则行尾?行尾注释会被并进出口名。
- 出口名在
[Proxy Group]里定义过吗?未定义且不是客户端已有出口名时,规则会使用「默认」出口,且不会显示错误。 - 用到
GEOIP/GEOSITE的,名字拼对了吗?模块详情页里那个规则集下载到多少条?0 条 = 永远不命中。 - 用到改写或脚本的:解密开关开了吗?根证书装了并且完全信任了吗?目标域名写进
[MITM] hostname了吗? - 还是不行,看日志。
没有错误提示但未生效
这是最常见的一类。原因几乎总在下面这张表里。
| 现象 | 原因 |
|---|---|
| 匹配值写了大写 | 只有被匹配的域名被转小写,规则里的值原样使用。DOMAIN-SUFFIX,Google.COM 永不命中 |
规则行尾写了 # 注释 |
没有行尾注释,DIRECT # 注释 整个被当成出口名,落到「默认」 |
| 规则已配置,流量仍使用原出口 | 出口名未定义,因此使用了「默认」出口 |
| 规则针对私网 IP / BT / ping | 客户端有前置规则把它们判给直连,排在所有模块规则之前 |
| 客户端在「直连」或「全局」模式 | 这两个模式下模块规则整体不参与 |
GEOSITE,xxx 从不命中 |
名字在规则集目录里不存在,下载 404,规则空转 |
GEOSITE / GEOIP 刚导入时不命中 |
规则集还没下载完,等一会或在模块详情页手动重拉 |
| 前面存在更宽泛的规则 | 规则从上到下匹配,第一条命中后停止。GEOSITE,cn,DIRECT 写在特定境外服务规则之前时,后者可能没有机会匹配 |
| 改写/脚本一点动静没有 | 域名没写进 [MITM] hostname;或者根证书没「完全信任」;或者你在 Android 上 |
[MITM] hostname 只剩排除项 |
一条包含规则都没有时整个解密层不启用 |
| YouTube / Google 系的改写不生效 | 走了 HTTP/3,没经过解密层。加一条 UDP 阻断规则 |
| 脚本启用后没有效果 | 脚本可能抛出异常。发生异常时请求保持原样继续处理,客户端不显示脚本错误 |
[Body Rewrite] / [Map Local] 里的双引号消失 |
这些配置段解析时会移除双引号,且不支持 \"。正则中使用 \x22,正文使用 data-type=base64 |
[URL Rewrite] 整行没生效 |
行尾动作拼错了,比如 reject-img-drop、reject-200-no-drop 这些不存在的组合 |
DST-PORT,80-443 不生效 |
不支持端口区间,只能写单个端口 |
URL-REGEX / USER-AGENT 规则不生效 |
这些类型不受支持,配置会被忽略。按路径拦截应使用 [URL Rewrite] |
| 新建的分组未显示 | 分组名与已有出口重名,新分组被忽略 |
| 分组只剩一个成员 | 手写的成员名都没定义过,合并成同一个「默认」出口了 |
内核无法启动或节点列表为空
配置被拒绝了,三个原因:
- 分组正则用了 RE2 不支持的语法 ——
policy-regex-filter/exclude-regex里写了环视(?=(?!(?<=(?<!或反向引用\1。这是最常见的一个。 - 分组是空的 —— 既没写成员也没写正则筛选(
我的组 = select),或者写的成员全被丢掉(广告 = select, REJECT)。 - 规则里的值非法 ——
IP-CIDR的值不是合法 IP 或网段,DOMAIN-REGEX的正则编译不过。
解决:关掉刚装的模块,如果恢复了就是它;逐条对照上面三点改。
分组重名不会阻止内核启动。 重名时新分组会被忽略,内核仍可正常运行;此时表现为新分组未显示,而不是节点列表为空。重复安装同一模块时也是如此。
写法陷阱
注释只能独占一行
# 对
DOMAIN-SUFFIX,a.com,DIRECT
# 错:出口变成了 "DIRECT # 走直连",落到「默认」
DOMAIN-SUFFIX,a.com,DIRECT # 走直连
匹配值要写小写
# 错,永不命中
DOMAIN-SUFFIX,Google.COM,默认
# 对
DOMAIN-SUFFIX,google.com,默认
GEOIP / GEOSITE 的名字例外,大小写都行。
逗号
[Proxy Group] 的定义按逗号切分。正则里带 {2,3} 这类量词时整个值要用双引号包起来:
测试 = url-test, policy-regex-filter="(?i)节点[0-9]{2,3}", interval=300
[Script] 的 KV 列表也按逗号切,但不含 = 的片段会自动并回上一段,所以 pattern 里的量词、argument 里的 JSON 一般不会被切断。但 argument 的值里出现 = 就会被当成新的 key,那一串从此断掉。
双引号会在解析时被移除
[URL Rewrite] / [Header Rewrite] / [Body Rewrite] / [Map Local] 四个配置段按空白分隔字段,解析时会移除所有双引号,且不支持 \" 转义:
- 正则或替换串里要一个字面双引号,写
\x22。 - 要输出一段 JSON,用
[Map Local]的data-type=base64,或者用[Body Rewrite]的 jq 变体。 - 值里要有空格,把整段用双引号包住(引号本身会被剥掉,起的是「不切分」的作用)。
正则用的是 RE2
分组筛选、规则里的 DOMAIN-REGEX、改写和脚本的 pattern,全部是 RE2:
- 没有环视:
(?=)(?!)(?<=)(?<!) - 没有反向引用:
\1\2 (?i)可以用,写在开头
从其他客户端移植正则时需要检查这两项。JavaScript 支持这些语法,但此处不支持;用于分组筛选时会导致内核无法启动。
*.example.com 不含 example.com
[MITM] hostname 里的 *.example.com 只匹配子域。主域要单独写一条:
hostname = example.com, *.example.com
DOMAIN-SUFFIX,example.com 则是两个都匹配,不用重复写。
[MITM] 里的排除优先
只要命中任何一条 - 排除,就一定不解密,不管别的规则怎么写。全是排除项时整个解密层不启用。
FINAL 会替换全局默认规则
FINAL 指定其他规则均未命中时使用的出口,并替换客户端原有的默认规则。仅修改少量域名出口时不要配置 FINAL。配置多条时最后一条生效;FINAL,REJECT 会被忽略。
模块不能定义节点
[Proxy] 段会被忽略。节点由客户端管理,模块只能通过 [Proxy Group] 的正则筛选引用节点。[General] 仅支持 dns-server,其他全局设置不受模块控制。
DNS 配置没生效
- 地址写成域名:
server:dns.corp.local整条被丢掉,只收 IP(可带端口和tls://https://前缀)或system。 - 域名模式写成裸通配:单独一个
*或+.不接受,得写到具体域名(+.corp.com)。 - 目标是修改节点或入口域名的解析:模块 DNS 配置只作用于用户访问的目标域名;节点和入口域名固定使用客户端内置的解析路径。
- 解析出内网地址但连不上:再补一条
DOMAIN-SUFFIX,内网域名,DIRECT,否则地址可能被路由进代理。 - 只写了
[Rule]想把内置判直连的域名改走节点:改不动。那条规则确实生效了,但 DNS 可能已经获得中国大陆的真实 IP,随后流量仍会经代理连接该地址。应同时配置[Host] 域名 = server:fakeip,分配虚拟 IP 并由[Rule]决定出口。
一行一个值
# 错:b.com 被解析为出口名,规则将使用「默认」出口且不显示错误
DOMAIN-SUFFIX,a.com,b.com,默认
# 对
DOMAIN-SUFFIX,a.com,默认
DOMAIN-SUFFIX,b.com,默认
关于解密
- Android 端不支持,
[MITM]及其后面几段永远不生效。 - 做了证书钉扎的 App 连不上,没有绕过办法。这不是配置写错了。
- 不要写
hostname = *。全量解密会让设备明显变慢,还会让一批 App 直接连不上。 - 证书装完之后,iOS 上还要去「设置 → 通用 → 关于本机 → 证书信任设置」里勾上。少这一步全部改写都不生效,而且没有任何提示。
导入时的提示
- 规则集名字核对失败:
GEOIP/GEOSITE的名字在目录里不存在,改掉。 - 提示「无法核对」:一般是网络不通,规则集本身可能是对的,连上网再看。
除此之外没有其他导入提示。不支持的规则类型、无效改写行和被忽略的重名分组不会显示错误。导入成功仅表示文件可读取,不表示每一行配置都已生效。