Clash 自定义规则写法详解:匹配顺序、优先级与 MATCH 兜底
Clash 的分流行为完全由 rules 列表决定,而多数配置问题并非规则类型用错,而是顺序与优先级理解偏差。本文逐条拆解自定义规则的语法结构,说明内核自上而下、命中即停的匹配机制,厘清自定义规则与订阅规则的先后关系,并给出 MATCH 兜底规则的正确写法与常见失效原因。
规则如何驱动分流
Clash 内核每接到一个连接,都会取出它的目标地址、端口与来源特征,再拿这些信息逐条比对配置文件中的 rules 列表。列表里第一条命中的规则决定这个连接的去向:交给某个代理节点、某个策略组、内置的 DIRECT 直连,或是 REJECT 拒绝。判定在命中的一刻完成,排在后面的规则不再参与。
因此,rules 列表是 Clash 分流的唯一事实来源。无论配置来自订阅链接、客户端的覆写功能还是手工编辑,最终都要落成这一段逐行排列的规则。实践中规则类型用错的情况并不多,绝大多数分流结果偏离预期,根源都在顺序:一条更宽泛的规则排在前面,把本该由后面的精确规则处理的流量提前截走。看懂匹配顺序,比背熟规则类型更要紧。
无论流量从系统代理、TUN 模式还是混合端口进入内核,比对的都是同一份 rules 列表,顺序机制完全一致。
单条规则的语法结构
一条规则由逗号分隔的若干段组成,完整形态为四段,大多数类型只用前三段:
类型,负载,策略[,附加参数]
- 类型:从哪个维度匹配,例如 DOMAIN、DOMAIN-SUFFIX、IP-CIDR、GEOIP。
- 负载:匹配的具体内容,例如一个域名、一个后缀、一段网段或一个国家代码。
- 策略:命中后交给谁。可以是内置策略 DIRECT、REJECT,也可以是 proxies 或 proxy-groups 中定义过的节点名、策略组名。
- 附加参数:目前只有 no-resolve,仅供 IP 类规则使用,后文单独说明。
书写层面有四条硬性约束。其一,规则集中在配置文件的 rules 段内,YAML 格式下每条以短横线起行。其二,策略名必须与配置中定义的名称逐字一致,含大小写与空格,写错会使整份配置加载失败。其三,域名负载一律小写,不带协议头、不带路径,带 http:// 前缀的写法永远不会命中。其四,井号起行的是注释,内核不予解析。
rules:
- DOMAIN,update.example.com,DIRECT
- DOMAIN-SUFFIX,example.com,Proxy
- DOMAIN-KEYWORD,tracker,REJECT
- IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
- GEOIP,CN,DIRECT
- MATCH,Proxy
常用规则类型对照
下表收录自定义规则中最常见的类型。GEOSITE、PROCESS-NAME 等仅 mihomo 内核提供,原版 Clash Premium 不支持,混用会导致配置无法加载。
| 类型 | 负载示例 | 匹配行为 |
|---|---|---|
| DOMAIN | www.example.com | 精确匹配该域名,不含子域 |
| DOMAIN-SUFFIX | example.com | 匹配该域及其全部子域 |
| DOMAIN-KEYWORD | tracker | 域名中含该关键词即命中 |
| GEOSITE | cn | 匹配域名分类集,仅 mihomo 内核 |
| IP-CIDR | 10.0.0.0/8 | 匹配 IPv4 网段 |
| IP-CIDR6 | fd00::/8 | 匹配 IPv6 网段 |
| GEOIP | CN | 按 IP 归属地匹配 |
| DST-PORT | 443 | 按目标端口匹配 |
| SRC-PORT | 7891 | 按来源端口匹配 |
| PROCESS-NAME | curl.exe | 按进程名匹配,限桌面平台 |
| RULE-SET | adblock | 引用 rule-providers 托管的规则集 |
| MATCH | 无负载 | 匹配全部剩余流量,置于末尾 |
体量较大的清单不宜逐行写进 rules。数万行的广告域名或站点分类应交给 rule-providers 托管,rules 中只用一条 RULE-SET,清单名,策略 引用;内核按 interval 周期自动更新清单,条目再多也只占一个匹配位,加载与维护都更省力。
匹配顺序:自上而下,命中即停
内核处理每个连接时,从 rules 列表的第一行开始向下逐条比对,第一条命中的规则立即生效,比对随即终止。由这一机制可以推出三条直接结论:
- 精确规则必须排在宽泛规则之前。若希望 update.example.com 直连、example.com 的其余子域走代理,DOMAIN 条目要写在 DOMAIN-SUFFIX 条目上方;次序颠倒后,后缀条目会先把流量收走,精确条目永远没有出场机会。
- 后写的规则不能覆盖先写的规则。Clash 没有后来者居上的层叠逻辑,先命中先生效,调整优先级的唯一手段是调整行序。
- 自定义规则与订阅规则的先后,取决于二者在最终生效列表中的相对位置。多数图形客户端的覆写功能会把自定义规则插入订阅规则之前,使其优先命中;若客户端把自定义条目附加在订阅规则之后,而订阅里已有更宽泛的条目,自定义条目就可能永远轮不到。
排查规则写了却不生效时,第一步是打开客户端展示的最终 rules 列表,确认该条目实际落在第几行,而不是反复检查语法。
IP 类规则与 no-resolve 参数
域名类规则直接比对连接携带的域名,IP-CIDR 与 GEOIP 则需要 IP 才能比对。连接目标是域名时,内核必须先做一次 DNS 解析,拿到结果后才能继续判断。也就是说,只要列表里存在 IP 类规则,每个未被前文域名规则拦截的连接都可能多触发一次解析,既增加延迟,也扩大 DNS 查询的暴露面。
no-resolve 用来关闭这一行为。带 no-resolve 的 IP 规则,只在目标本身就是 IP 字面量时参与匹配,内核不会为了它去解析域名:
IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
GEOIP,CN,DIRECT,no-resolve
内网网段、局域网设备这类纯 IP 场景,建议一律附加 no-resolve。反过来,依赖先解析、再按归属地分流的 GEOIP 规则不能加这个参数,否则以域名发起的连接会直接从它身边滑过,落进后面的条目。
MATCH 兜底规则
MATCH 是唯一没有负载的规则类型,写法只有两段:MATCH,策略。它匹配一切尚未被前文规则命中的连接,使用上有三条纪律:必须放在 rules 列表的最后一行;一份配置只需要一条 MATCH;建议始终显式写出,而不是依赖内核的默认走向。
写在中间的 MATCH 会拦截全部剩余流量,其后的规则统统成为死行,这是自定义规则中最常见、也最难察觉的错误。mihomo 对未命中流量默认直连,但显式的 MATCH 让最终走向确定、可读,日后维护时不必猜测内核行为。
两种常见取向:MATCH,Proxy 表示凡是没有专门交代的流量一律走代理,配合前面的直连例外,属于黑名单式写法;MATCH,DIRECT 表示只有列表明确放行的流量走代理,其余全部直连,属于白名单式写法,适合仅少数站点需要代理的场景。
完整示例与命中验证
把前面的要点合在一起,一份典型的自定义 rules 段如下:
rules:
# 本地与内网:后缀 .lan 与内网网段直连
- DOMAIN-SUFFIX,lan,DIRECT
- IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
# 广告与跟踪:关键词命中即拒绝
- DOMAIN-KEYWORD,tracker,REJECT
# 精确例外:更新服务器直连
- DOMAIN,update.example.com,DIRECT
# 其余 example.com 子域走代理
- DOMAIN-SUFFIX,example.com,Proxy
# 国内地址按归属地直连
- GEOIP,CN,DIRECT
# 兜底:剩余流量走代理
- MATCH,Proxy
注意示例中的 GEOIP 条目未附加 no-resolve:以域名发起、且未被前面条目拦截的连接,会在这里触发一次解析再按归属地判断。若希望完全避免这类解析,可改用 GEOSITE 类别清单在域名阶段完成分流,把 GEOIP 留给纯 IP 连接并加上 no-resolve。
规则是否符合预期,不需要靠猜。图形客户端的连接面板,例如 Clash Verge Rev 的连接页、各类 Dashboard 的 Connections,会实时列出每个连接命中的具体规则与策略;命令行场景把日志级别设为 info,内核会逐条打印命中记录。发现结果与预期不符时,按面板显示的规则名回到列表核对行序,问题通常立刻现形。
- MATCH 未置于末行,其后的规则全部失效。
- 精确规则排在宽泛的后缀规则之后,永远不会命中。
- 策略名与 proxies、proxy-groups 中的定义不一致,配置加载报错。
- 域名负载带协议头或路径,匹配失败。
- 自定义条目被客户端附加在订阅规则之后,被更宽泛的订阅条目抢先命中。
- 指望后写的规则覆盖先写的规则,Clash 没有这种层叠机制。