V2Ray 設定檔結構逐段解析:inbounds、outbounds 與 routing 各自負責什麼

拆解一份最小可用的 V2Ray JSON 設定,逐段說明 inbounds 入站、outbounds 出站與 routing 路由三大區塊的欄位意義,以及圖形化用戶端與設定檔的對應關係。

本文速覽

本文適合已經能匯入節點,卻看不懂核心設定與日誌欄位的使用者。讀完後即可分辨本機監聽、遠端連線與規則分流分別位於哪個區塊,並沿著 tag 找到「請求從哪裡進入、經過哪條規則,最後由哪個出口送出」。

先看全局:設定檔不只是一個節點

V2Ray 5.x 使用 JSON 描述核心的執行方式。一份完整的用戶端設定通常不只儲存伺服器位址與使用者 ID,還要定義本機接收流量的入口、向外傳送流量的出口、DNS 行為、日誌層級與路由規則。圖形化用戶端裡看到的「一個節點」,主要對應代理出站中的一組伺服器參數,並不等於完整的執行設定。

讀取設定時,可以先略過協定細節,把資料流理解成三個階段:應用程式將請求交給本機監聽埠,inbounds 接收並識別請求,routing 根據網域、IP、埠號或協定選擇目標,最後由某個 outbounds 項目送出。入站與出站透過 tag 命名,路由規則再引用這些名稱。

應用程式請求入站接收嗅探網域規則比對選擇出站傳送至目標

頂層欄位沒有固定的書寫順序,JSON 解析器不會因為 routing 寫在 outbounds 前面就改變執行結果。但陣列內的順序可能具有意義:路由規則通常由上到下比對,未命中規則的流量通常會交給第一個出站。因此,閱讀時既要看 tag,也要注意陣列位置。

inbounds

方向
應用程式到核心
常見協定
SOCKS、HTTP
關鍵欄位
listen、port、tag
典型埠號
10808

決定本機哪些位址與埠號可以將流量交給核心。

outbounds

方向
核心到目標
代理協定
VMess、VLESS
輔助出口
freedom、blackhole
識別方式
tag

節點伺服器資訊、傳輸層與 TLS 參數主要集中於此。

routing

規則類型
field
比對對象
網域、IP、埠號
執行結果
outboundTag
檢查順序
由上到下

負責選擇出口,不負責建立遠端協定連線。

dns 與 log

dns
解析策略
log
日誌層級
常用層級
warning
排錯層級
info

不是每份設定都會明確寫出,但會直接影響解析與排錯。

inbounds:流量從本機哪裡進入

inbounds 是陣列,每個物件代表一個本機入口。桌面用戶端常見的做法是同時建立 SOCKS 與 HTTP 入站,例如將 SOCKS 放在 127.0.0.1:10808,HTTP 放在 127.0.0.1:10809。瀏覽器、命令列工具或系統代理將請求送到對應埠號後,核心才會開始處理這條連線。

listen 決定監聽位址。設定為 127.0.0.1 時,只接受本機連線;設定為 0.0.0.0 則會監聽所有網路介面,區域網路裝置可能因此存取該埠號。除非明確需要區域網路代理,否則本機迴路位址更符合桌面使用情境。port 必須未被其他程式佔用;重複佔用時,日誌中常會出現 bind 或 address already in use。

10808
範例 SOCKS 埠號
10809
範例 HTTP 埠號
127.0.0.1
僅監聽本機
53
標準 DNS 埠號

protocol 代表入口協定,不是遠端節點協定。一個 SOCKS 入站完全可以將請求轉交給 VLESS 或 VMess 出站,兩者沒有「協定必須相同」的關係。settings 儲存該入站協定專屬的參數;SOCKS 入站常見的 udp: true 表示允許接收 UDP 請求。

sniffing 用來從連線內容中還原目標網域。應用程式有時會先將網域解析成 IP,再向本機代理發起連線;如果核心只能看到 IP,依網域撰寫的路由規則就無法命中。啟用嗅探並設定 destOverride 後,核心可以在適用的 HTTP、TLS 流量中識別網域,再交由 routing 判斷。

{
  "tag": "socks-in",
  "listen": "127.0.0.1",
  "port": 10808,
  "protocol": "socks",
  "settings": {
    "auth": "noauth",
    "udp": true
  },
  "sniffing": {
    "enabled": true,
    "destOverride": ["http", "tls"]
  }
}

outbounds:節點、直連與封鎖出口

outbounds 同樣是陣列。代理節點通常只是其中一項,實際用戶端還會建立直連出口與封鎖出口。代理出口使用 VMess 或 VLESS 等協定連線至遠端服務;freedom 讓核心直接存取目標;blackhole 則會終止由規則選中的連線。

代理出站可以再分成兩層。settings 描述協定身分與伺服器埠號,例如 VMess 的位址、埠號、使用者 ID 與安全參數;streamSettings 描述底層傳輸與安全層,例如 TCP、WebSocket、TLS 或 Reality。即使協定欄位正確,只要傳輸路徑、SNI 或安全層不一致,連線仍可能失敗。

VMess + WebSocket + TLS

protocol
vmess
network
ws
security
tls
遠端埠號
443
路徑
/v2ray

使用者身分放在 settings,傳輸路徑與 TLS 放在 streamSettings。

VLESS + TCP + Reality

protocol
vless
network
tcp
security
reality
flow
xtls-rprx-vision
指紋
chrome

Reality 參數必須與伺服器相符,不能只將 security 欄位改名。

直連出口

tag
direct
protocol
freedom
遠端節點
不需要
用途
本機與直連規則

命中 direct 後,由本機網路直接連線至目標。

封鎖出口

tag
block
protocol
blackhole
遠端連線
不建立
用途
封鎖指定流量

路由規則引用 block 後,請求不會繼續傳送至目標。

出站的 tag 是排查設定時最重要的索引。看到路由規則寫著 "outboundTag": "direct",就回到 outbounds 尋找 tag 為 direct 的物件。若規則引用不存在的 tag,核心通常會在啟動階段回報設定錯誤,而不會自動猜測目標出口。

訂閱提供的通常是節點連線參數,不會完整決定本機埠號、日誌層級與所有分流規則。v2rayN、v2rayNG 或 v2flyNG 匯入訂閱後,會將節點欄位與用戶端自身的設定合併,再產生交給核心的執行設定。因此,同一份訂閱在不同用戶端產生的完整 JSON 可能不同。

結論:先按層定位出站錯誤

認證失敗時,先核對 settings 中的位址、埠號與使用者資訊;TLS、Reality 或 WebSocket 交握失敗時,再檢查 streamSettings。將兩層參數混在一起修改,最容易造成欄位看似齊全,連線卻仍然逾時。

routing:依序將請求交給指定出口

routing.rules 是規則陣列。常用的規則類型為 field,可以依照 domainipportnetworkprotocolinboundTag 等條件進行比對。規則本身不會轉送資料,只透過 outboundTag 指定由哪個出站處理。

規則順序會改變結果。假設第一條將某個網域交給代理,第二條則將更寬泛的網域集合交給直連,該網域在第一條命中後就會停止繼續比對。更具體的封鎖或強制代理規則應放在前面,涵蓋範圍較大的直連規則與最後的兜底規則則放在後面。

比對欄位 比對對象 典型用途 執行結果
domain 完整網域、後綴或網域集合 依網站類別分流 交給指定的 outboundTag
ip 單一 IP、CIDR 或 IP 集合 區域網路與目標網段分流 直連、代理或封鎖
port 單一埠號或埠號範圍 控制特定服務流量 選擇對應出口
network tcp、udp 或兩者 最後的兜底規則 涵蓋剩餘連線
inboundTag 一個或多個入站 tag 不同本機入口使用不同出口 實現入口級分流

domainStrategy 決定路由器何時為網域解析 IP。AsIs 優先依原始網域進行比對,不會為了 IP 規則主動解析;IPIfNonMatch 會先檢查網域規則,未命中時再解析 IP 並嘗試 IP 規則;IPOnDemand 遇到可能需要 IP 的規則時,會更早觸發解析。選擇哪一種取決於規則設計,不是越積極越好。

如果沒有任何規則命中,V2Ray 通常會使用第一個出站。為避免依賴隱含順序,可以在末尾加入涵蓋 TCP 與 UDP 的兜底規則,並明確寫出目標 outboundTag。如此一來,調整 outbounds 順序時就不會意外改變預設流量方向。

{
  "domainStrategy": "IPIfNonMatch",
  "rules": [
    {
      "type": "field",
      "protocol": ["bittorrent"],
      "outboundTag": "block"
    },
    {
      "type": "field",
      "ip": ["geoip:private"],
      "outboundTag": "direct"
    },
    {
      "type": "field",
      "domain": ["geosite:cn"],
      "outboundTag": "direct"
    },
    {
      "type": "field",
      "network": "tcp,udp",
      "outboundTag": "proxy"
    }
  ]
}

結論:路由排錯從第一條規則開始

先確認目標網域或 IP 實際命中了哪條規則,再檢查該規則引用的 outboundTag。節點連線正常但存取方向錯誤,通常是規則順序、網域嗅探或 DNS 結果造成,而不是代理協定本身損壞。

一份易讀的最小用戶端設定

以下範例將日誌、一個 SOCKS 入站、三個出站與四條路由規則放在同一份檔案中。範例位址與使用者 ID 僅用於展示結構,不能作為實際節點使用。設定檔採用標準 JSON,鍵名與字串必須使用雙引號,結尾不能保留多餘逗號,也不能直接插入註解。

從資料流來看,應用程式先連線至 127.0.0.1:10808。核心檢查路由:BitTorrent 流量進入 block,私人位址與指定網域集合進入 direct,其餘 TCP 與 UDP 請求進入 proxy。proxy 再使用 VMess、WebSocket 與 TLS 連線至範例伺服器的 443 埠號。

{
  "log": {
    "loglevel": "warning"
  },
  "inbounds": [
    {
      "tag": "socks-in",
      "listen": "127.0.0.1",
      "port": 10808,
      "protocol": "socks",
      "settings": {
        "auth": "noauth",
        "udp": true
      },
      "sniffing": {
        "enabled": true,
        "destOverride": ["http", "tls"]
      }
    }
  ],
  "outbounds": [
    {
      "tag": "proxy",
      "protocol": "vmess",
      "settings": {
        "vnext": [
          {
            "address": "server.example.com",
            "port": 443,
            "users": [
              {
                "id": "00000000-0000-4000-8000-000000000000",
                "alterId": 0,
                "security": "auto"
              }
            ]
          }
        ]
      },
      "streamSettings": {
        "network": "ws",
        "security": "tls",
        "tlsSettings": {
          "serverName": "server.example.com"
        },
        "wsSettings": {
          "path": "/v2ray"
        }
      }
    },
    {
      "tag": "direct",
      "protocol": "freedom",
      "settings": {}
    },
    {
      "tag": "block",
      "protocol": "blackhole",
      "settings": {}
    }
  ],
  "routing": {
    "domainStrategy": "IPIfNonMatch",
    "rules": [
      {
        "type": "field",
        "protocol": ["bittorrent"],
        "outboundTag": "block"
      },
      {
        "type": "field",
        "ip": ["geoip:private"],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "domain": ["geosite:cn"],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "network": "tcp,udp",
        "outboundTag": "proxy"
      }
    ]
  }
}
  1. 先檢查 JSON 語法,尤其確認雙引號、逗號與方括號是否成對。
  2. 接著核對所有 tag 是否唯一,以及 routing 引用的 outboundTag 是否確實存在。
  3. 確認入站埠號未被佔用,並讓系統代理或應用程式指向相同埠號。
  4. 核對代理出站的協定、伺服器埠號、傳輸方式與安全層是否完整對應。
  5. 最後檢查規則順序,確認兜底規則位於更具體的規則之後。

圖形化用戶端與核心 JSON 如何對應

v2rayN、v2rayNG 與 v2flyNG 都會將常用欄位拆分為表單。節點編輯頁中的位址、埠號、使用者 ID、傳輸方式與安全設定,主要對應至代理 outbound;本機 SOCKS 埠號、允許區域網路連線等選項對應至 inbounds;路由模式、規則集與自訂規則則對應至 routing。

以 v2rayN 為例,本機埠號與基本行為通常可從「設定」→「參數設定」進入調整,節點參數則在伺服器編輯介面修改。用戶端啟動核心時,會將節點、全域參數與路由設定組合成執行設定。直接修改暫時產生的核心 JSON,下一次切換節點、更新訂閱或重新啟動核心時,可能會被重新產生。

Android 上的 v2rayNG 與 v2flyNG 也採用相似的分層方式,但兩者使用的核心不同:v2rayNG 使用 Xray 核心,v2flyNG 使用 v2fly 核心。部分進階欄位與預設值會有所差異,不能將某個用戶端匯出的完整設定原樣視為另一個用戶端的介面設定檔。

為什麼介面裡只有一個節點,執行設定卻有三個出站?

節點只對應 proxy 出站。用戶端會額外建立 direct 與 block,供直連與封鎖規則引用,因此 outbounds 數量通常會多於節點數量。

修改產生的 JSON 後,為什麼重新啟動又恢復原狀?

產生的檔案屬於執行產物。應回到「設定」→「參數設定」、節點編輯或路由設定中修改來源資料,再重新啟動核心驗證。

匯入訂閱後,本機埠號為什麼沒有跟著變更?

訂閱主要提供節點連線參數,本機監聽埠號屬於用戶端設定。請檢查 SOCKS 埠號是否仍為 10808,並同步更新系統代理。

路由規則寫了網域,為什麼還是走錯出口?

先啟用適用的網域嗅探,再檢查 domainStrategy、DNS 結果與規則順序。可暫時將日誌層級調至 info,觀察實際目標與出站 tag。

依日誌順序排查啟動失敗與分流錯誤

設定問題可以分為啟動階段與執行階段。啟動階段失敗通常與 JSON 語法、欄位類型、埠號重複或無效 tag 有關,核心甚至不會建立入站監聽。執行階段才出現的問題,則多半與節點參數、DNS、規則命中與目標網路有關。

排錯時不要一次修改多個區塊。先將 loglevelwarning 暫時調整為 info,重現一次問題並記錄時間。確認是入站未監聽、規則選錯出口,還是 proxy 出站連線失敗,再回到對應區塊修改。問題解決後可恢復為 warning,減少平時的日誌量。

{
  "log": {
    "loglevel": "info"
  }
}

日誌中的 inbound tag、目標位址與 outbound tag 可以串起完整路徑。例如請求由 socks-in 進入,目標顯示為某個網域,最後選擇 direct,表示節點本身並未參與這次連線;若預期應使用代理,就應檢查 routing,而不是反覆修改 VMess 或 VLESS 身分參數。

反過來,如果日誌已顯示規則選擇 proxy,之後才發生 TLS 交握或連線逾時,代表路由基本上已完成職責。此時應將注意力轉向代理 outbound 的位址、埠號、SNI、傳輸路徑、系統時間與遠端可達性。

結論:用 tag 追蹤完整鏈路

將排錯流程固定為「入站 tag → 目標網域或 IP → 命中規則 → 出站 tag → 傳輸連線」。每一步只對應一個設定區塊,能避免將埠號佔用、分流錯誤與節點交握失敗混為同一個問題。

下載 v2rayN 查看 Windows、macOS、Android、Linux 用戶端