CH-01
策略组类型与实战
策略组(proxy-groups)是分流规则与具体节点之间的中间层:规则命中后交给策略组,策略组再按自身逻辑决定实际走哪个节点。理解每种类型的判定机制,是把配置从"能用"改到"好用"的第一步。mihomo 支持的常用类型有五种,判定逻辑差异很大,选错类型是延迟抖动与频繁断流的常见根源。
五种类型的判定逻辑
url-test 的三个关键参数
url 是测速目标,通常选一个返回 204 空响应的地址,流量开销可以忽略;interval 是测速周期(秒),太短会放大订阅节点的测速流量,太长则节点劣化后迟迟不切换,日常取 300 左右比较平衡;tolerance 是切换容差(毫秒)——只有新节点比当前节点快出这个差值才切换。不设 tolerance 时,两个延迟 60ms 与 65ms 的节点会来回横跳,每次切换都可能打断正在传输的连接,建议至少设 50。
proxy-groups:
- name: 自动测速
type: url-test
proxies: [HK-01, HK-02, JP-01]
url: https://www.gstatic.com/generate_204
interval: 300
tolerance: 50
- name: 故障转移
type: fallback
proxies: [主力-HK, 备用-JP, 兜底-US]
url: https://www.gstatic.com/generate_204
interval: 180
- name: 均衡下载
type: load-balance
strategy: consistent-hashing
proxies: [SG-01, SG-02, SG-03]
load-balance 的两种 strategy
consistent-hashing 按目标地址哈希,同一网站的请求固定落在同一节点,兼顾分摊与会话稳定,是默认推荐;round-robin 逐连接轮换节点,分摊最彻底,但同一网站的不同请求会从不同 IP 发出,遇到会话校验严格的服务容易被登出,只建议用在纯下载类分组。
分组的组合套路
实战里通常做两层:底层建"HK 自动""JP 自动"等按地区的 url-test 组,上层建一个 select 组把这些地区组和"手动选择"并列收进来,规则统一指向上层 select 组。这样日常交给自动测速,需要固定地区时在客户端面板一键切到对应地区组,不必改任何规则。策略组还可以嵌套引用其他策略组(proxies 列表里写组名即可),但不要造出循环引用——内核会拒绝加载这样的配置。三种自动类型的更细对比与参数实验,可以参考博客的 策略组类型对比 一文;不知道该把哪些节点收进组,先看 节点挑选的四个维度。
提示
订阅提供的节点名会变(如"HK-01"改名"香港 01"),proxies 里写死节点名的分组会随之失效。改用 include-all: true 搭配 filter: "(?i)hk|港" 按正则收节点,订阅更新后分组自动跟进,不必再手工维护列表。
可用性判定与 lazy 惰性测速
url-test 与 fallback 都依赖健康检查来判断节点是否"可用",这背后是内核对 url 目标发起的周期性探测请求。默认情况下,只要一个策略组被创建,内核就会持续对组内全部节点测速——即便这个组当前根本没被规则命中。节点数量多、订阅嵌套层级深时,这些后台探测会累积成一笔可观的固定流量,甚至拖慢内核启动。给 url-test 组加上 lazy: true 可以开启惰性模式:只有当组真正被选中并承载流量时才触发测速,长期闲置的备用地区组不再空转,这在收进十几个地区分组的大型配置里节流效果很明显。需要注意的是,lazy 模式下节点的延迟数字要等第一次被使用后才出现,客户端面板初始显示为空是正常现象,并非节点失效。
测速目标该选谁
url 目标的选择常被忽视,却直接影响测速结果的可信度。理想的目标应满足三个条件:响应体极小(最好是 204 空响应,避免测速本身消耗带宽)、全球部署且不针对代理流量做特殊处理、稳定可达不会因区域封锁而全组判失败。常用的 https://www.gstatic.com/generate_204 与 http://cp.cloudflare.com/generate_204 都符合。切忌用某个具体网站首页当测速目标——它可能因 CDN 就近调度让不同节点测出的延迟失去可比性,也可能因该站临时故障导致整组节点被误判为不可用而集体切走。若发现某地区节点延迟数字异常一致或整齐地测不出,先怀疑测速目标在该地区被干扰,换一个再看。
CH-02
规则集订阅化管理
把几千条分流规则直接堆在 rules 段,是配置难以维护的主要原因:订阅一更新,手工加的规则就被冲掉;想调整一类站点的走向,要在长列表里逐条找。rule-providers 把规则按用途拆成独立文件、以订阅方式引入,rules 段只留十几行"骨架",可读性和可维护性都会明显改善。
rule-providers 的字段含义
type 取 http(远程订阅,按 interval 自动更新)或 file(本地文件,自己维护);behavior 声明这份规则文件的内容形态——domain 是纯域名列表,ipcidr 是纯 IP 段列表,classical 则允许混写各种规则类型,通用性最强但匹配开销略高;format 支持 yaml、text 与 mihomo 的二进制 mrs 格式,mrs 体积小、加载快,大规则集优先选它;path 是本地缓存路径;interval 是自动更新周期(秒),规则集变动不频繁,86400(一天)足够。
rule-providers:
streaming:
type: http
behavior: classical
format: yaml
url: https://example.com/rules/streaming.yaml
path: ./rule-sets/streaming.yaml
interval: 86400
cn-ip:
type: http
behavior: ipcidr
format: mrs
url: https://example.com/rules/cn-ip.mrs
path: ./rule-sets/cn-ip.mrs
interval: 86400
rules:
- RULE-SET,streaming,流媒体分组
- RULE-SET,cn-ip,DIRECT
- GEOIP,CN,DIRECT
- MATCH,自动测速
规则顺序与兜底
rules 段自上而下匹配、命中即停,顺序就是优先级:个人的例外规则放最前,大规则集居中,GEOIP,CN,DIRECT 之类的地理规则靠后,最后一行必须是 MATCH 兜底——没有兜底时,未命中的流量走向取决于内核默认行为,排查问题时会非常困惑。另一个常见坑是把 IP 类规则(GEOIP/IP-CIDR)放在域名规则前面:IP 规则会触发一次 DNS 解析来拿到目标 IP,既拖慢匹配又可能产生不期望的解析行为,如确有需要且不想触发解析,给规则加 no-resolve 参数。
GeoIP 与 GeoSite 数据库
GEOIP,CN 依赖内核加载的 GeoIP 数据库,GEOSITE 规则依赖 GeoSite 数据库,两者都会随时间过时:数据库太旧时,一些实际在中国大陆的 IP 会被判成境外而错误走代理。多数在维护的客户端在设置里提供"更新 Geo 数据库"入口,建议每一两个月手动点一次;mihomo 也支持在配置里声明 geo-auto-update: true 与更新周期,让内核自行拉取。数据库文件存放在客户端的工作目录,与配置文件同级,更新后需重载配置生效。
注意
RULE-SET 引用的名字必须与 rule-providers 里定义的键完全一致,大小写敏感;引用了未定义的规则集,整份配置会加载失败,客户端日志里会给出具体的名字,报错后先核对这一点。
CH-03
DNS 配置优化
分流的准确性一半取决于 DNS:域名解析被污染,GEOIP 规则拿到的就是错误的 IP,分流随之全盘出错;解析走了不合适的服务器,还会拿到远离当前线路的 CDN 节点,表现为"节点延迟不高但网页就是慢"。dns 段是配置里最值得花时间调的一节。
enhanced-mode:redir-host 与 fake-ip
作为代理客户端的默认选择,fake-ip 综合体验更好,尤其在 TUN 模式下几乎是标配(见第四章)。fake-ip-filter 用来列出必须拿到真实 IP 的域名:局域网设备发现、NTP 时间同步、部分游戏平台的连通性检测等场景拿到假 IP 会工作异常,常见写法如下例。切换 enhanced-mode 后,建议清空一次客户端的 DNS 缓存(多数客户端在设置里提供按钮,或直接重启内核),避免新旧映射混用。
dns:
enable: true
listen: 0.0.0.0:1053
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
fake-ip-filter:
- "*.lan"
- "+.local"
- time.windows.com
- "+.ntp.org"
nameserver:
- https://223.5.5.5/dns-query
- https://doh.pub/dns-query
fallback:
- https://1.1.1.1/dns-query
fallback-filter:
geoip: true
geoip-code: CN
nameserver、fallback 与分组解析
nameserver 是主解析组,建议填国内可直连的 DoH 服务器,保证国内域名解析快且拿到就近 CDN;fallback 是校验组,填境外 DoH:内核会把两组结果做比对,当 nameserver 返回的 IP 落在 fallback-filter 声明的范围(如 geoip-code 为 CN)之外时,判定可能被污染,改用 fallback 的结果。这套机制兼顾了国内解析速度与境外解析纯净度。更进一步可以用 nameserver-policy 按域名指派解析服务器,例如把某个规则集里的域名全部交给境外 DoH,精度最高但配置量也大,按需使用即可。
解析协议的选择
DNS 服务器地址支持多种协议前缀:纯 UDP(223.5.5.5)最快但明文可被篡改;DoT(tls://)与 DoH(https://)加密传输,抗污染能力强,推荐所有服务器都写成 DoH 形式。注意 DoH 服务器域名本身也需要解析,内核用 default-nameserver(应填纯 IP 的 UDP 服务器)完成这一步引导,忘写会导致启动时全部解析失败。怀疑降速与 DNS 有关时,可按 三层定位法 的本地设置层逐项排除;更多解析类问题收录在 常见问题 的故障排查分类。
常见的 DNS 自锁与解析回环
DNS 配置最隐蔽的坑是"自锁":内核要解析 DoH 服务器的域名,而解析这一步又依赖尚未就绪的 DNS 服务,形成鸡生蛋的死结,表现为客户端启动后所有网站都打不开、日志里刷满解析超时。规避办法是把 default-nameserver 填成纯 IP 的 UDP 服务器(如 223.5.5.5 与 119.29.29.29),它专门负责引导阶段解析那些写成域名的 DoH 地址,只应填 IP、绝不能再填域名。另一类问题是解析回环:开启 TUN 且 dns-hijack 生效后,内核自己发出的 DoH 查询若又被虚拟网卡接回内核,就会打转,通常靠 auto-detect-interface 正确识别物理出口来避免,手工指定出口网卡的场景要额外确认 DNS 查询走的是真实链路而非代理链路。
proxy-server-nameserver 的作用
还有一个容易漏配的字段是 proxy-server-nameserver:它专门用来解析各个代理节点自身的服务器域名。如果订阅里的节点地址写成域名(而非 IP),内核在拨号到节点前必须先解析这个域名——这一步若混用了普通 nameserver 的分流逻辑,可能因为把节点域名误判为需要代理而再次陷入回环。把节点服务器域名的解析单独交给 proxy-server-nameserver(通常指向可直连的国内 DoH),既保证解析速度,也让这条解析路径与业务流量的解析彻底隔离,是使用域名型节点时的推荐做法。
CH-04
TUN 与 Fake-IP
系统代理只对"尊重代理设置"的应用生效,命令行工具、游戏客户端、部分 IM 的 UDP 流量都会绕开它。TUN 模式在系统里创建一块虚拟网卡,把全部三层流量接进内核处理,是覆盖面最完整的接管方式,也是处理 UDP 与非常规端口流量的正解。
核心参数
tun:
enable: true
stack: mixed
auto-route: true
auto-detect-interface: true
dns-hijack:
- any:53
auto-route 自动写入路由表,把默认路由指向虚拟网卡,关掉就需要手工配路由,一般保持开启;auto-detect-interface 让内核自动识别真实物理出口网卡,避免代理流量回环打转,多网卡设备(有线+无线、虚拟机网卡)必须开;dns-hijack 把发往 53 端口的明文 DNS 请求劫持给内核 DNS 处理,配合 fake-ip 才能保证 TUN 下的域名分流准确——这也是为什么 TUN 与 Fake-IP 几乎总是成对出现:应用通过虚拟网卡发出的 DNS 查询被内核接住,立即回以假 IP,后续连接命中假 IP 段时内核反查出原始域名,按域名规则精确分流,全程不依赖系统解析器。
stack 三种协议栈
各平台的授权差异
TUN 需要创建网卡的系统权限,各平台路径不同:Windows 上以管理员身份运行客户端,或在客户端设置里安装系统服务,由服务代持权限,日常免提权;macOS 首次启用会弹出系统扩展/网络扩展授权,到"系统设置 → 隐私与安全性"放行后重开开关;Linux 需要 root 或给内核二进制授予 cap_net_admin 能力;Android 不叫 TUN 而是 VpnService,首次开启弹出 VPN 连接授权,同意即可,但厂商省电策略常会杀掉后台服务导致断连,需要把客户端加入省电白名单,具体路径见 Android 端使用要点;iOS 客户端(如 App Store 版 Clash Plus)基于 Network Extension,授权流程由系统统一接管。各平台客户端的获取见 下载页。
注意
TUN 与系统代理同时开启并不冲突,但排查问题时建议只保留一种接管方式,否则难以判断流量走的是哪条路径。关闭 TUN 后若网络异常,多为路由表残留,重启一次内核或系统网络即可恢复。
CH-05
域名嗅探
并非所有连接都天然携带域名:应用自带 DNS(如浏览器内置 DoH)时,内核看到的只是一个目标 IP,域名规则全部失配,只能退化到 GEOIP 判断;fake-ip-filter 放行的域名同样以真实 IP 形态出现。域名嗅探(sniffer)从流量本身还原域名——HTTP 请求的 Host 头、TLS 握手的 SNI 字段、QUIC 初始包里都带有明文域名,内核读出后用它重写连接元数据,再走一遍域名规则,把这类"只见 IP"的连接重新纳入精确分流。
配置示例
sniffer:
enable: true
sniff:
HTTP:
ports: [80, 8080-8880]
override-destination: true
TLS:
ports: [443, 8443]
QUIC:
ports: [443]
skip-domain:
- "+.push.apple.com"
force-domain:
- "+.v2ex.com"
sniff 下按协议声明嗅探的端口范围,三种协议覆盖了绝大多数场景;override-destination 决定是否用嗅探出的域名覆盖连接的目标地址,开启后分流与日志都以域名呈现;skip-domain 排除嗅探后反而出问题的域名——个别推送服务、证书校验严格的客户端在目标被改写后会连接失败,遇到时把对应域名加进来;force-domain 则相反,强制对命中的域名执行覆盖。
何时需要、何时不需要
已启用 fake-ip 且应用都通过内核 DNS 解析时,连接本身就带域名,嗅探的增益有限;真正受益的是 TUN 下自带 DoH 的浏览器流量、绕过系统解析的移动应用,以及 redir-host 模式下的分流精度补偿。嗅探会对每条新连接的首包做一次解析,CPU 开销很小,常开无碍;但若某类应用启用嗅探后出现异常断连,优先怀疑目标覆盖行为,用 skip-domain 定点排除,而不是整体关闭。日志(见第七章)里连接条目从 IP 变成域名,就说明嗅探已生效。
CH-06
本地覆写与多订阅合并
直接编辑订阅下发的配置文件是最常见的维护误区:订阅一刷新,所有手工修改全部丢失。正确姿势是把"订阅提供的节点"与"自己维护的规则、DNS、策略组"分离——订阅负责节点,本地覆写负责其余一切,更新订阅只更新节点,个人配置永远不动。
客户端层的覆写机制
在维护的桌面客户端普遍内置覆写能力:Clash Verge Rev 提供"全局扩展配置"与脚本覆写,可以用 YAML 合并或 JavaScript 函数在订阅配置落地前改写任意字段;Clash Plus、FlClash 也提供各自的覆写/混合入口。以 Verge Rev 的 Merge 覆写为例,前缀语义为:prepend- 插到原列表最前,append- 追加到最后,直接写字段名则整段替换。
prepend-rules:
- DOMAIN-SUFFIX,internal.example.com,DIRECT
append-rules:
- MATCH,自动测速
dns:
enable: true
enhanced-mode: fake-ip
上例把一条内网直连规则插到所有订阅规则之前(保证优先命中),补一条兜底规则,并整体替换 dns 段。规则类覆写优先用 prepend,因为 rules 是顺序匹配,插在前面才能确保生效。
内核层的 proxy-providers 合并多订阅
同时持有多家订阅时,不必在客户端里来回切换配置,用 proxy-providers 把多个订阅作为节点来源统一收进一份配置:
proxy-providers:
sub-a:
type: http
url: https://example.com/sub-a
path: ./providers/sub-a.yaml
interval: 43200
health-check:
enable: true
url: https://www.gstatic.com/generate_204
interval: 600
sub-b:
type: http
url: https://example.com/sub-b
path: ./providers/sub-b.yaml
interval: 43200
proxy-groups:
- name: 全部节点
type: select
use: [sub-a, sub-b]
- name: 香港自动
type: url-test
use: [sub-a, sub-b]
filter: "(?i)hk|香港"
url: https://www.gstatic.com/generate_204
interval: 300
策略组用 use 引用 provider 而不是逐个写节点名,配合 filter 正则筛选,两家订阅的香港节点会自动汇入同一个测速组;订阅各自按 interval 更新,互不影响。health-check 让 provider 内的节点独立保活探测,避免失效节点滞留在分组里。两家订阅出现同名节点时内核会报冲突,可用 provider 的 override.additional-prefix 给节点名统一加前缀区分。
建议
把覆写文件纳入自己的备份习惯:换机、重装或更换客户端时,节点靠订阅链接即可还原,真正不可再生的是这些本地规则与 DNS 调优。客户端停更需要迁移时,覆写文件同样是最先要导出的资产,迁移路线见博客 停更迁移方案。
CH-07
外部控制面板
mihomo 内核暴露一套 RESTful 控制接口(通称 external controller),客户端面板本身就是它的消费者;把接口打开后,还可以接入独立的 Web 面板,或直接用命令行查询与操控内核——远程管理软路由上的内核、写自动化脚本都靠它。
开启接口
external-controller: 127.0.0.1:9090
secret: "your-secret"
external-ui: ./ui
external-ui-url: https://example.com/panel.zip
external-controller 声明监听地址:只在本机使用写 127.0.0.1:9090;要从局域网其他设备访问(如管理软路由)才改成 0.0.0.0:9090,此时 secret 必须设为强口令——接口能读取全部连接记录并切换节点,裸奔等于把控制权交给局域网里的任何人。external-ui 指向一个静态面板目录,内核会在同端口的 /ui 路径下托管它;external-ui-url 则让内核自动下载面板压缩包解压到该目录,省去手工部署。
常用接口速查
命令行验证接口是否可用,以及做一次手动切换节点:
curl -H "Authorization: Bearer your-secret" \
http://127.0.0.1:9090/proxies
curl -X PUT \
-H "Authorization: Bearer your-secret" \
-H "Content-Type: application/json" \
-d '{"name":"香港自动"}' \
http://127.0.0.1:9090/proxies/手动选择
用连接视图排查分流
这套接口最实用的日常价值是排查"某个网站到底走了哪条规则":打开面板的连接页(或 GET /connections),按域名过滤,每条连接都标注了命中的规则与最终出口节点。分流不符合预期时,先看这里确认是规则写错、顺序不对,还是 DNS/嗅探层没拿到域名(条目显示为纯 IP 即是信号,回到第三、五章处理),比盲改配置高效得多。日志级别可在配置里用 log-level: info 调整,排查阶段临时改 debug,定位完记得改回,避免日志刷屏影响性能。
延伸
本页各章示例可自由组合进同一份覆写。仍未覆盖的问题,先查 常见问题 的分类索引;完全从零开始的读者,回到 快速上手 按主线走一遍,再回本页逐章加深。
接口安全的几条底线
外部控制接口的能力等同于对内核的完全控制,因此暴露它必须谨慎。第一条底线是监听地址:除非确有远程管理需求,一律用 127.0.0.1 只对本机开放,绝不轻易改成 0.0.0.0;确需局域网访问时,也应通过防火墙把来源限制到具体的管理机 IP,而不是对整个网段敞开。第二条是口令:一旦监听地址不是回环,secret 必须设为足够长的随机串,并且不要在博客、截图、配置分享里连同真实口令一起贴出——很多人排查问题时随手把整份配置发到论坛,secret 就这样泄露。第三条是绝不把控制端口直接映射到公网:软路由用户尤其容易为了"在外面也能管"而做端口转发,这等于把内核控制台挂到互联网上,正确做法是通过 VPN 或 SSH 隧道回到内网再访问。
面板与内核的版本匹配
独立 Web 面板(如各类基于该接口的开源面板)与内核之间存在接口版本差异:内核迭代时偶尔会调整接口字段或新增鉴权要求,过旧的面板可能出现节点列表加载不全、切换无响应、流量图不刷新等现象。遇到面板行为异常而命令行 curl 直连接口一切正常时,基本可以判定是面板侧过时,升级面板或换用客户端自带面板即可,不必怀疑内核配置。反过来,若 curl 直连也失败,才需要回到 external-controller 与 secret 的配置本身逐项核对。