Mihomo 的配置项很多,但真正困难的不是记住每个 YAML 字段,而是理解不同模块的职责边界。
如果把所有配置都看成“代理设置”,很容易出现下面几类问题:
- 在
override中尝试过滤节点; - 在
proxy-group中配置测速,却忘记 Provider 节点由 Provider 自己维护健康状态; - 把节点来源、节点筛选、节点选择和流量路由混在一起;
- TUN 已经接管流量,但 DNS 仍然从系统路径泄漏;
- 规则写得很多,却没有形成稳定的匹配顺序。
理解 Mihomo,首先要建立一条完整的数据链路。
应用流量
↓
入站:mixed-port / redir-port / tproxy-port / TUN / listeners
↓
DNS 解析与域名嗅探
↓
rules 路由匹配
↓
proxy-groups 策略决策
↓
proxies / proxy-providers 提供实际节点
↓
网络出口这条链路同时给出了配置模块之间的职责边界。
一、Mihomo 配置的核心分层
可以把主配置拆成八层。
| 层级 | 主要配置 | 核心职责 |
|---|---|---|
| 运行层 | mode、log-level、ipv6、profile | 控制内核本身如何运行 |
| 入站层 | mixed-port、tproxy-port、tun、listeners | 决定流量如何进入内核 |
| 识别层 | dns、hosts、sniffer | 将 IP、域名和连接信息关联起来 |
| 节点来源层 | proxies、proxy-providers | 定义实际可用的出站节点 |
| 策略层 | proxy-groups | 决定在多个节点之间如何选择 |
| 路由层 | rules | 决定一条流量进入哪个策略组 |
| 规则来源层 | rule-providers、sub-rules | 管理大规模和可复用规则 |
| 管理层 | external-controller、external-ui | 提供 API、面板和运行时控制 |
最重要的四个概念是:
proxy-providers:节点从哪里来
proxy-groups:节点怎样被选择
rules:流量进入哪个策略组
rule-providers:规则从哪里来这四者名称相似,但职责完全不同。
二、全局运行配置
一份常见的基础配置如下:
mode: rule
log-level: info
ipv6: false
allow-lan: true
bind-address: "*"
unified-delay: true
tcp-concurrent: true
profile:
store-selected: true
store-fake-ip: truemode
常见值包括:
rule:按照rules进行分流;global:所有流量进入GLOBAL策略;direct:所有流量直接连接。
生产配置一般使用 rule。
unified-delay
启用统一延迟计算方式,使不同协议节点的延迟结果更容易横向比较。
tcp-concurrent
当域名解析得到多个 IP 时,并发尝试建立 TCP 连接,使用更快成功的连接。它优化的是建连路径,不是简单地“多开几个连接”。
profile
profile:
store-selected: true
store-fake-ip: truestore-selected保存策略组的上次选择;store-fake-ip保存 Fake-IP 映射,减少内核重启后映射全部失效的问题。
三、入站:流量如何进入 Mihomo
1. 普通代理端口
mixed-port: 7890mixed-port 同时接受 HTTP 和 SOCKS5 代理,桌面环境中通常一个端口就够用。
其他常见端口包括:
port: 7890
socks-port: 7891
redir-port: 7892
tproxy-port: 7893port:HTTP 代理;socks-port:SOCKS 代理;redir-port:透明接管 TCP;tproxy-port:在 Linux 中透明接管 TCP 和 UDP。
2. TUN
TUN 创建虚拟网卡,将原本不支持系统代理的应用流量送入 Mihomo。
tun:
enable: true
stack: mixed
auto-route: true
auto-redirect: true
auto-detect-interface: true
strict-route: true
dns-hijack:
- any:53
mtu: 1500这里需要区分三个动作:
auto-route把系统流量路由到 TUN;dns-hijack把 DNS 请求交给 Mihomo;strict-route收紧路由边界,减少绕过 TUN 的流量。
TUN 只是流量入口。它并不自动保证 DNS 路径正确,也不决定流量最终走哪个节点。
四、DNS:恢复域名语义
规则系统更擅长基于域名分流,但网络连接最终需要 IP。DNS 模块负责在域名、IP 和规则之间建立联系。
典型的 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
fake-ip-filter:
- "*.lan"
- "*.local"
default-nameserver:
- 223.5.5.5
- 119.29.29.29
nameserver:
- https://dns.alidns.com/dns-query
- https://doh.pub/dns-query
proxy-server-nameserver:
- https://dns.alidns.com/dns-query三组 DNS 的职责
default-nameserver
用于解析 DNS 服务器自身的域名。
例如配置中使用:
https://dns.alidns.com/dns-query在请求这个 DoH 服务之前,内核必须先知道 dns.alidns.com 的 IP。这个启动阶段的解析由 default-nameserver 处理。
nameserver
用于解析普通业务域名,例如网页、API 和应用服务域名。
proxy-server-nameserver
专门解析代理节点的 server 域名。
它的重要性在于避免循环依赖:
连接代理节点
→ 需要先解析节点域名
→ 如果节点域名解析又必须经过该代理
→ 形成依赖环将代理服务器域名解析单独隔离,可以让节点建立连接的前置路径更明确。
五、Sniffer:从连接中恢复域名
部分应用绕过系统 DNS,或者直接连接 IP。此时规则系统只能看到目标 IP,无法使用域名规则。
sniffer 可以从协议数据中提取域名:
- HTTP Host;
- TLS SNI;
- QUIC 握手信息。
sniffer:
enable: true
force-dns-mapping: true
parse-pure-ip: true
override-destination: true
sniff:
HTTP:
ports:
- 80
- 8080-8880
TLS:
ports:
- 443
- 8443
QUIC:
ports:
- 443
- 8443Sniffer 的职责不是“解析所有加密流量”,而是在协议握手仍然暴露域名信息时恢复目标域名。
六、proxies 与 proxy-providers
静态节点:proxies
proxies:
- name: 香港节点
type: ss
server: hk.example.com
port: 443
cipher: aes-128-gcm
password: password
udp: true适合少量、稳定、由自己维护的节点。
动态节点:proxy-providers
proxy-providers:
ss:
type: http
url: "https://example.com/subscription"
path: ./proxy_providers/ss.yaml
interval: 3600
proxy: DIRECTProvider 负责管理一批节点的生命周期:
下载或读取订阅
↓
解析节点
↓
覆写统一属性
↓
过滤不需要的节点
↓
执行健康检查
↓
向 proxy-groups 提供节点这比把订阅理解为“一个节点列表”更准确。
七、Proxy Provider 的四个处理阶段
1. 来源
proxy-providers:
airport:
type: http
url: "https://example.com/subscription"
path: ./proxy_providers/airport.yaml
interval: 3600
proxy: DIRECT
size-limit: 10485760常见类型:
http:远程下载;file:读取本地文件;inline:在主配置中直接写payload。
2. 统一覆写:override
override:
udp: true
tfo: true
ip-version: ipv4-prefer
additional-prefix: "[机场 A] "override 用于修改节点属性,例如:
- 是否启用 UDP;
- 是否启用 TCP Fast Open;
- IP 版本偏好;
- 指定出口网卡;
- 增加节点名前后缀;
- 按正则表达式重命名节点。
例如:
override:
proxy-name:
- pattern: "IPLC-(.*?)倍"
target: "IPLC x $1"需要注意:override 的职责是修改节点,不是删除节点。
3. 节点过滤
只保留符合条件的节点:
filter: "(?i)(香港|HK|Hong[ _-]?Kong|🇭🇰)"排除符合条件的节点:
exclude-filter: '(?i)(剩余流量|流量剩余|套餐流量|到期时间|过期时间|有效期|重置时间|官网|公告|remaining[ _-]*traffic|traffic[ _-]*left|expire[sd]?|expiry)'按协议类型排除:
exclude-type: "ssr|http"三者的差异是:
| 字段 | 匹配对象 | 结果 |
|---|---|---|
filter | 节点名称 | 只保留匹配节点 |
exclude-filter | 节点名称 | 删除匹配节点 |
exclude-type | 节点类型 | 删除指定协议类型 |
因此,过滤“剩余流量”“到期时间”等伪节点应该写在 Provider 顶层:
proxy-providers:
airport:
type: http
url: "https://example.com/subscription"
override:
udp: true
tfo: true
exclude-filter: '(?i)(剩余流量|到期时间|官网|公告)'而不是写成:
proxy-providers:
airport:
override:
exclude-filter: "剩余流量" # 错误的职责层级4. 健康检查
health-check:
enable: true
url: https://www.gstatic.com/generate_204
interval: 300
timeout: 5000
lazy: false
expected-status: 204这部分负责维护 Provider 内节点的可用性和延迟状态。
字段含义:
enable:启用健康检查;url:测试目标;interval:检查间隔,单位秒;timeout:超时时间,单位毫秒;lazy:未使用该 Provider 时是否停止主动测试;expected-status:期望 HTTP 状态码。
八、(?i) 到底是什么
下面的过滤表达式:
filter: "(?i)(香港|HK|Hong Kong)"(?i) 是正则表达式的忽略大小写标志,即 case-insensitive。
它能同时匹配:
HK
hk
Hong Kong
HONG KONG
hong kong中文本身没有大小写,因此 (?i) 主要影响英文节点名。
下面的表达式:
Hong[ _-]?Kong其中 [ _-]? 表示中间允许出现零个或一个空格、下划线或连字符,因此可以匹配:
HongKong
Hong Kong
Hong_Kong
Hong-Kong九、Proxy Group:对节点执行选择策略
Provider 解决“节点从哪里来”,代理组解决“节点怎样选”。
select
手动选择节点或其他策略组:
- name: 🚀 节点选择
type: select
proxies:
- ⚡ 自动选择
- 🇭🇰 香港自动
- DIRECTurl-test
自动选择低延迟节点:
- name: 🇭🇰 香港自动
type: url-test
use:
- ss
- paofu
filter: "(?i)(香港|HK|Hong[ _-]?Kong|🇭🇰)"
tolerance: 50
lazy: false这里发生了三步处理:
use从ss和paofu两个 Provider 引入节点;filter只留下香港节点;url-test在这批候选节点中选择延迟更低的节点。
Provider 健康检查与代理组测试的边界
代理组中的:
url: https://www.gstatic.com/generate_204
interval: 300只直接检查代理组 proxies 字段中引入的节点,不直接检查通过 use 引入的 Provider 节点。
因此,使用 use 时应该在每个 Provider 内配置 health-check:
proxy-providers:
ss:
type: http
url: "https://example.com/ss"
health-check:
enable: true
url: https://www.gstatic.com/generate_204
interval: 300
lazy: false
paofu:
type: http
url: "https://example.com/paofu"
health-check:
enable: true
url: https://www.gstatic.com/generate_204
interval: 300
lazy: false这个边界非常重要:
Provider 维护节点状态
Proxy Group 消费节点状态并执行选择策略tolerance
tolerance: 50表示新节点需要明显快于当前节点,超过一定延迟差后才切换。它用于减少延迟轻微波动导致的频繁跳节点。
tolerance: 0更接近绝对最低延迟,但容易频繁切换;tolerance: 30或50通常更稳定。
fallback
按顺序选择可用节点,当前节点失效后回退:
- name: 🛟 故障转移
type: fallback
use:
- ss
- paofu
lazy: falseload-balance
把不同连接分配给多个节点:
- name: ⚖️ 负载均衡
type: load-balance
use:
- ss
- paofu
strategy: consistent-hashing负载均衡不是单连接带宽叠加,而是把不同连接分散到不同节点。
十、按照国家自动选择最低延迟节点
一份常用配置如下:
proxy-providers:
ss:
type: http
url: "https://example.com/ss"
path: ./proxy_providers/ss.yaml
interval: 3600
health-check:
enable: true
url: https://www.gstatic.com/generate_204
interval: 300
timeout: 5000
lazy: false
exclude-filter: '(?i)(剩余流量|到期时间|官网|公告)'
paofu:
type: http
url: "https://example.com/paofu"
path: ./proxy_providers/paofu.yaml
interval: 3600
health-check:
enable: true
url: https://www.gstatic.com/generate_204
interval: 300
timeout: 5000
lazy: false
exclude-filter: '(?i)(剩余流量|到期时间|官网|公告)'
proxy-groups:
- name: 🇭🇰 香港自动
type: url-test
use:
- ss
- paofu
filter: "(?i)(香港|HK|Hong[ _-]?Kong|🇭🇰)"
tolerance: 50
lazy: false
- name: 🇯🇵 日本自动
type: url-test
use:
- ss
- paofu
filter: "(?i)(日本|东京|大阪|JP|Japan|Tokyo|Osaka|🇯🇵)"
tolerance: 50
lazy: false
- name: 🇸🇬 新加坡自动
type: url-test
use:
- ss
- paofu
filter: "(?i)(新加坡|狮城|SG|Singapore|🇸🇬)"
tolerance: 50
lazy: false
- name: 🚀 节点选择
type: select
proxies:
- 🇭🇰 香港自动
- 🇯🇵 日本自动
- 🇸🇬 新加坡自动
- DIRECT这个结构实现了两级决策:
第一级:每个国家内部自动选择低延迟节点
第二级:手动或按业务选择国家策略组相比把所有国家节点放进一个 url-test,这种方式更加稳定,也更容易针对不同业务制定规则。
十一、Rules:把业务流量交给策略组
规则基本格式为:
规则类型,匹配内容,目标策略例如:
rules:
- DOMAIN-SUFFIX,github.com,🚀 节点选择
- DOMAIN-KEYWORD,youtube,🎬 视频
- GEOSITE,cn,DIRECT
- GEOIP,CN,DIRECT,no-resolve
- IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
- MATCH,🐟 漏网之鱼规则从上到下匹配,命中后通常不再继续匹配。因此规则顺序本身就是路由逻辑。
一般顺序可以组织为:
局域网和私有地址
↓
需要强制直连的域名
↓
特定业务规则
↓
国内域名和国内 IP
↓
代理规则
↓
MATCH 兜底MATCH 应该放在最后。
十二、Rule Provider:管理大型规则集
当规则数量变多时,不应全部堆进主配置。
rule-providers:
private:
type: http
behavior: domain
format: mrs
url: "https://example.com/private.mrs"
path: ./ruleset/private.mrs
interval: 86400在主规则中引用:
rules:
- RULE-SET,private,DIRECT
- MATCH,🚀 节点选择常见 behavior:
domain:域名集合;ipcidr:IP 网段集合;classical:完整规则行集合。
rule-providers 解决的是规则文件的下载、更新和解析,rules 仍然负责决定规则的匹配顺序和目标策略。
十三、完整配置骨架
下面这份配置不包含真实订阅地址,但展示了主要模块如何组合:
mode: rule
log-level: info
ipv6: false
allow-lan: true
bind-address: "*"
unified-delay: true
tcp-concurrent: true
profile:
store-selected: true
store-fake-ip: true
mixed-port: 7890
external-controller: 127.0.0.1:9090
secret: ""
tun:
enable: true
stack: mixed
auto-route: true
auto-detect-interface: true
strict-route: true
dns-hijack:
- any:53
dns:
enable: true
ipv6: false
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
default-nameserver:
- 223.5.5.5
- 119.29.29.29
nameserver:
- https://dns.alidns.com/dns-query
- https://doh.pub/dns-query
proxy-server-nameserver:
- https://dns.alidns.com/dns-query
sniffer:
enable: true
force-dns-mapping: true
parse-pure-ip: true
sniff:
HTTP:
ports: [80, 8080-8880]
TLS:
ports: [443, 8443]
QUIC:
ports: [443, 8443]
proxy-providers:
airport:
type: http
url: "https://example.com/subscription"
path: ./proxy_providers/airport.yaml
interval: 3600
health-check:
enable: true
url: https://www.gstatic.com/generate_204
interval: 300
timeout: 5000
lazy: false
override:
udp: true
tfo: true
exclude-filter: '(?i)(剩余流量|到期时间|官网|公告)'
proxy-groups:
- name: 🇭🇰 香港自动
type: url-test
use:
- airport
filter: "(?i)(香港|HK|Hong[ _-]?Kong|🇭🇰)"
tolerance: 50
lazy: false
- name: 🚀 节点选择
type: select
proxies:
- 🇭🇰 香港自动
- DIRECT
rules:
- GEOSITE,cn,DIRECT
- GEOIP,CN,DIRECT,no-resolve
- MATCH,🚀 节点选择十四、常见配置错误
1. 在 override 中写 exclude-filter
错误原因:覆写和过滤是两个独立阶段。
override:
exclude-filter: "剩余流量"正确写法:
override:
udp: true
exclude-filter: "剩余流量"2. 把 use 当成节点名列表
use 引用的是 Provider 名称:
use:
- ss
- paofuproxies 引用的是静态节点或其他代理组:
proxies:
- 香港节点
- 🇭🇰 香港自动
- DIRECT3. Provider 没有健康检查
如果代理组通过 use 引入 Provider,Provider 应该自己配置 health-check,否则自动选择缺乏持续更新的节点状态。
4. 国家关键词过于宽泛
例如只写:
filter: "港"可能误匹配包含该字符的其他说明节点。更稳妥的写法是组合多个明确标记:
filter: "(?i)(香港|HK|Hong[ _-]?Kong|🇭🇰)"5. exclude-filter 过于激进
直接排除:
exclude-filter: "流量"可能误伤名称中包含“流量优化”等文字的正常节点。应该优先使用“剩余流量”“套餐流量”“到期时间”等完整语义。
6. 忽略空代理组
当某个 Provider 没有符合国家正则的节点时,国家策略组可能为空。生产配置需要确保:
- Provider 节点命名稳定;
- 正则覆盖机场实际命名;
- 关键业务策略存在备用组或
DIRECT; - 更新订阅后检查策略组是否仍有节点。
十五、最终心智模型
Mihomo 配置不应该被理解为一份巨大的 YAML,而应该被理解为多个阶段组成的处理管线:
入站负责接管流量
DNS 与 Sniffer 负责恢复目标语义
Rules 负责业务分类
Proxy Groups 负责策略决策
Proxy Providers 负责节点供应和状态维护
Proxies 负责真正建立出站连接当配置出现问题时,也应该沿着这条链路排查:
流量有没有进入内核?
↓
域名是否被正确识别?
↓
规则命中了哪个策略?
↓
策略组有哪些候选节点?
↓
Provider 是否成功更新和测速?
↓
最终节点能否建立连接?只要保持职责边界清晰,Mihomo 即使配置项很多,也不会失去可维护性。