自訂分流先確認規則順序,再檢查比對條件,最後確認 DNS 策略。本文適合已能正常連線至節點、需要新增網站例外規則的使用者,說明 V2Ray 與 Xray 常見的 field 路由寫法,以及如何在 v2rayN 中設定與驗證。範例使用保留的示範網域與文件位址,不代表實際網站分類。
一、路由規則先比對條件,再選擇出站
路由不是節點連線參數。VMess、VLESS 等協定負責連線至伺服器;路由則決定進入核心的請求要交由哪個出站處理。v2rayN 是設定介面,實際執行規則的是目前執行中的核心。下文使用 V2Ray/Xray 的 JSON 語法,不能直接貼到其他設定格式的編輯器。
常見規則包含 type: "field"、比對欄位與 outboundTag。標籤必須對應現有出站的 tag。將標籤設為 proxy 不會自動建立代理節點,設為 direct 也不會自動建立直連出站。用戶端產生的標籤可能不同,修改前請先確認實際設定。
這些連接埠是請求的目標連接埠,不是用戶端的本機監聽連接埠。例如,下方規則只會將目標連接埠為 443、且網域屬於 example.com 的請求交由代理出站處理,不會涵蓋該網域的所有連線。
{
"type": "field",
"domain": ["domain:example.com"],
"port": "443",
"outboundTag": "proxy"
}
- 同一欄位內通常是「或」:
domain陣列中只要有任一項符合,就符合網域條件。 - 不同欄位之間是「且」:同時填入
domain和port,兩者都必須符合。 - 規則依序比對:遇到第一條完全符合的規則後,就會選定出站,不再繼續尋找更精確的規則。
二、domain、full、regexp:網域比對範圍
需要涵蓋主網域及所有子網域時,使用 domain:;只允許特定完整主機名稱時,使用 full:。不要只因規則名稱都含有「網域」,就認為兩者相同。網域欄位填寫的是主機名稱,不是網頁網址,不應包含通訊協定、路徑或查詢參數。
| 規則寫法 | 比對範圍 | 容易混淆的邊界 |
|---|---|---|
domain:example.com | example.com 及其子網域,例如 api.example.com | 不符合 notexample.com,也不符合 example.com.test |
full:example.com | 僅限 example.com | 不符合 www.example.com |
example | 網域中包含這段字串 | 可能符合 unrelated-example.test,不適合用於精確的網站例外規則 |
regexp:^api[0-9]+\.example\.com$ | 例如 api1.example.com、api25.example.com | 需要加上開頭與結尾錨點;寫入 JSON 時,反斜線也必須跳脫 |
只有確實需要比對模式時才使用正規表示式。下例在 JSON 字串中將反斜線寫了兩次,因此核心收到的正規表示式才會包含用於比對字面句點的 \.。如果介面欄位接收的是原始規則文字,而非 JSON 字串,就不需要這層 JSON 跳脫。
{
"type": "field",
"domain": [
"full:login.example.com",
"regexp:^api[0-9]+\\.example\\.com$"
],
"outboundTag": "proxy"
}
結論:單一網站例外先用 full
只想調整某個登入主機時,先新增完整主機名稱規則並進行驗證;確認所有子網域都需要使用相同出口後,再擴大為 domain 規則,避免連帶改變靜態資源及其他服務的出口。
三、ip、geoip、geosite:分開設定位址與網域集合
ip 是 JSON 欄位,geoip: 是可放入該欄位陣列的集合參照;geosite: 則放在 domain 陣列中。這兩類集合都依賴核心可讀取的對應資料檔。集合名稱及內容由資料檔決定,不是核心依名稱即時產生。
{
"type": "field",
"domain": ["geosite:cn"],
"outboundTag": "direct"
}
{
"type": "field",
"ip": [
"192.0.2.15/32",
"2001:db8::15/128",
"geoip:private",
"geoip:cn"
],
"outboundTag": "direct"
}
上方的 192.0.2.15 與 2001:db8::15 是文件示範位址,實際使用時請替換成目標服務的位址。IPv4 的 /32 和 IPv6 的 /128 都代表單一位址;網段前綴越短,涵蓋範圍通常越大。不要只為了解決單一位址的連線問題,就直接加入涵蓋整個大型網段的規則。
- geosite:cn:依資料集中的網域分類進行比對,但不保證該網域的所有解析結果都位於同一地區。
- geoip:cn:依目標 IP 是否屬於該位址集合進行比對,但不保證該位址承載的網站屬於特定網域分類。
- geoip:private:用於比對資料集中定義的私人及保留位址範圍,常見用途是讓本機資源直連。
- 找不到集合:若啟動記錄顯示無法載入 geosite 或 geoip,請先檢查資料檔及項目名稱,不要當成節點故障處理。
四、比對優先順序:例外規則必須排在寬泛規則之前
核心不會自動判斷「完整網域比網域集合更精確」。規則會依照 rules 陣列由上往下執行。如果第一條已使用 domain:example.com 設為直連,後面的 full:api.example.com 代理規則就沒有機會覆蓋它。正確順序是先放例外,再放涵蓋範圍較大的集合,最後放兜底規則。
以下是可合併至現有設定的 routing 片段,不是完整的用戶端設定。前提是現有 outbounds 中已有 proxy 和 direct 這兩個標籤,且具備所參照的資料集合。若實際使用的標籤不同,請先統一標籤,不能只複製規則而忽略出站設定。
{
"routing": {
"domainStrategy": "IPOnDemand",
"rules": [
{
"type": "field",
"domain": ["full:api.example.com"],
"outboundTag": "proxy"
},
{
"type": "field",
"domain": ["domain:example.com", "geosite:cn"],
"outboundTag": "direct"
},
{
"type": "field",
"ip": ["geoip:private", "geoip:cn"],
"outboundTag": "direct"
},
{
"type": "field",
"network": "tcp,udp",
"outboundTag": "proxy"
}
]
}
}
| 測試目標 | 首次符合規則 | 預期出站 |
|---|---|---|
| api.example.com:443 | 第 1 條:完整網域例外 | proxy |
| www.example.com:443 | 第 2 條:主網域及子網域規則 | direct |
| 192.168.1.20:80 | 第 3 條:私人位址集合 | direct |
| 未符合上述集合的公開網路目標 | 第 4 條:TCP/UDP 兜底 | proxy |
表格是設定推演,不是網路速度測試結果。示範網域不保證提供實際服務,驗證網頁時請改用已知可正常連線的目標。如果移除最後一條兜底規則,未符合任何規則的請求通常會使用設定中的第一個出站;因此不能脫離完整設定,籠統地說「未符合規則就一定走代理」或「一定直連」。
五、domainStrategy:為什麼 IP 規則沒有生效
請求進入核心時,目標可能是網域,也可能已經是 IP。只有位址的請求,不會因為新增網域規則就自動還原成原始網域。反過來說,只有網域的請求若要符合 ip 條件,通常需要路由解析策略提供位址資訊。這就是為什麼需要另外檢查 domainStrategy。
| 策略 | 路由階段的行為 | 設定注意事項 |
|---|---|---|
AsIs | 不會為路由比對主動將目標網域解析為 IP | 目標原本是 IP 時仍可符合 IP 規則;這不代表出站永遠不會解析網域 |
IPIfNonMatch | 網域在第一輪沒有符合任何規則時,嘗試解析後再次比對 | 若第一輪已符合無條件兜底規則,就不會觸發這次補充解析 |
IPOnDemand | 比對過程遇到需要 IP 的規則時,嘗試解析目標網域 | 可能增加 DNS 查詢;也應考量解析延遲及 DNS 出口 |
上一節使用 IPOnDemand,是為了讓第三條位址集合規則能在最後的兜底規則之前參與判斷。如果直接改成 IPIfNonMatch,網域請求可能先符合第四條寬泛規則,導致預期的位址分流沒有生效。這不是 geoip 寫法錯誤,而是觸發解析的時機不同。
結論:先確認需要哪一種資訊
依網站分流時,先確保請求中保留網域資訊;依解析位址分流時,再選擇解析策略。DNS 伺服器、DNS 查詢的出站方式,以及嗅探是否涵蓋目標,都應分別確認,不能只切換一個 domainStrategy 就期待同時解決所有問題。
- 應用程式明確連線至 HTTP 或 SOCKS 代理並提交主機名稱時,核心通常可以直接依網域規則判斷。
- 應用程式先自行解析再提交 IP 時,網域資訊可能已遺失;嗅探只能嘗試辨識受支援的流量,無法保證還原所有請求。
- 路由中的
domainStrategy與出站連線階段同類型的解析選項,負責的工作不同;修改時請確認所在的設定層級。
六、在 v2rayN 中套用與驗證
一般使用者建議透過路由設定介面管理規則。v2rayN 會產生執行設定,直接修改暫時產生的 JSON,可能在重新啟動服務或切換節點後被覆蓋。以下以含有「設定」→「路由設定」入口的桌面介面為例;不同版本的介面按鈕位置可能不同,但仍須逐項確認規則順序與出站對應。
-
保留原有設定
開啟「設定」→「路由設定」,記下目前使用的規則集與網域解析策略。修改前請先備份現有設定,不要直接清空預設規則集。
-
新增單一規則
在目標規則集中新增完整網域條件,例如
full:api.example.com,並選擇代理出站。介面中的網域輸入欄位只需填寫規則項目,不要貼上整個 routing 物件。 -
調整規則順序
將這條例外規則移至對應的
domain:、geosite:或其他寬泛規則之前。儲存後,確認主介面目前選取的就是剛修改的規則集。 -
重新建立連線
重新啟動服務或重新載入設定,再關閉目標網頁的舊連線並重新瀏覽。規則變更後,既有連線通常不會自動切換至另一個出站。
-
確認執行記錄
查看核心記錄中的目標主機、目標連接埠及出站標籤。先用已知可正常連線的網站驗證,再擴大規則範圍;若記錄層級不足,可暫時調高至 info 或 debug,完成後再恢復原設定。
驗證時至少測試三類請求:例外主機、同一主網域下的一般主機,以及區域網路資源。前兩類用來確認網域規則的邊界,第三類則確認私人位址直連是否被前面的寬泛代理規則攔截。若記錄中沒有出現請求,請先確認應用程式是否經過目前的代理入口,而不是繼續修改路由運算式。
七、常見規則衝突快速解答
已設定 full,為什麼還是直連?
先檢查前面是否有涵蓋該網域的 domain:、geosite: 或全流量規則。將完整網域例外移到寬泛規則之前,儲存後使用新連線測試;同時確認這條規則選擇的出站標籤。
把 domain 和 ip 放在一起,為什麼反而不符合?
在同一條 field 規則中,這兩者是必須同時符合的條件。若要「網域或位址任一項符合」就生效,請拆成兩條使用相同出站的規則;只有確實需要同時限制兩項條件時,才將兩者寫在同一條規則中。
有 geosite:cn,為什麼有些網站仍走代理?
先確認實際請求的目標主機名稱,例如頁面引用的資源可能使用不同網域。再檢查前置規則、資料檔是否已載入,以及集合是否包含該網域。可以先新增一條明確的 full: 規則進行驗證,並透過存取日誌確認實際出站。
設定 port 443 就能比對所有網頁嗎?
不能。它只會限制目標連接埠;傳統 HTTP 可能使用 80,其他服務也可能使用自訂連接埠。HTTPS 也可能透過 TCP 或 UDP 傳輸,若另外設定 network: "tcp",就不會符合 UDP 請求。
更新訂閱後,自訂規則還會生效嗎?
節點訂閱與路由規則屬於不同的設定內容。更新後請確認目前選取的仍是正確規則集,且代理出站仍指向有效節點。不要把訂閱網址當成路由設定,也不要將路由 JSON 貼到訂閱網址欄位。
請維持固定的排查順序:確認請求已進入核心、確認網域或位址資訊可用、檢查第一條符合的規則,再確認出站本身能否連線。每次只修改一類條件,才能分辨結果變化是由規則範圍、DNS 策略,還是節點網路造成。