先看清配置文件的处理链路
一份 Clash 或 mihomo 配置并不是单纯的“节点列表”。内核启动时会先解析 YAML,再建立本地监听端口、DNS 模块、代理节点和策略组,最后按 rules 从上到下匹配连接。某一段能通过语法检查,不代表它与其他段之间的引用一定正确:规则可以指向不存在的策略组,策略组也可能引用已经改名的节点。
理解配置时,可以把文件分成五层:基础运行参数负责端口与工作模式;DNS 段负责域名解析;proxies 定义可用的单个出站;proxy-groups 把出站组织成可选择或自动测试的策略;rules 决定每一类连接最终交给哪个策略。订阅配置还可能加入 proxy-providers 与 rule-providers,用于从外部文件加载节点或规则集合。
YAML 最容易出错的三个基础点
- 层级使用空格缩进,不能用 Tab。常见做法是每层缩进 2 个空格。
- 冒号后通常要留一个空格,例如
mode: rule;列表项以短横线和空格开头。 true、false、数字与字符串含义不同。端口写成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 |
选择 rule、global 或 direct |
日常使用通常采用 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-ip 与 redir-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 配置有效但仍打不开网站时
- 查看日志中是否出现
dns resolve failed、超时或证书连接错误。 - 确认系统或 TUN 的 DNS 请求确实进入内核监听,而不是继续发往旧的局域网 DNS。
- 暂时把
enhanced-mode改为redir-host复测,用于判断问题是否与 fake-ip 兼容有关。 - 检查
fake-ip-filter,只把确有兼容问题的域名加入列表,避免使用覆盖范围过大的通配规则。 - 分别测试域名和 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 使用 cipher 与 password,SOCKS5 可以带 username 和 password;其他协议还会涉及 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 对该测试地址响应更快;访问另一地区的服务时,结果可能相反。
检查策略组的循环引用
策略组可以引用其他策略组,但不能形成环。例如“默认代理”包含“手动选择”,而“手动选择”又包含“默认代理”,内核就无法得到最终出站。阅读复杂配置时,从规则目标开始向下追踪:规则指向哪个组、该组包含什么成员、成员最终能否落到节点或 DIRECT、REJECT。
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 而额外解析域名。它不是所有规则都必须添加的固定后缀。域名规则本来就依据域名判断,而某些需要地址结果的场景仍要正常解析。
为什么规则看起来正确却没有命中
- 前面已有更宽的规则:例如先写
DOMAIN-SUFFIX,example.com,DIRECT,后面的DOMAIN,api.example.com,默认代理永远没有机会执行。 - 应用直接访问 IP:日志只看到目标地址,没有域名信息,此时域名规则无法参与匹配,可结合 IP 规则或调整 DNS 接管方式。
- 策略名称拼写不同:规则目标必须与
proxy-groups中的名称完全一致。 - 配置没有重新加载:编辑的是本地文件,但客户端仍运行旧配置。应保存后执行「配置」→「重新加载」,再观察日志。
- 连接没有重新建立:已有 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,DIRECT。behavior 要与规则文件内容对应: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,同一条规则仍然命中,但最终改为直接连接。这也是“规则”和“策略选择”需要分开理解的原因。
保存后的验证顺序
- 先检查 YAML 缩进、列表符号和冒号后的空格。
- 确认每个规则目标都能在策略组中找到,每个策略组成员都能落到节点或内置策略。
- 重新加载配置,查看启动日志是否出现字段错误、引用失败或端口占用。
- 确认
7890、9090、1053等端口没有被其他程序占用。 - 用一个直连目标和一个代理目标分别测试,并在日志中核对实际命中规则。
- 最后再启用系统代理或 TUN,避免同时改动多个变量后难以定位问题。
如果内核启动后立即退出,最有效的排查方式不是大范围删配置,而是按段缩小范围:先保留通用字段和一个可用节点,再加入策略组,接着加入 DNS,最后恢复规则与 provider。每加入一段就重新加载一次,能把错误定位到具体字段。以 200 行配置为例,按五段逐步恢复通常只需 5 至 8 次加载,比逐行猜测更快。
常见误区与维护建议
把订阅链接直接当作节点地址
订阅 URL 返回的是节点集合或完整配置,不是某个节点的 server。完整订阅应交给客户端的订阅管理或 proxy-providers,单节点信息则按协议字段写进 proxies。两种数据层级不同,不能互换。
只看测速数字,不看策略命中
节点测速成功说明内核能通过该节点访问测试地址,但业务连接可能被规则送往 DIRECT、另一个策略组或另一个节点。排错应先在日志中确认规则目标,再查看策略组当前选择,最后检查节点连接结果。
把所有问题都归因于 DNS
DNS 只负责解析链路的一部分。端口被占用、系统代理未启用、TUN 路由未接管、规则顺序错误、策略组为空、节点协议参数不匹配,都可能表现为“网页打不开”。用分层检查法比反复更换 DNS 地址更可靠。
长期直接编辑自动更新配置
订阅刷新后,手工加入的规则、策略组或 DNS 字段可能被重新生成的内容替换。长期维护应明确分层:订阅负责节点更新,本地覆写负责固定参数,规则 provider 负责大规模规则集合,少量个人规则放在顺序可控的前置规则区。这样更新节点时不需要重新合并整份 YAML。