Clash 自訂規則寫法詳解:比對順序、優先權與 MATCH 兜底
Clash 的分流行為完全由 rules 清單決定,而多數設定問題並非規則類型用錯,而是順序與優先權理解有偏差。本文逐條拆解自訂規則的語法結構,說明核心自上而下、命中即停的比對機制,釐清自訂規則與訂閱規則的先後關係,並給出 MATCH 兜底規則的正確寫法與常見失效原因。
規則如何驅動分流
Clash 核心每接到一個連線,都會取出它的目標位址、通訊埠與來源特徵,再拿這些資訊逐條比對設定檔中的 rules 清單。清單裡第一條命中的規則決定這個連線的去向:交給某個代理節點、某個策略群組、內建的 DIRECT 直連,或是 REJECT 拒絕。判定在命中的那一刻完成,排在後面的規則不再參與。
因此,rules 清單是 Clash 分流唯一的事實來源。無論設定來自訂閱連結、用戶端的覆寫功能還是手動編輯,最終都要落成這一段逐行排列的規則。實務上規則類型用錯的情況並不多,絕大多數分流結果偏離預期,根源都在順序:一條較寬泛的規則排在前面,把本該由後面精確規則處理的流量提前截走。看懂比對順序,比背熟規則類型更重要。
無論流量是從系統代理、TUN 模式還是混合埠進入核心,比對的都是同一份 rules 清單,順序機制完全一致。
單條規則的語法結構
一條規則由逗號分隔的若干段組成,完整形態為四段,大多數類型只用前三段:
類型,負載,策略[,附加參數]
- 類型:從哪個維度比對,例如 DOMAIN、DOMAIN-SUFFIX、IP-CIDR、GEOIP。
- 負載:比對的具體內容,例如一個網域名稱、一個字尾、一段網段或一個國家代碼。
- 策略:命中後交給誰。可以是內建策略 DIRECT、REJECT,也可以是 proxies 或 proxy-groups 中定義過的節點名稱、策略群組名稱。
- 附加參數:目前只有 no-resolve,僅供 IP 類規則使用,後文會單獨說明。
書寫層面有四條硬性約束。其一,規則集中在設定檔的 rules 段內,YAML 格式下每條以短橫線起行。其二,策略名稱必須與設定中定義的名稱逐字一致,含大小寫與空格,寫錯會使整份設定載入失敗。其三,網域名稱負載一律小寫,不帶協定頭、不帶路徑,帶 http:// 前綴的寫法永遠不會命中。其四,井號起行的是註解,核心不會解析。
rules:
- DOMAIN,update.example.com,DIRECT
- DOMAIN-SUFFIX,example.com,Proxy
- DOMAIN-KEYWORD,tracker,REJECT
- IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
- GEOIP,CN,DIRECT
- MATCH,Proxy
常用規則類型對照
下表收錄自訂規則中最常見的類型。GEOSITE、PROCESS-NAME 等僅 mihomo 核心提供,原版 Clash Premium 不支援,混用會導致設定無法載入。
| 類型 | 負載範例 | 比對行為 |
|---|---|---|
| DOMAIN | www.example.com | 精確比對該網域名稱,不含子網域 |
| DOMAIN-SUFFIX | example.com | 比對該網域及其全部子網域 |
| DOMAIN-KEYWORD | tracker | 網域名稱中含該關鍵字即命中 |
| GEOSITE | cn | 比對網域名稱分類清單,僅 mihomo 核心支援 |
| IP-CIDR | 10.0.0.0/8 | 比對 IPv4 網段 |
| IP-CIDR6 | fd00::/8 | 比對 IPv6 網段 |
| GEOIP | CN | 依 IP 歸屬地比對 |
| DST-PORT | 443 | 依目標埠比對 |
| SRC-PORT | 7891 | 依來源埠比對 |
| PROCESS-NAME | curl.exe | 依處理程序名稱比對,限桌面平台 |
| RULE-SET | adblock | 引用 rule-providers 託管的規則集 |
| MATCH | 無負載 | 比對全部剩餘流量,置於末尾 |
體量較大的清單不宜逐行寫進 rules。數萬行的廣告網域或站點分類應交給 rule-providers 託管,rules 中只用一條 RULE-SET,清單名,策略 引用;核心按 interval 週期自動更新清單,條目再多也只佔一個比對位,載入與維護都更省力。
比對順序:自上而下,命中即停
核心處理每個連線時,從 rules 清單第一行開始向下逐條比對,第一條命中的規則立即生效,比對隨即終止。由這個機制可以推出三條直接結論:
- 精確規則必須排在寬泛規則之前。若希望 update.example.com 直連、example.com 其餘子網域走代理,DOMAIN 條目要寫在 DOMAIN-SUFFIX 條目上方;次序顛倒後,字尾條目會先把流量收走,精確條目永遠沒有出場機會。
- 後寫的規則不能覆蓋先寫的規則。Clash 沒有後來者居上的層疊邏輯,先命中先生效,調整優先權的唯一手段是調整行序。
- 自訂規則與訂閱規則的先後,取決於兩者在最終生效清單中的相對位置。多數圖形用戶端的覆寫功能會把自訂規則插入訂閱規則之前,使其優先命中;若用戶端把自訂條目附加在訂閱規則之後,而訂閱裡已有更寬泛的條目,自訂條目就可能永遠排不到。
排查規則寫了卻不生效時,第一步是打開用戶端顯示的最終 rules 清單,確認該條目實際落在第幾行,而不是反覆檢查語法。
IP 類規則與 no-resolve 參數
網域名稱類規則直接比對連線攜帶的網域名稱,IP-CIDR 與 GEOIP 則需要 IP 才能比對。連線目標是網域名稱時,核心必須先做一次 DNS 解析,拿到結果後才能繼續判斷。也就是說,只要清單裡存在 IP 類規則,每個未被前文網域名稱規則攔截的連線都可能多觸發一次解析,不僅增加延遲,也擴大 DNS 查詢的暴露面。
no-resolve 用來關閉這個行為。帶 no-resolve 的 IP 規則,只在目標本身就是 IP 字面量時參與比對,核心不會為了它去解析網域名稱:
IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
GEOIP,CN,DIRECT,no-resolve
內網網段、區域網路裝置這類純 IP 場景,建議一律附加 no-resolve。反過來,依賴先解析、再按歸屬地分流的 GEOIP 規則不能加這個參數,否則以網域名稱發起的連線會直接從它身邊滑過,落進後面的條目。
MATCH 兜底規則
MATCH 是唯一沒有負載的規則類型,寫法只有兩段:MATCH,策略。它比對一切尚未被前文規則命中的連線,使用上有三條紀律:必須放在 rules 清單的最後一行;一份設定只需要一條 MATCH;建議始終顯式寫出,而不是依賴核心的預設走向。
寫在中間的 MATCH 會攔截全部剩餘流量,其後的規則全部變成死行,這是自訂規則中最常見、也最難察覺的錯誤。mihomo 對未命中流量預設直連,但顯式的 MATCH 讓最終走向確定、可讀,日後維護時不必猜測核心行為。
兩種常見取向:MATCH,Proxy 表示凡是沒有特別交代的流量一律走代理,搭配前面的直連例外,屬於黑名單式寫法;MATCH,DIRECT 表示只有清單明確放行的流量走代理,其餘全部直連,屬於白名單式寫法,適合僅少數站點需要代理的場景。
完整範例與命中驗證
把前面的要點合在一起,一份典型的自訂 rules 段如下:
rules:
# 本地與內網:字尾 .lan 與內網網段直連
- DOMAIN-SUFFIX,lan,DIRECT
- IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
# 廣告與追蹤:關鍵字命中即拒絕
- DOMAIN-KEYWORD,tracker,REJECT
# 精確例外:更新伺服器直連
- DOMAIN,update.example.com,DIRECT
# 其餘 example.com 子網域走代理
- DOMAIN-SUFFIX,example.com,Proxy
# 台灣本地位址按歸屬地直連
- GEOIP,CN,DIRECT
# 兜底:剩餘流量走代理
- MATCH,Proxy
注意範例中的 GEOIP 條目未附加 no-resolve:以網域名稱發起、且未被前面條目攔截的連線,會在這裡觸發一次解析再按歸屬地判斷。若希望完全避免這類解析,可改用 GEOSITE 類別清單在網域名稱階段完成分流,把 GEOIP 留給純 IP 連線並加上 no-resolve。
規則是否符合預期,不需要靠猜。圖形用戶端的連線面板,例如 Clash Verge Rev 的連線頁、各類 Dashboard 的 Connections,會即時列出每個連線命中的具體規則與策略;命令列場景把日誌等級設為 info,核心會逐條印出命中記錄。發現結果與預期不符時,按面板顯示的規則名稱回到清單核對行序,問題通常立刻現形。
- MATCH 未置於末行,其後的規則全部失效。
- 精確規則排在寬泛的字尾規則之後,永遠不會命中。
- 策略名稱與 proxies、proxy-groups 中的定義不一致,設定載入時報錯。
- 網域名稱負載帶協定頭或路徑,比對失敗。
- 自訂條目被用戶端附加在訂閱規則之後,被更寬泛的訂閱條目搶先命中。
- 指望後寫的規則覆蓋先寫的規則,Clash 沒有這種層疊機制。