进阶配置 预计阅读 12 分钟

Clash 规则分流写法实战:GEOIP、DOMAIN-SUFFIX 与 RULE-SET 组合

从规则匹配顺序讲起,演示国内直连、海外走代理的常见分流写法,以及 rule-providers 规则集的引用与更新方法。

先确认规则模式与配置入口

规则分流负责决定一条连接使用哪个出站,不负责创建代理节点。开始前,先确认订阅已经导入、节点能够连接,并在客户端的“代理模式”中选择“规则”。全局模式通常把流量交给全局策略,直连模式则不会按本文的规则列表完成分流。

本文以 Clash Meta 延续项目 mihomo 的 YAML 配置为主要对象。经典 Clash 与不同客户端对规则集格式、更新入口的支持存在差异;实际编辑前,在“关于”或“内核信息”中确认运行内核。以下示例使用 YAML 规则集,不依赖 MRS 二进制规则集格式。

  1. 在“配置”或“订阅”页面导出当前配置,保留可以重新导入的副本。
  2. 确认配置中存在名为 代理选择 的策略组。若实际名称为其他文字,应统一修改示例中所有引用。
  3. 找到客户端提供的“覆写”“扩展配置”或“配置编辑”入口,确认它采用合并还是替换规则的方式。
  4. 先保存一份最小规则,加载成功后再引入远程规则集。

匹配顺序:第一条命中的规则决定出站

rules 是有顺序的列表。内核从上向下检查,一旦某条规则命中,就采用它指定的策略,不会继续寻找“更精确”的下一条。因此,个人例外规则放在前面,公共规则集放在中间,兜底的 MATCH 放在最后。

mode: rule

rules:
  - DOMAIN,github.com,代理选择
  - DOMAIN-SUFFIX,home.arpa,DIRECT
  - IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
  - GEOIP,CN,DIRECT
  - MATCH,代理选择

这是配置片段,不包含节点与策略组定义。合并到现有配置时,保留一份顶层 rules,不要连续粘贴两个同名键。最后一行表示“前面的规则均未命中时使用代理选择”,并不等于内核已经识别出目标一定属于海外。

三个容易混淆的名称

  • DIRECT:内置直连出站,由本机网络直接连接目标。
  • 代理选择:本例约定的策略组名称,必须已经定义,且其当前选择确实是可用节点。
  • MATCH:兜底规则类型,不是策略组;它后面的字段才是出站目标。

如果把 MATCH,代理选择 放到第一行,后面的直连规则都不会获得匹配机会。如果策略组当前选择的是 DIRECT,即便日志显示命中了“代理选择”,连接仍可能直连。排查时要同时看规则和最终出站链。

DOMAIN-SUFFIX:先处理确定的域名边界

域名规则适合表达明确的站点意图。DOMAIN 只匹配完整域名,DOMAIN-SUFFIX 匹配该域名本身及其子域名。规则值只写域名,不带协议、路径或端口。

规则写法命中范围使用场景
DOMAIN,github.com,代理选择仅 github.com精确覆盖单个主机名
DOMAIN-SUFFIX,github.com,代理选择github.com 与 api.github.com 等子域名覆盖同一域名下的服务
DOMAIN-SUFFIX,home.arpa,DIRECThome.arpa 及其子域名家庭网络中的本地域名

DOMAIN-SUFFIX,github.com 不会匹配 notgithub.com,也不会自动覆盖 githubusercontent.com。站点的登录、图片与下载可能分布在不同域名上,不能只凭浏览器地址栏判断全部请求。应在连接记录中确认实际目标,再补充必要规则。

域名规则能否命中,取决于内核是否拿到域名

通过 HTTP 代理发起的域名请求通常可以保留主机名;应用直接连接 IP 时,情况不同。在 TUN 场景中,DNS 接管、fake-ip 映射或流量嗅探可能帮助恢复域名,但这些机制不能保证所有协议都能恢复。浏览器启用独立加密 DNS 后,也要检查实际 DNS 路径是否绕开了预期配置。

不要把“开启 TUN”理解成“所有域名规则自然生效”。先在连接详情中查看目标是域名还是纯 IP,再决定检查 DNS、嗅探或 IP 规则。相关概念可在概念速查中核对。

GEOIP:用目标 IP 补充地域判断

GEOIP,CN,DIRECT 表示目标 IP 命中当前地理数据库中的 CN 条目时直连。判断对象是 IP,不是域名后缀或运营主体。一个中文站点使用境外 CDN,或者一个海外服务使用境内边缘节点,都可能让实际结果与直觉不同。

rules:
  - DOMAIN-SUFFIX,github.com,代理选择
  - 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,fc00::/7,DIRECT,no-resolve
  - GEOIP,CN,DIRECT
  - MATCH,代理选择

这里先列出常见私有地址范围,避免局域网设备落入代理兜底。它们不是完整的特殊地址清单;如果环境涉及回环、链路本地地址或其他保留地址,还应结合客户端的 TUN 路由排除项处理。规则直连与路由排除是不同层次,前者并不意味着流量没有进入内核。

no-resolve 的实际影响

IP 类规则检查域名目标时,可能需要先解析域名。附加 no-resolve 表示不为了该条规则主动触发域名解析;它不等于禁用整个连接的 DNS,也不会让已有目标 IP 的连接跳过 IP 判断。

  • 局域网网段规则通常可带 no-resolve,避免在列表开头就为每个域名触发解析。
  • 如果希望 GEOIP,CN 对尚未解析的域名也做地域判断,可以像示例一样不附加 no-resolve。
  • 如果给 GEOIP 加上 no-resolve,需要接受一部分域名连接可能继续向后匹配,最终进入代理兜底。

GEOIP 结果还取决于数据库来源、更新时间与 DNS 返回的地址。修改规则并不会同步修正数据库。出现个别服务误判时,优先添加经过确认的域名例外,而不是立刻把整套地域规则倒置。

RULE-SET:把公共列表与个人规则拆开维护

rule-providers 定义规则集的数据来源,RULE-SET 在规则列表中引用它。仅声明 provider 不会产生分流效果,必须在 rules 中引用相同名称。以下片段把公共直连域名与个人局域网规则拆开,并给远程资源设置一天的更新间隔。

rule-providers:
  direct-domains:
    type: http
    behavior: domain
    format: yaml
    url: https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/direct.txt
    path: ./rules/direct-domains.yaml
    interval: 86400

  local-policy:
    type: file
    behavior: classical
    format: yaml
    path: ./rules/local-policy.yaml

rules:
  - RULE-SET,local-policy,DIRECT
  - DOMAIN-SUFFIX,github.com,代理选择
  - RULE-SET,direct-domains,DIRECT
  - GEOIP,CN,DIRECT
  - MATCH,代理选择

远程地址是第三方公开规则源,由内核在运行时下载;可达性和内容更新由该项目决定。文件扩展名为 .txt 不代表内容一定是纯文本列表,这个来源的内容采用 YAML 的 payload 结构,因此声明 format: yaml。

path 是内核工作目录下的缓存或文件路径,不是浏览器下载目录。图形客户端可能把工作目录放在应用数据目录,不能默认认为它就在安装程序旁边。对于 type: file,应先创建文件,再加载配置。

个人规则文件的完整内容

在工作目录的 rules/local-policy.yaml 中保存下面的内容。文件型 provider 负责提供匹配条件,最终策略由外部的 RULE-SET,local-policy,DIRECT 指定,因此文件内不再追加 DIRECT。

payload:
  - DOMAIN-SUFFIX,home.arpa
  - IP-CIDR,10.0.0.0/8,no-resolve
  - IP-CIDR,172.16.0.0/12,no-resolve
  - IP-CIDR,192.168.0.0/16,no-resolve
  - IP-CIDR6,fc00::/7,no-resolve

behavior 必须与内容对应

behavior内容示例注意事项
domain'+ .example.com' 的实际写法应去掉加号后的空格,即 '+‌.example.com' 不应含隐藏字符;推荐直接采用来源提供的原始内容域名列表,不是完整 rules 行
ipcidr192.168.0.0/16IP 地址段列表
classicalDOMAIN-SUFFIX,home.arpa带规则类型,不带最终策略

不要把广告过滤语法、完整 Clash 配置或网页 HTML 直接当作规则集。下载成功只说明拿到了响应内容,不代表内容可以被解析。遇到解析错误,应同时检查 behavior、format、缩进与响应正文。

规则更新:区分订阅、规则集与地理数据库

这三类数据有不同的更新链路。订阅更新通常刷新节点及订阅自带配置;HTTP 规则集依据 provider 的 interval 更新;GEOIP 数据库则由内核或客户端相应的数据库更新功能管理。点击一次“更新订阅”,不等于三类内容都已经更新。

  1. 首次加载:检查规则集是否下载成功、是否完成解析。没有可用缓存且下载失败时,配置可能无法按预期加载,不应假设会自动获得完整直连列表。
  2. 定期更新:interval: 86400 的单位是秒,即 24 小时。没有必要为了普通域名列表设置成每 10 秒请求一次。
  3. 手动验证:在客户端的“规则集”或相关管理页面执行更新;没有此入口时,依据客户端支持的方法重新加载配置,并观察日志。
  4. 本地文件:type: file 不从远程拉取内容。修改文件后,使用客户端支持的重载入口让内核读取新内容。

远程规则也是需要审阅的配置输入。批量直连列表可能让某些登录或下载服务绕过代理。对有明确出站要求的域名,应把个人规则放在公共列表之前,并保留一份已验证的配置用于回退。

验证顺序:看命中规则,再看最终连接

“网页能打开”只能证明某条访问路径可用,不能证明分流符合设计。修改后应关闭测试页面的旧连接,再重新请求,避免复用修改前建立的连接。必要时在客户端“连接”页面结束对应连接,但应注意正在进行的下载也会中断。

用三类目标验证规则

  • 局域网目标:若路由器实际地址为 192.168.1.1,访问其管理页面,检查命中局域网规则且最终出站为 DIRECT。
  • 明确代理域名:访问 github.com,检查是否命中前置的域名规则,并确认“代理选择”最终落到预期节点。
  • 普通直连域名:选择公共直连规则集中确实存在的域名,检查命中的是 RULE-SET 还是后面的 GEOIP,而不是只看页面内容。

如果当前配置的混合代理端口确实为 7890,还可以用下面的命令显式经过本机 HTTP 代理。端口应以客户端显示值为准;该测试验证的是显式代理路径,不能替代 TUN 接管测试。

curl --proxy http://127.0.0.1:7890 --head --max-time 15 https://github.com

在 Windows PowerShell 中,如果 curl 被映射到其他命令,可使用 curl.exe。HTTP 状态码不是唯一判断标准,即便响应为重定向,也可以结合连接记录确认请求走向。

按现象缩小问题范围

现象优先检查处理动作
所有连接都走代理全局模式、过早出现的 MATCH切换规则模式,将 MATCH 移到列表末尾
域名规则没有命中实际请求域名、连接是否只有 IP查看连接详情,再检查 DNS 与域名恢复路径
配置加载失败策略组名称、重复键、缩进按日志指出的字段修正,重新加载
规则集存在但不生效RULE-SET 名称与引用位置核对 provider 名称,并检查前面是否已命中
更新订阅后规则消失编辑的是生成配置还是持久覆写把个人规则迁移到客户端的持久扩展入口

最终保留一套容易解释的顺序:个人例外、局域网规则、公共域名列表、GEOIP、MATCH。每增加一条规则,都应能回答“匹配什么、走哪个策略、为什么放在这里”。遇到系统代理或 TUN 接管层面的故障,可继续查看排查手册;规则列表本身无法修复没有进入内核的流量。

下载Clash