Clash 自定义规则语法与优先级:DOMAIN-SUFFIXIP-CIDR 与 MATCH 的匹配顺序

逐条拆解 rules 段的写法与匹配顺序:从 DOMAIN、DOMAIN-SUFFIX、IP-CIDR 到 GEOIP 与 MATCH 兜底,讲清自上而下短路匹配的机制与常见写错方式。

rules 段的三段式写法与自上而下的短路匹配

Clash 与 mihomo 的规则全部写在配置顶层的 rules: 数组里,每条规则是一个 YAML 列表项,结构固定为三段:规则类型,匹配值,策略名。第一段决定用哪种方式匹配,第二段是匹配目标,第三段是命中后要走的出口。出口可以写 DIRECT(直连)、REJECT(拒绝),也可以写 proxy-groups 里定义过的任意策略组名。部分类型还接受第四段参数,目前最常用的是 no-resolve

rules:
  - DOMAIN,api.github.com,Proxy
  - DOMAIN-SUFFIX,github.com,Proxy
  - IP-CIDR,10.0.0.0/8,DIRECT,no-resolve
  - GEOIP,CN,DIRECT
  - MATCH,Proxy

匹配过程是自上而下的短路匹配:内核从第一条开始逐条比对,一旦命中就立刻结束,后面的规则不再参与。也就是说,规则顺序本身就是优先级,内核不会因为某条规则写得更具体就把它自动提前。把 DOMAIN-SUFFIX,github.com,Proxy 排在 DOMAIN,api.github.com,DIRECT 前面,后者永远不会生效。

MATCH 的位置决定兜底范围

MATCH 不带匹配值,任何流量都会命中它。一旦它被写在规则表中间,后面所有规则都成了永远不会执行的死代码。规则改动后先检查这一条。

策略名必须与 proxy-groups 里定义的完全一致,包括大小写;可以直接写的只有 DIRECTREJECT,其余都是自定义组名。

域名规则:DOMAIN、DOMAIN-SUFFIX 与 DOMAIN-KEYWORD 的边界

域名类规则分三档,匹配范围依次放宽,写之前先确认要覆盖的是单个主机还是整站:

写法命中示例不命中示例
DOMAIN,api.github.com api.github.com github.com、cdn.api.github.com
DOMAIN-SUFFIX,github.com github.com、api.github.com raw.githubusercontent.com、github.com.cn
DOMAIN-KEYWORD,github github.com、githubassets.com、mygithub.io gitlab.com

DOMAIN 是精确匹配,只认完全相同的域名。DOMAIN-SUFFIX 按域名层级边界匹配:github.com 本身,以及以 .github.com 结尾的主机名都算命中,但 github.com.cn 不算——它既不完全相等,也不以 .github.com 结尾。很多人把它理解成字符串后缀,于是误以为 github.com.cnnotgithub.com 会被这条规则带走,实际都不会。

DOMAIN-KEYWORD 是纯子串匹配,github 会同时命中 githubusercontent.commygithub.io。它适合域名变体多、后缀不统一的服务,但关键词越短误伤越大,appapicloud 这类词不建议直接作为关键词。

mihomo 另外支持 DOMAIN-REGEX,用正则表达复杂模式。每条连接都要跑一次正则,规则条数多时开销可观,通常只在少数必要场景下使用。

IP 类规则:IP-CIDR、GEOIP 与 no-resolve 的解析代价

IP 类规则包括 IP-CIDRIP-CIDR6SRC-IP-CIDRGEOIP,匹配对象是 IP 地址。而浏览器和客户端发起的连接通常只带域名,所以内核遇到域名请求时,会先做一次 DNS 解析拿到 IP,再拿去比对。

这次解析有两个副作用:每条连接多一次查询;解析结果依赖 dns 段的配置,可能与规则编写时的预期不一致。

no-resolve 用来关掉这个行为。加上它以后,如果当前请求携带的是域名,内核不会为了匹配这条规则去解析,直接判定不匹配并继续往下走。

rules:
  - IP-CIDR,127.0.0.0/8,DIRECT,no-resolve
  - IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
  - IP-CIDR,100.64.0.0/10,DIRECT,no-resolve
  - IP-CIDR6,fc00::/7,DIRECT,no-resolve
  - GEOIP,CN,DIRECT
  - MATCH,Proxy

内网段、回环地址和运营商保留网段基本都靠 IP 规则处理,加上 no-resolve 后不会产生额外解析。GEOIP,CN,DIRECT 这类规则必须拿到真实 IP 才能判断归属,一般不加 no-resolve,让它正常触发解析。

dns.enhanced-mode: fake-ip 下要额外注意:应用拿到的是内核伪造的地址(默认落在 198.18.0.1/16),这些地址不代表真实位置,不要用 IP 规则去匹配。把域名类规则排在 IP 类规则前面,能少走一轮解析。

GEOIP 依赖本地数据文件

GeoIP 数据文件缺失或加载失败时,所有 GEOIP 规则都不会命中,流量会一路掉到 MATCH,表现为国内站点也走了代理。排查规则前先确认数据文件在位。

端口、进程与来源网段:细粒度规则怎么摆

DST-PORTSRC-PORT 按端口匹配,PROCESS-NAMEPROCESS-PATH 按发起连接的进程匹配,SRC-IP-CIDR 匹配发起连接的本机地址。这几类规则一般放在域名规则之后、MATCH 之前。

rules:
  - PROCESS-NAME,Telegram.exe,Proxy
  - PROCESS-PATH,/usr/bin/curl,Proxy
  - SRC-IP-CIDR,192.168.1.0/24,DIRECT,no-resolve
  - DST-PORT,22,DIRECT
  - MATCH,Proxy

进程类规则需要先确定连接属于哪个进程,单条匹配成本高于纯域名比对,放在规则表靠前的位置更划算。PROCESS-NAME 在 Windows 和 macOS 上直接可用;Linux 上进程信息受权限限制,多数场景用 PROCESS-PATH 更可靠。

SRC-IP-CIDR 常用来把虚拟机网卡、Docker 网桥这类来源的流量单独引到直连,配合 no-resolve 使用。端口规则的覆盖范围很宽,DST-PORT,22,DIRECT 会影响所有目标端口为 22 的连接,写之前确认它不会把后面本该走代理的流量截断。

RULE-SET 与 rule-providers:把规则移出主配置

规则条数上百之后,全部堆在主配置里既难读也难更新。rule-providers 把规则拆成独立文件,rules 里用 RULE-SET 引用:

rule-providers:
  ad-block:
    type: file
    behavior: domain
    path: ./ruleset/ad-block.yaml

rules:
  - RULE-SET,ad-block,REJECT
  - MATCH,Proxy

behavior 决定文件内容的格式:domain 是纯域名列表,ipcidr 是网段列表,classical 是完整的规则语法。RULE-SET 后面的名字必须与 rule-providers 下的键完全一致,写错时配置加载会直接报错。

如果规则集需要定期从远端更新,把 type 换成 http,补上 urlinterval 两个字段,interval: 86400 表示每 24 小时拉取一次。规则集文件损坏或格式不符时,整条 RULE-SET 会失效——把 MATCH 兜底写好,故障时的行为至少是可预期的。

六种常见写错方式与日志排查路径

按出现频率从高到低排列,规则不生效时依次对照:

  1. MATCH 写在中间:后面所有规则失效,是排查时最容易忽略的一处。
  2. DOMAIN-SUFFIX 当字符串后缀github.com.cnnotgithub.com 都不会命中,要覆盖变体得换 DOMAIN-KEYWORDDOMAIN-REGEX
  3. DOMAIN-KEYWORD 用得过宽:短关键词会连带命中无关域名,把整条链路拖进代理。
  4. IP 规则漏写 no-resolve:每条域名连接都多一次解析,延迟和 DNS 压力都会上升。
  5. 策略名大小写不一致proxy-groups 里叫 Proxy,规则里写成 proxy,配置校验会失败。
  6. GeoIP 数据文件缺失GEOIP 规则全部落空,流量掉到 MATCH

排查路径:在配置里打开 external-controller: 127.0.0.1:9090,用面板查看每条连接实际命中的规则;内核日志会打印 match DomainSuffix(github.com) using Proxy 这样的记录,直接指出是哪一条生效。修改规则后重新加载配置,再复现一次同样的连接即可确认。

规则表本质上是一份按顺序执行的判定清单。写完从上往下读一遍,确认每一条都不会被前面的宽规则截胡,再把 MATCH 放在最后,规则部分基本就不会出问题。

下载 Clash 客户端