进阶原理 预计阅读 14 分钟

Clash 配置文件结构逐段解析:从 port 到 rules 读懂一份 YAML

把一份完整配置按段拆开讲:通用字段、DNS 段、proxies 节点定义、proxy-groups 策略组到 rules 规则列表,每段配示例说明字段含义与常见写法误区。

先看清配置文件的处理链路

一份 Clash 或 mihomo 配置并不是单纯的“节点列表”。内核启动时会先解析 YAML,再建立本地监听端口、DNS 模块、代理节点和策略组,最后按 rules 从上到下匹配连接。某一段能通过语法检查,不代表它与其他段之间的引用一定正确:规则可以指向不存在的策略组,策略组也可能引用已经改名的节点。

理解配置时,可以把文件分成五层:基础运行参数负责端口与工作模式;DNS 段负责域名解析;proxies 定义可用的单个出站;proxy-groups 把出站组织成可选择或自动测试的策略;rules 决定每一类连接最终交给哪个策略。订阅配置还可能加入 proxy-providersrule-providers,用于从外部文件加载节点或规则集合。

YAML 最容易出错的三个基础点

  • 层级使用空格缩进,不能用 Tab。常见做法是每层缩进 2 个空格。
  • 冒号后通常要留一个空格,例如 mode: rule;列表项以短横线和空格开头。
  • truefalse、数字与字符串含义不同。端口写成 7890,而包含特殊字符的名称或密码更适合放进引号。

常见桌面客户端可从「配置」→选中当前配置→「编辑」打开 YAML;保存后再进入「配置」→「重新加载」或「应用」。不同客户端的按钮名称略有差异,但检查顺序相同:先保存,确认内核没有报告解析错误,再测试代理连接。排错时可进入「日志」→「日志等级」→「debug」,完成定位后改回 info,避免长时间记录大量调试信息。

通用字段:端口、模式与控制接口

配置开头通常是本地监听和内核运行参数。下面是一组适合本机桌面环境阅读的示例,其中 HTTP 代理监听 7890,SOCKS5 代理监听 7891,外部控制接口只绑定本机回环地址:

port: 7890
socks-port: 7891
allow-lan: false
bind-address: "*"
mode: rule
log-level: info
ipv6: false
external-controller: 127.0.0.1:9090
secret: "change-this-token"
字段 具体作用 常见判断
port 提供 HTTP 代理监听端口 系统代理常见设置为 127.0.0.1:7890
socks-port 提供 SOCKS4、SOCKS5 代理入口 支持 SOCKS5 的应用可连接 127.0.0.1:7891
mixed-port 在一个端口同时接受 HTTP 与 SOCKS 连接 使用它时通常不再单独配置相同用途的端口
allow-lan 决定局域网设备能否连接本机代理端口 开启后还要检查绑定地址、系统防火墙和访问控制
mode 选择 ruleglobaldirect 日常使用通常采用 rule
external-controller 向图形界面或面板提供控制 API 仅本机使用时绑定 127.0.0.1 更合适

mode: rule 表示让每条连接进入规则匹配;global 会把连接统一交给全局策略;direct 则直接连接。这里的模式不是某一种代理协议,也不会改变节点自身参数。遇到“节点能测速,但指定网站不走代理”时,应先检查当前是不是误切到了直连模式,再看规则命中了什么策略。

局域网共享不能只改一个开关

allow-lan 改为 true 后,手机或其他电脑还要使用运行 Clash 设备的局域网地址,例如 192.168.1.20:7890,而不是对方设备自己的 127.0.0.1。同时需要放行 TCP 7890 端口。若电脑地址由 DHCP 自动分配,重连路由器后可能变化,适合在路由器中为该设备设置固定租约。

DNS 段:解析路径与 fake-ip 模式

DNS 配置决定域名如何得到 IP 地址,也会影响域名规则能否稳定命中。mihomo 常见的增强模式包括 fake-ipredir-host。前者向应用返回保留地址池中的映射地址,内核收到连接后再还原域名;后者更接近传统的真实地址解析流程。TUN 模式下使用 fake-ip 往往能保留更多域名信息,但部分局域网服务、联网检测或依赖真实地址的应用需要加入过滤列表。

dns:
  enable: true
  listen: 0.0.0.0:1053
  ipv6: false
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  default-nameserver:
    - 223.5.5.5
    - 1.1.1.1
  nameserver:
    - https://dns.alidns.com/dns-query
    - https://1.1.1.1/dns-query
  proxy-server-nameserver:
    - https://dns.alidns.com/dns-query
  fake-ip-filter:
    - "*.lan"
    - "*.local"
    - "time.*.com"
    - "+.msftconnecttest.com"

default-nameserver 主要承担引导解析,因此一般填写纯 IP 的 DNS 地址;如果加密 DNS 服务器本身写的是域名,内核需要先知道去哪里解析这个域名。nameserver 是常规查询使用的上游。mihomo 中的 proxy-server-nameserver 可专门解析代理服务器域名,减少“节点地址尚未解析,DNS 查询又等待代理节点”的依赖问题。

DNS 配置有效但仍打不开网站时

  1. 查看日志中是否出现 dns resolve failed、超时或证书连接错误。
  2. 确认系统或 TUN 的 DNS 请求确实进入内核监听,而不是继续发往旧的局域网 DNS。
  3. 暂时把 enhanced-mode 改为 redir-host 复测,用于判断问题是否与 fake-ip 兼容有关。
  4. 检查 fake-ip-filter,只把确有兼容问题的域名加入列表,避免使用覆盖范围过大的通配规则。
  5. 分别测试域名和 IP。能访问 IP、不能访问域名,通常优先排查 DNS;两者都失败则继续看策略组和节点连接。

示例中的 198.18.0.1/16 是常见 fake-ip 地址池。应用看到该地址并不表示网站真实部署在那里,而是内核维护的临时映射。抓包时如果反复看到 198.18.x.x,应结合 Clash 日志中的原始域名判断,不能把它直接当作远端服务器地址。

proxies:单个节点怎样写成 YAML

proxies 是节点对象列表。每个对象至少要有唯一的 name、协议 type、服务器地址 server 与端口 port,其余字段取决于具体协议。下面用 Shadowsocks 与 SOCKS5 演示结构,示例域名和凭据只用于说明格式:

proxies:
  - name: "东京-SS"
    type: ss
    server: ss-node.example.com
    port: 443
    cipher: aes-128-gcm
    password: "demo-password"
    udp: true

  - name: "本地-SOCKS"
    type: socks5
    server: 192.168.1.30
    port: 1080
    username: "proxy-user"
    password: "demo-password"
    udp: false

字段名必须符合协议定义。Shadowsocks 使用 cipherpassword,SOCKS5 可以带 usernamepassword;其他协议还会涉及 TLS、传输层、服务器名称等参数。不能因为两个节点都在图形界面里显示为一行,就把一个协议的字段直接复制到另一个协议中。

节点名称其实是引用键

name 不只负责显示,还会被策略组逐字引用。若节点定义叫“东京-SS”,策略组中写成“东京 SS”,中间字符不同就会成为无效引用。节点名也不宜与策略组同名,否则阅读日志和规则目标时很难快速判断指向哪一层。

  • 同一列表内保持名称唯一,可采用“地区-协议-编号”的固定格式。
  • 包含冒号、井号、星号或前后空格的名称应加引号,避免 YAML 把字符解释成语法。
  • udp: true 只表示该节点配置允许 UDP,实际可用性还取决于协议、服务端和接管方式。
  • 服务器地址填写域名时,要同步检查用于解析节点域名的 DNS 路径。

proxy-groups:从节点到可操作策略

规则通常不直接指向某个固定节点,而是指向策略组。这样可以在“工作服务”“流媒体”“默认代理”等不同用途之间独立选择出站。策略组也是客户端代理页的主要操作对象,用户切换的往往不是规则,而是某个 select 组当前选中的成员。

proxy-groups:
  - name: "手动选择"
    type: select
    proxies:
      - "自动测速"
      - "东京-SS"
      - "本地-SOCKS"
      - DIRECT

  - name: "自动测速"
    type: url-test
    proxies:
      - "东京-SS"
      - "本地-SOCKS"
    url: "https://www.gstatic.com/generate_204"
    interval: 300
    tolerance: 50
    lazy: true

  - name: "默认代理"
    type: select
    proxies:
      - "手动选择"
      - "自动测速"
      - DIRECT
组类型 选择逻辑 适用情况
select 由用户手动选择成员 需要明确指定地区、线路或直连时
url-test 定期请求测试地址,选择延迟较低的成员 节点较多,希望自动择优时
fallback 按顺序使用可用成员,当前成员失效后切换 重视固定优先级和故障转移时
load-balance 按指定策略把不同连接分配给多个成员 需要分散连接且上游条件允许时

示例中 interval: 300 表示每 300 秒进行一次周期测试,tolerance: 50 表示延迟差异较小时避免频繁切换。测速值只反映到测试 URL 的请求耗时,不等同于下载带宽。一次实测中,节点 A 延迟为 86 毫秒、节点 B 为 112 毫秒,只能说明 A 对该测试地址响应更快;访问另一地区的服务时,结果可能相反。

检查策略组的循环引用

策略组可以引用其他策略组,但不能形成环。例如“默认代理”包含“手动选择”,而“手动选择”又包含“默认代理”,内核就无法得到最终出站。阅读复杂配置时,从规则目标开始向下追踪:规则指向哪个组、该组包含什么成员、成员最终能否落到节点或 DIRECTREJECT

rules:按顺序决定每条连接的去向

rules 是有顺序的匹配列表。连接从第一条开始检查,命中后立即采用该条指定的策略,不再继续向下。精确规则应放在宽泛规则之前,最终通常用 MATCH 接住前面没有命中的流量。

rules:
  - DOMAIN,api.example.com,默认代理
  - DOMAIN-SUFFIX,example.net,默认代理
  - DOMAIN-KEYWORD,video,手动选择
  - IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
  - IP-CIDR,10.0.0.0/8,DIRECT,no-resolve
  - GEOIP,CN,DIRECT
  - MATCH,默认代理

DOMAIN 匹配完整域名;DOMAIN-SUFFIX 匹配指定域名及其子域;DOMAIN-KEYWORD 只要域名包含关键词就可能命中,范围更宽,误匹配概率也更高。IP-CIDR 按地址段判断,GEOIP 依赖内核加载的地理数据库,MATCH 则是兜底规则。

no-resolve 常用于 IP 类规则,表示匹配时不要为了取得 IP 而额外解析域名。它不是所有规则都必须添加的固定后缀。域名规则本来就依据域名判断,而某些需要地址结果的场景仍要正常解析。

为什么规则看起来正确却没有命中

  1. 前面已有更宽的规则:例如先写 DOMAIN-SUFFIX,example.com,DIRECT,后面的 DOMAIN,api.example.com,默认代理 永远没有机会执行。
  2. 应用直接访问 IP:日志只看到目标地址,没有域名信息,此时域名规则无法参与匹配,可结合 IP 规则或调整 DNS 接管方式。
  3. 策略名称拼写不同:规则目标必须与 proxy-groups 中的名称完全一致。
  4. 配置没有重新加载:编辑的是本地文件,但客户端仍运行旧配置。应保存后执行「配置」→「重新加载」,再观察日志。
  5. 连接没有重新建立:已有 TCP 或 QUIC 会话可能继续沿用旧路径。关闭应用连接、等待数秒后再测试更容易得到明确结果。

provider 段:把节点与规则拆到外部文件

当节点来自订阅、规则集合数量较大时,可以使用 provider。proxy-providers 管理外部节点集合,rule-providers 管理规则集合。provider 并不会自动决定流量去向:节点 provider 仍要被策略组引用,规则 provider 仍要通过 RULE-SET 写进 rules

proxy-providers:
  airport:
    type: http
    url: "https://subscription.example.com/clash.yaml"
    path: ./providers/airport.yaml
    interval: 3600
    health-check:
      enable: true
      url: "https://www.gstatic.com/generate_204"
      interval: 600

rule-providers:
  private-sites:
    type: http
    behavior: domain
    format: yaml
    path: ./rules/private-sites.yaml
    url: "https://rules.example.com/private-sites.yaml"
    interval: 86400

节点 provider 可通过策略组中的 use 引入,规则 provider 则需要写成 RULE-SET,private-sites,DIRECTbehavior 要与规则文件内容对应:domain 面向域名规则,ipcidr 面向地址段,classical 可容纳经典规则表达式。格式声明与文件内容不一致时,常见结果是 provider 下载成功但解析失败。

proxy-groups:
  - name: "订阅自动选择"
    type: url-test
    use:
      - airport
    url: "https://www.gstatic.com/generate_204"
    interval: 300

rules:
  - RULE-SET,private-sites,DIRECT
  - MATCH,订阅自动选择

interval: 3600 表示节点 provider 每 3600 秒尝试更新,规则示例中的 86400 则是 24 小时。更新频率应结合来源变化速度设置;过短会产生不必要的网络请求,过长则可能让已调整的节点或规则迟迟不能生效。

一份可读的最小配置怎样串起来

把前面的结构合并后,可以得到一份便于学习的最小配置。它不是通用成品,因为节点协议、DNS 上游和分流目标仍需按实际环境填写,但能清楚展示字段之间的引用关系:

mixed-port: 7890
allow-lan: false
mode: rule
log-level: info
ipv6: false
external-controller: 127.0.0.1:9090

dns:
  enable: true
  listen: 0.0.0.0:1053
  ipv6: false
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  default-nameserver:
    - 223.5.5.5
  nameserver:
    - https://dns.alidns.com/dns-query
  fake-ip-filter:
    - "*.lan"
    - "*.local"

proxies:
  - name: "东京-SS"
    type: ss
    server: ss-node.example.com
    port: 443
    cipher: aes-128-gcm
    password: "demo-password"
    udp: true

proxy-groups:
  - name: "代理"
    type: select
    proxies:
      - "东京-SS"
      - DIRECT

rules:
  - DOMAIN-SUFFIX,example.net,代理
  - IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
  - GEOIP,CN,DIRECT
  - MATCH,代理

连接 api.example.net 时,内核先通过 DNS 段处理域名解析,再由 DOMAIN-SUFFIX,example.net,代理 命中“代理”组。如果组内当前选中“东京-SS”,连接就交给该节点;如果用户在代理页把组切换为 DIRECT,同一条规则仍然命中,但最终改为直接连接。这也是“规则”和“策略选择”需要分开理解的原因。

保存后的验证顺序

  1. 先检查 YAML 缩进、列表符号和冒号后的空格。
  2. 确认每个规则目标都能在策略组中找到,每个策略组成员都能落到节点或内置策略。
  3. 重新加载配置,查看启动日志是否出现字段错误、引用失败或端口占用。
  4. 确认 789090901053 等端口没有被其他程序占用。
  5. 用一个直连目标和一个代理目标分别测试,并在日志中核对实际命中规则。
  6. 最后再启用系统代理或 TUN,避免同时改动多个变量后难以定位问题。

如果内核启动后立即退出,最有效的排查方式不是大范围删配置,而是按段缩小范围:先保留通用字段和一个可用节点,再加入策略组,接着加入 DNS,最后恢复规则与 provider。每加入一段就重新加载一次,能把错误定位到具体字段。以 200 行配置为例,按五段逐步恢复通常只需 5 至 8 次加载,比逐行猜测更快。

常见误区与维护建议

把订阅链接直接当作节点地址

订阅 URL 返回的是节点集合或完整配置,不是某个节点的 server。完整订阅应交给客户端的订阅管理或 proxy-providers,单节点信息则按协议字段写进 proxies。两种数据层级不同,不能互换。

只看测速数字,不看策略命中

节点测速成功说明内核能通过该节点访问测试地址,但业务连接可能被规则送往 DIRECT、另一个策略组或另一个节点。排错应先在日志中确认规则目标,再查看策略组当前选择,最后检查节点连接结果。

把所有问题都归因于 DNS

DNS 只负责解析链路的一部分。端口被占用、系统代理未启用、TUN 路由未接管、规则顺序错误、策略组为空、节点协议参数不匹配,都可能表现为“网页打不开”。用分层检查法比反复更换 DNS 地址更可靠。

长期直接编辑自动更新配置

订阅刷新后,手工加入的规则、策略组或 DNS 字段可能被重新生成的内容替换。长期维护应明确分层:订阅负责节点更新,本地覆写负责固定参数,规则 provider 负责大规模规则集合,少量个人规则放在顺序可控的前置规则区。这样更新节点时不需要重新合并整份 YAML。

查找对应客户端 按平台进入下载页