Clash 国内外分流规则怎么写:GEOIP、GEOSITE 与 RULE-SET 组合实战
从规则匹配顺序讲起,用 GEOIP、GEOSITE 与 RULE-SET 搭出一套国内直连、境外走代理的分流配置,并说明 MATCH 兜底与常见误判的修正方法。
先确认内核与规则模式
国内外分流不是一条“国内直连”规则就能完成的。域名归类、IP 归属、人工例外和最后的默认出口,各管一层。实用的组合是:先处理明确例外,再匹配国内域名,接着用国内 IP 补漏,最后让其余连接走指定策略组。
本文配置以 Clash Meta,也就是现今的 mihomo 内核为目标。Clash 是一类内核和客户端生态的常用称呼,不代表所有旧内核都支持同一组字段。尤其是 GEOSITE 与 geodata 配置,不能直接套用到所有传统 Clash 版本。先从客户端的“关于”或内核信息页确认实际内核,再动配置;只看窗口标题里的 Clash 字样不够。
- 模式选 Rule/规则。全局模式不会按本文规则逐条选择出口,直连模式也不适合验证分流。
- 确认已有可用策略组。下文约定现有配置中有一个名为
境外出口的组,组内已有可用节点。名称必须逐字一致。 - 保留订阅原件。优先用客户端的持久覆写或合并功能加入自定义规则,直接修改订阅生成文件,下一次更新可能丢失。
规则顺序比规则数量重要
规则按从上到下的顺序判断,命中一条后就使用该条的目标策略,后面的规则不再为这次选择重新投票。所谓“更精确的规则优先”,不是内核自动比较出来的结果,而是需要配置作者把它放在前面。
rules:
- DOMAIN-SUFFIX,github.com,境外出口
- GEOSITE,cn,DIRECT
- GEOIP,CN,DIRECT,no-resolve
- MATCH,境外出口
这四行里,github.com 及其子域名先走人工指定的组;命中国内域名集合的连接直连;已有目标 IP 且被数据库识别为中国地址的连接也直连;剩下的交给 MATCH。第一行只覆盖这个后缀,不会自动涵盖 GitHub 使用的所有静态资源域名。
三个容易混淆的词
| 规则类型 | 判断依据 | 适合解决的问题 |
|---|---|---|
GEOSITE | 域名分类数据库中的集合 | 按域名类别分流,减少依赖 IP 归属 |
GEOIP | 目标 IP 的国家或地区归属 | 补充域名列表未覆盖的连接 |
RULE-SET | 单独声明的规则提供者 | 维护自己的例外清单或独立规则文件 |
DIRECT 是内置直连策略,境外出口 是本文约定的策略组名,二者不是同一类对象。规则指向一个策略组,只能说明“交给这个组”;组当前选了节点还是 DIRECT,还要继续检查。
准备 GEOSITE 与 GEOIP 数据
GEOSITE,cn 中的 cn 是数据库里的分类名,不是内核即时查询出来的国家标签。它是否存在、收录哪些域名,取决于所用的 geosite.dat。同样,GEOIP,CN 判断的是 IP 数据库归属,不等于网站公司的注册地,也不保证服务器的物理位置。
下面的组合明确启用 geodata-mode: true,因此 GEOIP 使用 geoip.dat,GEOSITE 使用 geosite.dat。请用客户端已有的数据管理方式准备这两个文件,并确认启动日志没有加载失败。若现有配置使用 MMDB 模式,不要只切开关却没有补齐对应数据。
- 数据文件应来自可信维护来源,并与当前内核兼容;文件名正确不代表内容格式一定正确。
- 遇到分类不存在的错误,先核对数据库包含的分类名,不要凭印象把
cn改成其他集合名。 - 更新数据库会改变分类结果。保留旧配置和已知可用数据,更新后用同一组站点复测。
这里不展开自动下载地址,避免把“文件获取失败”和“规则写错”混在一起。首次调试先让本地数据稳定可读,再考虑更新周期,定位起来更直接。
用 RULE-SET 管理人工例外
人工例外放在分类规则前面。这样遇到某个站点分类不合适时,只需要改一份小清单,不必复制整个大规则库。以下采用本地 YAML 文件,不依赖规则文件的在线下载,也便于确认到底加载了哪一份内容。
第一步:声明两个规则提供者
把下面字段合并到现有配置的顶层。若已有 rule-providers,就在其下添加两个条目,不要再创建第二个同名顶层键。相对路径以实际内核工作目录为基准,不一定是下载文件所在目录;沙箱客户端还可能限制可读取的路径。
mode: rule
geodata-mode: true
rule-providers:
local-direct:
type: file
behavior: classical
format: yaml
path: ./rules/local-direct.yaml
local-proxy:
type: file
behavior: classical
format: yaml
path: ./rules/local-proxy.yaml
behavior: classical 表示文件中写的是带规则类型的条目,例如 DOMAIN-SUFFIX。提供者里的条目不写出口;出口由主配置的 RULE-SET 那一行决定。若换成 behavior: domain,文件语法也要相应调整,不能原封不动混用。
第二步:建立本地清单
下面两份内容用于演示“指定域名直连”和“指定域名走代理”。example.com 是文档示例域名,并不是推荐的连通性测试站点;实际使用时删去该条,再按自己的业务需求维护。
rules/local-direct.yaml:
payload:
- DOMAIN-SUFFIX,example.com
rules/local-proxy.yaml:
payload:
- DOMAIN-SUFFIX,github.com
- DOMAIN-SUFFIX,githubusercontent.com
这两条代理例外只是配置用法示范,不代表相关服务在所有网络环境下都必须走代理,也不是其全部关联域名。网页能打开而图片加载失败时,要从失败请求的域名继续补查,不宜直接把整个 CDN 网段都改为同一出口。
第三步:按层次编排 rules
将现有 rules 列表整理为下面的顺序。示例涵盖 IPv4 回环、常见私网以及 IPv6 回环、唯一本地地址和链路本地地址;它不是所有特殊用途地址的完整清单。
rules:
- 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
- IP-CIDR6,fe80::/10,DIRECT,no-resolve
- RULE-SET,local-direct,DIRECT
- RULE-SET,local-proxy,境外出口
- GEOSITE,cn,DIRECT
- GEOIP,CN,DIRECT,no-resolve
- MATCH,境外出口
本地地址先处理,避免访问路由器或内网服务时被最后的代理出口带走。但这些地址规则带有 no-resolve,不会为了判断一个尚未解析的域名而主动查询 DNS。依赖内网域名的场景,还应在直连清单中补充实际域名,并配置可访问的内网 DNS。
两个自定义清单若出现重复域名,前面的 local-direct 会优先命中。维护时尽量让清单互斥,避免几个月后忘记某条规则为何不生效。若使用订阅附带的拒绝、应用或特殊服务规则,也要结合需求重新安排位置,不要直接丢弃已有规则。
理解 no-resolve 与 MATCH 的边界
no-resolve 不等于禁用 DNS
GEOIP,CN,DIRECT,no-resolve 的含义是:如果当前还没有可用于判断的目标 IP,不要仅为了这一条 IP 规则主动发起域名解析。若连接本来就是 IP 访问,或内核已经取得可用的真实目标 IP,仍然可以参与匹配。这个参数不会让浏览器停止解析域名,也不会关闭整个 DNS 模块。
代价也很明确:某个国内域名没有进入 GEOSITE,cn,而到 GEOIP 这一行时又没有可用 IP,它可能一路落到 MATCH,最终走代理。这是这套保守配置的预期边界,不应直接认定为内核忽略了 GEOIP。
- 优先修正域名清单:把确认需要直连的域名加入
local-direct,结果明确,也便于回滚。 - 必要时允许解析:去掉 GEOIP 行的
no-resolve,让 IP 判断有机会触发解析,但要同时检查解析等待和 DNS 路径。 - 不要把 fake-ip 地址当服务器地址:例如
198.18.0.0/16可能被用作 fake-ip 池,不能仅凭这个地址给业务站点判定归属。
MATCH 是未命中兜底,不是故障切换
MATCH,境外出口 只保证前面都未命中时有一个明确目标。它不会因为代理节点连接失败而回头试直连;若需要节点故障切换,应在策略组层使用合适的组类型并正确配置检测。反过来,写成 MATCH,DIRECT 就是“未识别的都直连”,可能让未收录的境外域名直接连接。
本文选择“国内白名单直连,其余代理”。它便于让新增境外域名沿用代理出口,但不能保证所有国内服务都被准确识别。分流策略没有自动消除误判的能力,最后仍需要少量人工例外。
按连接记录验证实际出口
配置能加载,只说明语法和引用大体成立,不代表流量一定按预期经过内核。先确认浏览器已使用系统代理,或者 TUN 已正确接管目标应用。系统代理通常只影响遵循代理设置的程序,不能据此推断所有 UDP 或独立网络栈应用都已被接管。
- 重新加载并检查日志。确认没有规则文件读取失败、GEOSITE 分类缺失、目标策略不存在等错误。先保持
info;细节不足时临时开启debug,复现后再恢复。 - 先测一条人工例外。访问清单中的域名,在连接详情中检查是否命中
RuleSet,并查看对应提供者与最终策略链。 - 再测域名分类。选一个当前数据库确实收录在
cn集合中的域名,确认规则类型为GeoSite、策略为DIRECT。 - 最后观察兜底。找一条未命中前面规则的连接,确认它落到
Match,并检查境外出口当前选中的实际节点。
每次测试前关闭相关旧连接,再建立新连接。已经建立的 TCP 连接不会因为规则文件修改而自动迁移出口,浏览器复用连接时尤其容易造成“规则改了但没变化”的错觉。测试时记录域名、目标 IP、命中规则和最终出口四项,比只截图一个访问失败页面更有用。
常见误判的修正顺序
| 现象 | 优先检查 | 具体处理 |
|---|---|---|
| 国内站点走了代理 | 是否命中 Match,域名是否被收录 | 确认业务域名后加入 local-direct,再检查 GEOIP 是否跳过解析 |
| 境外站点被判为直连 | 是否命中 GeoIP 或前置直连清单 | 把域名加入 local-proxy,并保证位置在 GEOSITE、GEOIP 之前 |
| RULE-SET 完全不生效 | 提供者名称、路径、文件格式 | 核对 classical 条目语法及 payload 层级,重新加载后看错误日志 |
| 命中代理组仍显示直连 | 组内当前选项与嵌套策略链 | 查看组是否选了 DIRECT,逐层确认最终出口 |
| 首页正常但资源加载失败 | 失败资源使用的独立域名 | 按实际连接记录补充资源域名,避免扩大为整个共享 IP 段 |
| 更新订阅后配置恢复原样 | 修改是否写在临时生成文件里 | 迁移到客户端持久覆写入口,确认合并后的最终配置顺序 |
遇到国内站点解析到境外 CDN 的情况,域名规则放在 GEOIP 前面就有价值:只要域名已命中直连集合,后面的境外 IP 归属不会推翻结果。反过来,境外业务使用国内地址时,单靠 GEOIP 也可能直连,因此明确的代理例外要放在 IP 判断之前。
最后保留一套小而稳定的测试清单:一个人工直连域名、一个人工代理域名、一个国内分类域名,以及一条实际落到兜底的连接。每次只改一处,再用同一组请求复测。能解释每条连接为什么走这个出口,才算分流配置真正落地;继续堆叠规则数量,通常解决不了顺序、DNS 或策略组选错的问题。