兩個內核的版本現況與血緣

原版 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 獨有的寫法,有就換,沒有就先不動。