rule-providers 的定位:把规则内容与主配置解耦

在 Clash 与 Mihomo 配置中,rules 决定流量按照什么顺序匹配,rule-providers 则负责从本地文件或远程 URL 提供一组可复用的规则。两者不要混为一谈:规则提供者本身只是一个规则数据源,不会自动生效;只有在 rules 中通过 RULE-SET 引用对应名称,这些域名、IP 或进程规则才会真正参与分流。把数百行第三方域名直接粘贴进主配置,看起来简单,却会让订阅更新、版本回滚和问题定位变得非常困难。

rule-providers 的核心价值是模块化。你可以把广告域名、AI 服务、开发者工具、局域网例外或流媒体站点分别维护成独立文件,再在主配置中用清晰的名称引用。例如 AI_SERVICES、AD_BLOCK、LAN_DIRECT 代表的是策略意图,而不是某一次临时复制的域名清单。未来更换规则来源时,只需要替换 provider 的 URL 或文件内容,不必重新整理整份 rules。

需要注意的是,不同 Clash 客户端对配置编辑方式的支持并不完全一致。Clash Verge、Clash Verge Rev、Mihomo Party 通常更适合直接编辑或覆写 YAML;Clash for Android 可能通过配置文件或订阅转换结果加载;旧版 Clash for Windows 是否支持某些字段,则取决于实际使用的内核。本文以支持 rule provider 的 Mihomo 兼容配置为基础,示例中的字段名称和行为应以当前内核日志为最终判断依据。

ℹ 先确认内核再写字段:如果日志出现 unknown field、failed to parse 或 provider 类型不识别,不要先怀疑 GitHub 链接。先确认客户端实际运行的是 Mihomo 或兼容内核,并检查配置是否被订阅更新覆盖。

字段拆解:type、behavior、format 与 interval

一个远程规则集通常放在 rule-providers 节点下,每个 provider 由自定义名称和字段组成。最重要的字段是 type、behavior、url、path 与 interval。其中 type 常见值为 http、file 或某些内核支持的其他类型;http 表示启动时或更新时从远程地址获取文件,file 表示读取本地规则文件。远程 provider 通常还要配置本地缓存路径,方便内核在下一次更新失败时继续使用旧版本。

behavior 描述规则内容的形态,常见值包括 domain、domain 类规则集合以及 classical。如果文件每行只是一个域名,通常应使用域名行为;如果文件包含 DOMAIN-SUFFIX、IP-CIDR 等完整 Clash 规则行,则应使用 classical。行为写错时,文件可能能够下载,却在解析阶段产生错误,或者匹配结果与预期完全不同。不要根据文件扩展名判断行为,真正应该查看文件内容。

format 用来说明规则文件是 YAML 还是纯文本。部分 Mihomo 版本对格式字段支持较好,尤其适合把带有 payload: 的 YAML 规则集与传统纯文本规则区分开。为了减少跨版本差异,自定义 GitHub 规则集建议优先选择结构单一、编码为 UTF-8、内容不包含复杂锚点和模板语法的格式。一个可维护的远程 provider 示例可以写成下面这样:

rule-providers.yaml

rule-providers:
  AI_SERVICES:
    type: http
    behavior: classical
    format: yaml
    url: https://raw.githubusercontent.com/example/clash-rules/main/rules/ai-services.yaml
    path: ./ruleset/ai-services.yaml
    interval: 86400

  LAN_DIRECT:
    type: file
    behavior: classical
    format: yaml
    path: ./ruleset/lan-direct.yaml

interval 通常以秒为单位,表示自动更新间隔。设置为一天并不意味着每次启动都会强制下载,也不等于 GitHub 文件一变化客户端就能立即感知。过短的间隔会增加请求次数,过长则可能让规则集长期停留在旧版本。个人桌面设备可以从 86400 秒开始;如果规则集更新频率很低,三天或七天更合理。关键不是追求最小间隔,而是让更新周期与规则维护节奏一致。

GitHub 托管自定义规则集:目录、Raw URL 与版本管理

将规则放到 GitHub 上,建议单独建立一个仓库或至少使用固定目录,而不是把文件散落在个人项目的临时分支里。一个清晰的结构可以按用途拆分:rules/ai-services.yaml 保存 AI 相关域名,rules/developer.yaml 保存代码托管与包管理服务,rules/lan-direct.yaml 保存内网和本地服务。文件名尽量使用小写英文、数字和短横线,避免空格、中文路径以及频繁变化的日期后缀,这样 provider 的 path 和日志更容易阅读。

Clash 需要读取的是可直接返回文件内容的 Raw 地址,而不是 GitHub 网页地址。网页地址通常包含仓库浏览器界面、脚本和 HTML 标记,内核无法把它当成规则文件解析。正确的远程地址应指向具体分支和文件,例如 raw.githubusercontent.com 下的文件路径。创建 provider 后,先在浏览器或命令行中访问该 Raw URL,确认返回内容不是 404 页面、登录页或 Git LFS 指针,再把它写入 YAML。

Git 分支和提交历史是这套方案的关键优势。稳定使用时可以固定到 main 分支;如果你正在测试大规模变更,则可以先在测试分支验证,再合并到主分支。对于对稳定性要求较高的设备,还可以将 URL 固定到某个提交对应的路径,避免上游文件被修改后立即影响所有客户端。代价是固定提交不会自动跟随更新,需要你在确认新规则后手动修改 provider URL 或通过自动化流程生成新版本。

每次提交规则集时,建议在 commit message 中说明变更原因,例如新增某个服务的 API 域名、删除已经失效的 CDN 域名,或修正 CIDR 的掩码长度。不要只写「update rules」,否则几周后很难判断某条规则为什么出现。对于多人协作,可以通过 Pull Request 审查域名来源,避免把拼写错误、过宽的后缀或不明 IP 段直接发布到生产配置。

自定义文件格式与规则粒度

规则集的粒度应该服务于分流目标,而不是追求条目数量。对于同一组织下的大量子域名,优先使用 DOMAIN-SUFFIX;对于单个精确主机名,使用 DOMAIN;只有确实需要按地址段匹配时才加入 IP-CIDR 或 IP-CIDR6。过度使用 DOMAIN-KEYWORD 容易误伤无关网站,例如一个常见词同时出现在多个品牌域名中,排障时也很难解释命中原因。

如果使用 classical 规则集,可以将策略组写在每一条规则的末尾;如果使用只包含域名的 provider,则把策略组留到主配置的 RULE-SET 行中。两种方式不要混杂到无法辨认。还要统一换行符和文件编码,避免 Windows 编辑器写入异常字符后,Linux 或 macOS 上的内核无法解析。提交前可以用文本编辑器显示不可见字符,并确保文件末尾保留换行。

加载流程与匹配优先级:provider 不是规则的终点

Clash 加载远程规则集大致经历几个阶段:读取主配置,创建 provider 定义,根据 type 读取本地缓存或发起远程请求,按照 behavior 和 format 解析内容,最后把 provider 注册到规则匹配器中。只要其中一个阶段失败,界面上就可能出现「配置已加载但规则没有生效」的假象。因此看到 provider 文件存在,并不能证明它已经被 rules 成功引用。

在主规则中引用 provider 时,通常使用 RULE-SET。例如:

rules.yaml

rules:
  - RULE-SET,LAN_DIRECT,DIRECT
  - RULE-SET,AI_SERVICES,AI_PROXY
  - MATCH,FINAL

规则是从上到下匹配的,第一条命中的规则决定出站策略。这个优先级非常重要:如果前面已经有一条宽泛的国内直连规则,后面的 AI provider 可能永远没有机会命中;如果 MATCH 提前出现,后续所有 provider 都会失效。建议把最明确的例外放在前面,把范围较大的分类规则放在中间,最后才使用兜底的 MATCH。对于同一域名既可能属于某个服务又可能属于广告统计域的情况,要根据实际目的明确排序,而不是简单叠加多个规则集。

还要区分域名规则和 IP 规则的匹配时机。开启增强模式、DNS 假解析或嗅探后,内核可能获得更多域名信息;关闭这些能力时,部分连接只能看到 IP 地址。此时即使域名 provider 写得正确,也可能因为请求没有暴露域名而无法命中。调试时应同时观察请求的 Host、SNI、解析结果和最终命中规则,不能只盯着 provider 文件内容。

调试与故障排查:从 URL、缓存到命中日志

第一步是单独验证 GitHub Raw URL。检查 HTTP 状态码、响应内容类型和文件正文,重点排除 404、403、429、重定向过多以及返回 HTML 的情况。若仓库是私有仓库,普通 Clash provider 通常无法直接完成需要身份认证的下载;不要把访问令牌明文放进公开订阅或截图中。对于 GitHub 访问不稳定的网络环境,还要确认客户端自身能够访问规则 URL,因为浏览器能打开并不代表内核进程使用了同样的代理路径。

第二步检查本地缓存路径。相对路径一般相对于配置工作目录,但不同客户端可能把配置放在不同位置。Clash Verge Rev、Mihomo Party 和移动端客户端的配置目录并不相同,不能直接照搬另一台设备的绝对路径。若日志显示无法创建文件,检查目录是否存在、是否有写入权限,以及路径中是否包含当前平台不接受的字符。首次下载失败时没有缓存文件,内核自然无法继续提供旧规则;所以稳定运行前最好先确认至少成功更新过一次。

第三步检查行为和格式。文件是纯域名列表,却声明为 classical,或者文件包含 YAML 的 payload,却按纯文本读取,都可能导致解析失败。可以先把规则集缩减为两三条已知规则,确认加载流程无误后再逐步恢复内容。对于大量规则,不建议一次性盲目替换整个文件;二分删除或回退到上一个 Git commit,通常比逐行猜测更快。

第四步观察连接日志和规则命中信息。一个完整的排障记录至少包括:请求域名、解析出的地址、命中的 provider 名称、规则类型、目标策略组以及最终使用的节点。如果日志只显示 MATCH,通常意味着前面的 provider 没有命中,或者规则顺序被其他宽泛规则截断。如果 provider 显示更新成功但连接仍走错策略,则重点检查 RULE-SET 拼写、策略组名称和规则顺序。

ℹ 建议的排查顺序:先访问 Raw URL,再查看 provider 更新日志,然后验证文件格式和行为,最后用一个明确域名进行连接测试。不要在 URL、YAML 缩进、规则优先级和节点质量之间同时反复修改,否则很难知道哪一次变化真正解决了问题。

可持续维护:测试、回滚与多设备同步

自定义规则集一旦被多台设备使用,就应该采用类似软件配置的维护流程。先在 GitHub 的测试分支修改,使用一台测试设备刷新 provider,确认目标域名和非目标域名分别命中预期策略,再合并到主分支。更新后保留前一个可用提交,出现大面积误分流时可以快速回滚。对长期运行的家庭网关或服务器,这种回滚能力比单纯追求最新域名列表更加重要。

建议给规则集建立最小化测试样本。每次改动至少测试一个应该代理的域名、一个应该直连的域名、一个不存在的随机域名,以及一个可能触发兜底规则的地址。若规则集包含 IP 段,还要测试 IPv4 和 IPv6 的行为。测试结果可以写入仓库的说明文件,记录使用的客户端、内核版本、更新日期和预期策略。这样当其他设备出现差异时,可以先判断是配置问题还是内核版本差异。

对多设备用户,主配置和规则 provider 最好分开管理。主配置中只保留 provider 定义、引用关系和策略组;具体域名放到 GitHub 仓库。这样 Windows、macOS、Android 和路由器可以共享同一套规则数据,同时为不同平台保留各自的端口、DNS、TUN 和系统权限设置。若某个平台不支持某个字段,不要为了迁就它而破坏所有设备的配置,可以维护一个兼容版本或在该平台单独关闭不必要的高级选项。

与把所有域名直接写入订阅相比,GitHub 托管的 rule-providers 更容易审查、回滚和复用;与完全依赖第三方远程规则相比,自定义仓库能够让你明确知道每条规则为何存在。需要付出的成本是维护 URL 可用性、检查上游变更和理解规则优先级。Clash for Windows 等旧壳层在高级字段支持上可能落后,Clash Verge Rev、Mihomo Party 或其他 Mihomo 客户端通常更适合管理这类模块化配置;而 Clash V.CORE 则把规则集引用、更新状态与日志排查放在更清晰的工作流中,减少手动改 YAML 和反复重启的成本。如果你正在为 GitHub 托管规则集寻找更稳定的运行环境,可以前往下载 Clash V.CORE,再用本文的 Raw URL、版本回滚与命中日志方法完成迁移验证。

// 编辑推荐

用 Clash V.CORE 管理可维护的规则集

从 GitHub 托管到本地缓存,从规则优先级到连接日志,让 rule-providers 不再只是配置文件中的一段 YAML。

  • 清晰查看规则集加载状态
  • 支持模块化 YAML 配置
  • 方便定位规则命中结果
  • 适合多设备同步与回滚
  • 兼容常见 Mihomo 配置结构
获取 Clash V.CORE →