Clash 自定义规则写法:DOMAIN-SUFFIX、GEOIP 与 MATCH 的匹配顺序
逐条拆解常用规则类型的语法,解释自上而下首条命中的匹配机制,演示 rule-providers 引用与规则冲突的调整方法。
先确认规则模式,再调整匹配顺序
把具体例外放在前面,把范围较大的规则放在后面,最后用 MATCH 接住剩余连接。Clash 的常规规则列表从上到下检查,命中一条后就按该条指定的策略处理,不会继续寻找“更精确”的规则。规则写得更具体,并不代表它能自动获得更高优先级。
修改前先确认客户端处于规则模式。全局模式不会按这份普通分流列表决定出口;直连模式也不能用来验证代理规则。客户端界面名称可能不同,可以在模式切换处选择“规则”或“Rule”,并在运行配置中确认 mode: rule。
分清规则、策略与实际出口
- 规则:判断连接是否满足条件,例如域名以
example.com结尾。 - 策略:决定交给谁处理,例如内置的
DIRECT、REJECT,或名为PROXY的策略组。 - 实际出口:策略组当前选中的节点或直连项。命中
PROXY不等于一定经过远端节点,要继续查看组内选择。
PROXY 在本文中是自定义组名,不是所有配置都自带的内置策略。如果订阅里的组名是“节点选择”,规则末尾就应引用那个准确名称。名称不同、大小写不同或缺少对应组,可能导致配置加载失败。
识别 DOMAIN、DOMAIN-SUFFIX 与 IP 规则
先按目标信息选择规则类型。域名类规则适合网站与服务分流;IP 类规则适合固定地址、局域网和地理 IP 判断。常规写法是 类型,匹配内容,策略,MATCH 没有匹配内容,因此只有两个字段。
| 类型 | 规则示例 | 匹配范围 |
|---|---|---|
| DOMAIN | DOMAIN,api.example.com,DIRECT |
仅匹配这个完整域名 |
| DOMAIN-SUFFIX | DOMAIN-SUFFIX,example.com,PROXY |
匹配根域名及其子域名 |
| DOMAIN-KEYWORD | DOMAIN-KEYWORD,example,PROXY |
匹配域名中包含该字符串的目标 |
| IP-CIDR | IP-CIDR,192.168.0.0/16,DIRECT,no-resolve |
匹配指定 IPv4 网段 |
| GEOIP | GEOIP,CN,DIRECT |
依据 IP 数据判断是否属于 CN |
| MATCH | MATCH,PROXY |
接住前面未匹配的连接 |
域名字段只填主机名
写 DOMAIN-SUFFIX,example.com,PROXY,不要写成 https://example.com/path。这里不填写协议、路径、查询参数或端口,也不需要写 *.example.com。后缀规则本身就覆盖 example.com 与 www.example.com,不会因为字符串相似就匹配 notexample.com。
DOMAIN-KEYWORD 的范围更宽。关键词 example 也可能命中与你想处理的网站无关的域名。只有确实需要字符串匹配时才使用它;网站分流通常先选精确域名或域名后缀。
区分 IP-CIDR 与 GEOIP
IP-CIDR 直接检查地址是否落在网段内;GEOIP 依赖内核加载的地理 IP 数据。后者只按目标 IP 的地理归属判断,不依据网页内容、域名注册地或访问者位置。一个中文网站使用海外 CDN 时,也可能不命中 GEOIP,CN。
IPv6 网段应使用对应的 IP-CIDR6 规则,例如 IP-CIDR6,fc00::/7,DIRECT,no-resolve。不要只补 IPv4 例外后,就认定同一服务的 IPv6 连接也会获得相同出口。
按首条命中排列具体例外与兜底规则
先看一个明确冲突:需要让 api.example.com 直连,其他 example.com 子域名走代理。精确例外必须出现在后缀规则之前。
rules:
- DOMAIN,api.example.com,DIRECT
- DOMAIN-SUFFIX,example.com,PROXY
- GEOIP,CN,DIRECT
- MATCH,PROXY
- 访问
api.example.com,第一条命中,直接选择DIRECT。 - 访问
www.example.com,第一条不匹配,第二条命中,交给PROXY。 - 访问其他域名,继续检查 IP 归属;符合 CN 条件时走直连。
- 前面全部不匹配时,由最后一条
MATCH交给PROXY。
如果交换前两条,后缀规则就会先接住 api.example.com,精确域名规则不会再执行。把 MATCH 放到第一条则更直接:后面的普通规则全部失去匹配机会。
使用一份可加载的最小结构检查名称
下面的结构用于演示配置关系,不包含远端代理节点。为了能引用 PROXY,示例创建了同名选择组,并暂时只放入 DIRECT。因此即使规则命中了这个组,最终仍会直连;实际使用时应保留订阅中已有的节点和策略组。
mixed-port: 7890
mode: rule
log-level: info
proxy-groups:
- name: PROXY
type: select
proxies:
- DIRECT
rules:
- DOMAIN,api.example.com,DIRECT
- DOMAIN-SUFFIX,example.com,PROXY
- IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
- GEOIP,CN,DIRECT
- MATCH,PROXY
mixed-port: 7890 只是此处的本地 HTTP/SOCKS 混合代理端口,不是规则匹配条件。若当前客户端使用其他端口,测试时应以实际监听值为准。修改已有配置时,也不要重复新增第二个顶层 rules:,应调整原列表或使用客户端提供的合并机制。
理解 GEOIP、DNS 与 no-resolve 的关系
先让明确的域名规则完成匹配,再考虑是否需要按 IP 判断。连接只有域名、还没有可用目标 IP 时,IP 类规则可能触发解析。将常用域名例外放在 GEOIP 前面,有助于让分流意图更明确,也能减少不必要的 IP 判断。
no-resolve 不是禁用 DNS
在支持此选项的 IP 类规则末尾添加 no-resolve,表示不要为了检查这一条规则而主动解析域名。如果连接已经带有可用 IP,仍可据此判断。它不会关闭系统 DNS,也不保证该连接在后续处理时完全不发生解析。
rules:
- DOMAIN-SUFFIX,example.com,PROXY
- IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
- GEOIP,CN,DIRECT,no-resolve
- MATCH,PROXY
这段配置与没有 no-resolve 的版本不一定得到相同结果。如果尚无目标 IP,带该选项的 GEOIP 可能无法命中,请求便继续落到 MATCH。不要为了减少解析而机械地给所有 IP 规则添加这个参数。
域名没有进入内核时,域名规则无法凭空匹配
应用可能直接连接 IP,或自行完成加密 DNS 解析。此时连接记录里未必带有原始域名。TUN 接管的是网络流量,不等于一定保留每个请求的域名。正确配置的 Fake-IP 映射或嗅探能力可以在相应条件下帮助恢复域名信息,但不能假定所有协议都能恢复。
- 先查看连接详情中的主机名与目标 IP,判断内核实际掌握了哪些信息。
- 再检查 DNS 请求是否按预期进入内核,避免应用和系统各走一套解析路径。
- 最后调整 DNS 或嗅探设置,不要用不断新增域名规则掩盖域名信息缺失的问题。
使用 rule-providers 拆分规则文件
把重复维护的规则放到独立文件,再用 RULE-SET 引用。rule-providers 负责声明规则来源,rules 中的引用位置负责决定优先级。仅声明提供器而不引用,不会让这份规则自动参与分流。
在主配置中声明本地规则集
以下示例采用 mihomo 支持的本地文件提供器,文件路径相对于内核工作目录解析。客户端可能使用自己的配置目录,因此应先确认内核工作目录,再创建 rules/local-direct.yaml。
rule-providers:
local-direct:
type: file
behavior: classical
format: yaml
path: ./rules/local-direct.yaml
rules:
- DOMAIN,api.example.com,PROXY
- RULE-SET,local-direct,DIRECT
- GEOIP,CN,DIRECT
- MATCH,PROXY
在规则文件中只写匹配条件
把下面内容保存到上述路径。classical 格式可以容纳域名、网段等规则条件;每条不再填写最终策略,因为策略已经由主配置中的 RULE-SET,local-direct,DIRECT 指定。
payload:
- DOMAIN-SUFFIX,example.com
- DOMAIN,intranet.example.net
- IP-CIDR,192.168.0.0/16,no-resolve
在这个排列中,api.example.com 会先命中主配置里的精确规则而交给 PROXY;其余符合规则集条件的连接走 DIRECT。如果把 RULE-SET 提到最前面,规则集内的后缀条件就会先接住该 API 域名。
behavior: domain、ipcidr 与 classical 的内容格式不同,不能只更改声明而保留不兼容的文件内容。使用他人规则集时,先核对格式、路径和内核支持情况,再重新加载并查看日志。远程提供器还涉及下载与更新状态,下载失败时应先排查提供器,不要直接认定是规则顺序错误。
按连接记录定位规则冲突
用同一个目标建立新连接,再记录“命中规则、策略链、实际出口”三项。不要只凭页面是否打开判断规则有效:缓存、旧连接和策略组选择都可能让结果看起来没有变化。
- 确认接管:打开客户端的连接列表,发起一次访问。没有对应连接时,先检查系统代理、应用代理或 TUN 接管,而不是继续改规则。
- 确认模式:检查当前为规则模式,并确认启用的是刚修改的配置。
- 查第一条命中:在连接详情或日志中查看规则类型及匹配内容,找到主配置或规则集中对应的位置。
- 查策略链:确认组内当前选项。例如命中
PROXY,但组内选中DIRECT时,实际结果仍是直连。 - 重建连接:保存并重新加载配置后,关闭测试目标的旧连接,再重试。已有连接通常不会因为规则更新而自动换出口。
用明确的本地端口发起测试
如果混合代理实际监听在 127.0.0.1:7890,可使用以下命令建立经过该端口的请求。测试目标应选择需要检查的真实服务;此处的保留示例域名仅演示命令格式,不能代表你的线路表现。
curl --proxy http://127.0.0.1:7890 --connect-timeout 10 --max-time 20 -I https://example.com
若要通过 SOCKS 测试并把域名交给代理端处理,可使用 socks5h。它与本地先解析的测试方式可能提供不同的域名信息,因此比较结果时要记录命令所用协议。
curl --proxy socks5h://127.0.0.1:7890 --connect-timeout 10 --max-time 20 -I https://example.com
| 现象 | 优先检查 | 调整动作 |
|---|---|---|
| 所有连接都命中 MATCH | MATCH 的位置、目标是否有域名、前置规则是否加载 | 将兜底放末尾,核对运行配置与连接元数据 |
| 精确域名例外没有生效 | 前方的后缀、关键词或 RULE-SET | 把具体例外移到覆盖它的规则之前 |
| 命中代理组但仍然直连 | 策略组当前选择与嵌套策略链 | 选择需要的出口,再建立新连接 |
| 配置重新加载失败 | YAML 缩进、策略名、规则集路径与格式 | 按错误日志定位字段,恢复可用配置后逐项修改 |
保留订阅更新后的自定义规则
优先使用客户端明确支持的持久化覆写、合并或自定义规则功能。直接编辑订阅下载生成的配置,可能在下一次更新时被替换。不同客户端菜单名称和处理流程不同,先确认该功能是修改源配置、生成配置,还是只编辑一次运行结果。
核对最终运行配置,而不只看编辑器
- 检查插入位置:“前置规则”适合精确例外;追加到
MATCH后面的规则不会获得匹配机会。 - 检查数组处理:有的合并方式追加
rules,有的直接替换整个列表。先用一条测试规则确认行为。 - 检查名称稳定性:订阅更新若改变策略组名,本地规则也要同步调整,避免引用不存在的策略。
- 检查提供器状态:主配置引用、提供器文件和路径需要同时有效,缺少其中一项都可能影响加载。
每次只调整一类规则,保存前后各一份可用配置。先验证一个精确域名,再扩展到域名后缀或规则集。这样可以区分“规则没有命中”“命中了错误策略”和“出口本身连接失败”,也更容易在订阅更新后复查。