config.json 結構逐段解析:inbounds、outbounds 與 routing 的作用

拆解一份最小可用設定,逐段說明入站如何監聽本機、出站如何連線遠端、routing 如何決定流量出口,並解釋 tag 如何串起完整鏈路。

無論設定是由 v2rayN 的訂閱功能產生,還是由維護人員手動整理,核心結構都能歸納成三個問題:流量從哪裡進入、準備從哪裡離開,以及匹配條件決定使用哪個出口。理解這三點後,排查「連得上連接埠卻打不開網頁」、「直連網域仍走代理」、「攔截規則沒有命中」等故障會更直接。

本文速覽

本文適合已能匯入訂閱、希望進一步理解底層設定的使用者。閱讀後可以辨識 inbounds、outbounds、routing 與 tag 的職責,讀懂一份包含 SOCKS 入站、VMess 代理出口、直連出口與攔截出口的設定,並依照日誌順序定位規則未命中、連接埠衝突與出站引用錯誤。

先建立完整流量鏈:入站、匹配、出站

應用程式不會直接「進入 routing」。瀏覽器或其他程式會先將請求傳送到本機監聽連接埠,inbounds 接收連線並產生供核心處理的目標資訊;routing 再讀取目標網域、目標 IP、連接埠、網路類型與入站標籤;匹配成功後,規則中的 outboundTag 會指向某個 outbounds 項目。沒有規則命中時,通常會使用 outbounds 陣列的第一項作為預設出口,因此陣列順序同樣屬於設定邏輯。

應用程式傳送請求入站連接埠接收路由規則匹配選擇出站標籤建立遠端連線
10808
範例 SOCKS 連接埠
3 段
核心設定結構
3 個出站
代理、直連、攔截
127.0.0.1
本機回環監聽

可以把 config.json 視為一張有向連線圖,而不是一組彼此無關的參數。inbounds 中的 tag 用來標記流量來源,outbounds 中的 tag 用來命名出口,routing.rules 則引用這些名稱完成連線。tag 本身不傳輸資料,也不會自動建立代理鏈;它只是核心內部穩定且區分大小寫的引用鍵。

inbounds:定義本機如何接收流量

inbounds 是入站陣列,每個項目代表一個監聽入口。桌面端常見入口包括 SOCKS、HTTP,或由用戶端管理的透明代理入口。最基本的 SOCKS 入站至少要明確設定 listen、port、protocol 與 settings。監聽位址設為 127.0.0.1 時,只允許本機程式存取;改成 0.0.0.0 則會監聽所有網路介面,區域網路裝置可能存取該連接埠,因此不能將兩種寫法視為等價。

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

逐欄位讀取入站設定

  • tag:將此入口命名為 socks-in,後續規則可以透過 inboundTag 只處理來自這個入口的請求。
  • listen:指定繫結位址。127.0.0.1 是本機回環位址,適合只供目前電腦使用的用戶端設定。
  • port:指定監聽連接埠。範例使用 10808,瀏覽器或應用程式的 SOCKS5 代理連接埠也必須同步填寫 10808。
  • protocol:宣告應用程式如何與本機核心通訊。這裡是 SOCKS,不代表遠端節點也使用 SOCKS。
  • settings.udp:允許 SOCKS 入站接收 UDP 請求。它只會開啟入站能力,最終是否可用仍取決於遠端協定、傳輸方式與目標應用程式。
  • sniffing:從 HTTP 請求或 TLS 握手中還原目標網域,讓依網域分流的規則有機會命中。

連接埠衝突發生在核心建立監聽套接字時。如果 10808 已被其他程序佔用,inbounds 尚未開始接收流量,後續的 routing 與 outbounds 也不會執行。在 v2rayN 中可進入「設定」→「參數設定」,調整本機 SOCKS 連接埠;改為 10818 後,還要同步修改瀏覽器代理、系統代理或其他應用程式中的連接埠。

outbounds:定義代理、直連與攔截出口

outbounds 是出口陣列。每個出口都必須有唯一的 tag,protocol 決定核心如何處理離站流量。遠端代理出口包含伺服器位址、連接埠、使用者識別碼與傳輸參數;直連出口使用 freedom;主動終止連線的出口使用 blackhole。三者可以同時存在,再由 routing 選擇實際出口。

proxy:VMess 代理出口

協定
VMess
伺服器連接埠
443
傳輸
WebSocket
傳輸安全性
TLS

節點參數通常由訂閱匯入,address、id、路徑與傳輸安全性必須與伺服器端一致。

direct:直接連線

協定
freedom
遠端節點
不需要
典型用途
區域網路與指定網域
引用標籤
direct

直連表示由本機網路直接存取目標,不經過 proxy 出站。

block:終止連線

協定
blackhole
遠端連線
不建立
典型用途
廣告網域規則
引用標籤
block

命中後由核心終止請求,適合明確需要攔截的目標集合。

預設出口

判定方式
陣列第一項
範例標籤
proxy
生效條件
規則未命中
排查重點
排列順序

希望未分類流量走代理時,應將 proxy 放在 outbounds 的第一項。

{
  "outbounds": [
    {
      "tag": "proxy",
      "protocol": "vmess",
      "settings": {
        "vnext": [
          {
            "address": "node.example.net",
            "port": 443,
            "users": [
              {
                "id": "11111111-1111-4111-8111-111111111111",
                "security": "auto"
              }
            ]
          }
        ]
      },
      "streamSettings": {
        "network": "ws",
        "security": "tls",
        "wsSettings": {
          "path": "/connection"
        }
      }
    },
    {
      "tag": "direct",
      "protocol": "freedom",
      "settings": {}
    },
    {
      "tag": "block",
      "protocol": "blackhole",
      "settings": {}
    }
  ]
}

上方的網域、使用者識別碼與路徑僅用於展示結構,不能取代訂閱中的實際節點參數。VMess 的 settings 描述使用者與伺服器,streamSettings 描述傳輸層。即使位址與連接埠正確,只要 WebSocket 路徑、TLS 設定或使用者識別碼不一致,連線仍會失敗。

結論:先確認預設出口,再檢查複雜規則

暫時停用 routing 後仍無法存取,問題更可能出在 proxy 出站參數或網路連線;停用 routing 後恢復正常,則應回頭檢查規則順序、匹配條件與 outboundTag 引用。

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

routing 不負責建立監聽,也不儲存遠端節點憑據。它的職責是讀取請求特徵並回傳出站標籤。rules 陣列會依從上到下的順序進行匹配,通常在第一條有效規則命中後停止繼續尋找。因此,應將範圍小、優先級高的規則放在前面,把涵蓋範圍大的兜底規則放在後面。

{
  "routing": {
    "domainStrategy": "IPIfNonMatch",
    "rules": [
      {
        "type": "field",
        "domain": [
          "geosite:category-ads-all"
        ],
        "outboundTag": "block"
      },
      {
        "type": "field",
        "ip": [
          "geoip:private"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "inboundTag": [
          "socks-in"
        ],
        "network": "tcp,udp",
        "outboundTag": "proxy"
      }
    ]
  }
}

三條規則分別解決什麼問題

  1. 第一條讀取 GeoSite 分類,匹配廣告網域後交給 block。這條規則需要核心能正常讀取本機 GeoSite 資料。
  2. 第二條匹配私有 IP 範圍並交給 direct,用來避免區域網路位址繞到遠端代理出口。
  3. 第三條限定來源為 socks-in,並將其餘 TCP、UDP 請求交給 proxy。它的範圍較大,因此放在精確規則之後。
欄位 檢查對象 常見值 容易出現的問題
domain 目標網域 domain:full:geosite: 分類資料過舊,網域未歸入預期集合
ip 目標 IP CIDR、geoip:private 網域未解析為 IP,導致規則未參與匹配
port 目標連接埠 5380,443、連接埠範圍 誤將本機監聽連接埠當成目標連接埠
network 傳輸類型 tcpudptcp,udp 只填寫 tcp,遺漏 UDP 請求
inboundTag 流量來源 socks-in 引用名稱與 inbounds 中的 tag 不一致
outboundTag 目標出口 proxydirectblock 引用了 outbounds 中不存在的標籤

domainStrategy 控制網域與 IP 規則之間的解析策略。AsIs 優先依原始網域進行匹配,不會為了所有 IP 規則主動解析網域;IPIfNonMatch 會先嘗試網域規則,未匹配時再解析 IP 並繼續檢查 IP 規則;IPOnDemand 會在匹配過程中更積極地觸發解析。一般分流設定可從 IPIfNonMatch 開始,既保留網域分類能力,也讓私有 IP 等規則有機會生效。

結論:規則順序比規則數量更重要

先放廣告攔截與區域網路直連,再放涵蓋全部 TCP、UDP 的代理規則。若寬泛規則提早出現,後續更精確的 direct 或 block 規則可能沒有執行機會。

tag 如何串起三段設定,形成完整鏈路

tag 的關鍵要求是「定義存在、拼寫一致、用途明確」。假設入站標籤是 socks-in,三個出站標籤分別為 proxydirectblock,那麼 routing 只能引用這四個已定義的名稱。將 outboundTag 寫成 Proxyproxy-main,都不會自動關聯到 proxy

inbounds[0].tag = "socks-in"
routing.rules[2].inboundTag = ["socks-in"]

outbounds[0].tag = "proxy"
routing.rules[2].outboundTag = "proxy"

outbounds[1].tag = "direct"
routing.rules[1].outboundTag = "direct"

outbounds[2].tag = "block"
routing.rules[0].outboundTag = "block"

依請求實際經過的順序檢查

  1. 確認應用程式代理類型為 SOCKS5,位址是 127.0.0.1,連接埠與 inbounds.port 相同。範例連接埠為 10808。
  2. 確認核心日誌中沒有「位址已被使用」或設定解析失敗的訊息。監聽失敗時不要繼續檢查遠端協定。
  3. 確認請求來自預期的入站。如果規則限制了 inboundTag,從另一個 HTTP 入站進入的請求不會命中該規則。
  4. 依 routing.rules 的排列順序尋找第一個匹配項,記錄其 outboundTag
  5. 在 outbounds 中尋找名稱完全相同的 tag,並檢查對應的 protocol、伺服器位址、連接埠及 streamSettings。
  6. 若沒有任何規則命中,檢查 outbounds 第一項是否確實是預計使用的預設出口。

如果要依來源區分策略,可以設定多個入站。例如 10808 的 socks-in 預設走 proxy,10818 的另一個 SOCKS 入站預設走 direct。此時兩個入口必須使用不同的 port 與不同的 tag,再分別撰寫帶有 inboundTag 的規則。只複製一份入站卻保留相同連接埠,會在啟動階段直接產生監聽衝突。

修改設定時的安全步驟與常見問題

v2rayN 會根據目前節點、路由設定與核心選項產生執行設定。直接編輯產生的檔案可能只在目前程序週期內有效,切換節點、更新訂閱或重新啟動用戶端後,檔案可能再次產生。需要長期保留的路由邏輯,應優先在用戶端提供的路由設定中維護;需要調整本機連接埠時,請使用「設定」→「參數設定」,並同步修改所有使用該連接埠的應用程式。

  • 修改前先保存目前可用的設定副本,每次只調整一組欄位。
  • 編輯 JSON 後,先檢查逗號、引號、陣列與物件的閉合關係,再啟動核心。
  • 調整 outbounds 順序時,記錄第一項的 tag,因為它關係到規則未命中時的預設出口。
  • 調整 routing.rules 時,依精確規則到寬泛規則排列,並逐條記錄預期出口。
  • 更新訂閱後,重新檢查協定、傳輸、TLS、伺服器連接埠與使用者識別碼是否完整匯入。
  • 路由分類結果異常時,檢查目前核心是否能讀取 GeoIP 與 GeoSite 資料。

連接埠 10808 可以連線,為什麼網頁還是打不開?

本機連接埠能連線只代表 inbounds 已在監聽。將日誌層級暫時設為 info,檢查請求是否命中 proxy,以及 VMess 出站的伺服器位址、443 連接埠、使用者識別碼、WebSocket 路徑與 TLS 設定是否與訂閱一致。

已設定 direct 規則,為什麼目標網域仍然走代理?

先檢查這條規則是否排在寬泛的 proxy 規則之前,再確認 domainStrategy 與匹配類型。若規則依 IP 分類,可將策略設為 IPIfNonMatch,並確認網域解析結果確實落在目標 IP 範圍內。

outboundTag 可以隨意命名嗎?

名稱可以自訂,但必須與 outbounds 中某個項目的 tag 完全一致,並避免重複。建議使用 proxy、direct、block 這類職責清楚的短名稱;修改名稱時,請同步搜尋所有 routing 引用。

訂閱更新後,手動路由為什麼消失了?

執行設定可能會由 v2rayN 重新產生。請將長期規則寫入用戶端的路由設定,不要只修改暫時產生的 config.json;更新後再檢查規則順序與出站標籤是否保持一致。

VMess 與 VLESS 的設定結構完全相同嗎?

頂層仍使用 inbounds、outbounds 與 routing,但出站 protocol、settings 使用者欄位及 streamSettings 組合會不同。不要只替換 protocol 字串,應以訂閱匯入的完整節點參數為準。

讀懂 config.json 的重點不是記住所有欄位,而是維持固定的排查路徑:入站是否正在監聽、請求帶有什麼目標資訊、哪條規則先命中、outboundTag 指向哪個出口,以及該出口能否完成連線。沿著這條鏈逐段驗證,比同時修改連接埠、協定與路由更容易定位根因。

下載用戶端v2rayN / v2rayNG