01 / POLICY
策略组类型与实际组合
先区分节点、策略组和最终策略
Clash 配置里的代理节点是具体连接参数,策略组是对节点或其他策略组的组织方式,规则行末尾写的则是最终策略名称。三者名称可能同时出现在界面里,但职责不同。例如订阅提供了多个节点,可以先把它们放进名为“节点选择”的 select 组,再让“开发服务”“流媒体”等业务组引用“节点选择”。规则只需要指向业务组,不必逐条绑定某个节点。这样更换节点时无需修改规则,订阅更新后也不必重新整理每一行分流逻辑。
策略组名称必须与规则目标完全一致,包括空格和大小写。配置能被解析并不代表策略一定存在:部分客户端会在载入时直接提示找不到策略,另一些情况下则要到规则命中后才暴露问题。调整名称后需要重载配置,随后在连接详情或日志中确认规则命中的目标组。不要仅凭网页是否打开判断,因为浏览器缓存、现有连接复用和系统 DNS 缓存都可能让旧结果暂时延续。
四种常用组的职责
| 类型 | 选择逻辑 | 适用位置 | 需要注意 |
|---|---|---|---|
select |
由用户手动选择 | 总入口、业务分组 | 不会自行切换,结果最可控 |
url-test |
定期测试并选择响应较合适的候选项 | 同类节点的自动选择 | 测试结果只反映测试地址,不代表所有站点体验 |
fallback |
按候选顺序选择当前可用项 | 主备线路切换 | 顺序表达优先级,不以最低响应为唯一目标 |
load-balance |
按策略把不同连接分配给多个候选项 | 多出口并行使用 | 同一业务出现不同出口时可能触发登录风控 |
url-test 适合一组可互换的节点。常见参数包括测试地址 url、测试间隔 interval 和可接受差值 tolerance。间隔过短会产生额外连接和耗电,移动端尤其明显;差值过小则可能让选择结果频繁变化。测试地址应返回稳定、体积很小的响应。测试成功只能说明从当前网络经候选节点到测试地址的链路可用,不等于目标业务的握手、地区判断或账号状态一定正常。
fallback 更看重顺序。它适合“主线路优先,主线路不可用时才切备用”的场景。与之相比,load-balance 会让并发连接分布到不同节点。需要保持来源地址稳定的登录、支付、即时通信和长连接业务,不宜直接放进负载均衡组。即使使用一致性散列,也要理解域名变化、连接重建和规则变化仍可能让出口发生改变。
一套可维护的分层写法
proxy-groups:
- name: 节点选择
type: select
proxies:
- 自动选择
- 故障转移
- DIRECT
- name: 自动选择
type: url-test
use:
- airport-main
url: https://www.gstatic.com/generate_204
interval: 600
tolerance: 80
- name: 故障转移
type: fallback
use:
- airport-main
url: https://www.gstatic.com/generate_204
interval: 600
- name: 开发服务
type: select
proxies:
- 节点选择
- 自动选择
- DIRECT
- name: 最终匹配
type: select
proxies:
- 节点选择
- DIRECT
这套结构把“节点如何选”和“业务走哪里”拆开。use 引用的是 proxy-providers 名称,而 proxies 引用的是具体节点或其他策略组名称。两者不能互换。订阅节点很多时,优先用 provider 加过滤条件维护候选项,避免每次订阅变化后手工改 proxies。如果客户端覆写系统支持给策略组追加内容,也应保持同一层次:节点来源由 provider 管,业务语义由本地策略组管。
组之间不能形成循环引用。例如“节点选择”包含“自动选择”,而“自动选择”又把“节点选择”写入 proxies,就无法得到明确的最终出口。实际修改时可以从规则末端反向检查:规则指向业务组,业务组指向总入口,总入口最终指向节点或 DIRECT。每条链都应能够终止。对于 REJECT、DIRECT 这类内置策略,不需要再建立同名节点。
验证策略组时,先在客户端界面明确选中预期项,再关闭目标应用中的现有连接并重新发起请求。随后查看连接记录中的规则类型、规则内容、策略组和最终节点。如果界面显示的是旧组名,通常说明当前运行配置尚未重载;如果组里缺少新节点,则检查 provider 是否更新成功、过滤表达式是否排除了全部节点。更完整的规则优先级说明可继续阅读自定义规则语法与匹配优先级。
02 / RULE PROVIDERS
规则集订阅化管理
把规则内容与主配置分开
规则数量增长后,继续把所有条目写进主配置的 rules 会带来三个问题:更新配置容易覆盖本地修改,重复域名难以追踪,加载失败时也难以确定是哪一批规则有问题。rule-providers 用来声明外部规则集的来源、行为类型、文件路径和更新周期,主规则区只通过 RULE-SET 决定它在匹配顺序中的位置以及命中后使用哪个策略组。
规则集并不会绕过自上而下的匹配机制。RULE-SET,developer,开发服务 出现在国内直连规则之前还是之后,会直接改变重叠域名的结果。规划时先确定业务优先级,再排列规则集,而不是按下载文件的名称或体积排序。高确定性的自定义域名通常放前面,局域网与必要直连规则靠前,宽泛的地区集合靠后,最后用 MATCH 接住未命中流量。
provider 字段逐项说明
rule-providers:
developer:
type: http
behavior: domain
format: yaml
path: ./ruleset/developer.yaml
url: https://example.com/rules/developer.yaml
interval: 86400
private-network:
type: file
behavior: ipcidr
format: text
path: ./ruleset/private-network.txt
rules:
- RULE-SET,developer,开发服务
- RULE-SET,private-network,DIRECT,no-resolve
- GEOIP,CN,DIRECT
- MATCH,最终匹配
type: http 表示由内核按 url 获取并缓存,type: file 表示只读取本地文件。示例域名用于展示结构,实际使用时应替换为自己确认可访问的规则来源。path 是缓存或本地规则文件位置,同一配置中的 provider 不应共用一个路径,否则后写入的内容可能覆盖先前文件。相对路径的基准取决于客户端给内核设置的工作目录,桌面客户端通常会把它映射到自己的配置目录,而不是用户当前打开的终端目录。
behavior 决定规则载荷如何解释。domain 适合域名集合,ipcidr 适合 IPv4 与 IPv6 网段,classical 则允许每行携带完整的规则类型。选择错误时,文件可能下载成功但无法按预期匹配。例如把含有 DOMAIN-SUFFIX,example.com 的 classical 内容声明成 domain,解析方式就不一致。先查看规则源提供的原始格式,不要根据文件扩展名推断行为。
format 描述载荷编码,常见为 yaml、text 或内核支持的二进制规则格式。不同格式的内容结构不同。YAML domain provider 常见写法是顶层 payload 数组;文本格式通常逐行保存条目。订阅源说明若明确提供 Mihomo 格式,应按说明选择,不要把普通 hosts 文件、广告过滤语法或浏览器扩展规则直接当成 Clash 规则集。
interval 单位为秒,它控制检查更新的周期,不代表配置载入后必须等待该时间才首次获取。周期不宜设置得过短;规则源更新通常没有节点状态那么频繁,频繁拉取只会增加启动与网络开销。若客户端提供“更新规则集”操作,可以在修改来源后手动触发一次,再从日志确认 HTTP 状态、解析结果和缓存路径。
域名集、IP 集与 no-resolve
域名规则在请求仍保留域名信息时最直接。IP-CIDR 规则针对目标 IP;当一条 IP 规则后带有 no-resolve,含义是匹配该条规则时不要为了获得目标 IP 主动解析域名。它不是“禁用 DNS”,也不会阻止应用自身已经完成的解析。对纯 IP 连接,内核仍然可以直接拿目标 IP 匹配。是否添加该参数,要看前面的 DNS 与嗅探流程是否已经提供足够信息,以及这条规则是否值得触发额外解析。
| 规则集内容 | behavior | 典型载荷 | 常见用途 |
|---|---|---|---|
| 域名与域名后缀 | domain |
example.com、+.example.org |
网站与服务分组 |
| IPv4/IPv6 网段 | ipcidr |
192.0.2.0/24 |
地区网段、私有网络 |
| 完整规则行 | classical |
DOMAIN-SUFFIX,example.com |
混合多种规则类型 |
更新失败时的检查顺序
首先区分“下载失败”和“解析失败”。下载失败通常会在日志里出现连接、证书、超时或 HTTP 状态相关信息;解析失败则多半表示文件已经取得,但字段、缩进、行为类型或格式不符合要求。其次检查 URL 是否能在当前网络路径下访问。规则 provider 的下载流量如何路由,受当前内核启动阶段和配置影响;首次加载时若依赖一个尚未创建成功的策略,可能出现先后顺序问题。
然后检查缓存目录是否可写。桌面客户端由图形界面管理配置时,不建议把 path 指向受系统保护的目录。文件名应彼此唯一,目录层级也不要依赖未创建的绝对路径。最后确认主规则中确实存在对应的 RULE-SET,名称与 provider 键一致。provider 下载成功但未在 rules 中引用,只会占用缓存,不会参与分流。
当规则集来源不稳定时,应保留一套最小可运行配置:基础直连、必要代理与最终规则不要全部依赖远程文件。这样即使某个 provider 暂时无法刷新,已有缓存或本地基础规则仍能让配置启动。若要按国内直连、其他流量代理的场景组织完整顺序,可参考国内外规则分流配置思路,再按本章方法把稳定的大型集合拆成 provider。
03 / DNS
DNS 配置优化与泄漏排查
理解 DNS 在分流链中的位置
DNS 配置不是单纯更换解析服务器。开启 Mihomo DNS 后,内核需要决定向哪个上游查询、查询流量走什么网络路径、返回真实地址还是 Fake-IP,以及解析结果如何参与规则匹配。应用可能直接向系统 DNS 发请求,也可能自带加密 DNS;浏览器还可能启用安全 DNS。只有先确认请求是否进入内核,后续的 nameserver 调整才有意义。
常见流程是:应用请求域名,系统或 TUN 将 DNS 请求交给内核,内核按域名规则选择上游,取得结果或分配 Fake-IP,随后在连接建立时恢复域名并执行分流。若应用绕过系统解析并直接访问自己的 DNS 服务器,需要靠 TUN 路由、DNS 劫持或应用设置把请求纳入同一链路。仅把系统 DNS 地址改成某个公共服务,并不能自动保证所有查询都跟随 Clash 策略。
一份便于排错的基础配置
dns:
enable: true
listen: 0.0.0.0:1053
ipv6: false
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
fake-ip-filter-mode: blacklist
fake-ip-filter:
- "*.lan"
- "localhost.ptlogin2.qq.com"
- "+.stun.*.*"
default-nameserver:
- 223.5.5.5
- 1.1.1.1
nameserver:
- https://dns.alidns.com/dns-query
- https://cloudflare-dns.com/dns-query
proxy-server-nameserver:
- https://dns.alidns.com/dns-query
direct-nameserver:
- https://dns.alidns.com/dns-query
respect-rules: true
default-nameserver 主要用于解析加密 DNS 上游自身的域名,因此通常填写可直接访问的 IP 地址,避免出现“需要先解析 DNS 服务器域名,但解析它又必须先连接该服务器”的循环依赖。它不是所有业务域名的默认最终答案来源。nameserver 才是普通查询的主要上游,既可以使用 IP 形式的传统 DNS,也可以使用内核支持的加密 DNS 地址。
proxy-server-nameserver 用来解析代理服务器本身的域名。节点地址如果写成域名,内核必须先得到其真实 IP 才能建立代理连接;这一步不能依赖尚未建立的代理链。该上游应能在当前直连环境中稳定访问。若节点地址本身就是 IP,此项的重要性会降低,但保留清晰的引导解析路径仍有利于切换订阅来源。
direct-nameserver 可为预计直连的域名指定解析路径,配合 respect-rules 时要特别关注规则与 DNS 之间的依赖。配置过于复杂时,可能发生查询需要先知道规则,而规则又依赖查询结果的情况。排错阶段建议先使用少量确定可达的上游,确认普通查询和代理节点解析都正常,再增加按域名分流的 nameserver-policy。
nameserver-policy 的精确使用
dns:
nameserver-policy:
"geosite:cn":
- https://dns.alidns.com/dns-query
"+.example.internal":
- 192.168.1.1
"rule-set:developer":
- https://cloudflare-dns.com/dns-query
nameserver-policy 根据域名选择解析上游,适合内网域名、特定服务或地区域名的解析要求。它决定的是“向哪里问”,不直接等同于连接流量的代理策略。一个域名由本地 DNS 解析,并不表示连接一定直连;最终仍由 rules 决定。相反,通过远程加密 DNS 取得地址,也不代表业务连接必须代理。把解析路径与连接路径分开理解,能避免很多看似矛盾的命中结果。
内网域名必须由路由器或企业 DNS 回答时,可以为明确的后缀指定局域网 DNS。不要把宽泛通配符都交给内网服务器,否则离开该网络后会造成大量超时。笔记本经常切换网络时,可以把办公网络专属规则放进单独覆写,并在需要时启用,而不是永久写入所有场景的主配置。
IPv6、缓存与回退行为
ipv6: false 通常表示 DNS 模块不返回 AAAA 结果,但它不等同于从操作系统层面关闭 IPv6。应用若通过其他解析路径得到 IPv6 地址,或者直接连接 IPv6,仍可能绕过预期链路。网络本身没有稳定 IPv6、代理节点不支持 IPv6 或规则集只覆盖 IPv4 时,先关闭 DNS 的 IPv6 返回有助于减少连接等待;确实需要 IPv6 时,则应同时检查 TUN 路由、规则集和出口能力。
DNS 缓存会让修改后的结果不会立即体现。重载配置后,应清理客户端内部缓存;必要时再清理操作系统和浏览器缓存,并重新建立连接。不要在同一个未关闭的浏览器标签页里连续刷新来判断规则,因为 HTTP/2、HTTP/3 和连接池可能继续复用旧连接。可靠方法是关闭目标应用连接、清理缓存、重载配置,然后结合 DNS 日志与连接记录重新测试。
| 现象 | 优先检查 | 常见原因 |
|---|---|---|
| 节点域名无法解析 | default-nameserver、proxy-server-nameserver |
引导解析循环或上游直连不可达 |
| 内网域名打不开 | nameserver-policy、Fake-IP 过滤 |
内网查询发到公共上游 |
| 修改规则后仍走旧路径 | DNS 缓存、现有连接 | 旧解析和连接池仍在复用 |
| 部分应用不进入日志 | 应用安全 DNS、TUN 路由 | 应用绕过系统 DNS 或代理设置 |
判断 DNS 是否按预期工作时,应记录四项事实:应用询问的域名、请求进入内核的方式、实际使用的上游和连接最终命中的规则。若只有“检测网站显示某个 DNS”这一项,无法定位是浏览器安全 DNS、系统缓存、上游转发还是内核配置导致。遇到复杂故障,可在帮助中心按 DNS、系统代理和连接日志的顺序继续核对。
04 / TUN & FAKE-IP
TUN 模式与 Fake-IP 协同
系统代理与 TUN 的覆盖范围
系统代理只影响遵循操作系统代理设置的应用。浏览器和多数桌面软件通常支持,但命令行工具、游戏、虚拟机、部分商店应用和自行实现网络栈的软件可能忽略它。TUN 模式创建虚拟网络接口,通过系统路由把更多 TCP、UDP 流量交给内核,因此覆盖范围更广。代价是它会介入路由、DNS 与接口选择,配置错误时影响也比普通系统代理更明显。
启用 TUN 前,先确认普通代理模式下节点、规则与 DNS 都能工作。否则一旦进入 TUN,节点不可用、DNS 循环和路由冲突会叠在一起,难以判断根因。推荐顺序是:先验证节点连接,再验证规则命中,然后开启 TUN,最后再开启 DNS 劫持和 Fake-IP。每次只改变一组变量,并保留能够恢复的配置副本。
TUN 基础参数
tun:
enable: true
stack: mixed
dns-hijack:
- any:53
- tcp://any:53
auto-route: true
auto-detect-interface: true
strict-route: true
mtu: 1500
dns:
enable: true
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
stack 决定 TUN 流量由哪种网络栈处理。Mihomo 常见选择包括 system、gvisor 和 mixed。系统栈通常性能路径直接,gVisor 用户态栈在部分平台或特殊网络下兼容性不同,mixed 用于组合处理。不存在适合所有系统的固定答案;若默认配置稳定,就没有必要只为追求参数复杂度而切换。遇到 UDP、局域网访问或特定游戏异常时,再把网络栈作为单独变量进行对照测试。
auto-route 让内核自动添加必要路由,auto-detect-interface 用于识别当前默认出口。笔记本在有线、无线、热点和 VPN 之间切换时,自动检测通常更方便;服务器、多网卡主机或策略路由环境则可能需要明确指定接口。若日志显示流量反复进入 TUN,或者代理节点连接本身又被送回 TUN,要检查出口接口、路由排除与已有 VPN 是否形成环路。
strict-route 用于更严格地约束流量经过 TUN,在不同操作系统上的具体效果与权限要求存在差异。它有助于减少部分绕行,但也可能暴露本来被系统自动处理的路由冲突。启用后若局域网打印机、共享目录或虚拟机网络不可达,应先检查私有网段规则和路由排除,而不是直接把所有局域网地址加入代理策略。
dns-hijack 把指定端口的 DNS 流量交给内核。any:53 覆盖常见 UDP 查询,补充 TCP 形式可处理截断响应后的 TCP 重试。它无法自动拦截所有基于 HTTPS 或 TLS 的应用自带 DNS;这类流量表面上是普通加密连接,需要通过应用设置、域名规则或完整路由路径处理。是否需要劫持取决于应用是否遵循系统 DNS。
Fake-IP 的工作原理
Fake-IP 模式收到域名查询后,不立即把真实目标地址交给应用,而是从保留地址池分配一个映射地址。应用连接该地址时,内核根据映射还原原始域名,再执行域名规则和代理转发。这样即使应用后续只携带 IP,内核仍保留域名上下文,域名分流更稳定,也减少了先在本地取得真实地址再决定策略的依赖。
198.18.0.0/15 属于基准测试用途的保留地址范围,常被 Fake-IP 使用。配置中的地址池不能与现有局域网、容器网络、实验网络或企业路由冲突。如果当前网络恰好使用同一范围,系统可能把 Fake-IP 当成真实路由目标。此时需要更换不冲突的保留范围,并重启相关连接、清理 DNS 缓存,确保旧映射不再被使用。
某些协议需要真实地址或会校验 DNS 行为,不适合返回 Fake-IP。常见对象包括局域网主机名、STUN、网络连通性检测、特定游戏发现协议和少数设备控制服务。它们应放入 fake-ip-filter。过滤条目要尽量精确,先从日志确认域名,再添加后缀或通配模式。把大范围域名全部排除,会让 Fake-IP 的域名保留优势明显下降。
MTU、UDP 与局域网访问
MTU 过大时,某些隧道、移动网络或叠加 VPN 环境会发生分片、丢包,表现为网页部分资源卡住、TLS 握手超时或 UDP 不稳定;过小则会增加包数量和处理开销。不要仅因某个网站慢就盲目降低 MTU。先确认问题只在 TUN 下出现,再比较不同网络和协议,观察日志是否有明显重传或握手失败。每次调整幅度保持可记录,并在重启 TUN 后测试。
局域网访问应同时考虑规则和路由。规则中可把 RFC1918 私有网段、链路本地地址及实际局域网域名设为 DIRECT,但 DIRECT 只决定连接不经过代理节点,不保证操作系统路由一定指向正确接口。若 TUN 自动路由抢占了局域网路径,还需检查路由排除和严格路由设置。共享代理给同网段设备时,则需要额外配置监听地址、allow-lan 与防火墙,可参阅混合端口与局域网共享。
| 问题范围 | 对照测试 | 下一步 |
|---|---|---|
| 仅系统代理正常 | 关闭 TUN 后恢复 | 查路由、接口检测与权限 |
| 域名规则失效 | 检查 Fake-IP 映射与嗅探结果 | 查 DNS 是否真正进入内核 |
| 局域网设备不可达 | 查看目标网段和出口接口 | 补直连规则与路由排除 |
| UDP 应用异常 | 更换网络栈并单独测试 | 查节点 UDP 能力与 MTU |
05 / SNIFFER
域名嗅探与连接还原
嗅探解决什么问题
规则系统更擅长按域名分类,但部分应用建立连接时只向内核暴露目标 IP。域名嗅探会从连接早期数据中识别 HTTP Host、TLS ClientHello 中的 SNI,或支持协议里的目标域名,再用恢复出的域名参与规则匹配。它不会解密 HTTPS 正文,也不读取页面内容;可见信息来自协议握手阶段本来就携带的域名字段。
嗅探与 Fake-IP 都能保留域名上下文,但路径不同。Fake-IP 在 DNS 查询阶段建立域名到映射地址的关系;嗅探则在连接建立阶段从协议数据恢复域名。两者可以同时启用:Fake-IP 处理经过内核 DNS 的连接,嗅探补足绕过该解析流程或直接使用目标 IP 的部分场景。若 DNS 已经稳定提供映射,不必把所有故障都归因于嗅探。
按协议和端口限制范围
sniffer:
enable: true
force-dns-mapping: true
parse-pure-ip: true
override-destination: false
sniff:
HTTP:
ports:
- 80
- 8080-8880
override-destination: true
TLS:
ports:
- 443
- 8443
QUIC:
ports:
- 443
skip-domain:
- "Mijia Cloud"
- "+.push.apple.com"
skip-src-address:
- 192.168.0.0/16
skip-dst-address:
- 192.168.0.0/16
parse-pure-ip 允许对目标最初表现为纯 IP 的连接尝试嗅探,这正是很多按域名分流的补足场景。force-dns-mapping 与 DNS 映射协作,用于利用已经存在的映射关系。不同客户端附带的内核配置模板可能对默认值有调整,修改前应查看当前实际运行配置,而不是只看订阅原文。
override-destination 决定在识别出域名后,是否用嗅探结果覆盖原始目标用于后续连接。开启后能改善部分域名分流,但错误识别的影响也更直接。建议先在协议子项中针对 HTTP 等明确场景启用,而不是一开始全局覆盖。修改后要检查连接详情里的原始目标、嗅探域名和最终规则,确认变化确实符合预期。
端口范围越宽,不代表识别效果越好。嗅探器需要按协议解析连接前段数据,在明显不是 HTTP、TLS 或 QUIC 的端口上强行尝试,只会增加误判和处理成本。常用端口之外的业务应根据真实应用补充。例如某个内部 HTTPS 服务运行在 9443,可以把该端口加入 TLS 范围;不应为了覆盖它而把所有端口都交给 TLS 嗅探。
QUIC、ECH 与不可见边界
QUIC 通常基于 UDP,是否能识别取决于内核、网络栈和握手信息是否可用。浏览器可能在网络变化后回退到 TCP/TLS,所以同一个站点的连接记录会出现不同协议。排查时应分别观察 TCP 与 UDP,而不是只看一次访问。若节点或网络对 UDP 支持不稳定,可以临时关闭应用的 QUIC 作为对照,但这只是定位方法,不应替代对真实 UDP 路径的检查。
加密客户端问候等机制会减少中间层可见的域名信息。当握手中没有可供识别的明文域名时,嗅探无法凭空恢复业务名称。此时应依赖内核 DNS、Fake-IP 映射、应用进程规则或目标 IP 规则。配置目标应是让多个可靠信息来源互补,而不是要求嗅探覆盖所有连接。
CDN 共享 IP 也是嗅探存在价值的原因之一。仅按 IP 判断时,同一个地址可能承载多个完全不同的域名;按宽泛网段分流容易误伤其他业务。如果能取得域名,就应优先使用域名规则。只有连接确实没有域名上下文,才退回 IP-CIDR、GEOIP 或最终规则。
跳过列表与误判处理
skip-domain 用于跳过已知不适合嗅探或覆盖目标的域名,skip-src-address 和 skip-dst-address 可排除特定来源、目标网段。智能家居、投屏、局域网发现和厂商推送服务出现异常时,应先通过日志锁定具体连接,再添加最窄的排除范围。直接跳过整个私有网络虽然简单,却可能让需要域名分流的本地容器或开发环境失去信息。
识别出的域名若与应用预期不符,先检查目标是否经过 CDN、重定向或第三方静态资源。一个页面会同时连接主域名、登录域名、图片域名和统计端点,连接列表里出现多个名称是正常现象。真正的误判通常表现为原本可用的连接在开启覆盖后失败,关闭该协议的 override-destination 即恢复,并且日志中的嗅探结果与证书或服务目标明显不一致。
| 日志现象 | 含义 | 处理方向 |
|---|---|---|
| 目标只有 IP,未出现域名 | 没有可用映射或协议信息 | 查 DNS 路径、端口范围和协议支持 |
| 已识别域名但仍命中 IP 规则 | 规则顺序或覆盖设置未采用域名 | 查域名规则位置与 override 设置 |
| 关闭嗅探后应用恢复 | 可能误判或目标覆盖不兼容 | 缩小端口范围并加入精确跳过项 |
| TCP 正常、UDP 异常 | QUIC 路径与 TLS 路径不同 | 分别检查 TUN、节点 UDP 和 QUIC |
进程规则可以作为补充,但不同平台获得进程信息的能力、权限和准确性并不一致。移动端应用沙箱、系统服务以及容器环境尤其需要谨慎。能用稳定域名规则解决时,优先域名;没有域名且进程信息可靠时,再考虑进程;两者都不可用时才使用 IP 范围和最终规则。这样的降级顺序比把所有流量绑定到应用名更容易跨平台维护。
06 / OVERRIDES
本地覆写与多订阅合并
把远程订阅视为输入,不直接当成成品
远程订阅主要提供节点,有时也包含策略组、规则和 DNS。直接在订阅生成的 YAML 上修改,下一次更新通常会覆盖本地内容。更稳妥的结构是把订阅当作可更新输入,把长期规则、策略命名、DNS 和 TUN 参数保存在本地覆写层。客户端每次更新订阅后重新应用覆写,运行配置因此保持一致。
不同客户端对覆写的称呼和能力不完全相同,可能表现为脚本、扩展配置、合并配置或配置预处理。Clash Plus 等客户端应以界面实际提供的配置入口为准。无论使用哪种方式,都要区分三份内容:远程原始订阅、本地覆写源和内核最终运行配置。排错时最后一份最重要,因为界面保存成功并不意味着合并结果符合预期。
合并映射与数组的差异
YAML 映射由键值组成,例如 dns 下的 enable;数组则由有顺序的项目组成,例如 rules 和 proxy-groups。映射通常可以按键覆盖,数组却涉及替换、前置追加、后置追加和去重。若合并工具对数组采用整体替换,本地只写一条规则就可能把订阅原有规则全部删掉;若采用追加,关键自定义规则放到末尾又可能永远匹配不到。
因此应先查清客户端的合并语义,再决定覆写结构。规则数组通常需要“前置”能力,让精确本地规则排在宽泛规则之前;策略组数组常需要按名称替换或追加;DNS 映射适合按键覆盖。不要假设所有名为 Merge 的功能都实现同一套行为。更新客户端或迁移平台后,应重新导出最终配置进行对照。
# 本地维护的逻辑示例,具体合并入口以客户端为准
prepend-rules:
- DOMAIN-SUFFIX,example.internal,DIRECT
- DOMAIN-SUFFIX,github.com,开发服务
override:
mode: rule
log-level: info
dns:
enable: true
enhanced-mode: fake-ip
append-proxy-groups:
- name: 本地服务
type: select
proxies:
- DIRECT
- 节点选择
上面的 prepend-rules、override 和 append-proxy-groups 用于说明合并意图,不是 Mihomo 主配置的通用顶层键。实际客户端可能使用图形表单、JavaScript 处理脚本或自己的扩展语法。不要把这段直接粘贴进内核配置。真正交给内核的结果仍应是标准的 rules、proxy-groups 和 dns 等字段。
用 provider 组合多个节点来源
proxy-providers:
provider-a:
type: http
url: https://example.com/subscription/a
path: ./providers/a.yaml
interval: 21600
health-check:
enable: true
url: https://www.gstatic.com/generate_204
interval: 600
provider-b:
type: http
url: https://example.com/subscription/b
path: ./providers/b.yaml
interval: 21600
filter: "(?i)香港|HK|Hong Kong"
health-check:
enable: true
url: https://www.gstatic.com/generate_204
interval: 600
proxy-groups:
- name: 全部节点
type: select
use:
- provider-a
- provider-b
- name: 香港自动
type: url-test
use:
- provider-a
- provider-b
filter: "(?i)香港|HK|Hong Kong"
url: https://www.gstatic.com/generate_204
interval: 600
proxy-providers 能让多个订阅独立更新、独立缓存,再由策略组通过 use 引用。它比把多个订阅文本直接拼接更容易定位问题:某个来源失效时,其他 provider 仍可载入。每个 provider 必须使用不同的 path。订阅链接属于敏感配置,不应复制到日志截图、公开规则仓库或分享配置中;示例里的地址只是结构演示。
filter 通常按节点名称筛选,正则表达式应兼顾订阅的真实命名。过滤后组为空,是多订阅合并中很常见的故障。先查看 provider 实际载入的节点名称,再测试表达式;不要只凭地区中文名编写。使用 (?i) 可在支持的表达式中忽略拉丁字母大小写,但中文别名、旗帜符号和缩写仍需按来源调整。
两个来源存在同名节点时,界面识别和策略引用可能产生歧义。最稳妥的做法是在预处理阶段为节点添加来源前缀,或者让订阅提供方保持唯一名称。若客户端支持 provider 级前缀,可以在合并层统一加上“A-”“B-”等简短标记。不要靠节点排列位置区分,因为订阅更新后顺序可能改变。
多订阅更新的故障隔离
更新失败时逐个 provider 检查,不要一次删除全部缓存。先看请求是否成功,再看 YAML 是否能解析,然后看过滤后是否还有节点,最后看策略组是否正确引用。某个 provider 失败不应让基础配置失去 DIRECT 和本地故障组。可以让总入口同时包含多个独立 provider 产生的组,以便在单一来源异常时手动切换。
合并后的配置还要检查端口冲突、策略重名和规则目标缺失。多个完整订阅若直接合并,常会重复定义 mixed-port、external-controller、DNS 监听地址以及名为“节点选择”的组。节点来源可以多份,控制端口和核心策略结构却应只有一个权威定义。将这些全局字段固定在本地层,远程输入只负责节点,维护成本最低。
| 内容 | 推荐归属 | 原因 |
|---|---|---|
| 节点参数 | 远程 provider | 需要随订阅更新 |
| 业务策略组 | 本地覆写 | 名称要与本地规则长期稳定对应 |
| DNS 与 TUN | 本地覆写 | 取决于设备和当前网络环境 |
| 大型公共规则集 | rule provider | 独立更新并减少主配置体积 |
| 少量精确规则 | 本地规则前部 | 便于控制优先级与快速修正 |
迁移客户端时,不要只导出订阅链接。还应记录本地策略组名称、规则集来源、覆写顺序、Fake-IP 过滤和 provider 路径。不同客户端支持的扩展合并语法可能不同,但标准 Mihomo 配置部分可以复用。先在新客户端建立最小配置,再逐层迁移 provider、策略、规则和 TUN,可避免一次导入大量扩展字段后无法启动。
07 / CONTROLLER
外部控制面板与安全边界
控制接口能做什么
Mihomo 的外部控制接口供图形客户端或网页面板读取运行状态、切换策略、查看连接和日志,并执行配置重载等操作。它不是普通的代理端口,权限明显更高。桌面客户端内置界面通常已经通过本地控制接口管理内核;只有需要独立网页面板、远程运维或其他工具接入时,才需要手动调整监听范围。
控制接口与面板静态文件是两件事。external-controller 定义 API 监听地址,external-ui 指向本地面板文件目录。浏览器打开面板后,面板仍需连接 API 才能显示策略和连接。页面能加载但数据为空,通常是控制地址、鉴权、跨域许可或协议不一致,而不是面板文件本身损坏。
本机使用的最小配置
external-controller: 127.0.0.1:9090
secret: "your-password"
external-ui: ./ui
external-ui-name: metacubexd
external-controller-cors:
allow-origins:
- http://127.0.0.1
- http://localhost
allow-private-network: true
只在本机管理时,应优先监听 127.0.0.1。这样控制端口不会直接出现在局域网接口上。secret 用于 API 鉴权,示例值必须替换为自己的高强度随机字符串,并保存在本机配置中。控制面板要求填写密钥时,使用的就是这里的值。修改后需要重启或重载内核,并同步更新面板连接设置。
external-ui 是面板静态资源目录。部分客户端会自行下载和管理面板,用户无需手动配置;自行部署时则要确认目录存在且内核进程有读取权限。external-ui-name 是否生效取决于当前内核和下载机制,遇到界面仍显示旧内容时,应检查实际目录、浏览器缓存和客户端是否覆盖了该字段。
CORS 许可决定哪些网页来源能在浏览器中调用控制 API。允许来源应写成确切的协议、主机和端口组合,而不是宽泛放开。面板通过本机静态服务访问时,浏览器来源可能是 http://127.0.0.1:端口;通过文件协议直接打开又会有不同限制。先从浏览器开发者工具查看被拒绝的 Origin,再增加精确条目。
局域网管理的额外约束
external-controller: 0.0.0.0:9090
secret: "your-password"
external-controller-cors:
allow-origins:
- http://192.168.1.20:8080
allow-private-network: true
监听 0.0.0.0 表示控制接口绑定所有可用网络接口,只有确实需要局域网管理时才应这样做。还要在系统防火墙中把来源限制到可信网段或指定管理设备,不能只依赖面板的登录输入框。面板输入的密钥会被用于调用 API,但网络层仍应先阻止不可信设备接触端口。
如果设备会连接公共 Wi-Fi,长期监听所有接口风险更高。可通过操作系统防火墙区分专用网络与公用网络,或在不需要时恢复环回监听。远程跨互联网管理不应直接暴露控制端口;更合适的方式是先建立受控的私有网络通道,再像访问局域网服务一样连接,并继续保留 API 鉴权。
代理端口的 allow-lan 与控制接口监听范围互不等价。允许局域网设备使用 mixed-port,并不要求控制 API 也对局域网开放;反过来,控制接口监听所有地址也不会自动让代理端口可用。应分别检查代理监听、控制监听、系统防火墙和鉴权,避免为了修复其中一项而扩大另一项的访问范围。
连接面板时的排错路径
第一步确认内核正在监听预期地址和端口。端口被其他程序占用时,内核日志通常会出现 bind 失败;客户端也可能自动改用自己的控制端口,因此最终值要以运行配置和日志为准。第二步在同一设备上测试 API 是否可达,再测试面板。若 API 本身不可达,先处理监听和防火墙,不必反复清除浏览器缓存。
第三步检查鉴权。返回未授权通常说明密钥为空、填错或面板没有按要求发送。注意复制时不要带入额外空格,也不要把 YAML 外层引号当作密钥内容。第四步检查 CORS。浏览器控制台出现跨域拒绝时,API 可能实际上已经响应,只是浏览器不允许面板读取;此时应添加面板的精确来源,而不是关闭所有来源限制。
第五步检查协议与地址。HTTPS 页面调用 HTTP 控制接口时,浏览器可能按混合内容规则阻止请求。面板填写 localhost 时,它指向运行浏览器的设备;如果面板在手机上打开,localhost 就是手机而不是运行 Mihomo 的电脑。局域网访问必须填写电脑在该局域网中的地址,并确认防火墙放行来自手机的连接。
| 现象 | 可能层级 | 检查动作 |
|---|---|---|
| 面板页面无法打开 | 静态文件或 Web 服务 | 检查 external-ui 目录和访问地址 |
| 页面打开但没有数据 | API 地址、鉴权或 CORS | 查看浏览器网络请求与控制台 |
| 本机可用,手机不可用 | 监听地址或防火墙 | 检查是否仅绑定 127.0.0.1 |
| 返回未授权 | secret 不一致 | 重新填写密钥并检查空格 |
| 切换策略后立即恢复 | 配置重载或客户端托管 | 检查客户端是否重新应用订阅配置 |
日志、连接信息与最小暴露
控制面板能显示访问域名、目标地址、进程信息和策略选择,这些都属于设备的网络使用信息。分享排错截图前,应遮盖订阅名称、节点地址、控制密钥、内网地址和与问题无关的访问记录。日志级别保持在满足排错需要的范围即可;长期启用过于详细的日志会增加存储与信息暴露。
使用第三方面板前,应明确它只是 API 客户端,不会替代内核配置。策略切换通常是运行状态操作,配置重载后是否保留取决于客户端与组类型。要长期固定策略,应在本地配置或客户端的持久化机制中设置,而不是只在网页面板里点击一次。订阅更新会重新生成策略组时,名称变化也会让旧选择无法恢复。
完成配置后做一次闭环验证:重启客户端,确认控制端口成功监听;从允许的设备打开面板,使用密钥连接;切换一个 select 组并观察新连接;重载配置后确认状态符合预期;最后从不受信任的网络接口测试端口不可达。这样验证的不只是“面板能打开”,还包括鉴权、访问边界和配置持久化。
如果修改控制接口后客户端无法启动,先恢复为环回地址并暂时移除外部 UI 扩展字段,确保核心配置能够载入,再逐项加回。常见原因是端口占用、YAML 缩进错误、客户端已经托管同一字段或面板目录无效。其他启动与配置载入问题可在帮助中心按错误日志查找;需要重新安装时,前往下载页选择当前平台客户端。