適合已完成節點匯入,並希望精確控制直連、代理與封鎖流量的使用者。讀完後可區分完整網域名稱、根網域、關鍵字、CIDR 與 geosite 分類,理解由上而下的首次命中規則,並使用一套包含兜底項目的設定完成驗證。
路由規則究竟處理什麼
V2Ray 或 Xray 的路由模組不會改變節點協定,也不會提升節點本身的頻寬。它會接收連線的目標資訊,再決定將這條連線交給哪個出站。常見的出站標籤有 proxy、direct 與 block,分別代表交由代理節點、直接連線或拒絕連線。標籤名稱可以自訂,但規則中的 outboundTag 必須與出站設定中的 tag 完全一致,包括大小寫。
一次請求可提供的比對資訊不只有網域。目標位址可能還包含 IP、連接埠、網路類型,部分用戶端也能提供程序名稱或入站標籤。本文聚焦於最容易混淆的三類條件:domain、ip 與 geosite。其中 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.0 到 192.168.255.255 的位址;10.0.0.0/8 涵蓋整個以 10 開頭的私有網段。需要處理家用路由器、儲存裝置與區域網路服務時,直接使用 geoip:private 通常比逐條列出網段更省事。
網域請求能否進入 IP 規則,取決於路由的 domainStrategy。設為 AsIs 時,路由模組會依原始目標判斷,網域不會為了 IP 比對而主動解析;設為 IPIfNonMatch 時,網域規則未命中後才解析 IP,並繼續嘗試 IP 規則;設為 IPOnDemand 時,比對過程遇到需要目標 IP 的規則,便可能觸發解析。
- 只依網域分流:選擇
AsIs,避免在路由階段產生額外的解析動作。 - 網域優先、IP 補漏:選擇
IPIfNonMatch,先讓手寫網域與 geosite 分類決定去向。 - 前置規則依賴 IP:再考慮
IPOnDemand,並確認 DNS 設定能回傳可用結果。 - 區域網路必須直連:將
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.com 和 geoip:cn,原意是「網域或地區 IP 任一命中就直連」,實際卻變成「網域屬於 example.com,而且解析結果屬於該 IP 分類才直連」。要表達「或」,應拆成兩條規則,並讓它們指向相同的 outboundTag。
結論:網域規則在前,IP 規則負責補漏
先用 full、domain 與 geosite 表達明確意圖,再把 geoip 和 CIDR 放到後面。採用 IPIfNonMatch 後,未命中網域規則的請求才會進入 IP 判斷,規則順序更容易預測。
比對優先順序與可直接套用的規則順序
規則優先順序不是由 domain、ip 或 geosite 的類型決定,也不存在「精確規則自動優先於分類規則」的機制。唯一可靠的優先順序就是陣列順序。自訂例外應放在批次分類之前,封鎖規則應放在可能涵蓋它的直連或代理分類之前,最後再加入涵蓋 TCP 與 UDP 的兜底規則。
以下範例依「自訂直連、廣告封鎖、私有位址直連、地區網域直連、地區 IP 直連、其餘代理」排列。實際使用前,應確認出站標籤確實叫做 direct、block 和 proxy。若訂閱範本使用其他標籤,只替換標籤值,不要任意改變條件順序。
{
"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,但應以目前介面顯示的數值為準;連接埠修改後,測試命令也要同步替換。若系統代理已開啟,可以分別存取一個自訂直連網域、一個代理網域與一個區域網路位址,觀察三類請求是否前往預期的出站。
- 準備 4 類測試目標:自訂例外、geosite 分類、IP 網段與未分類網域。
- 每類連續測試 3 次,共記錄 12 條請求,排除快取或偶發解析失敗。
- 在即時日誌中核對目標位址、命中的出站標籤與失敗原因。
- 修改規則後重新啟動核心,不要使用舊連線判斷新規則是否生效。
- 測試區域網路時直接填入裝置 IP,例如
192.168.1.1,確認它命中 private 直連規則。
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 是否符合網域優先的設計。只要這四項能直接從設定中讀出,後續新增規則時就不容易破壞既有分流。
- 先寫入單一目標的
full:規則,確認出站標籤有效。 - 再擴大為
domain:,驗證根網域與兩個子網域。 - 加入 geosite 分類,並將自訂例外保留在分類之前。
- 最後啟用 geoip、CIDR 和 TCP/UDP 兜底,逐層觀察日誌。