Xray 設定檔結構解析:逐段了解 inbounds、outbounds 與 routing

依序解析 log、inbounds、outbounds、routing 與 dns,說明 Xray 設定 JSON 各欄位的用途,以及流量如何在各區段間傳遞。

本文重點

本文適合已經會匯入節點,並準備閱讀 Xray 原生設定檔的使用者。先以一份僅包含本機入口、直連與封鎖出口的完整 JSON 作為範例,再說明記錄、連接埠、標籤、路由順序與 DNS 之間的關係。讀完後,你可以找出流量在哪個環節中斷,也能釐清用戶端設定、分享連結與核心執行設定各自的用途。

設定物件與流量路徑

Xray 是處理連線的核心,v2rayN 則是用來管理節點、產生設定並啟動核心的桌面用戶端。節點分享連結通常只描述一個遠端連線;原生 JSON 則能同時設定本機監聽、多個出口、路由與 DNS。把分享連結存成 config.json,不會自動變成可供核心執行的設定檔。

應用程式發出請求 由入站接收 比對路由 連線至出站 目標服務

上述流程是閱讀設定檔的主線。log 負責記錄狀態;需要解析網域名稱時,dns 會參與處理。兩者都不是每個請求必須依序經過的獨立轉送站。頂層物件在 JSON 中的排列順序,不會決定流量的處理順序。

完整 JSON:本機入口與直連基礎設定

以下是一份用來理解結構的獨立設定。SOCKS 入口監聽 127.0.0.1:10808,HTTP 入口監聽 127.0.0.1:10809。此設定不含遠端代理節點:一般請求會直連,前往保留測試網域 blocked.test 的請求則會遭到封鎖。這份設定無法用來測試遠端代理是否可用。

{
  "log": {
    "loglevel": "warning"
  },
  "inbounds": [
    {
      "tag": "socks-in",
      "listen": "127.0.0.1",
      "port": 10808,
      "protocol": "socks",
      "settings": {
        "auth": "noauth",
        "udp": true
      }
    },
    {
      "tag": "http-in",
      "listen": "127.0.0.1",
      "port": 10809,
      "protocol": "http",
      "settings": {}
    }
  ],
  "outbounds": [
    {
      "tag": "direct",
      "protocol": "freedom",
      "settings": {
        "domainStrategy": "UseIP"
      }
    },
    {
      "tag": "block",
      "protocol": "blackhole",
      "settings": {}
    }
  ],
  "routing": {
    "domainStrategy": "AsIs",
    "rules": [
      {
        "type": "field",
        "domain": [
          "full:blocked.test"
        ],
        "outboundTag": "block"
      },
      {
        "type": "field",
        "ip": [
          "127.0.0.0/8",
          "10.0.0.0/8",
          "172.16.0.0/12",
          "192.168.0.0/16"
        ],
        "outboundTag": "direct"
      }
    ]
  },
  "dns": {
    "servers": [
      "localhost"
    ]
  }
}

此範例是嚴格格式的 JSON:鍵名與字串都使用雙引號、不含註解,且最後一個陣列項目後不加逗號。本文後續的欄位說明是用來解讀這份設定,不需要再逐段拼成另一份設定檔。

log:先確認錯誤發生在哪個環節

loglevel 用來設定錯誤記錄的詳細程度。常見值有 debug、info、warning、error 和 none。排除問題時,可以暫時將範例中的 warning 改成 info;完成後再改回來,避免保留過多連線細節。

欄位用途排查時應留意的內容
loglevel設定錯誤記錄層級設定載入、監聽失敗或連線失敗的具體訊息
access指定存取記錄檔請求目標與實際使用的出站資訊
error指定錯誤記錄檔啟動及執行期間的錯誤脈絡

本例未指定記錄檔路徑;透過命令列執行時,請先查看終端機輸出。若要自行加入 access 或 error,請選擇目前程序有權寫入的路徑,並留意相對路徑是以啟動工作目錄為基準。記錄中可能包含存取目標,分享排錯資訊前請先移除敏感內容。

inbounds:監聽位址、連接埠與入口標籤

每個入站物件都是一個接收流量的入口。listen 是綁定位址,port 是監聽連接埠,protocol 則決定應用程式要用哪種協定連線。tag 是設定檔內部的識別標籤,不是密碼,也不是要填入瀏覽器的主機名稱。

SOCKS 入口

標籤
socks-in
位址
127.0.0.1
連接埠
10808
協定
socks
UDP
true

應用程式必須使用 SOCKS 協定連線;若要使用 UDP,應用程式與後續連線路徑也都必須支援。

HTTP 入口

標籤
http-in
位址
127.0.0.1
連接埠
10809
協定
http
協定設定
{}

HTTPS 網站通常透過 HTTP CONNECT 建立通道,不需要把入口協定改成 HTTPS。

127.0.0.1 僅接受本機連線。改成 0.0.0.0 會擴大 IPv4 監聽範圍;其他裝置能否連線,還要視防火牆與網路環境而定。本例的 SOCKS 使用 noauth,因此不要為了嘗試在區域網路共用,就直接擴大監聽範圍。

outbounds:出站協定與預設出站

outbounds 是可供路由選擇的出站陣列。本例中的 freedom 會直接連線至目標,blackhole 則會封鎖連線。這裡的 direct、block 都是自行定義的標籤;實際行為由 protocol 決定,而不是由標籤的英文名稱決定。

設定層級範例欄位用途
出站識別標籤tag供路由透過 outboundTag 引用
代理協定protocol例如 freedom、blackhole、VMess、VLESS、Trojan 或 Shadowsocks 所對應的協定實作
協定參數settings依出站協定設定目標、使用者或其他協定選項
傳輸參數streamSettings為支援的代理出站設定傳輸方式與傳輸安全性

新增遠端代理出站時,協定、伺服器位址、連接埠、身分參數與傳輸設定都必須彼此相符。不能只把 freedom 改成 vless,就以為已經設定好節點。TLS 或 REALITY 相關欄位屬於相應的傳輸安全設定,不應隨意加入 SOCKS 入站的 settings。

結論:調整出站順序前,先補上兜底規則

若沒有任何路由規則符合,通常會使用第一個出站。本例將 direct 排在第一位,因此未符合規則的請求會直連;若要預設使用代理,應明確設計兜底出站,不能只確認某條規則有指定代理標籤。

routing:規則順序、標籤引用與解析策略

routing.rules 會依陣列順序比對,第一條符合的規則決定出站。本例第一條規則會將完整網域 blocked.test 導向 block;第二條則將列出的 IPv4 網段導向 direct。這些網段僅供示範,並非完整的特殊用途位址清單,也不含 IPv6。

  1. 請求進入後,核心會取得入口標籤、目標網域或 IP、連接埠等可用資訊。
  2. 從第一條規則開始依序檢查;同一條規則中的不同條件類別通常必須同時符合。
  3. 同類清單中的候選項目通常採「符合任一項即可」的方式判斷,例如符合 ip 陣列中的任一網段。
  4. 找到符合的規則後,使用其 outboundTag;若沒有符合項目,則使用預設出站。

full: 表示比對完整網域;domain: 用於比對網域及其子網域。若要限制特定入口,可在規則中加入 inboundTag 陣列。引用的標籤必須與對應物件的 tag 完全一致;入口與出口標籤各有用途,不能將 socks-in 當成出站標籤引用。

routing.domainStrategy網域解析時機閱讀規則時的注意事項
AsIs不主動為路由比對解析網域不能只靠 IP 規則,為網域目標分流
IPIfNonMatch網域未符合規則後,再解析並繼續比對過早符合範圍過廣的規則,會阻止後續解析比對
IPOnDemand比對過程遇到需要 IP 的規則時,會觸發解析IP 規則的位置會影響解析時機

範例使用 AsIs,因此以網域形式提交的請求不會只為了符合第二條 IP 規則而進行解析。不過,本例的預設出站仍是直連,所以看到請求直連,不能據此推斷它符合了私有網段規則。排查規則時,應查看實際符合的規則與出站,而不只是確認網頁最後能否開啟。

dns:釐清路由解析與連線解析

設定 dns 不代表所有應用程式的 DNS 查詢都會交由 Xray 處理。應用程式可能先自行解析,再將 IP 傳給代理;也可能把網域交給 SOCKS 或 HTTP 入口。路由能取得哪些資訊,首先取決於入口實際收到的內容。

本例的 dns.servers 使用特殊值 localhost,表示透過本機系統解析器進行解析,而不是指定一台在本機執行的 DNS 伺服器。這也不會建立 UDP 53 監聽連接埠。若要提供 DNS 服務給應用程式使用,必須另外設計接收 DNS 請求的入口與處理路徑。

本例在 freedom 出站設定 UseIP,讓直連出站透過內建 DNS 解析流程處理網域。這與路由的 AsIs 並不衝突:前者是在出站準備連線時生效,後者則限制規則比對階段。即使出站之後取得 IP,也不會自動重新執行已完成的路由選擇。

結論:先確認應用程式提交的是網域還是 IP

網域規則未符合時,先確認應用程式是否已在本機完成解析。不要同時修改路由策略、DNS 伺服器與出站協定;每次只調整一個層面,才能判斷是哪個步驟改變了結果。

驗證與排錯:從設定檢查到實際連線

先使用核心內建的檢查命令驗證設定,再啟動監聽,最後讓應用程式連線。以下命令請在能找到 xray 執行檔的終端機中執行;若執行檔不在命令搜尋路徑中,請改用實際路徑。先查看版本與說明,即可確認目前的執行檔支援哪些參數。

xray version
xray run -help
xray run -test -config ./config.json
xray run -config ./config.json

設定檢查通過,只代表核心接受這份設定,不表示遠端服務可連線,也不表示應用程式已使用代理。若要進行可重複的本機測試,可先在另一個終端機啟動測試服務,再分別透過兩個入口存取:

python -m http.server 8000 --bind 127.0.0.1
curl --noproxy "" --proxy socks5h://127.0.0.1:10808 http://127.0.0.1:8000/
curl --noproxy "" --proxy http://127.0.0.1:10809 http://127.0.0.1:8000/

測試前,本機必須已安裝 Python 和 curl。回應內容來自本機測試目錄,驗證的是「應用程式連上入口、路由選擇、直連出站」這段流程。--noproxy "" 可避免既有的略過代理設定跳過本次入口測試。測試完成後請停止暫時啟動的服務,不要把終端機顯示的目錄清單當成代理節點的測速結果。

設定檢查通過,為什麼一啟動就結束?

檢查終端機是否提示監聽失敗。確認 10808、10809 未被占用;必要時改用 11808、11809,並同步修改應用程式的代理連接埠。

加入網域規則後,為什麼仍然使用預設出站?

先確認請求中包含網域,再檢查是否有更早的通用規則先行攔截。核對 full: 的完整比對範圍,以及 outboundTag 是否指向正確的出站。

在 v2rayN 修改執行設定檔,重啟後為什麼不見了?

用戶端可能會重新產生執行設定。請先保留獨立副本,再透過目前版本提供的自訂設定入口載入;也可以在用戶端對應的路由或 DNS 設定中修改。不要把暫時使用的執行檔當成長期設定來源。

這份 JSON 可以直接匯入所有用戶端嗎?

先確認匯入功能接受的是原生設定檔,還是節點分享內容。v2rayNG 使用 Xray 核心,v2flyNG 使用 v2fly 核心;完整設定檔是否相容,仍取決於核心版本、欄位支援情況與用戶端的載入方式。

完成基礎設定驗證後,再新增遠端代理出站,並為其設定明確的路由。每次只修改一個部分,並保留上一份可正常運作的設定。發生問題時,才能將排查範圍縮小到入口、規則、解析或遠端連線,而不必在多項無關設定間反覆切換。

下載 v2rayN