规则匹配顺序:从上到下,首条命中

Clash 客户端使用规则模式时,内核按配置文件中 rules 列表的顺序检查连接。遇到第一条满足条件的规则,就把连接交给该规则指定的策略,不再继续寻找“更精确”的规则。因此,规则的书写顺序本身就是优先级,不存在 DOMAIN 天生高于 IP-CIDR 的通用排序。

下面的片段假设当前配置中已经存在名为“代理选择”的代理组。这个名称必须与 proxy-groups 中的 name 完全一致。示例域名使用 example.com,用于说明语法,不代表需要对该网站采用某种固定策略。

mode: rule

rules:
  - DOMAIN,api.example.com,代理选择
  - DOMAIN-SUFFIX,example.com,DIRECT
  - MATCH,代理选择
  • 访问 api.example.com:第一条命中,进入“代理选择”。
  • 访问 www.example.com:第一条不匹配,第二条命中,交给 DIRECT。
  • 访问其他没有命中前两条规则的目标:由末尾的 MATCH 接管。

如果把第二条放到第一条前面,api.example.com 也会先命中后缀规则并直连。后面的精确域名规则即使写得正确,也不会再被检查。维护规则时,应先确定例外,再安排覆盖范围更大的集合。

DOMAIN 家族:精确域名、后缀与关键词

域名规则通常写成“规则类型、匹配内容、目标策略”三个字段。这里的域名不是完整 URL:不要附带 https://、端口、路径或查询参数。要匹配 https://api.example.com/v1/status,应写 api.example.com,而不是把整段地址放进 DOMAIN。

三类常用域名规则的匹配边界
类型 示例 匹配结果
DOMAIN DOMAIN,example.com,DIRECT 只匹配 example.com,不包括 www.example.com。
DOMAIN-SUFFIX DOMAIN-SUFFIX,example.com,DIRECT 匹配 example.com 及其子域名,不匹配 notexample.com。
DOMAIN-KEYWORD DOMAIN-KEYWORD,example,代理选择 匹配域名中包含 example 字符串的目标,范围比后缀规则更宽。

例外域名放在后缀规则前

rules:
  - DOMAIN,download.example.com,代理选择
  - DOMAIN-SUFFIX,example.com,DIRECT
  - DOMAIN-KEYWORD,telemetry,REJECT
  - MATCH,代理选择

这个顺序先保留下载域名的独立出口,再处理整个域名后缀。关键词规则位于后缀规则之后,因此即使 telemetry.example.com 含有关键词,也会先命中 example.com 的后缀规则而直连。如果需要阻止它,应把精确拒绝规则放到前面,而不是假定 REJECT 会自动拥有最高优先级。

关键词规则应控制范围

DOMAIN-KEYWORD,ad,REJECT 会匹配许多正常域名中的短字符串,容易造成误伤。已知完整域名时,优先使用 DOMAIN;需要覆盖一组子域名时,使用 DOMAIN-SUFFIX。关键词更适合确实存在统一命名特征、且已经核对匹配范围的目标。

域名规则需要连接元数据中具有可用域名。应用直接连接 IP、DNS 路径不同或域名嗅探未生效时,连接记录可能只有目标地址。此时不能仅凭浏览器地址栏中的域名,断定内核一定能命中相应 DOMAIN 规则。

IP-CIDR 与 no-resolve:控制解析触发

IP-CIDR 按目标 IPv4 地址匹配网段,IPv6 通常使用 IP-CIDR6。CIDR 后面的数字是网络前缀长度:IPv4 的 /32 表示单个地址,192.168.1.0/24 表示从 192.168.1.0 到 192.168.1.255 的地址范围。

rules:
  - IP-CIDR,192.168.1.10/32,DIRECT,no-resolve
  - IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
  - IP-CIDR,10.0.0.0/8,DIRECT,no-resolve
  - IP-CIDR,172.16.0.0/12,DIRECT,no-resolve
  - IP-CIDR6,fc00::/7,DIRECT,no-resolve
  - MATCH,代理选择

no-resolve 的作用是:不要仅为了检查这条 IP 规则而主动解析尚未解析的目标域名。它不是“关闭 DNS”,也不是“禁止所有域名经过这条规则”。如果目标 IP 已经存在,内核仍可据此匹配网段;如果尚无可用目标 IP,该规则不会为了匹配而触发一次解析。

两条连接路径的区别

  1. 应用直接连接 192.168.1.10:443:目标 IP 已知,可以命中单地址规则,no-resolve 不会阻止这次匹配。
  2. 应用提交 nas.example.com:若内核还没有可用的真实目标 IP,带 no-resolve 的网段规则不会主动解析它,连接可能继续匹配后面的规则。

如果这个 NAS 域名必须直连,通常应额外添加 DOMAIN,nas.example.com,DIRECT,而不是依赖未必会触发的 IP 判断。对需要根据解析结果分流的域名,则要结合 DNS 配置,决定是否移除对应规则的 no-resolve。

在 fake-ip 场景下,客户端看到的合成地址也不能直接当成网站的真实服务端地址。应结合连接详情、域名映射与 DNS 日志判断,不要把 fake-ip 地址池整体加入直连规则来修复某个网站。

策略目标与 MATCH:出口选择和兜底

规则最后指定的是策略,不一定是具体代理节点。DIRECT 表示直连,REJECT 表示拒绝;自定义名称可以指向已定义的代理或代理组。规则命中“代理选择”后,实际出口由这个组当前选中的成员决定。

因此,连接详情显示“命中代理组”,但实际仍然直连,并不一定是规则失效。应继续检查组内是否选择了 DIRECT、是否经过另一个包含 DIRECT 的组,以及自动选择组当前的结果。规则命中与最终出口是两个相邻但不同的判断步骤。

rules:
  - DOMAIN,blocked.example.com,REJECT
  - DOMAIN,intranet.example.com,DIRECT
  - DOMAIN-SUFFIX,example.com,代理选择
  - MATCH,代理选择

MATCH 必须放在兜底位置

MATCH 没有域名或网段参数,语法只有 MATCH,策略。它无条件匹配到达这一行的连接。若放在规则列表第一行,后面所有规则都失去执行机会;若放在两个规则集之间,第二个规则集也不会再被检查。

  • 希望未分类流量进入代理组:使用 MATCH,代理选择。
  • 希望未分类流量直连:使用 MATCH,DIRECT。
  • 希望只允许明确列出的连接:可使用 MATCH,REJECT,但必须先补齐必要依赖,否则登录、更新与资源加载可能被一起拒绝。

更换兜底策略会影响大量尚未分类的流量。修改前保存当前配置,修改后检查一次完整业务流程,而不只测试网站首页能否打开。

mihomo 规则集:集合位置仍然决定优先级

mihomo 支持用 rule-providers 管理规则集,再通过 RULE-SET 引用。规则集不是绕过主列表的独立优先级系统:某个 RULE-SET 位于第几行,就在那个位置参与匹配。前面的普通规则已经命中时,后面的集合不会执行。

下面是 mihomo 本地文件规则集的片段。它需要与现有配置合并,保留原有节点和“代理选择”组。./rules/work.yaml 应相对于内核的配置工作目录实际存在;不要只创建声明而遗漏文件。

rule-providers:
  work:
    type: file
    behavior: classical
    format: yaml
    path: ./rules/work.yaml

rules:
  - DOMAIN,login.example.com,DIRECT
  - RULE-SET,work,代理选择
  - IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
  - MATCH,代理选择

对应的 work.yaml 内容如下。策略由引用处的 RULE-SET 指定,因此 classical 集合中的每一项不再附加“代理选择”:

payload:
  - DOMAIN-SUFFIX,example.com
  - IP-CIDR,203.0.113.0/24

203.0.113.0/24 是文档示例网段,不是可直接用于业务的目标地址。实际配置应使用业务提供的网段。这里的 login.example.com 先命中主列表第一条,所以即使它属于 work 集合中的域名后缀,也仍然直连。

behavior 与文件内容必须对应

  • classical:条目包含 DOMAIN-SUFFIX、IP-CIDR 等规则类型,适合混合规则。
  • domain:条目是域名匹配内容,不应原样复制带类型前缀的 classical 条目。
  • ipcidr:条目是 IP 网段,不是域名列表。

这些配置按 mihomo 语法展示。不同 Clash 内核对规则集格式及扩展类型的支持不同,应以客户端显示的内核信息和配置检查结果为准。文件名相同,不代表旧内核能够解析全部字段。

自定义规则排序与订阅覆盖

规则数量增加后,建议按“明确例外 → 分类规则 → 兜底策略”维护,而不是不断往列表末尾追加。下面是一套可审查的排序思路,具体拒绝规则是否置顶,取决于业务允许哪些例外。

  1. 必须覆盖其他分类的精确规则。 例如单个登录域名直连、单个跟踪域名拒绝。发生冲突时,明确决定哪条应先匹配。
  2. 本地服务与局域网目标。 已知域名用域名规则,已知网段用 IP 规则,并确认是否需要主动解析。
  3. 业务分类和规则集。 按办公、媒体或其他用途划分;有交集的集合,应把优先分类放在前面。
  4. 较宽泛的域名、地区或 IP 分类。 覆盖范围较大的集合容易遮住后续例外,调整时要抽样检查。
  5. 最后一条 MATCH。 明确未分类连接的去向,后面不再放需要执行的规则。

订阅更新可能重新生成主配置。直接修改订阅生成的 YAML,即使当前生效,也可能在下一次更新后丢失。若客户端提供覆写、合并或持久化自定义规则功能,应使用该功能;入口名称随客户端而异,不能把某个界面的菜单路径当成所有 Clash 客户端的共同设置。

尤其要检查“追加”与“前置”的区别:自定义规则若被追加到订阅已有的 MATCH 后面,内容虽然存在,却永远无法命中。应查看内核最终加载的规则列表,确认合并后的实际位置,而不是只查看编辑器中的片段。

规则不生效:按连接记录逐项验证

排错时一次只改一个条件。先选一个明确目标,例如 api.example.com,记录预期策略,再检查新建连接的命中规则和最终出口。浏览器复用的长连接可能继续沿用旧路径,重新加载页面并不总等于建立新连接。

  1. 确认流量经过内核。 系统代理只覆盖遵循系统代理设置的应用。未进入内核的连接不会受 rules 控制;TUN 也需要路由实际覆盖目标流量。
  2. 确认运行配置和模式。 检查是否载入了修改后的配置,运行模式是否为规则,订阅切换后是否又加载了另一份配置。
  3. 检查解析错误。 YAML 使用空格缩进,不使用制表符;确认规则类型拼写、逗号数量及策略名称。重复的顶层 rules 键应合并为一个列表。
  4. 检查更早的命中项。 查找覆盖目标的 DOMAIN-SUFFIX、关键词、RULE-SET 或提前出现的 MATCH。日志里已经命中的规则比预想中的规则更有判断价值。
  5. 核对目标元数据。 记录里是域名还是 IP,是否为 IPv6,是否已有解析结果。只有 IPv4 网段规则时,不能期待它匹配 IPv6 目标。
  6. 重新建立测试连接。 在允许中断的情况下关闭对应旧连接,或退出并重开测试应用,再观察新的规则命中记录。

一份可维护的规则配置,应能回答三个问题:目标为什么命中这一行,这一行把连接交给哪个策略,策略最终使用哪个出口。把这三层分别验证,DOMAIN、IP-CIDR、规则集和 MATCH 的关系就能落到具体连接上,而不是停留在配置文本的表面顺序。