V2Ray 自訂路由規則設定:domain、ip、geosite 比對語法與規則順序

整理 domain、full、regexp、geosite、geoip 等比對前綴的用法,說明 routing 規則的由上而下比對順序,以及 domainStrategy 如何影響結果。

本文重點

本文適合需要手動調整分流的使用者。先了解網域、IP 與資料集的比對語法,再透過 routing 範例掌握規則順序、欄位組合與 DNS 解析時機。排查問題時,請以用戶端實際產生的核心設定為準;介面上的「直連」或「代理」名稱,不一定等同於 outboundTag。

1. 路由比對對象與執行順序

V2Ray 的 routing 會根據連線的目標位址、目標連接埠、網路類型與入站標籤等資訊選擇出站。它不是網頁內容過濾器,也不會依 URL 路徑分流。造訪同一網域下的不同頁面,通常不會因此符合不同的網域規則。

本機入站 識別目標 比對規則 選擇出站 建立連線

routing.rules 會依陣列順序由上而下逐一判斷。符合某條規則後,就會依該規則指定的出站處理;後續規則不會再拿來比較「哪條更精確」。因此,精確網域例外通常要放在網域後綴規則之前,具體規則則要放在兜底規則之前。

2. domain、full、regexp 與 geosite 的用法

domain 是規則欄位名稱,domain: 則是該欄位中的一種比對前綴,兩者不要混淆。以下範例一律使用保留示例網域 example.com 說明語法,不代表任何實際服務的分流建議。

項目寫法比對方式注意事項
full:example.com只比對這個完整網域不會一併涵蓋 www.example.com
domain:example.com比對該網域及其子網域涵蓋 api.example.com,不涵蓋 notexample.com
example.com未加前綴時會以子字串比對可能比對到網域名稱中包含此字串的其他名稱
regexp:^api[0-9]+\.example\.com$使用正規表示式比對寫入 JSON 時,反斜線需要再跳脫一次
geosite:cn引用網域資料檔中的 cn 分類分類內容取決於實際載入的資料檔

若要涵蓋某個網站及其子網域,建議使用 domain:example.com,不要只依賴裸字串。若只需處理單一主機名稱,再使用 full:。網域項目不可包含 https://、連接埠、路徑或查詢參數;這些都不是此欄位的輸入格式。

{
  "type": "field",
  "domain": [
    "full:status.example.com",
    "domain:example.net",
    "regexp:^api[0-9]+\\.example\\.com$"
  ],
  "outboundTag": "proxy"
}

這段 JSON 中的三個網域項目彼此為「或」的關係。正規表示式中的 \\. 經 JSON 解碼後才會成為正規表示式需要的 \.;若只寫一個反斜線,設定可能在 JSON 解析階段就失敗。正規表示式須遵循核心使用的 Go 語法,不支援回溯參照或前後查找。

判斷方式:單一網站規則先用 full 或 domain

只有在網域結構確實需要用模式表示時,才使用 regexp。修改後請分別測試主網域、一個子網域,以及一個名稱相似但無關的網域,避免誤把子字串比對當成規則已生效。

3. ip、geoip 與目標連接埠的組合方式

ip 欄位可填入單一 IP、CIDR 網段,以及 geoip: 資料集參照。IPv4 的 /32 代表單一位址;192.0.2.0/24 則是文件範例網段。不要把 CIDR 填入 domain 陣列,也不要在 ip 陣列中加入 https://。

/32
IPv4 單一位址的前綴長度
/128
IPv6 單一位址的前綴長度
443
此範例比對的目標連接埠
{
  "type": "field",
  "ip": [
    "192.0.2.0/24",
    "2001:db8::/32"
  ],
  "port": "443",
  "network": "tcp",
  "outboundTag": "direct"
}

這條規則只會比對目標位址落在兩個示例網段之一、目標連接埠為 443,且網路類型為 TCP 的連線。它不會比對相同位址的 TCP 80,也不會比對 UDP 443。這裡的 port 指目標連接埠,不是用戶端的本機監聽連接埠;若要依標籤區分本機入站,請使用 inboundTag。

4. domainStrategy 決定路由何時解析網域

routing.domainStrategy 控制路由階段如何處理網域目標。它不等同於系統 DNS 設定,也不等同於出站本身名稱相同或相近的設定。即使路由階段沒有解析,後續出站為了連線到伺服器,仍可能需要解析位址。

設定值路由階段的行為常見影響
AsIs依原始目標進行比對,不會為路由額外解析網域只有網域的目標不會因此取得可供 IP 規則比對的解析結果
IPIfNonMatch網域階段沒有規則符合時,才嘗試解析並重新比對若先前的網域規則或一般兜底規則已符合,解析階段可能不會觸發
IPOnDemand比對過程遇到需要判斷 IP 的規則時,嘗試解析網域較前面的 IP 規則可能先於後續網域規則決定結果

一種容易忽略的情況是:使用 IPIfNonMatch,卻在末尾加入符合所有 TCP、UDP 連線的規則。網域請求會直接符合這條兜底規則,因此不能再期待「前面的 geoip 沒符合,接著自動解析並重試」。若要先套用網域規則,再依解析出的 IP 分流,應一併檢查解析策略與兜底方式。

網域優先,未符合時再解析

domainStrategy
IPIfNonMatch
規則起點
明確的網域例外
後續條件
需要額外判斷的 IP 規則
兜底檢查
避免一般規則提早符合

確認所有規則都未符合時,第一個出站就是預期的預設出站。

依規則順序視需要解析

domainStrategy
IPOnDemand
規則起點
需優先保留的網域例外
後續條件
IP 或 geoip 條件
兜底檢查
可在 IP 判斷後明確設定兜底規則

先測試 DNS 是否能取得解析結果,再確認 IP 分類是否符合預期。

如果應用程式交給核心的目標原本就是 IP,路由不需要透過這項設定取得該位址,但此時可能沒有網域資訊。入站嗅探功能可在部分協定中補充網域線索,效果受流量類型與具體設定限制,不能假設啟用後所有連線都能還原網域。

5. 可用來核對規則順序的 routing 範例

以下是設定片段,不是可獨立執行的完整設定。前提是已經有標籤為 proxy、direct 和 block 的出站,分別指向代理、直連與阻斷出站。標籤由設定作者定義,並非核心自動建立的保留名稱。此範例也要求可用的資料檔包含 private 分類。

{
  "routing": {
    "domainStrategy": "IPOnDemand",
    "rules": [
      {
        "type": "field",
        "domain": ["full:status.example.com"],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "domain": ["domain:example.com"],
        "outboundTag": "proxy"
      },
      {
        "type": "field",
        "ip": ["geoip:private"],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "network": "tcp,udp",
        "port": "6881-6889",
        "outboundTag": "block"
      },
      {
        "type": "field",
        "network": "tcp,udp",
        "outboundTag": "proxy"
      }
    ]
  }
}
  1. 精確例外放前面:status.example.com 符合第 1 條後會直連,不會繼續符合第 2 條涵蓋整個網域後綴的規則。
  2. 網站規則放後面:www.example.com 符合第 2 條,選擇 proxy。
  3. 內網位址優先處理:前兩條都未符合時,私有位址可符合第 3 條。若目標是網域,這裡可能會觸發按需解析。
  4. 連接埠規則不是全域封鎖:第 4 條只會處理先前未符合規則的連線。已符合前面網站或私有位址規則的連線,不會再進入這條規則。
  5. 明確兜底放在最後:其餘 TCP、UDP 連線會符合第 5 條。此處使用 IPOnDemand,讓前面的 IP 判斷有機會先執行。

操作方式:將必須全域生效的限制移到前面

若必須優先阻斷連接埠 6881–6889,請將連接埠規則移到網域與私有位址規則之前。調整的是陣列中的位置,而不是替規則加上一個不存在的「優先順序數字」。

使用 geosite:cn 時,可依實際需求新增網域規則,但不要只因分類名稱熟悉就直接涵蓋所有例外。先確認資料檔能正常載入,再判斷這條規則應放在精確網域例外之後、IP 規則之前,或其他位置。資料更新也可能改變分類的比對結果。

6. 從用戶端介面檢查實際生效的設定

v2rayN、v2rayNG、v2flyNG 的介面名稱與路由匯入方式會隨版本變動。排查時,先記下用戶端版本、核心名稱與使用中的路由模式,再找出目前啟用的規則集。不要把訂閱節點中的 VMess、VLESS 連線參數當成路由規則;節點負責定義出站連線,路由則負責選擇出站。

  1. 備份目前規則:先儲存修改前的路由內容。訂閱更新通常用於更新節點,不應視為散布本機自訂路由的一般方式。
  2. 確認請求有進入核心:檢查應用程式是否使用系統代理或指定的本機代理入口。未經入站的請求,不受這些規則控制。
  3. 檢查產生的設定:查看目前 routing.rules 的實際順序,以及 outboundTag 是否與 outbounds[].tag 完全一致。
  4. 套用後重新測試:儲存規則後,依用戶端要求重新載入或重新啟動核心,再建立新連線。瀏覽器重用連線時,舊連線可能仍沿用原本的出站。
  5. 檢查記錄:必要時可暫時使用 info 層級,觀察入站、目標與選用的出站。不同核心的記錄格式不同,不一定會顯示具體規則序號。

建議一次只修改一個條件。先用 full: 確認明確網域能否正確分流,再改用 domain: 擴大範圍,最後加入 geosite 或 geoip 分類。若要查找設定物件的上下文,可搭配設定參考核對入站、出站與 DNS 欄位。

7. 路由規則常見問題

加了網域規則,為什麼還是走原本的節點?

先檢查前面是否已有範圍較廣的規則先行符合。暫時將測試用的 full: 規則移到最前面,重新載入核心並建立新連線。若仍未生效,再確認請求目標是網域還是 IP,以及流量是否確實進入目前使用的用戶端。

geosite 或 geoip 顯示找不到分類,該修改哪裡?

檢查目前核心實際使用的資料檔及其中的分類名稱。geosite: 應放在 domain,geoip: 則應放在 ip。先用單一網域或明確網段確認規則結構,再處理資料資源缺漏;不要反覆修改節點密碼。

同一條規則同時填了 domain 和 ip,為什麼更難符合?

兩個欄位都必須符合,不是二選一。若目的是讓「這個網域或這個網段都直連」,應拆成兩條規則,並分別指定相同的 outboundTag。拆分後再確認網域解析策略是否允許 IP 條件參與判斷。

改成 IPIfNonMatch 後,geoip 還是沒作用?

檢查末尾是否有 network: "tcp,udp" 這類一般比對規則。它可能在網域階段就已符合,導致「未符合後再解析」的流程無法進行。可依需求改為按需解析,或移除過早觸發的兜底規則並檢查預設出站;兩種調整都應重新測試網域與 IP 目標。

下載用戶端