Clash 自定义规则

梳理 DOMAIN、DOMAIN-SUFFIX、IP-CIDR、GEOIP、PROCESS-NAME 等规则类型,解释自上而下的匹配顺序、no-resolve 参数与 rule-providers 的组合方式。

规则生效的三个前提

Clash 规则负责为连接选择出站策略,不负责生成代理节点。配置中的节点、策略组与规则是不同层次:节点提供出口,策略组组织可选出口,rules 决定连接交给哪个出口。排查时先把这三层分开,避免把节点不可用误判为规则没有命中。

  1. 连接已进入内核。系统代理通常只影响遵循代理设置的程序;游戏、部分命令行工具和 UDP 流量可能没有进入代理。TUN 可以扩大接管范围,但仍要检查路由、排除项和权限。
  2. 当前模式为规则模式。配置中对应 mode: rule。全局模式和直连模式不会按这里的规则列表进行常规分流。
  3. 修改的是实际运行配置。客户端的订阅原文、覆写配置与内核最终配置可能不同。保存后应检查配置验证结果,再重新加载。

规则语法与常用类型

多数规则采用 类型,匹配内容,策略 的形式。逗号使用英文半角字符;规则作为 YAML 列表项放在 rules: 下,每项前面有一个短横线。内置策略 DIRECT 表示直连,REJECT 表示拒绝;其他策略名称必须与已定义的节点或策略组名称完全一致。

规则类型示例匹配范围
DOMAINDOMAIN,api.example.com,DIRECT精确匹配该域名,不包含它的子域名。
DOMAIN-SUFFIXDOMAIN-SUFFIX,example.com,DIRECT匹配根域及其子域,不匹配 otherexample.com。
DOMAIN-KEYWORDDOMAIN-KEYWORD,example,DIRECT匹配域名中出现的字符串,范围比后缀规则更宽。
IP-CIDRIP-CIDR,192.168.0.0/16,DIRECT,no-resolve匹配 IPv4 目标网段,示例覆盖 192.168.0.0 至 192.168.255.255。
IP-CIDR6IP-CIDR6,fc00::/7,DIRECT,no-resolve匹配 IPv6 网段,示例为唯一本地地址范围。
GEOIPGEOIP,CN,DIRECT,no-resolve依据本地 IP 地理数据库匹配地址,准确性取决于数据库。
PROCESS-NAMEPROCESS-NAME,curl.exe,DIRECT匹配内核识别到的进程名,受系统与权限影响。
MATCHMATCH,出口接住此前没有匹配的连接,不填写匹配内容。

域名规则不填写协议、端口和路径

对 https://api.example.com:443/v1/status 分流时,域名规则中只写 api.example.com。把整条 URL 放进 DOMAIN 不会按网页地址匹配。若需要按目标端口区分,可以使用内核支持的 DST-PORT;但单独一条 DST-PORT,443,出口 会覆盖所有经过该位置的 443 端口连接,并非只匹配某个网站。

文中的 example.com 属于保留示例域名,用来展示语法。正式配置应替换成实际需要分流的域名,而不是期待示例条目改变常用网站的线路。

匹配顺序与例外规则

常规规则按列表自上而下检查,第一条成功命中的规则决定策略,之后不再继续比较。内核不会自动选择“更精确”的规则,也不会因为下面还有一条拒绝规则就重新计算结果。因此,特例通常放在通用规则之前,MATCH 放在最后。

rules:
  - DOMAIN,api.example.com,DIRECT
  - DOMAIN,ads.example.com,REJECT
  - DOMAIN-SUFFIX,example.com,出口
  - IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
  - MATCH,出口
  • api.example.com 命中第一条,使用直连。
  • ads.example.com 命中第二条,连接被拒绝。
  • www.example.com 命中第三条,交给“出口”策略组。
  • 已知目标地址为 192.168.1.20、且未命中前面域名规则的连接,命中局域网条目。
  • 其余连接交给最后的 MATCH。

如果把第三条后缀规则移到第一条,那么 api.example.com 和 ads.example.com 都会提前命中它。后面的直连与拒绝条目即使语法完全正确,也没有机会执行。

进程规则同样遵守顺序

把 PROCESS-NAME,curl.exe,DIRECT 放在列表顶部,意味着该进程的连接可能在检查网站规则之前就被直连。若只是给某个域名设置例外,应优先采用域名规则;若确实要让整个程序固定走一条线路,再使用进程规则。Windows 常见名称带 .exe,Linux 与 macOS 常见名称不带该扩展名,应以连接详情中实际识别到的进程名称为准。

no-resolve 的准确含义

no-resolve 的作用是:检查这条 IP 类规则时,不为只有域名的连接主动发起一次域名解析。它不是禁止 DNS,也不代表连接最终不会解析域名。域名解析仍可能由客户端 DNS、其他规则或实际建立出站连接的过程触发。

rules:
  - DOMAIN-SUFFIX,example.com,出口
  - IP-CIDR,10.0.0.0/8,DIRECT,no-resolve
  - GEOIP,CN,DIRECT,no-resolve
  - MATCH,出口

假设某个连接只有域名信息,且没有命中第一条。检查后面的 IP 规则时,no-resolve 会阻止为了这些规则而额外解析。如果连接已经有可用的目标 IP,IP 类规则仍可以据此匹配。是否具备真实目标 IP 与 DNS 模式、连接入口以及元数据有关,不能只看域名的实际解析结果推断一定命中。

两种常见取舍

  • 优先域名分流:把主要域名规则放前面,IP 规则加 no-resolve,减少规则求值时附带的解析。代价是部分只有域名信息的连接可能直接落到兜底。
  • 希望按解析地址分类:对特定 IP 规则不加 no-resolve,允许求值时解析。但这会引入对 DNS 响应和解析耗时的依赖,应同时检查 DNS 配置。

GEOIP,CN 判断的是数据库中的 IP 归属,不是网站经营主体,也不等价于“所有国内网站”。使用 CDN 的网站可能因解析地址不同而得到不同结果;需要稳定控制的服务,更适合通过明确的域名规则分流。

使用 rule-providers 复用规则

当多份配置需要复用同一组域名和网段时,可以把匹配条件移入规则提供器,再通过 RULE-SET 引用。提供器负责加载规则内容,真正的优先级由 RULE-SET 在主 rules 列表中的位置决定,而不是由提供器的声明位置决定。

主配置:本地 classical 规则集

rule-providers:
  local-direct:
    type: file
    behavior: classical
    path: ./rules/local-direct.yaml

rules:
  - DOMAIN,api.example.com,出口
  - RULE-SET,local-direct,DIRECT
  - MATCH,出口

规则集文件:rules/local-direct.yaml

payload:
  - DOMAIN-SUFFIX,example.com
  - IP-CIDR,192.168.0.0/16,no-resolve
  - IP-CIDR6,fc00::/7,no-resolve

规则集中的条目不写 DIRECT 或策略组名称,目标策略由主配置的 RULE-SET,local-direct,DIRECT 统一指定。这个例子里,api.example.com 仍先命中主列表第一条;同一根域的其他子域才进入规则集并直连。

path 通常相对于内核工作目录解析,不一定是下载的订阅文件所在目录。需要确认客户端允许的规则文件位置,并先创建文件;文件缺失、目录不可访问或内容格式错误,都可能导致提供器加载失败。

behavior内容形式适用场景
classical带类型的规则,例如 DOMAIN-SUFFIX,example.com同一个集合需要容纳域名与 IP 等多种条件。
domain按内核域名规则集语法填写域名条目专门维护域名集合,不沿用 classical 的类型前缀。
ipcidr填写 192.168.0.0/16 等地址段专门维护 IPv4、IPv6 网段集合。

三种格式不能只改 behavior 就混用。若换成 HTTP 提供器,还需要可信的实际规则地址与更新周期;远程规则会改变分流结果,应检查来源与更新内容,不要把未知集合放在所有自定义例外之前。

可验证的最小配置

下面配置用于验证 mihomo 的语法和命中顺序。它不包含代理节点,“出口”组里只有 DIRECT,因此除拒绝条目外,实际出站仍是直连。确认规则行为之后,再把已有的节点或节点提供器接入策略组。

mixed-port: 7890
allow-lan: false
mode: rule
log-level: info

proxy-groups:
  - name: 出口
    type: select
    proxies:
      - DIRECT

rules:
  - DOMAIN,api.example.com,DIRECT
  - DOMAIN,ads.example.com,REJECT
  - DOMAIN-SUFFIX,example.com,出口
  - IP-CIDR,127.0.0.0/8,DIRECT,no-resolve
  - IP-CIDR,10.0.0.0/8,DIRECT,no-resolve
  - IP-CIDR,172.16.0.0/12,DIRECT,no-resolve
  - IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
  - IP-CIDR6,::1/128,DIRECT,no-resolve
  - IP-CIDR6,fc00::/7,DIRECT,no-resolve
  - MATCH,出口

这里显式使用 7890 端口,便于命令行测试;如果已被其他进程占用,需要改成空闲端口,并同步修改测试命令。allow-lan: false 不向局域网开放代理入口。实际客户端可能覆盖监听端口,应以运行配置与监听状态为准。

先验证配置,再验证请求

mihomo -t -f ./config.yaml
curl -I --proxy http://127.0.0.1:7890 https://example.com

第一条命令要求本机可执行文件名称为 mihomo,且当前目录存在 config.yaml。使用图形客户端时,可改用客户端提供的配置检查功能。第二条命令明确将请求送入 HTTP 代理,避免系统代理是否被命令行继承这一变量;Windows PowerShell 中可使用 curl.exe 调用对应程序。

示例请求应命中 DOMAIN-SUFFIX,example.com,出口。验证依据是连接详情或日志中的规则类型、匹配内容和策略链,不是网页打开速度,也不是单看出口 IP。两个不同规则都可能指向同一个策略,所以出口相同不能证明规则相同。

规则未生效的排查顺序

  1. 看连接是否出现。客户端连接列表没有目标请求时,先检查代理入口、TUN 路由和应用设置。请求根本没进入内核,调整规则位置不会解决问题。
  2. 看实际规则模式。确认不是全局或直连模式,并检查当前激活的是哪份配置,而不是只看编辑器里的文件名。
  3. 看命中的第一条规则。连接落到宽泛的后缀、关键词或进程规则时,把必要的特例移到它前面。不要在 MATCH 后追加需要生效的规则。
  4. 看策略名称。“出口”和“代理出口”是两个不同名称。引用未定义的策略通常会导致配置验证失败,应先修复加载错误。
  5. 看域名与进程元数据。连接只有 IP 时,域名规则未必有可用匹配对象;进程名为空时,进程规则也无法按预期工作。TUN 不会自动补齐所有连接的域名和进程信息。
  6. 看提供器状态。确认文件存在、格式与 behavior 一致,且客户端已经成功加载规则集。修改本地文件后按客户端要求更新提供器或重新加载配置。
  7. 重建测试连接。配置更新后,已建立的长连接可能仍沿用原来的出站。停止原请求,再发起新连接,必要时关闭对应连接后复测。

整理规则时可以采用固定顺序:明确的拒绝与直连特例在前,业务域名集合随后,进程和 IP 类规则按实际优先级安排,最后保留一个清晰的 MATCH。每次只修改一类条件,再用新连接核对命中结果,比同时调整 DNS、TUN 和整套规则更容易定位原因。

Clash 客户端下载