CONFIG.YAML / FIELD REFERENCE

Clash 配置文件参考

YAML 结构、端口、DNS、代理节点、策略组与规则。以 mihomo 配置语义为基准,区分内核字段与客户端覆写。

首次导入订阅、启用系统代理与验证连接,请按快速上手完成操作。本页用于逐项查阅字段与定位配置差异;客户端选择见Clash 下载页,跨平台优先查看 Clash Plus。

YAML 结构与文件边界

Clash 配置文件通常使用 YAML。文件名常见为 config.yaml,但名称本身不决定用途;实际加载哪个文件,取决于客户端当前选中的配置,或内核启动时的文件参数。本页示例采用 mihomo 常用字段。其他 Clash 系内核可能只实现其中一部分,客户端还可能在启动前生成另一份运行配置。排查时先确认内核名称、配置来源与最终加载路径,再讨论某个字段是否生效。

映射、列表与缩进

YAML 的映射通过键和值表达设置,例如 mode: rule;列表用短横线逐项排列,例如 rules 中的多条规则。顶层字段从行首开始,子字段使用空格缩进,建议统一为两个空格。缩进深度表示归属关系,不是视觉装饰。把 nameserver 与 dns 对齐,会把它从 DNS 子项变成另一个顶层键,即使文件能被语法解析,也不等于内核会按预期使用。

mixed-port: 7890
allow-lan: false
mode: rule
log-level: info

dns:
  enable: true
  listen: 127.0.0.1:1053
  enhanced-mode: fake-ip
  nameserver:
    - https://dns.alidns.com/dns-query

proxy-groups:
  - name: 出站选择
    type: select
    proxies:
      - DIRECT

rules:
  - MATCH,出站选择

这是一份用于观察结构的直连配置,不包含远程代理节点。导入后,规则会把请求交给“出站选择”,该组当前只有 DIRECT。它适合验证文件能否加载、端口是否监听、组名能否被规则引用,不能据此判断远程代理是否可用。其他章节的片段默认需要合入相应字段,不应把几段各自含有顶层 dns 的示例直接首尾拼接。

字符串与数据类型

布尔值写为 true 或 false,端口使用整数,地址与名称一般是字符串。密码、以特殊符号开头的值、包含冒号加空格的文本,建议加引号。注释由 # 开始;若密码包含井号,正确引用能避免其余内容被当成注释。单引号字符串不处理反斜杠转义,双引号会解释部分转义序列,因此从其他格式复制密码时不要随意增删反斜杠。

列表中的每个节点通常是一个映射。节点的 name、type、server 等键必须属于同一个列表项。漏掉短横线可能把新节点合入上一项;同一映射重复写 name 或重复写顶层字段,则可能被解析器拒绝,也可能出现后值覆盖前值的行为。不要依赖重复键实现覆写,应使用客户端明确提供的合并机制。

完整配置与节点集合的区别

完整配置可以包含端口、DNS、节点、策略组与规则;代理集合文件通常只提供 proxies 列表。规则集合也有自己的 payload 结构。三者都能使用 YAML,但不能交换加载位置。订阅地址返回一份合法 YAML,并不说明它可以直接当作主配置导入。若返回的是单节点 URI、Base64 文本或登录页面,应先核对订阅格式,而不是继续修改缩进。

编辑前保存原文件副本,编辑器使用 UTF-8,并显示空白字符。先保留最小可加载结构,再按 DNS、节点、策略组、规则的顺序增加内容,每次只改一个区域。这样出现错误时,回退范围明确。不要把在线 YAML 格式化工具当作必需步骤;配置通常包含订阅地址与认证信息,本地编辑与本地语法检查更适合处理这类文件。

端口、模式与访问范围

通用字段决定内核如何接收请求、采用哪种路由模式以及允许谁访问。先区分三个入口:应用向 HTTP 或 SOCKS 端口主动发送代理请求;系统代理设置把支持该设置的应用指向这些端口;TUN 则通过虚拟网络接口接管符合路由条件的流量。启用一个监听端口不会自动设置系统代理,启用系统代理也不代表所有程序都会遵循。定位入口问题时,应查看应用实际使用的代理方式。

port、socks-port 与 mixed-port

字段主要用途配置边界
portHTTP 代理入口支持 HTTP 请求及 CONNECT 隧道
socks-portSOCKS 代理入口应用需选择对应代理协议
mixed-portHTTP 与 SOCKS 混合入口同一端口接受两类请求
redir-port透明转发入口需要配套系统重定向规则
tproxy-portTProxy 透明代理入口需要系统支持及策略路由

普通桌面使用可以先只设置 mixed-port,减少应用与端口之间的对应关系。不要让多个监听字段占用同一地址上的同一端口,也不要忽略其他客户端或旧内核进程已经占用端口的情况。修改端口后,应用内手工填写的代理地址不会必然同步更新。客户端管理的系统代理可能会跟随变化,但仍应检查系统设置中的主机与端口是否对应当前实例。

mixed-port: 7890
allow-lan: false
bind-address: "127.0.0.1"
mode: rule
log-level: info
ipv6: false

allow-lan 与 bind-address

allow-lan: false 用于本机访问场景。需要向局域网设备提供代理时,再将其设为 true,并配置合适的 bind-address。绑定 127.0.0.1 只接受本机 IPv4 回环访问;绑定 "*" 会扩大监听范围。监听范围、操作系统防火墙、路由器隔离和客户端认证共同决定可达性,单独改一个布尔值不能保证手机或电视能够连接。

局域网设备应填写运行内核的电脑地址,而不是填写自己的 127.0.0.1。电脑地址可能因 DHCP 租约变化而改变,可使用路由器地址保留减少变动。共享时优先只允许可信网段访问,不要在公网映射代理端口。相关操作和防火墙检查见mixed-port 与 allow-lan 局域网共享说明。共享入口不等于管理入口,两者应分开限制。

mode 与日志等级

mode: rule 按 rules 顺序选择目标;global 使用全局策略选择;direct 采用直连模式。切换模式适合缩小排查范围,但不应把全局模式下可访问直接解释为规则模式存在语法错误,也可能是某条规则选择了不同出站。规则模式下,内网请求、指定域名和兜底请求可以使用不同目标,这也是维护规则顺序的原因。

log-level 常用 info,定位问题时可短时改为 debug。详细日志可能包含访问域名、连接目标或订阅相关信息,不适合长期公开保存。ipv6: false 控制内核的相关 IPv6 行为,但不会自动关闭操作系统所有 IPv6 网络能力;DNS 子项还有独立的 ipv6 设置。两处设置需要结合流量入口理解,不能据此声称整台设备的 IPv6 已被阻断。

TUN 的 enable、auto-route、auto-detect-interface 与 dns-hijack 涉及权限、网卡和系统路由。配置语法相似不代表各平台安装流程相同。先按上手步骤确认普通代理入口正常,再启用 TUN;否则端口、权限与 DNS 三类问题同时出现,会使故障边界变得不清晰。

DNS 与 Fake-IP

dns 是独立的映射区域。enable 决定是否启用内置 DNS,listen 指定监听地址,enhanced-mode 决定增强解析模式。DNS 开启后,系统查询是否真正进入内核,仍取决于系统 DNS、TUN 劫持或其他转发设置。把监听地址写进配置但没有任何查询到达该地址,内核就无法为这些查询建立域名映射,也无法代替应用自行使用的加密 DNS。

基础解析链与加密上游

dns:
  enable: true
  listen: 127.0.0.1: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"
    - "localhost"
  nameserver-policy:
    "+.lan": 192.168.1.1

示例中的 192.168.1.1 假设是能够解析本地名称的路由器,实际网络不同就需要替换。nameserver 是常规上游列表,支持的地址形式取决于内核;示例使用 HTTPS DNS。上游地址自身含有主机名时,还需要先解析该主机名,default-nameserver 常用于这类引导解析。不要让引导解析又依赖尚未建立的同一条代理链,否则会形成启动阶段的循环依赖。

nameserver-policy 按域名指定解析器,适合将局域网域名交给本地 DNS。它控制的是查询交给谁,不等同于 rules 中的连接出站选择。fallback 与 fallback-filter 可以参与结果选择,但不是“第一个服务器失败后再查第二个”这么简单。没有明确分流需求时,先维护一条可解释的解析链,比同时堆入多个公共上游更容易验证。

Fake-IP 与 redir-host 的差别

在 fake-ip 模式下,内核可向应用返回保留地址池中的合成地址,再依据映射还原域名并选择出站。这里的地址不是目标网站真实地址,命令行看到 198.18 开头的结果并不必然代表解析错误。redir-host 则以真实解析结果为主。两种模式都需要正确的流量入口与域名信息;选择哪一种,应依据应用兼容性、DNS 路径与透明代理方式判断。

fake-ip-filter 用来排除不适合返回合成地址的域名,例如部分本地名称或有特殊校验逻辑的服务。它不会把整个应用的流量改为直连,也不会自动修改路由规则。遇到兼容问题,应先用一个明确域名做最小排除,再比较行为,不要把所有常见后缀加入过滤列表。过大的排除范围会让不同流量采用不同解析路径,增加后续维护难度。

节点解析与规则解析

代理服务器的域名必须在连接代理前解析。mihomo 的 proxy-server-nameserver 可用于指定这类查询的上游;需要按规则处理 DNS 连接时,还会涉及 respect-rules。这类组合必须防止代理服务器域名的解析再次依赖该代理本身。先在普通直连上游下确认节点地址能解析,再逐步引入 DNS 出站规则,比直接复制复杂分流片段更可靠。

IP 类规则可能需要解析域名后才能判断目标地址是否位于某个网段。规则上的 no-resolve 可以避免为该条 IP 匹配额外触发解析,但不会阻止应用已经发起的 DNS 查询。排查 DNS 泄漏时,需要分别观察系统解析、应用内置 DoH、内核上游与代理侧解析;只检查浏览器显示的一个 DNS 地址,不能代表设备全部查询都走了同一条路径。

验证时先查询一个普通域名,再查询一个本地域名,最后测试对应服务连接。若普通域名可用而本地名称失败,优先检查本地解析策略与过滤项;若所有查询超时,则检查监听地址、端口、防火墙与上游可达性。DNS 返回结果与应用连接成功是两个阶段,不应在解析失败时先修改节点协议参数。

代理节点字段

proxies 是节点列表,每项描述一个可被策略组引用的出站。公共字段通常包含 name、type、server 与 port,认证与传输字段则随协议变化。节点名称是配置中的引用标识,不是显示备注那么简单。名称修改后,策略组里的同名引用也要更新。名称应保持唯一,避免两个不同节点共用一个名称,导致选择结果难以判断。

基础字段与协议专属字段

type 决定内核使用哪种协议解释其余参数。例如 Shadowsocks 需要 cipher 与 password,Trojan 使用密码并涉及 TLS,VMess 与 VLESS 使用各自的身份与传输参数。不能只把 type 从一种协议改成另一种就完成转换。服务器协议、认证方式、传输层与 TLS 设置必须对应服务端实际配置,缺少的参数需要从服务提供方确认。

proxies:
  - name: SS-示例
    type: ss
    server: 192.0.2.10
    port: 8388
    cipher: aes-128-gcm
    password: "your-password"
    udp: true

  - name: Trojan-示例
    type: trojan
    server: 192.0.2.20
    port: 443
    password: "your-password"
    sni: proxy.example.com
    skip-cert-verify: false
    udp: true

这里使用文档保留地址和示例域名,展示的是字段结构,不是可连接的服务。实际使用时,需要整体替换服务器地址、认证信息及 TLS 主机名。server 可以是 IP 或域名;port 是服务端监听端口,与本机 mixed-port 不同。服务器使用域名时,连接前还会经过节点域名解析;服务器使用 IP 时,也可能仍需要单独的 TLS 主机名。

TLS、SNI 与证书验证

Trojan 常用 sni 指定 TLS 握手使用的服务器名称;其他协议可能使用 servername 等字段,应按协议定义填写。TLS 主机名需要与服务端证书及部署方式相符,不能把网页域名随意填入。skip-cert-verify: false 保持证书验证。若证书报错,先检查系统时间、主机名与证书链,不应把跳过验证当成通用修复措施。

WebSocket 的请求路径、Host 请求头、gRPC 的服务名属于传输设置,不是同一个字段。服务端要求 WebSocket 时,客户端也需要对应的 network 与 ws-opts;路径中的大小写和斜杠可能影响路由。把已有 URI 转成 YAML 后,要逐项核对这些细节。链接中经过编码的字符需要正确解码,错误解码密码或路径会造成“配置加载成功但握手失败”。

UDP 与链路能力

udp: true 表示在支持该字段的协议中启用相应 UDP 能力,并不保证整条路径都能传递 UDP。应用入口、代理协议、服务端部署、防火墙和运营网络均可能形成限制。网页 TCP 请求正常而实时通信失败时,先确认应用是否真正通过支持 UDP 的入口,再检查节点设置。用一个 HTTP 探测成功的结果,不能证明 DNS、QUIC 或游戏流量一定正常。

部分协议还涉及 ALPN、客户端指纹、Reality 或其他专属参数。字段可用性受内核实现影响,旧客户端即使接受 YAML,也可能不支持对应协议。遇到未知字段或不支持的类型,应先核对内核能力,再决定是否更换客户端;可从下载页选择 Clash Plus 或其他适合平台的客户端。不要靠删除陌生字段强行让配置通过,这可能改变服务端所要求的认证或传输方式。

手工维护节点适合少量固定出站;节点经常变动时,应使用代理集合集中更新,再由策略组引用。不要在订阅生成的节点列表里逐次手改名称,因为下次刷新可能恢复原值。若问题发生在格式转换后,可对照YAML 订阅与节点链接格式说明检查认证、传输与 TLS 参数是否完整保留。

策略组与代理集合

proxy-groups 定义出站选择逻辑,proxy-providers 定义节点集合来源。两者职责不同:集合提供候选节点,策略组决定如何从候选中选择。规则通常引用一个稳定的组名,而不是直接引用经常变动的节点名。这样节点更新时,只要组名和集合引用保持有效,就不必逐条改写规则。策略组也可以引用其他组,但应避免自引用或相互循环。

select、url-test 与 fallback

select 由用户或管理接口选择成员,适合明确控制出站;url-test 根据指定 URL 的探测结果自动选择;fallback 通常按成员顺序选择可用项。load-balance 用于支持的负载分配策略,不能理解为把一个连接拆成多条线路叠加带宽。不同类型解决的问题不同,不应仅因为“自动”就把所有分流组都改成自动测试。

proxy-groups:
  - name: 出站选择
    type: select
    proxies:
      - 自动选择
      - 故障切换
      - DIRECT

  - name: 自动选择
    type: url-test
    use:
      - 自有节点
    url: https://cp.cloudflare.com/generate_204
    interval: 300
    tolerance: 50

  - name: 故障切换
    type: fallback
    use:
      - 自有节点
    url: https://cp.cloudflare.com/generate_204
    interval: 300

proxy-providers:
  自有节点:
    type: file
    path: ./providers/nodes.yaml
    health-check:
      enable: true
      url: https://cp.cloudflare.com/generate_204
      interval: 300

示例要求工作目录下存在 providers/nodes.yaml,其内容为带有 proxies 列表的节点集合。use 引用的是 provider 名称“自有节点”,不是文件名,也不是某个节点。proxies 列表则直接引用已有节点、其他组或内置出站。两种引用方式可以组合,但需要确认候选集合确实有内容,否则自动组可能没有可用成员。

探测参数的实际含义

url 决定健康检查请求的目标,interval 通常以秒为单位控制探测间隔,tolerance 在相应自动选择逻辑中用于减少微小差异造成的频繁切换。探测结果反映的是到该测试目标的请求过程,不代表所有网站、长连接或大文件传输的表现。目标站点屏蔽请求、TLS 握手异常或 DNS 故障,都可能让探测失败,即使代理服务器端口仍然可达。

provider 的健康检查与组级测试可能分别存在。配置前先确定哪些测试由集合负责、哪些由策略组负责,避免为同一批节点设置不必要的高频检查。检查间隔不是越短越好,尤其在移动设备上还会带来额外唤醒与网络请求。已有连接通常不会因组切换立即迁移到新节点,因此切换后测试时应建立新连接,而不是只观察先前保持的下载任务。

集合更新、筛选与名称稳定性

HTTP 类型的 proxy-providers 会用 url、path 与 interval 描述远程来源、本地缓存和更新周期。下载内容必须是内核接受的集合格式,不是任意网页或完整客户端配置。若远程链接含凭据,应保存在本地配置中,不要贴进公开问题报告。订阅更新错误可继续参照订阅更新失败排查,先判断请求失败还是内容解析失败。

组的 filter 可按名称筛选候选,使用时应按正则表达式理解匹配规则。名称约定一旦改变,筛选结果可能变空;因此更新订阅后,不只检查节点总表,还要检查每个组的实际成员。地区名称、特殊符号与大小写都会影响匹配。先用简单条件验证能选中目标,再逐步缩小范围,比一次写入复杂表达式更容易维护。

profile.store-selected 可保存策略组选择,profile.store-fake-ip 可保存相关映射状态。是否需要持久化取决于使用方式与客户端管理逻辑。修改组成员后应重新核对当前选择,避免旧选择、筛选结果和实际运行配置之间出现偏差。

规则与规则集合

rules 是有顺序的列表。内核从前向后寻找适用规则,匹配后使用该规则指定的出站目标。规则不是按“看起来更精确”自动排序,也不会把后面的域名规则提前执行。通常先放明确的本地或业务例外,再放较宽的域名、地址和规则集合,最后用 MATCH 兜底。顺序本身就是配置逻辑,编辑规则时需要同时检查它前后的条件。

域名、地址与兜底语法

rules:
  - DOMAIN,intranet.example.com,DIRECT
  - DOMAIN-SUFFIX,example.org,出站选择
  - DOMAIN-KEYWORD,example,出站选择
  - IP-CIDR,127.0.0.0/8,DIRECT,no-resolve
  - IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
  - IP-CIDR6,fc00::/7,DIRECT,no-resolve
  - RULE-SET,本地域名,DIRECT
  - MATCH,出站选择

DOMAIN 匹配完整域名,适合单个主机;DOMAIN-SUFFIX 匹配指定域名及其子域;DOMAIN-KEYWORD 依据关键词匹配,范围更宽。关键词规则写得过短,可能覆盖并不相关的站点。IP-CIDR 与 IP-CIDR6 分别匹配 IPv4 和 IPv6 网段。示例中的内网范围并不完整,只说明语法;应按实际网络补充,不能把这一段当作完整的私有地址清单。

规则末尾的出站可以是节点名、策略组名或 DIRECT、REJECT 等内置目标。名称必须与定义完全一致,包括空格和标点。MATCH 不需要额外条件,因此应置于兜底位置;写在列表开头会使后续多数规则没有机会执行。若一条业务规则未命中,先查它之前是否已有更宽规则截获,而不是直接增加相似规则。

rule-providers 的声明与文件格式

rule-providers 用于复用一组匹配条件。type 表示文件或 HTTP 来源,behavior 表示内容语义,format 表示序列化格式。domain 集合存域名匹配项,ipcidr 集合存地址范围,classical 集合可包含相应的经典规则条件。不要把代理节点集合放入规则集合目录,虽然都是 YAML,根字段与每项内容并不相同。

rule-providers:
  本地域名:
    type: file
    behavior: domain
    format: yaml
    path: ./rules/local-domain.yaml

# ./rules/local-domain.yaml 的内容:
# payload:
#   - "+.lan"
#   - "intranet.example.com"

上面文件中的 payload 是独立文件内容,不要把注释直接当作已经创建了该文件。主配置通过 RULE-SET,本地域名,DIRECT 给这组条件指定目标。使用 classical 格式时,集合项通常描述条件,不应机械附加主配置规则中的出站名。远程集合还涉及下载与缓存,若第一次启动无法获取且没有本地缓存,需要先解决资源可达性。

解析时机、进程与平台差异

某些 IP 条件为了匹配域名请求,会触发解析;带有 no-resolve 的相应规则不会为匹配主动解析域名。这一选项适合已经有目标 IP 的流量,但也可能让预期依赖解析结果的规则不再命中。域名规则需要内核获得域名信息,若流量只有目标 IP、也没有可用 DNS 映射或嗅探结果,就不能假设域名条件仍会生效。

PROCESS-NAME 等进程规则依赖操作系统提供的信息、内核权限和流量入口。桌面应用可用的进程条件,不一定适用于路由器后面的另一台设备。GEOIP、GEOSITE 还依赖对应数据资源及内核支持,数据库内容变化也会改变匹配结果。跨平台迁移时,先检查这些外部依赖,不要只比较规则文本是否相同。

规则文件应按职责分区并添加简短注释。测试例外规则时,先用一个明确域名放在较前位置,建立新连接确认命中,再调整长期位置。不要持续把新规则插在最顶部作为永久修复,否则后续维护者难以判断优先级的来源,宽规则也更容易掩盖已有分流逻辑。

订阅、覆写与合并

客户端中的“订阅配置”不一定就是内核最终读取的文件。常见过程是下载远程文档、保存订阅副本、应用本地覆写或脚本、补充界面控制的端口与 TUN 设置,最后生成运行配置。不同客户端的阶段名称与执行顺序可能不同。排查“文件已经修改但设置没变”时,应先找到运行配置或配置预览入口,对照最终字段,而不是反复编辑下载缓存。

区分来源文件、持久设置与运行结果

来源文件用于保留订阅提供的内容;本地覆写用于表达设备专属需求;运行配置是两者及客户端设置组合后的结果。三个层次可能各自存在相同的 mixed-port、dns 或 tun。界面开关也可能有较高优先级。不要根据文件名猜优先级,要查看客户端说明或进行单字段实验:只改一个端口或日志等级,重新生成后观察运行结果。

Clash Plus、Clash Verge Rev、FlClash 等客户端的配置管理界面并不完全一致,配置导入、扩展与合并的入口需要按实际客户端核对。更换客户端时,不应把某款客户端专用的扩展脚本当作通用 mihomo 字段。内核认识的是最终配置,客户端负责如何生成它。客户端选型与平台支持可查选型指南,首次操作仍按快速上手完成。

映射合并与列表替换

映射可以逐键覆盖,列表则可能整段替换、前置或后置;具体规则由合并工具定义。以 dns 为例,递归合并可能只替换 nameserver,保留其他子键;浅层替换则可能让整个 DNS 区域只剩新内容。对 rules 使用列表替换,可能丢失订阅中的全部分流规则。不能仅凭“合并”二字判断它一定会保留原值。

# 供支持 YAML 覆写的客户端使用;
# 是否递归合并,需要核对该客户端的规则。
log-level: info

profile:
  store-selected: true
  store-fake-ip: true

dns:
  enable: true
  nameserver:
    - https://dns.alidns.com/dns-query

应用这段覆写后,应检查原来的 dns.listen、enhanced-mode、过滤列表和解析策略是否仍存在。如果结果与预期不同,应调整合并方式,而不是继续叠加重复字段。规则的前置与后置也需要检查位置:在既有 MATCH 后追加普通规则,通常不会实现预期分流;前置过宽的规则,又可能截获原来的业务例外。

订阅刷新与本地改动保护

直接修改下载后的订阅文件,刷新后可能被远程内容覆盖。长期保留的本机 DNS、局域网规则和端口设置,应放在客户端支持的本地持久层。手工维护的节点集合与规则集合也应使用独立路径,不要与订阅缓存共用同一个文件。若多个 HTTP provider 使用相同缓存路径,会出现内容互相覆盖,表现可能是节点突然消失或解析出错误结构。

订阅格式转换并不等于所有字段都能保真。单节点 URI 通常不能表达完整的 DNS、规则与策略组;把完整 YAML 转成节点链接时,这些顶层设置可能被丢弃。转换后应先对比协议、认证、传输,再检查策略组和规则是否由转换器重新生成。涉及私人订阅时,不要把完整链接交给来源不明的在线转换服务,优先使用可信的本地工具或服务方提供的格式。

可回退的更新流程

更新前保存当前可用配置和本地扩展,记录当前选择的配置名称。刷新后先运行语法检查,再确认策略组成员与规则目标,最后建立新连接测试。若下载成功却加载失败,应比较返回内容是否变成网页、错误提示或其他订阅格式;若加载成功但行为变化,则对比运行配置,而不是只看原始订阅。关于超时、链接过期与自动更新间隔,可继续查阅订阅更新排查文章。

需要分享配置差异时,只保留相关字段与脱敏后的引用关系。不要上传整份运行配置来解释一个 DNS 子键,因为其中可能还带有节点密码、管理认证与远程订阅凭据。一个可重复的最小片段,比包含大量无关规则的完整文件更容易得到准确判断。

验证、日志与定位流程

配置验证应从静态结构走向实际连接,不要一开始就同时切换模式、节点和 DNS。先确认内核接受文件,再确认请求进入正确端口,再观察规则命中与节点连接。每一步只排除一层问题,记录输入、结果与改动。完整配置中存在多个可用节点,也不能证明当前策略组选择的那一个可用;同样,客户端界面显示运行中,也不能替代一次实际请求测试。

先检查文件,再加载运行

直接运行 mihomo 的用户可以使用配置测试参数。命令中的目录应替换为实际工作目录,相对 provider 路径与缓存路径会受到工作目录影响。GUI 用户优先使用客户端内置的检查、预览或日志功能,不要额外启动第二个实例占用同一组端口。配置检查通过后,还要查看启动日志是否存在监听失败或资源加载错误,这些问题未必都能在静态检查阶段发现。

# 在配置及资源所在目录执行
mihomo -t -d . -f ./config.yaml

# 通过本机 HTTP 代理入口建立请求
curl -I --proxy http://127.0.0.1:7890 https://example.com

# 使用 SOCKS,并把域名解析交给代理侧处理
curl -I --proxy socks5h://127.0.0.1:7890 https://example.com

两种 curl 请求的 DNS 路径可能不同,不能把它们当作完全相同的测试。socks5h 用于让代理处理主机名,普通 socks5 通常由本地先解析。Windows 上若终端中的 curl 被映射为其他命令,应明确调用实际 curl 程序。出现 HTTP 错误状态也不必然意味着代理不可达,需要区分网站拒绝请求、代理认证失败和底层连接失败。

按报错阶段缩小范围

现象优先检查下一步
YAML 解析错误报错行附近的缩进、引号与列表先恢复可解析结构
代理或组不存在名称引用、provider 是否加载核对最终配置中的实际成员
监听地址已占用旧进程、其他客户端、端口冲突关闭冲突实例或统一调整端口
DNS 查询超时查询入口、上游与引导解析用单一解析链测试
TLS 握手失败时间、主机名、证书与传输参数对照服务端要求逐项检查
请求走错出站模式、命中规则与组内选择建立新连接复测

错误行号有时指向解析器停止的位置,而不是最早写错的位置。检查该行的同时,也应查看前一行是否少了引号或冒号。未知代理名称则通常属于引用问题,不需要先调整网络。连接超时需要结合目标判断:是订阅服务器超时、节点服务器超时,还是目标网站超时,三者应分别沿下载链、代理链和网站链检查。

日志记录与最小复现

短时启用 debug 后,只复现一个目标请求,记录时间、目标、规则与最终出站,再恢复正常日志等级。如果存在 TUN、系统代理和应用手工代理三种入口,先保留一种明确入口进行对比。浏览器连接池、后台服务和 DNS 缓存可能让旧连接继续存在,因此每次重要修改后应使用新的请求进程或重启测试应用,避免观察到旧状态。

最小复现可以保留一个经过确认的节点、一个手选组、一条针对测试域名的规则和末尾兜底。若最小配置可用,再按 DNS 策略、规则集合、自动选择和本地覆写逐项恢复。不要一次删去所有规则后就认定规则有问题,因为删除过程也可能改变 DNS 解析时机与默认出站。保留每一步的配置差异,才能说明是哪项改变影响了结果。

常见边界问题

配置检查通过,为什么应用仍然无法连接?

检查只证明字段与引用满足内核要求。应用可能没有使用代理,节点也可能不可达。先用显式指定本机端口的请求测试,再查看连接记录;若该请求正常,应返回应用代理设置或系统入口排查。

更新订阅后,为什么手选节点发生变化?

节点名称、组成员或持久化状态可能改变。检查更新后的组成员及当前选择,并确认 profile.store-selected 与客户端保存行为。旧名称不存在时,保存过的选择不一定能够继续使用。

系统代理可用,为什么 TUN 不可用?

TUN 额外依赖权限、虚拟接口、系统路由与 DNS 接管。保留已验证的节点和规则,分别检查这些条件,不要因此重新改写节点认证。不同平台的授权与接口管理方式需要按客户端说明操作。

完成定位后,删除临时测试规则,恢复合适的日志等级,并确认局域网访问范围没有因排查而扩大。将稳定改动放回本地持久覆写层,再做一次订阅刷新与重载测试。这样既验证当前连接,也验证配置在下一次更新后仍能保持预期行为。