两个内核的版本现状与血缘

原版 Clash(Dreamacro/clash)在 2023 年底归档,最后一个正式版本是 v1.18.0,之后不再有新提交。同期还有一个闭源的 Clash Premium 内核,提供过 TUN、rule-provider 与 script 能力,但它不开源,也随原版一同停止更新。Clash.Meta 是社区在原版内核基础上重写的分支,2024 年改名为 mihomo,仓库为 MetaCubeX/mihomo,目前仍在持续更新。

配置文件层面两者是向上兼容的:port、socks-port、mixed-port、allow-lan、mode、log-level、external-controller、proxies、proxy-groups、rules 这些字段两边都认。差异集中在四块:入站协议、规则类型、DNS 解析链路、TUN 实现。下面逐块对照,并给出迁移时要改写的字段。

能力 原版 Clash v1.18.0 mihomo
入站方式 port、socks-port、redir-port 三个顶层开关 顶层开关 + listeners 段声明多个入站
代理协议 ss、vmess、trojan、snell、socks5、http 上述全部 + vless、hysteria2、tuic、wireguard、ssh、anytls
规则类型 域名、IP、端口、GEOIP、MATCH 上述全部 + GEOSITE、IP-ASN、正则、逻辑组合、SUB-RULE
规则集 不支持,规则只能写死在配置文件里 rule-providers,支持 mrs 二进制格式
DNS nameserver + fallback + fallback-filter nameserver-policy、分流 DNS、DoQ、fake-ip 白名单模式
TUN 不支持 system / gvisor / mixed 三种栈
维护状态 2023 年底归档 持续更新

协议支持:哪些 proxy type 只有 mihomo 认

原版 Clash 的 proxies 段只认六个 type:ss、vmess、trojan、snell、socks5、http。遇到清单外的 type,内核在解析阶段就报 unsupported proxy type 并退出,不会跳过这个节点继续运行——这是换内核后最常见的第一类报错。

mihomo 在这份清单上补了 vless(含 XTLS Vision 与 REALITY)、hysteria2、tuic v5、wireguard、ssh、anytls,并把 Shadowsocks 的加密方式扩到 2022 系列:2022-blake3-aes-128-gcm、2022-blake3-aes-256-gcm、2022-blake3-chacha20-poly1305。下面三个节点的字段组合,原版内核一条都解析不了。

proxies:
  - name: vless-vision
    type: vless
    server: edge.example.com
    port: 443
    uuid: 8f2c1d40-3a7e-4b91-9c2d-5e6f7a8b9c0d
    network: tcp
    tls: true
    udp: true
    flow: xtls-rprx-vision
    servername: www.example.com
    client-fingerprint: chrome
    reality-opts:
      public-key: uM7Kd2QpX1sVbN4tRzY8wLcE3aHfJgOiPqSvTnBm5kU
      short-id: 6ba85179e30d4fc2

  - name: hy2-edge
    type: hysteria2
    server: edge.example.com
    port: 8443
    password: 9f2c7d1a4b6e
    sni: www.example.com
    skip-cert-verify: false
    up: "30 Mbps"
    down: "200 Mbps"

  - name: tuic-edge
    type: tuic
    server: edge.example.com
    port: 10443
    uuid: 8f2c1d40-3a7e-4b91-9c2d-5e6f7a8b9c0d
    password: 9f2c7d1a4b6e
    congestion-controller: bbr
    udp-relay-mode: native
    alpn: [h3]

判断一份订阅能不能继续喂给原版内核,只看两处:proxies 里出现过的 type,以及 ss 节点的 cipher。type 落在 ss、vmess、trojan、snell 之内,cipher 又是 aes-128-gcm 这类旧值时,两边都能跑;一旦出现 reality-opts、congestion-controller 或 2022-blake3- 开头的加密方式,就必须换 mihomo。

反向迁移同样有坑 把 mihomo 的节点配置放回原版内核,client-fingerprint、reality-opts、packet-encoding 都属于未知字段。不同版本的容忍度不一样:有的在解析阶段直接报错退出,有的忽略后按默认参数连接,表现为节点能显示、延迟测试全部超时,排查时容易误判成线路故障。

规则语法与匹配顺序

匹配模型两边一致:rules 自上而下逐条比对,命中第一条就停止,MATCH 兜底。差异在可用类型、匹配代价,以及规则集的加载方式。

规则类型 原版 Clash mihomo 说明
DOMAIN / DOMAIN-SUFFIX / DOMAIN-KEYWORD 支持 支持 走域名索引,单条成本极低
DOMAIN-REGEX / DOMAIN-WILDCARD 不支持 支持 逐条正则匹配,放顶部会拖慢首包
IP-CIDR / IP-CIDR6 / SRC-IP-CIDR 支持 支持 域名连接会触发解析,建议加 no-resolve
GEOIP 支持 支持 依赖 GeoIP 数据文件
GEOSITE 不支持 支持 依赖 geosite 数据文件
IP-ASN / IP-SUFFIX 不支持 支持 按 ASN 或 IP 后缀段分流
PROCESS-NAME 仅闭源 Premium 支持 桌面端按进程名分流
PROCESS-PATH / PROCESS-NAME-REGEX 不支持 支持 按可执行文件路径匹配
RULE-SET 仅闭源 Premium 支持 可加 format: mrs
SUB-RULE / AND / OR / NOT 不支持 支持 多条件组合,注意括号与逗号
IN-TYPE / IN-USER / IN-PORT / NETWORK 不支持 支持 按入站来源与传输层协议匹配
MATCH 支持 支持 必须放在最后一条

规则集的差异比规则类型更容易被忽略。原版 Clash 不支持 rule-providers,规则只能写死在 config.yaml 里;mihomo 的 rule-providers 支持 behavior 取 domain、ipcidr、classical,format 取 yaml、text、mrs,其中 mrs 是二进制格式,只能搭配 domain 或 ipcidr。mrs 在加载时按域名前缀建索引,不需要把整份 YAML 解析成对象,规则条数上万时差距最明显。

rule-providers:
  reject-list:
    type: http
    behavior: domain
    format: mrs
    url: "https://rules.example.com/reject.mrs"
    path: ./ruleset/reject.mrs
    interval: 86400

rules:
  - DOMAIN-SUFFIX,example.org,直连
  - GEOSITE,category-ads-all,REJECT
  - RULE-SET,reject-list,REJECT
  - IP-CIDR,198.18.0.0/16,直连,no-resolve
  - AND,((NETWORK,udp),(DST-PORT,443)),节点选择
  - MATCH,节点选择

写 rules 段时,有三个顺序问题最容易踩:

  1. 具体域名要放在 GEOSITE 之前。GEOSITE 命中面大,如果写在 DOMAIN-SUFFIX,example.org 前面,后面那条规则永远不会执行。
  2. IP-CIDR 放在域名规则之前时,域名连接必须先解析出 IP 才能比对,既多一次 DNS 查询,也会把解析结果交给上游解析器。加上 no-resolve 可以让域名连接直接跳过这条。
  3. MATCH 指向的策略组里要留至少一个可用节点。规则集更新后出现未覆盖的域名时,全部流量都会落到 MATCH,组内为空的表现就是整机断网。

GEOSITE 与 GEOIP 依赖数据文件。原版 Clash 首次启动会去下载 Country.mmdb;mihomo 增加了 geodata-mode、geox-url、geo-auto-update 与 geo-update-interval,可以把数据源换成自建地址并按小时级周期自动更新,不必手动替换文件。

DNS 与 fake-ip 的实现差异

原版 Clash 的 dns 段只有 nameserver、fallback、fallback-filter、enhanced-mode、fake-ip-range、fake-ip-filter、hosts 这几组开关,所有域名走同一条解析链路,靠 fallback-filter 的 geoip 与 ipcidr 判断结果是否可信。下面是老配置里最常见的写法:

# 原版 Clash 的写法,mihomo 仍能解析,但不推荐继续沿用
dns:
  enable: true
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  nameserver:
    - 223.5.5.5
  fallback:
    - https://1.1.1.1/dns-query
  fallback-filter:
    geoip: true
    ipcidr:
      - 240.0.0.0/4

mihomo 把解析拆成多条链路:default-nameserver 只用来解析 DNS 服务器自身的域名,必须填 IP;proxy-server-nameserver 负责解析代理服务器地址;direct-nameserver 处理直连流量;nameserver-policy 按域名或规则集指定上游。这个拆分解决的是同一个问题——代理服务器的域名用哪条链路解析,直接决定节点能不能连上。

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"
    - "+.stun.*.*"
  default-nameserver:
    - 223.5.5.5
    - 1.1.1.1
  proxy-server-nameserver:
    - https://223.5.5.5/dns-query
  nameserver:
    - https://1.1.1.1/dns-query
    - quic://dns.adguard-dns.com:784
  nameserver-policy:
    "geosite:cn":
      - 223.5.5.5
    "rule-set:reject-list":
      - rcode://refused
  respect-rules: true
  cache-algorithm: arc

两处行为差异值得单独记:fake-ip-filter 在原版 Clash 里只有黑名单语义,mihomo 增加了 fake-ip-filter-mode: whitelist,可以反过来写成只对列表内域名分配假 IP;nameserver-policy 的键支持 geosite: 与 rule-set: 前缀,不必再维护一长串 fallback-filter.domain。另外 respect-rules: true 会让 DNS 查询本身也走 rules 分流,开启前必须先把 proxy-server-nameserver 配好,否则解析请求可能绕回自身形成死循环。

迁移时最容易漏的一项 fallback 与 fallback-filter 在 mihomo 里仍能被解析,不会导致启动失败,所以很多人只改了协议段和 TUN,忘了补 proxy-server-nameserver。典型现象是内核启动正常、日志没有报错、所有节点却一致超时,因为代理服务器域名走了一条不通的解析链路。

TUN 实现与三种网络栈

原版开源 Clash 完全没有 TUN,TUN 只存在于闭源的 Premium 内核里,且可调参数很少。mihomo 把 TUN 做成了配置内的一等公民,字段从设备名、MTU 一直覆盖到 Android 的按包名放行。

tun:
  enable: true
  stack: mixed
  device: mihomo
  mtu: 9000
  auto-route: true
  auto-detect-interface: true
  strict-route: false
  dns-hijack:
    - any:53
  udp-timeout: 300
  endpoint-independent-nat: false
  gso: true
  gso-max-size: 65536

stack 三个取值的取舍:

  • system:数据包交给系统协议栈转发,吞吐最高,代价是依赖系统的路由与防火墙状态,多网卡和 IPv6 环境下更容易出现回环或漏流。
  • gvisor:纯用户态实现,跨平台行为一致,不依赖系统转发,单连接吞吐低于 system,适合路由表复杂或权限受限的环境。
  • mixed:TCP 交给系统栈、UDP 交给 gvisor 栈,是多数客户端的默认值,也是从 gvisor 切到 system 之前可以先跑一轮的中间档。

平台侧的依赖各不相同:Windows 需要 wintun 驱动和系统服务权限,创建虚拟网卡失败时日志里会出现 configure tun interface;macOS 使用 utun 设备,首次启用会请求网络权限;Linux 上 auto-route 会写入路由表,auto-redirect 用 nftables 把流量重定向进 TUN,不再需要手写 iptables 规则;Android 客户端通过 include-package 与 exclude-package 控制哪些应用走 TUN。

TUN 模式下的解析走向 TUN 打开后,dns-hijack 会把发往 53 端口的查询接管给内核 DNS,所以解析走哪条链路由 dns 段决定,与系统 DNS 设置无关。调试阶段把 dns-hijack 写成 any:53,可以避免只劫持 IPv4 造成的解析遗漏。

性能取舍与迁移顺序

规则匹配的开销主要看类型和条数。域名类规则走索引,单条成本很低;DOMAIN-REGEX、PROCESS-NAME-REGEX 是逐条正则匹配,放在 rules 顶部会拖慢每个新连接的首包。连接侧还有几个开关值得按需打开:

  • tcp-concurrent: true —— 对同一域名的多个解析结果并发握手,缩短首包等待,代价是并发连接数上升。
  • unified-delay: true —— 延迟测试统一按完整握手耗时计算,避免不同协议之间的数值不可比。
  • sniffer 段 —— 对 IP 直连的流量还原域名,让域名规则能命中;override-destination 会把目标地址改写成还原出的域名,部分内网场景需要关掉。
  • find-process-mode: strict —— 进程匹配只在新连接建立时查询一次,比 always 更省 CPU。
mixed-port: 7890
allow-lan: false
mode: rule
log-level: warning
ipv6: false
unified-delay: true
tcp-concurrent: true
find-process-mode: strict
external-controller: 127.0.0.1:9090
profile:
  store-selected: true
  store-fake-ip: true
sniffer:
  enable: true
  sniff:
    HTTP:
      ports: [80, 8080-8880]
      override-destination: true
    TLS:
      ports: [443, 8443]
    QUIC:
      ports: [443]

从原版 Clash 迁到 mihomo,顺序可以固定成六步,每一步都能单独验证结果:

  1. 备份旧配置

    把 config.yaml 与 ruleset 目录整体复制一份,记录旧内核的版本串,方便回滚时对照。

  2. 先做语法校验

    用 mihomo -t -f config.yaml -d /etc/mihomo 做一次不启动的解析,unsupported proxy type 会在这一步暴露,不必等到启动后看日志。

  3. 处理协议段

    保留 hysteria2、tuic、vless 节点,逐条核对字段名;ss 节点的 2022-blake3- 加密需要内核版本支持,老版本内核会直接拒绝。

  4. 改写 DNS

    补上 default-nameserver 与 proxy-server-nameserver,把 fallback 列表迁进 nameserver-policy,fake-ip-range 保持 198.18.0.1/16 即可。

  5. 最后再开 TUN

    先确认驱动与服务就绪,stack 从 mixed 起步,dns-hijack 用 any:53,确认路由与解析都正常后再考虑改 system。

  6. 观察连接与规则命中

    打开 external-controller: 127.0.0.1:9090,在面板里看连接列表与规则命中,确认没有流量全部落到 MATCH。

需要留在原版 Clash 的场景也存在:配置文件里只有 ss、vmess、trojan,规则全写在 rules 段,没有 TUN 需求,那么换内核带来的收益有限,改动风险反而更高。是否迁移的判断标准很简单——上面四块里有没有一项用到了 mihomo 独有的写法,有就换,没有就先不动。