本文適合需要手動調整分流的使用者。先了解網域、IP 與資料集的比對語法,再透過 routing 範例掌握規則順序、欄位組合與 DNS 解析時機。排查問題時,請以用戶端實際產生的核心設定為準;介面上的「直連」或「代理」名稱,不一定等同於 outboundTag。
1. 路由比對對象與執行順序
V2Ray 的 routing 會根據連線的目標位址、目標連接埠、網路類型與入站標籤等資訊選擇出站。它不是網頁內容過濾器,也不會依 URL 路徑分流。造訪同一網域下的不同頁面,通常不會因此符合不同的網域規則。
routing.rules 會依陣列順序由上而下逐一判斷。符合某條規則後,就會依該規則指定的出站處理;後續規則不會再拿來比較「哪條更精確」。因此,精確網域例外通常要放在網域後綴規則之前,具體規則則要放在兜底規則之前。
- 規則之間:由最先符合的規則決定結果,不會自動依網域長度、前綴類型或網段大小排序。
- 同一欄位內:例如
domain陣列中的多個項目,只要符合其中一個即可。 - 不同條件欄位之間:例如同時填入
domain和port,兩者都必須符合。把domain和ip放在同一條規則中,不代表「網域或 IP」擇一符合。 - 全部都未符合:在沒有設定其他路由機制的一般設定中,會使用
outbounds陣列中的第一個出站。結果不一定是直連。
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://。
{
"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。
geoip:private常用於私有及本機位址範圍的分流,實際涵蓋範圍取決於載入的資料檔。geoip:cn是 IP 分類參照;geosite:cn是網域分類參照,兩者不可互換。- 網域分類與 IP 分類的結果不一定一致。同一網域可能解析至不同地區的 CDN 位址。
- 只填 IPv4 網段不會涵蓋 IPv6 連線。雙堆疊環境應同時檢查實際使用的位址類型。
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"
}
]
}
}
- 精確例外放前面:
status.example.com符合第 1 條後會直連,不會繼續符合第 2 條涵蓋整個網域後綴的規則。 - 網站規則放後面:
www.example.com符合第 2 條,選擇proxy。 - 內網位址優先處理:前兩條都未符合時,私有位址可符合第 3 條。若目標是網域,這裡可能會觸發按需解析。
- 連接埠規則不是全域封鎖:第 4 條只會處理先前未符合規則的連線。已符合前面網站或私有位址規則的連線,不會再進入這條規則。
- 明確兜底放在最後:其餘 TCP、UDP 連線會符合第 5 條。此處使用
IPOnDemand,讓前面的 IP 判斷有機會先執行。
操作方式:將必須全域生效的限制移到前面
若必須優先阻斷連接埠 6881–6889,請將連接埠規則移到網域與私有位址規則之前。調整的是陣列中的位置,而不是替規則加上一個不存在的「優先順序數字」。
使用 geosite:cn 時,可依實際需求新增網域規則,但不要只因分類名稱熟悉就直接涵蓋所有例外。先確認資料檔能正常載入,再判斷這條規則應放在精確網域例外之後、IP 規則之前,或其他位置。資料更新也可能改變分類的比對結果。
6. 從用戶端介面檢查實際生效的設定
v2rayN、v2rayNG、v2flyNG 的介面名稱與路由匯入方式會隨版本變動。排查時,先記下用戶端版本、核心名稱與使用中的路由模式,再找出目前啟用的規則集。不要把訂閱節點中的 VMess、VLESS 連線參數當成路由規則;節點負責定義出站連線,路由則負責選擇出站。
- 備份目前規則:先儲存修改前的路由內容。訂閱更新通常用於更新節點,不應視為散布本機自訂路由的一般方式。
- 確認請求有進入核心:檢查應用程式是否使用系統代理或指定的本機代理入口。未經入站的請求,不受這些規則控制。
- 檢查產生的設定:查看目前
routing.rules的實際順序,以及outboundTag是否與outbounds[].tag完全一致。 - 套用後重新測試:儲存規則後,依用戶端要求重新載入或重新啟動核心,再建立新連線。瀏覽器重用連線時,舊連線可能仍沿用原本的出站。
- 檢查記錄:必要時可暫時使用
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 目標。