V2Ray 自訂路由規則寫法:domain、ip、geosite 語法與比對優先順序

逐一說明 domain、ip、geosite 三類規則的語法與萬用字元範圍,釐清規則比對順序,並提供可直接套用的分流範例。

本文速覽

適合已完成節點匯入,並希望精確控制直連、代理與封鎖流量的使用者。讀完後可區分完整網域名稱、根網域、關鍵字、CIDR 與 geosite 分類,理解由上而下的首次命中規則,並使用一套包含兜底項目的設定完成驗證。

路由規則究竟處理什麼

V2Ray 或 Xray 的路由模組不會改變節點協定,也不會提升節點本身的頻寬。它會接收連線的目標資訊,再決定將這條連線交給哪個出站。常見的出站標籤有 proxydirectblock,分別代表交由代理節點、直接連線或拒絕連線。標籤名稱可以自訂,但規則中的 outboundTag 必須與出站設定中的 tag 完全一致,包括大小寫。

一次請求可提供的比對資訊不只有網域。目標位址可能還包含 IP、連接埠、網路類型,部分用戶端也能提供程序名稱或入站標籤。本文聚焦於最容易混淆的三類條件:domainipgeosite。其中 geosite 實際上寫在 domain 陣列內,引用的是預先整理好的網域分類,而不是獨立的規則欄位。

應用程式發起請求入站接收連線讀取目標資訊逐條比對規則選擇對應出站

路由判斷的核心是「由上而下,首次命中」。核心會依序讀取規則清單,一旦某條規則的所有條件成立,就使用該規則指定的出站,不再檢查後續規則。因此,同一個網域同時屬於廣告分類與地區分類時,排在前面的封鎖規則會優先於後面的直連規則生效。

規則條件 讀取的資訊 典型用途 關鍵限制
domain 請求目標網域 指定網站直連或代理 目標一開始只有 IP 時無法比對
geosite: 網域分類資料 依地區或用途批次分流 依賴本機分類資料檔案
ip 目標 IP 或解析結果 內網、地區 IP 與網段分流 網域請求是否解析受策略控制
port 目標連接埠 限定 53、80、443 等連接埠 與同一條規則的其他欄位以「且」計算

domain 與 geosite 的寫法差異

domain 陣列支援多種前綴。最穩妥的做法不是把所有位址都寫成普通字串,而是先確認要比對精確主機名稱、整個根網域,還是名稱中包含某段字元的網站。比對範圍過寬,會讓無關網域一併進入同一個出站;範圍過窄,則可能漏掉靜態資源、API 與登入子網域。

完整網域比對

寫法
full:api.example.com
命中
api.example.com
未命中
www.example.com
範圍
單一主機名稱

適合只調整單一 API 網域,不影響同網站的其他子網域。

根網域比對

寫法
domain:example.com
命中
example.com
同時命中
cdn.example.com
範圍
根網域及子網域

適合整個網站統一使用同一個出站,是手寫規則最常用的形式。

關鍵字比對

寫法
example
方式
包含字串
範圍
所有包含該片段的網域
風險
容易擴大命中範圍

只在確實需要模糊比對時使用,短詞應先檢查誤命中的情況。

分類清單比對

寫法
geosite:cn
來源
本機網域分類資料
方式
批次比對項目
維護
隨資料檔案更新

適合大範圍分流,但自訂網域仍應放在分類規則之前。

regexp: 可使用正規表示式,例如 regexp:^([a-z0-9-]+\.)*example\.com$。它可以描述更複雜的主機名稱結構,但維護成本高於 domain:。如果目標只是涵蓋根網域與所有子網域,直接寫 domain:example.com 更清楚,也比較不容易因跳脫錯誤導致規則失效。

geosite:cn 表示引用名稱為 cn 的網域分類,geosite:category-ads-all 通常用於比對廣告相關網域。分類內容來自用戶端使用的資料檔案,規則本身只儲存分類名稱。核心升級後若日誌提示分類不存在,應同步檢查 geosite 資料是否完整,以及分類名稱是否受目前資料版本支援。

{
  "type": "field",
  "domain": [
    "full:api.example.com",
    "domain:static.example.com",
    "geosite:category-ads-all"
  ],
  "outboundTag": "block"
}

ip、CIDR 與 domainStrategy 如何配合

ip 欄位可以寫單一位址、CIDR 網段或 geoip 分類。CIDR 中斜線後的數字代表網路前綴長度,例如 192.168.0.0/16 涵蓋從 192.168.0.0192.168.255.255 的位址;10.0.0.0/8 涵蓋整個以 10 開頭的私有網段。需要處理家用路由器、儲存裝置與區域網路服務時,直接使用 geoip:private 通常比逐條列出網段更省事。

網域請求能否進入 IP 規則,取決於路由的 domainStrategy。設為 AsIs 時,路由模組會依原始目標判斷,網域不會為了 IP 比對而主動解析;設為 IPIfNonMatch 時,網域規則未命中後才解析 IP,並繼續嘗試 IP 規則;設為 IPOnDemand 時,比對過程遇到需要目標 IP 的規則,便可能觸發解析。

  1. 只依網域分流:選擇 AsIs,避免在路由階段產生額外的解析動作。
  2. 網域優先、IP 補漏:選擇 IPIfNonMatch,先讓手寫網域與 geosite 分類決定去向。
  3. 前置規則依賴 IP:再考慮 IPOnDemand,並確認 DNS 設定能回傳可用結果。
  4. 區域網路必須直連:geoip:private 規則放在地區 IP 規則與最終代理兜底之前。
{
  "routing": {
    "domainStrategy": "IPIfNonMatch",
    "rules": [
      {
        "type": "field",
        "ip": [
          "geoip:private",
          "192.168.0.0/16",
          "10.0.0.0/8"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "ip": [
          "geoip:cn"
        ],
        "outboundTag": "direct"
      }
    ]
  }
}

常見錯誤是在同一條規則中同時寫入 domain:example.comgeoip:cn,原意是「網域或地區 IP 任一命中就直連」,實際卻變成「網域屬於 example.com,而且解析結果屬於該 IP 分類才直連」。要表達「或」,應拆成兩條規則,並讓它們指向相同的 outboundTag

結論:網域規則在前,IP 規則負責補漏

先用 full、domain 與 geosite 表達明確意圖,再把 geoip 和 CIDR 放到後面。採用 IPIfNonMatch 後,未命中網域規則的請求才會進入 IP 判斷,規則順序更容易預測。

比對優先順序與可直接套用的規則順序

規則優先順序不是由 domainipgeosite 的類型決定,也不存在「精確規則自動優先於分類規則」的機制。唯一可靠的優先順序就是陣列順序。自訂例外應放在批次分類之前,封鎖規則應放在可能涵蓋它的直連或代理分類之前,最後再加入涵蓋 TCP 與 UDP 的兜底規則。

以下範例依「自訂直連、廣告封鎖、私有位址直連、地區網域直連、地區 IP 直連、其餘代理」排列。實際使用前,應確認出站標籤確實叫做 directblockproxy。若訂閱範本使用其他標籤,只替換標籤值,不要任意改變條件順序。

{
  "routing": {
    "domainStrategy": "IPIfNonMatch",
    "rules": [
      {
        "type": "field",
        "domain": [
          "full:portal.example.com",
          "domain:intranet.example"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "domain": [
          "geosite:category-ads-all"
        ],
        "outboundTag": "block"
      },
      {
        "type": "field",
        "ip": [
          "geoip:private"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "domain": [
          "geosite:cn"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "ip": [
          "geoip:cn"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "network": "tcp,udp",
        "outboundTag": "proxy"
      }
    ]
  }
}
順序 規則用途 放在這裡的原因
1 手寫例外 覆蓋後續分類的預設決定
2 明確封鎖 避免被地區直連分類提前接手
3 私有位址 確保路由器與區域網路裝置直接存取
4 地區網域 優先依網域分類判斷,減少解析依賴
5 地區 IP 處理沒有網域或網域尚未分類的目標
6 最終兜底 為未命中的連線提供明確出口

兜底規則不是每份核心設定都必須手寫,因為未命中的連線也可能進入預設出站;但明確的兜底規則更方便閱讀與移轉。移轉到另一份設定時,看到最後一條就能確定未分類流量的去向,不必再猜測出站陣列中哪個項目排在第一位。

結論:例外必須寫在分類之前

如果某個網站需要強制代理,就把它的 full 或 domain 規則放在 geosite:cn 之前;放在後面時,前面的分類一旦命中,核心就不會繼續讀取這條例外規則。

在 v2rayN 中輸入並驗證規則

以 v2rayN 7.12.x 的桌面介面為例,先開啟「設定」→「路由設定」,複製目前使用中的規則集,再編輯副本。複製而不是直接覆寫,方便發生解析錯誤時立即切回原規則。不同小版本的按鈕位置可能調整,但需要核對的欄位仍是規則順序、網域清單、IP 清單、目標連接埠與出站標籤。

輸入完成後選擇新規則集並重新啟動核心。接著開啟「設定」→「參數設定」,確認本機監聽連接埠。常見的本機連接埠是 10808,但應以目前介面顯示的數值為準;連接埠修改後,測試命令也要同步替換。若系統代理已開啟,可以分別存取一個自訂直連網域、一個代理網域與一個區域網路位址,觀察三類請求是否前往預期的出站。

curl --proxy socks5h://127.0.0.1:10808 https://example.com
curl --proxy socks5h://127.0.0.1:10808 https://www.example.org

socks5h 中的 h 代表讓代理端處理網域解析,這有助於讓核心看見原始網域並執行 domain 或 geosite 規則。如果改用先在本機解析、再將 IP 交給代理的測試方式,日誌可能只會出現目標 IP,此時 domain 規則自然無法命中。

常見異常與定位方法

規則看似正確但結果不符,通常不是語法本身的問題,而是規則未被目前設定啟用、目標資訊與預期不同,或更前面的規則已經命中。排查時不要反覆交換所有規則,應先將問題縮小到一個目標網域,並從日誌確認核心實際接收到的是網域還是 IP。

寫了 domain 規則為什麼沒有命中?

先查看日誌中的目標是否已經變成 IP。若測試工具在本機完成解析,請改用能將網域交給代理的方式;同時確認該規則位於 geosite 分類與最終兜底之前。

geosite 分類提示找不到怎麼辦?

檢查目前核心讀取的資料目錄與 geosite 資料檔案,再確認分類名稱拼寫。更新核心後應同步更新對應資料,接著重新啟動核心以重新載入。

內網站點被送進代理怎麼辦?

在代理兜底前加入 geoip:private 直連規則;若使用自訂網段,再補充實際 CIDR,例如 172.16.0.0/12,並檢查前面是否有更寬泛的強制代理規則。

在同一條規則中寫 domain 和 ip 會更準確嗎?

只有確實要求兩個條件同時成立時才這樣寫。想表達網域或 IP 任一命中,應拆成兩條相鄰規則,並讓兩條規則使用相同的出站標籤。

規則儲存後網頁仍走舊出口?

先確認已選取新規則集,再重新啟動核心並建立新連線。瀏覽器的連線重用會保留舊出口,關閉相關頁面後重新開啟,再查看日誌。

最後進行一次順序檢查:手寫例外是否位於分類之前,封鎖規則是否早於大範圍直連,private 是否早於代理兜底,domainStrategy 是否符合網域優先的設計。只要這四項能直接從設定中讀出,後續新增規則時就不容易破壞既有分流。

  1. 先寫入單一目標的 full: 規則,確認出站標籤有效。
  2. 再擴大為 domain:,驗證根網域與兩個子網域。
  3. 加入 geosite 分類,並將自訂例外保留在分類之前。
  4. 最後啟用 geoip、CIDR 和 TCP/UDP 兜底,逐層觀察日誌。
V2Ray 用戶端下載