適合已能連線至節點、準備調整分流的使用者。本文以 V2Ray / Xray 的核心路由架構為基礎,說明網域後綴、完整網域、IP 網段與分類資料的差異,並提供可逐條推演的規則範例,再介紹如何在 v2rayN 與 v2rayNG 確認實際生效結果。重點不在堆疊規則,而是讓每筆連線都有明確且可驗證的出口。
路由入口:先確認連線已進入核心
系統代理與路由規則負責不同環節。系統代理決定支援代理的應用程式是否將連線送至本機連接埠;核心路由則決定已進入核心的連線要使用哪個出站。如果瀏覽器未使用系統代理,或程式自行直接連線,再準確的 geosite 規則也無法接管這筆連線。TUN 可以擴大接管流量的範圍,但是否啟用 TUN,不會改變規則由上而下比對的基本順序。
v2rayN 是桌面用戶端,負責產生並啟動核心設定;v2rayNG 使用 Xray 核心,v2flyNG 使用 V2Fly 核心。用戶端介面中的路由預設值不等同於協定本身:VMess、VLESS 說明代理連線使用的協定,domain、ip 與 outboundTag 則設定本機分流。更換節點協定,不會自動修正寫錯的網域規則。
domain 寫法:比對網域後綴,不是字串前綴
規則中的 domain 是字串陣列,符合陣列中的任一項即可符合網域條件。字串中的 domain:、full:、regexp: 是比對方式標記。最容易誤解的是 domain::它會比對指定網域及其子網域,不是「網域名稱以這串字元開頭」。
| 規則字串 | 比對方式 | 測試目標 |
|---|---|---|
domain:example.test | 指定網域及其子網域 | 比對 example.test、api.example.test;不比對 notexample.test |
full:api.example.test | 完整網域精確比對 | 比對 api.example.test;不比對 img.api.example.test |
example | 未加標記的子字串比對 | 也可能比對 another-example.test,涵蓋範圍較廣 |
regexp:^api[.]example[.]test$ | 正規表示式比對 | 此寫法限定比對完整網域 |
geosite:cn | 比對資料檔中的 cn 分類 | 實際涵蓋範圍取決於目前的 geosite 資料 |
若要讓某項服務及其所有子網域直連,優先使用 domain:;若只要替單一 API 設定例外,則使用 full:。未加標記的字串適合用於明確掌握比對範圍的關鍵字規則,不適合把短字串當成精確網域。正規表示式語法也受核心所採用的實作限制;複雜的表示式應先測試,不要假設其他工具支援的所有功能都能使用。
{
"type": "field",
"domain": [
"full:api.example.test",
"domain:assets.example.test"
],
"outboundTag": "direct"
}
這條規則會讓指定的 API 或靜態資源網域直連,但不會將整個 example.test 設為直連。將正規表示式放入 JSON 時,也要留意反斜線跳脫:若以 \. 表示句點,JSON 字串中應寫成 \\.。上表使用 [.] 表示句點,可減少因跳脫而寫錯的情況。
ip 與 geoip:位址範圍、分類與條件組合
ip 陣列可包含單一位址、CIDR 網段及 geoip: 分類。CIDR 斜線後的數字代表網路前綴長度:192.168.0.0/16 表示這個私有位址範圍,不是只比對一個區域網路位址;IPv6 也可以寫成 fc00::/7。分類比對仰賴核心能讀取 GeoIP 資料。
以上位址總數包含網段中的所有位址,不等於可指派給主機的數量。geoip:private 常用於區域網路與特殊本機位址的分流;geoip:cn 則用於比對資料檔標記為中國的 IP 範圍。後者不代表中文網站,也不保證與網域分類完全一致。同一個網域可能使用不同地區的 CDN 位址,位址分類也會隨 DNS 解析結果改變。
{
"type": "field",
"ip": ["192.168.0.0/16"],
"port": "443",
"network": "tcp",
"outboundTag": "direct"
}
重點:同一條規則中的不同欄位須同時符合
上方規則要求目標 IP 位於指定網段、目標連接埠為 443,且網路類型為 TCP,三項條件都成立才會直連。若要設定「指定網域或指定 IP 直連」,應拆成兩條規則;將 domain 與 ip 填在同一條規則中,不會產生二選一的效果。
geosite 與 domainStrategy:網域分類及解析時機
geosite:cn 是資料檔中的分類名稱,不是線上搜尋指令。核心必須能讀取包含該分類的 geosite.dat。不同來源的資料可能包含不同標籤,更新節點訂閱也不代表分類檔已更新。若啟動記錄顯示「找不到分類」或「無法讀取資料檔」,應先修復資源,再檢查規則順序。
優先比對網域,不另外解析
- 欄位位置
routing.domainStrategy- 設定值
AsIs- 網域連線
- 直接比對網域規則
- IP 條件
- 不會因路由比對而主動解析網域
適合希望主要依明確網域規則決定出口的設定;但出站連線本身仍可能需要解析網域。
網域未符合規則時,再比對 IP
- 欄位位置
routing.domainStrategy- 設定值
IPIfNonMatch- 解析觸發時機
- 首次路由比對未符合任何規則
- 後續處理
- 解析後以位址再次參與比對
適合在網域分類之外,使用 IP 分類補充分流;但必須保留首次比對未命中的機會。
另一個常見設定值是 IPOnDemand:比對過程中遇到需要 IP 的規則時,就可能觸發解析。因此,排在前面的 IP 規則可能會在後面的網域例外之前命中。它與 IPIfNonMatch 的主要差異在觸發時機,而不是哪個選項「比較強」。
這裡指的是 routing 下的 domainStrategy。DNS 模組的查詢策略,以及直連出站的網域策略,都不是同一項設定。路由解析只提供比對依據,無法單獨確保 DNS 查詢使用指定出口;DNS 伺服器的連線狀況、解析路徑及應用程式本身的解析方式,都需要另外檢查。
比對優先順序:具體例外優先,範圍規則其次
核心會依照 rules 陣列由上而下逐條比對,第一條符合條件的規則就會決定路由,不會因為後面的網域名稱較長就自動改用該規則。換句話說,「更具體」只是手動安排順序的依據,並非核心自動計算的優先權。規則中的標籤必須指向已定義的出站;若沒有任何規則符合,通常會使用 outbounds 陣列中的第一個出站,而不是自動選擇名為 proxy 的標籤。
- 特定服務例外:先放置明確需要代理或直連的完整網域、小範圍後綴及特定網段。
- 區域網路保護:接著處理私有位址,避免本機裝置的連線預設送往代理;若企業內網有特殊出口,應先設定更具體的例外。
- 分類規則:再加入 geosite、geoip 等涵蓋範圍較大的分流條件。
- 兜底處理:最後明確指定其餘連線的去向,並確認兜底規則是否會改變解析策略的觸發條件。
以下是 routing 設定片段:api.example.test 單獨走代理,同一父網域的其他連線直連,私有位址與中國分類直連,其餘 TCP / UDP 連線走代理。採用 IPOnDemand,是為了讓未涵蓋於網域分類的連線,仍能在 IP 規則處取得解析結果。此片段必須合併至現有核心設定,不能當成完整設定檔直接啟動。
{
"routing": {
"domainStrategy": "IPOnDemand",
"rules": [
{
"type": "field",
"domain": ["full:api.example.test"],
"outboundTag": "proxy"
},
{
"type": "field",
"domain": ["domain:example.test"],
"outboundTag": "direct"
},
{
"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"
}
]
}
}
| 輸入條件 | 命中規則 | 出口 |
|---|---|---|
| 網域 api.example.test | 第 1 條完整網域規則 | proxy |
| 網域 img.example.test | 第 2 條網域後綴規則 | direct |
| 目標 IP 為 192.168.1.10 | 第 3 條私有位址規則 | direct |
| 網域不屬於前述分類,解析後的 IP 符合 geoip:cn | 第 5 條 IP 分類規則 | direct |
| 其他未命中的 TCP 連線 | 第 6 條兜底規則 | proxy |
將第 2 條移到第 1 條前面後,api.example.test 會先符合父網域規則,結果改為直連。若將兜底規則移到陣列最前面,後續規則幾乎就不會生效。排查衝突時,應依照實際目標從第一條開始推演,而不是只檢查原本預期會命中的規則。
用戶端設定:檢查產生的設定,再進行最小化測試
在 v2rayN 中,可從「設定」→「路由設定」檢查目前的路由設定;選單名稱可能因版本而異。請確認編輯的是目前啟用的設定,而非其他未選取的預設值。在「設定」→「參數設定」中確認本機監聽連接埠;以下測試假設 SOCKS 監聽於 127.0.0.1:10808,若實際值不同請替換。範例連接埠不一定是所有版本的固定預設值。
- 備份目前規則。記下目前使用的核心、路由預設值、網域策略與出站標籤,先只新增一條容易辨識的網域例外。
- 儲存並重新套用。依照目前用戶端的流程重新啟動核心或重新連線,讓設定重新產生;只儲存編輯視窗的內容,不一定會切換正在使用的設定。
- 檢查執行記錄。先排除 JSON 解析失敗、分類缺漏、出站標籤不存在及監聽連接埠遭占用等問題。必要時可暫時提高記錄層級,測試完成後再恢復。
- 核對實際目標。查看連線記錄或存取記錄中的目標網域、目標 IP 與出站標籤;記錄格式取決於核心與記錄層級。
- 再擴大規則範圍。確認單一例外生效後,再加入 geosite / geoip 分類與兜底規則,避免一次修改多項設定而難以找出問題。
curl --socks5-hostname 127.0.0.1:10808 \
--connect-timeout 10 \
--max-time 20 \
-I https://v2rayworld.com/
--socks5-hostname 會將目標網域交由 SOCKS 端處理,有助於驗證網域規則;--socks5 通常會先在本機解析,核心收到的可能是 IP。這裡設定的 10 秒連線逾時與 20 秒總逾時,是為了限制測試等待時間,並非延遲或速度的實測數據。HTTP 要求成功只能證明這次連線可用;是否命中指定規則,還須查看出站記錄。
在 v2rayNG 中,先檢查目前的路由模式,再進入「設定」中對應的路由設定頁面;不同版本的選單層級可能不同。Android VPN 接管範圍也可能受應用程式代理範圍影響,測試用瀏覽器必須包含在接管範圍內。v2flyNG 的核心功能與資源檔案,應依照實際使用的 V2Fly 設定確認,不能直接照搬 Xray 專用欄位。本文提到的基本 field 規則,仍應以目前核心的啟動結果為準。
常見問題:網域未命中、分類錯誤與規則遭覆蓋
網域規則寫對了,為什麼還是命中 IP 規則?
先確認入站收到的是網域還是 IP。使用上方的 --socks5-hostname 測試進行對照;若應用程式已自行解析,網域規則可能沒有可供比對的依據。嗅探可從部分 HTTP / TLS 流量擷取網域,但不是所有連線都能擷取,也不能視為穩定涵蓋所有流量的補救方法。
geosite:cn 一儲存就無法啟動,該怎麼辦?
查看核心記錄是否顯示找不到 geosite 檔案或 cn 分類不存在。檢查資源檔案位置、讀取權限,以及用戶端使用的資料來源;先還原備份規則,讓核心順利啟動,再透過用戶端提供的資源更新功能處理資料。不要為了掩蓋資源錯誤而刪除所有路由規則。
加入 domain 和 ip 後,直連範圍反而變小了?
確認是否將兩種條件寫在同一條 field 規則中。若要表達「符合網域或符合位址」,請拆成兩條規則,並分別指定相同出口。同一條規則中的兩個欄位必須同時符合;網域連線是否符合 IP 條件,也會受到解析策略影響。
修改核心設定後,下次連線又恢復原狀?
用戶端可能會在啟動時重新產生暫存的核心設定。請在目前的路由預設值或用戶端支援的自訂設定入口修改,而不是只編輯執行期間的暫存檔。儲存後重新套用,再確認產生的 rules 順序,並檢查是否遭預設規則覆蓋。
最終檢查順序可固定為:連線是否進入核心、目標是否包含網域、分類資源是否可讀、規則排序是否符合預期,以及出站標籤是否有效。瀏覽器可能沿用既有連線,修改後應重新發出要求或重啟測試用應用程式。確認命中結果後,再分別測試一般網域、區域網路 IP 與未分類目標,避免只測試一個網站就認定整套分流設定正確。