JSON 結構總覽與設定讀取順序
V2Ray 與 Xray 的主設定可理解為描述流量處理管線的 JSON 物件:入站接收連線,路由判斷去向,出站執行連線,DNS 與策略物件則為這條管線補充解析與資源限制。
頂層物件不是執行步驟清單
設定檔最外層由一個 JSON 物件構成,常見鍵包括 log、dns、inbounds、outbounds、routing、policy 與 stats。這些鍵在文字中的先後位置通常不決定執行順序,因為 JSON 物件以鍵名表達結構,而不是以書寫位置表達流程。真正具有順序語意的地方主要是陣列,例如 routing.rules 會由前往後匹配,先命中的規則先決定出站;多個入站與出站也透過各自的 tag 被其他物件引用。
閱讀設定時,較穩妥的方法是先記錄所有標籤,再沿著引用關係檢查。一個入站標籤可能被路由規則的 inboundTag 使用,一個出站標籤會由 outboundTag 指向,DNS 伺服器也可能透過 tag 與路由規則連接。標籤本身只是設定內部的識別碼,不會自動產生分流效果。若規則寫入不存在的標籤,設定可能在啟動階段報錯,也可能在執行到相關路徑時表現為流量沒有可用去向,具體取決於核心與欄位位置。
{
"log": {
"loglevel": "warning"
},
"dns": {
"servers": ["1.1.1.1", "localhost"]
},
"inbounds": [
{
"tag": "socks-in",
"listen": "127.0.0.1",
"port": 10808,
"protocol": "socks",
"settings": {
"udp": true
}
}
],
"outbounds": [
{
"tag": "direct",
"protocol": "freedom"
},
{
"tag": "blocked",
"protocol": "blackhole"
}
],
"routing": {
"domainStrategy": "AsIs",
"rules": [
{
"type": "field",
"ip": ["geoip:private"],
"outboundTag": "direct"
}
]
}
}
陣列、物件與值的型別
inbounds、outbounds 與 routing.rules 都是陣列,因此使用方括號;單一入站、出站或規則則是物件,使用大括號。連接埠是數字,不應寫成帶單位的字串;布林值只能寫成 true 或 false;省略欄位與值為 null 並不等價。省略表示讓核心採用預設行為,而明確的空值只有在欄位定義允許時才有意義。許多啟動失敗都不是協定問題,而是括號未正確閉合、物件之間缺少逗號、字串誤用中文引號,或把原本應為陣列的欄位寫成單一字串。
標準 JSON 不允許註解,也不允許在最後一個成員後保留尾隨逗號。網路範例為了說明常會寫入 // 註解,但複製到用戶端核心設定前必須刪除。v2rayN、v2rayNG 與 v2flyNG 可能在圖形介面之外維護自己的設定層,介面中的節點、訂閱與路由設定經過轉換後才交給核心。因此,手動編輯前應先確認目前修改的是用戶端管理檔案、產生後的執行設定,還是獨立核心讀取的設定;三者不能因檔名相似就視為同一個物件。
從最小設定逐步增加複雜度
排查設定時,應先保留一個本機入站、一個明確可用的出站與最少量的路由,再逐步加入 DNS、嗅探、多種傳輸與統計策略。一次加入多個模組會讓錯誤來源彼此掩蓋。例如連線失敗可能來自遠端參數,也可能是網域先被錯誤的 DNS 路徑解析,或前置規則把連線送到了 blocked。最小化不是刪除必要的安全欄位,而是縮短變數鏈:維持伺服器要求的位址、連接埠、使用者識別碼、傳輸與安全參數不變,只暫時移除不影響連通性的附加規則。
儲存前還應確認文字編碼為 UTF-8、檔案內容只有一個根物件,且鍵名大小寫與欄位定義一致。outboundTag 與 outboundtag 是不同名稱,協定名稱也不應根據介面譯名自行推測。完成結構檢查後,再進入入站、出站與路由三部分逐段驗證,這比直接在大型設定中反覆修改連接埠,更容易得到可解釋的結果。
inbounds 入站、監聽範圍與協定設定
入站定義核心從哪裡接收連線、使用什麼協定理解連線,以及是否對目的位址進行嗅探。桌面用戶端常建立本機 SOCKS 與 HTTP 入站,行動裝置則可能由 VPN 服務將流量送入核心。
listen、port 與本機暴露範圍
每個入站至少需要明確指定協定及其設定,常見欄位包括 tag、listen、port、protocol、settings、sniffing 與 streamSettings。當 listen 寫為 127.0.0.1 時,只有本機程式能夠連線到該連接埠,適合作為瀏覽器、系統代理或本機工具的入口。若監聽所有網路介面,同一區域網路中的其他裝置也可能嘗試存取,因此必須同時考慮作業系統防火牆、身分驗證與實際共享需求。沒有明確區域網路共享目的時,本機回送位址通常是更清楚的邊界。
port 必須未被其他程式佔用。同一個位址與連接埠組合不能由兩個同時執行的入站重複監聽。圖形用戶端常為 SOCKS、HTTP 或混合入口分配相鄰連接埠,但這些連接埠不是協定固定值;將教學中的連接埠直接套用到另一台裝置,可能剛好與開發伺服器、舊用戶端程序或其他網路工具衝突。出現「位址已在使用中」一類錯誤時,應先關閉重複執行個體,或在用戶端設定中修改監聽連接埠,再同步更新系統代理指向。
{
"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": "http-in",
"listen": "127.0.0.1",
"port": 10809,
"protocol": "http",
"settings": {}
}
]
}
SOCKS、HTTP 與透明入口的邊界
SOCKS 入站能承載由應用程式主動發起的代理連線,啟用 udp 後還可接收符合 SOCKS UDP 轉送流程的請求;這不表示任意系統 UDP 都會自動進入該連接埠。HTTP 入站主要處理支援 HTTP 代理設定的應用程式。系統代理通常只影響主動讀取系統設定的軟體,不等於擷取裝置上的全部流量。透明代理或基於虛擬網路介面的接入方式需要作業系統網路規則與用戶端協作,欄位和權限條件更複雜,不應只替換普通 SOCKS 入站的協定名稱後直接使用。
在 v2rayN 中,介面負責建立本機入口並設定 Windows、macOS 或 Linux 的系統代理狀態;在 v2rayNG 與 v2flyNG 中,Android VPN 服務負責將所選應用程式的流量送入核心。由此可見,同一份節點出站參數可以跨用戶端移轉,但入站部分往往與平台整合方式綁定。移轉時應保留伺服器參數,重新讓目標用戶端產生本機入口,而不是完整覆蓋其執行設定。平台安裝與用戶端定位可在用戶端下載頁核對。
sniffing 的作用與誤判邊界
嗅探用於從連線早期資料中還原網域名稱,讓網域路由規則能處理原本只攜帶 IP 目的位址的請求。destOverride 中常見的 http 與 tls,分別對應可識別的 HTTP 主機資訊與 TLS 握手網域名稱。嗅探不會解密應用程式內容,也不能保證每條連線都能還原網域名稱;加密握手變化、非標準協定、連線多工或直接使用 IP 的應用程式,都可能無法提供可用網域名稱。
如果啟用嗅探後某個應用程式的目的位址被改寫並導致連線異常,可先將該應用程式流量放入獨立入站,或限制覆寫類型,比較啟用與停用時的日誌。不要把嗅探當成 DNS 的替代品:DNS 決定網域名稱如何解析,嗅探則是在連線進入後嘗試辨識原始網域名稱,兩者發生在不同階段。路由規則若同時包含網域與 IP 條件,還要結合 domainStrategy 判斷核心是否會為路由目的額外解析網域名稱。
| 欄位 | 常見值 | 檢查重點 |
|---|---|---|
listen |
127.0.0.1 |
是否確實需要允許其他裝置存取 |
port |
有效的連接埠數字 | 是否與其他程式或入站重複 |
protocol |
socks、http |
settings 是否屬於對應協定 |
tag |
自訂的唯一名稱 | 路由中的引用是否完全一致 |
outbounds 出站、節點參數與鏈式關係
出站負責將經由路由選擇的連線傳送至目標位置。它可以連線到遠端協定伺服器,也可以直接存取目標、拒絕連線,或將流量交給另一個出站繼續處理。
協定欄位必須整體核對
遠端出站通常由 protocol、settings 與 streamSettings 共同定義。以 VLESS 為例,伺服器位址與連接埠位於 vnext 項目,使用者識別碼位於 users;傳輸方式、安全層與伺服器名稱則在 streamSettings 中。只核對位址、連接埠與使用者識別碼,不足以證明設定一致;用戶端與伺服器端的網路傳輸、TLS 類安全設定、路徑、主機名稱及相關擴充參數,也必須彼此對應。
設定介面常將這些欄位分散在「位址」「使用者」「傳輸」「安全」等頁面中,而 JSON 則把它們放在相鄰物件裡。訂閱匯入異常時,先在用戶端詳細資訊頁逐項查看,不要只根據節點顯示名稱判斷。節點名稱通常只是本機備註,不參與協定握手;真正影響連線的是結構化欄位。手動移轉參數時,應避免把 URI 中經過編碼的文字直接當作 JSON 原值,也不要把介面中表示「預設」的空白項目擅自改成字串 "default"。
{
"outbounds": [
{
"tag": "remote-vless",
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "server.example.com",
"port": 443,
"users": [
{
"id": "11111111-1111-4111-8111-111111111111",
"encryption": "none"
}
]
}
]
},
"streamSettings": {
"network": "ws",
"security": "tls",
"tlsSettings": {
"serverName": "server.example.com"
},
"wsSettings": {
"path": "/example-path",
"headers": {
"Host": "server.example.com"
}
}
}
},
{
"tag": "direct",
"protocol": "freedom"
},
{
"tag": "blocked",
"protocol": "blackhole"
}
]
}
direct 與 blocked 是明確的處理路徑
freedom 出站通常用於直接連線到目標,常標記為 direct;blackhole 用於終止被規則選中的連線,常標記為 blocked。這些標籤只是約定俗成的名稱,可以更改,但路由引用必須同步。將 freedom 放入出站陣列,不會自動讓本機位址直連,仍需由路由規則將相應流量指向它。同樣地,定義 blackhole 也不會自動攔截任何網域名稱,只有在匹配規則引用後才會生效。
沒有規則命中時,核心通常會選擇預設出站,具體行為取決於設定結構與核心實作。為避免讀者依賴隱含順序,大型設定宜為關鍵流量寫出明確規則,並讓出站標籤具有可讀意義。遠端出站、直連出站與阻斷出站的名稱應呈現用途,而不是使用容易混淆的連續數字。名稱清楚後,日誌中的出站識別也更容易對應到設定。
出站鏈、代理設定與循環
部分核心允許透過 proxySettings 或其他機制,讓一個出站經由另一個出站建立連線。這適用於明確設計的鏈式出口,但也增加了 DNS、握手與故障定位的層次。鏈條中的每一段都要有唯一標籤,且不能形成 A 指向 B、B 又指向 A 的循環。遠端伺服器網域名稱如何解析也需要單獨考慮:若用於建立第一段連線的 DNS 查詢反過來依賴尚未建立的出站,就可能形成啟動後持續逾時的閉環。
排查鏈式設定時,應先讓最後負責實體連線的單一出站獨立可用,再逐段向前加入。日誌若只有「連線已關閉」,需要結合出站標籤判斷失敗發生在哪一層。遠端拒絕、網域名稱解析失敗、TLS 伺服器名稱不符與本機路由提前選錯出站,都可能在表面上表現為應用程式無法開啟頁面。逐層驗證比同時替換所有協定參數更能保留證據。
桌面端優先使用 v2rayN 管理節點與核心設定,Android 可依核心需求選擇 v2rayNG 或 v2flyNG。若需要比較 Xray 與 V2Fly 的定位,可繼續閱讀Xray 與 V2Fly 核心差異整理;核心分支支援的欄位範圍可能不同,移轉複雜設定前應確認目標用戶端實際啟用的核心。
routing 路由規則、匹配條件與優先順序
路由物件不負責建立連線,它接收入站已辨識的目標資訊,並依照規則陣列選擇出站。理解「由前往後、首個命中」是維護分流設定的核心。
規則陣列的匹配模型
routing.rules 中常見的規則類型是 field,可依 domain、ip、port、network、protocol、inboundTag、user 等條件篩選連線,並透過 outboundTag 指定去向。同一條規則內出現多個不同類別的條件時,通常需要同時符合;同一欄位陣列中的多個值,則通常表示任一值命中。維護時不要只看某個網域清單,還要檢查同一條規則是否附帶連接埠或入站標籤限制。
規則會從陣列第一項開始向後檢查。較具體的例外應放在較寬泛的規則之前,例如需要使用遠端出站的內部測試網域,應置於涵蓋範圍更大的直連網域集合之前。若寬泛規則先命中,後面的例外永遠沒有執行機會。最後可以設定一條涵蓋其餘連線的規則,也可以依賴預設出站,但前者通常更便於檢閱。調整規則時應一次只移動一組,並記錄移動前後的命中標籤,避免把「規則未匹配」與「出站不可用」混為一談。
{
"routing": {
"domainStrategy": "IPIfNonMatch",
"domainMatcher": "hybrid",
"rules": [
{
"type": "field",
"domain": [
"full:intranet.example",
"domain:local.example"
],
"outboundTag": "direct"
},
{
"type": "field",
"ip": [
"geoip:private"
],
"outboundTag": "direct"
},
{
"type": "field",
"protocol": [
"bittorrent"
],
"outboundTag": "blocked"
},
{
"type": "field",
"network": "tcp,udp",
"outboundTag": "remote-vless"
}
]
}
}
domain 語法與 IP 條件
full: 表示完整網域名稱匹配,適合只處理一個確定的主機名稱;domain: 通常匹配指定網域及其子網域範圍;regexp: 提供正規表示式能力,但複雜表達式會增加維護成本,也容易把點號、邊界或跳脫寫錯。沒有前綴的寫法如何解讀,應以核心定義為準。規則集識別如 geosite: 與 geoip:,依賴核心可讀取的規則資料;名稱存在不代表本機資料一定包含相應項目。
IP 規則可以寫入單一位址,也可以寫成 CIDR 網段。geoip:private 常用於涵蓋私有位址範圍,讓區域網路裝置與本機服務不經由遠端出站。但網域名稱最後解析至私有位址時,是否進入 IP 規則仍受 domainStrategy 影響。若策略保持 AsIs,路由階段不會為了匹配 IP 規則主動解析網域名稱;使用 IPIfNonMatch 時,網域規則未命中後可能繼續解析並進行 IP 匹配;更積極的策略則可能更早解析。策略越積極,路由與 DNS 的耦合越明顯。
依入站、網路與協定分流
inboundTag 適合將不同本機入口送往不同出站,例如讓測試入口固定使用一個遠端出站,而普通系統代理繼續依網域規則處理。它也適合隔離臨時實驗:新增獨立連接埠與標籤,不修改主要入口即可驗證一組規則。network 可區分 TCP 與 UDP,但遠端協定與傳輸是否完整承載相應網路,仍需單獨確認。protocol 條件依賴核心的辨識結果,往往與入站嗅探相關,不應假定所有連線都能可靠分類。
分流結果與用戶端介面中的「全域」「規則」或「直連」等模式有關。介面模式可能切換不同的路由範本,也可能改變預設出站,而不是簡單修改單一規則。關於三種常見模式的作用範圍,可參閱系統代理、全域模式與繞過中國大陸模式的差異詳解。偵錯自訂規則時應固定用戶端模式,否則介面切換可能重新產生設定,讓手動修改看似失效。
| 條件 | 適合表達 | 常見誤區 |
|---|---|---|
domain |
完整網域名稱、後綴範圍、規則集 | 忽略前綴語意或規則順序 |
ip |
單一位址、CIDR、IP 規則集 | 未考慮網域名稱是否會在路由階段解析 |
inboundTag |
依本機入口隔離路徑 | 引用不存在或拼寫不同的標籤 |
network |
區分 TCP 與 UDP | 把網路類型當成應用程式協定類別 |
dns 設定、伺服器選擇與路由聯動
DNS 設定決定核心需要解析網域名稱時要向哪些伺服器查詢,以及特定網域名稱應優先進入哪組解析路徑。它與作業系統 DNS、應用程式自行解析及路由階段解析並非同一層。
先區分查詢由誰發起
應用程式可能先在系統層完成解析,然後只將目標 IP 交給代理;也可能把網域名稱原樣交給 SOCKS 或 HTTP 入站;部分應用程式還會使用自己的加密 DNS 機制。只有進入核心並由核心執行的查詢,才會直接受頂層 dns 物件控制。因此,修改設定後若觀察不到預期變化,應先確認入站收到的是網域名稱還是 IP,並檢查嗅探是否還原了網域名稱。僅更換 dns.servers,不能強制所有系統程式放棄自己的解析路徑。
servers 可以包含簡單位址,也可以包含帶有 address、domains、expectIPs、skipFallback 等屬性的物件。簡單陣列適合單一路徑;物件形式適合依網域名稱選擇伺服器。伺服器清單並不總是按照「第一個失敗才使用第二個」的傳統備援概念運作,網域篩選、回退設定與核心實作會共同決定查詢對象。設計複雜 DNS 前,先用兩個職責清楚的伺服器驗證,再加入網域範圍與回退限制。
{
"dns": {
"hosts": {
"router.example": "192.168.1.1"
},
"servers": [
{
"address": "localhost",
"domains": [
"full:router.example",
"domain:internal.example"
],
"skipFallback": true
},
{
"address": "1.1.1.1",
"domains": [
"domain:public.example"
]
},
"8.8.8.8"
],
"queryStrategy": "UseIP"
}
}
hosts、domains 與預期結果
hosts 用於為明確名稱提供靜態對應,適合少量穩定的本機服務名稱,不適合作為大型動態網域表。靜態對應的優先順序較高,位址變更後若忘記更新,會造成「只有某個名稱持續指向舊位址」的現象。排查時應同時檢查作業系統 hosts 檔案、用戶端介面中的主機覆寫項目,以及核心設定中的 dns.hosts,避免多層覆寫互相衝突。
伺服器物件中的 domains 用於篩選交由該伺服器處理的網域名稱,語法與路由網域條件相近,但用途不同:前者選擇解析器,後者選擇連線出站。expectIPs 可限制預期回傳位址的範圍,用於判斷結果是否符合預設;它不是把任意回應改寫成目標範圍。限制過窄時,正常回應也可能被排除並進入回退。skipFallback 則會影響該伺服器參與回退的方式,組合使用前應先畫出「網域選擇—伺服器查詢—結果檢查—連線路由」四步關係。
DNS 查詢如何選擇出站
DNS 伺服器位址本身也需要建立連線。若伺服器寫成網域名稱,首先還有解析解析器網域名稱的問題;若寫成 IP,則省去這一層,但仍須由路由選擇網路出站。較複雜的設定會為 DNS 流量分配標籤,再在路由中依標籤或協定送往特定出站。此時必須避免閉環:遠端出站依賴網域名稱解析,而該網域名稱解析又被要求透過尚未建立的遠端出站完成。
建立可解釋路徑的方法,是先讓遠端伺服器位址具備穩定的基礎解析路徑,再決定一般目標網域名稱如何分流。若設定中同時使用 domainStrategy 與 DNS 規則,路由為判斷 IP 條件而觸發的解析也會進入 DNS 模組。因此,表面上的路由問題,實際上可能由 DNS 伺服器篩選或回退結果造成。排查日誌時應依時間順序觀察查詢、取得位址、選擇出站與連線目標,而不是只截取最後一筆逾時訊息。
快取、IPv4 與 IPv6 選擇
queryStrategy 用於限制或偏向查詢回傳的位址族群,支援範圍依核心而異。強制只使用一種位址族群,可能繞過本地網路不完整的問題,但也可能排除原本可達的目標。應先確認作業系統是否具備相應的網路連通性,再決定是否限制查詢。用戶端、核心與系統解析器都可能快取結果,修改 DNS 後立即重試不一定會觸發新查詢;可以重新啟動相關用戶端程序並建立新連線,但不應把清除快取當作長期設定方案。
針對「網域名稱無法存取、直接使用 IP 卻可以」的情況,先核對查詢是否回傳位址,再檢查回傳位址是否被路由規則送往預期出站。針對「部分網域偶爾失敗」,則需要比較失敗與成功時選用的 DNS 伺服器、位址族群與出站標籤。更換伺服器只能驗證解析器路徑,不能取代對規則條件的檢查。關於常見用戶端連線主線與驗證方法,可回到入門指南逐步確認。
policy 策略、連線時限與統計開關
policy 不決定流量要走哪個節點,而是為使用者等級與系統層級行為設定連線逾時、閒置時間與統計開關。它位於路由選擇之外,卻會影響長連線的生命週期與可觀測性。
level 與 levels 的引用關係
policy.levels 是以使用者等級為鍵的物件。協定使用者設定中的 level 數字會引用對應策略;若使用者未明確設定,通常會使用預設等級。等級不是速度評分,也不是權限高低的自動排序,它只是將一組使用者連線對應到一組策略參數。把等級從 0 改為 1,不會自動提升效能;只有同時定義 levels["1"] 並設定不同欄位時,才會產生實際差異。
用戶端作為本機連線發起端時,多數使用者只需要預設等級。多等級更常見於需要區分不同入站使用者的伺服器端設定。即使如此,也應依實際管理需求決定,而不是為每個使用者建立一套幾乎相同的策略。策略越多,移轉時越容易遺漏引用。檢查時先搜尋所有 level,再確認 policy.levels 中存在對應鍵,並注意 JSON 物件鍵在文字中會寫成字串形式。
{
"policy": {
"levels": {
"0": {
"handshake": 4,
"connIdle": 300,
"uplinkOnly": 2,
"downlinkOnly": 5,
"statsUserUplink": false,
"statsUserDownlink": false
}
},
"system": {
"statsInboundUplink": true,
"statsInboundDownlink": true,
"statsOutboundUplink": true,
"statsOutboundDownlink": true
}
},
"stats": {}
}
握手、閒置與單向連線時限
handshake 控制建立連線初期可等待的時間範圍。設定過短會讓高負載裝置、慢速網路或需要多層握手的連線尚未完成便被關閉;設定過長則會讓失敗連線佔用資源更久。connIdle 用於判斷連線在沒有活動時保留多久。即時通訊、推播、遠端終端機與串流媒體可能有不同的閒置行為,不能只根據網頁瀏覽測試決定所有長連線的數值。
uplinkOnly 與 downlinkOnly 處理連線只剩單向傳輸後的生命週期。它們不是上傳或下載速率限制,也不會為某個方向分配頻寬。如果應用程式在一段單向傳輸後提前中斷,應結合這些值檢查;若連線在雙向都沒有資料後中斷,則更可能與 connIdle 有關。遠端伺服器、中間網路設備與應用程式本身也可能主動關閉連線,因此本機 policy 只是排查鏈的一部分。
統計欄位需要完整的啟用鏈
statsUserUplink 與 statsUserDownlink 控制使用者層級統計,policy.system 中的欄位則控制入站與出站方向統計。僅將布林值設為 true,不一定會讓用戶端介面顯示資料,還需要頂層 stats 物件、相應 API 或用戶端讀取邏輯配合。反過來,介面沒有顯示也不能直接推斷核心沒有統計。應區分「計數器未啟用」「計數器存在但未被讀取」「讀取介面與用戶端顯示不相容」三種狀態。
統計會帶來額外的狀態維護,是否啟用應依診斷與管理需求決定。個人桌面設定若不讀取統計結果,可以保持簡化;需要分析某個入站或出站是否有流量時,可暫時啟用系統層級計數器,並配合日誌驗證標籤。不要把統計值當作判斷連線品質的唯一依據:它只能說明經過相應處理器的資料量變化,不能直接解釋握手耗時、應用程式回應或 DNS 選擇。
策略修改的驗證方式
修改連線時限後,應使用能穩定重現問題的情境驗證。例如讓一條長連線閒置超過原本的閾值,再傳送資料,觀察連線是否重新建立;不要透過快速重新整理網頁推斷閒置策略。若只有某個協定或應用程式異常,先確認其連線是否真的對應到修改過的使用者等級。用戶端產生設定時也可能覆寫手動設定的 policy,因此應在執行時設定或日誌中核對最終值。
policy 適合處理明確的生命週期與統計需求,不適合用來修正錯誤路由、錯誤傳輸或遠端參數。若連線從一開始就無法建立,應回到出站與傳輸層;若只有特定網域不通,應檢查路由與 DNS;若連線建立後在固定閒置階段中斷,再檢查策略物件。依照這個順序,可以避免透過放寬逾時掩蓋真正的握手失敗。
streamSettings、傳輸方式與安全參數
遠端協定定義身分與請求格式,streamSettings 則定義這些資料如何承載於網路連線上。兩端協定參數正確但傳輸層不一致,連線仍無法完成。
network 決定後續設定物件
streamSettings.network 指定傳輸類型,常見設定可能涉及 TCP、WebSocket、gRPC 或 mKCP。選擇某種網路後,應使用與之對應的設定物件,例如 WebSocket 使用 wsSettings,gRPC 使用對應的服務名稱設定。保留另一種傳輸的欄位,通常不會自動將兩者組合,反而會造成閱讀誤判。移轉節點時,應先確認介面顯示的傳輸類型,再展開其專屬欄位逐項核對。
傳輸類型不是可由用戶端單方面最佳化的選項。伺服器端監聽什麼傳輸、使用什麼路徑或服務名稱,用戶端就必須依相同結構連線。遇到錯誤時頻繁在 TCP、WebSocket 與 gRPC 之間切換,通常只會增加變數。較穩妥的做法是依來源設定固定傳輸類型,檢查位址是否可解析、連接埠是否可達,然後再檢查路徑、主機欄位與安全層。
{
"streamSettings": {
"network": "grpc",
"security": "tls",
"tlsSettings": {
"serverName": "edge.example.com",
"allowInsecure": false,
"alpn": ["h2"]
},
"grpcSettings": {
"serviceName": "example-service",
"multiMode": false
},
"sockopt": {
"tcpKeepAliveIdle": 100
}
}
}
WebSocket 路徑、Host 與 TLS 名稱
WebSocket 設定中的 path 是 HTTP 握手路徑,是否帶有前導斜線、是否包含查詢部分,都應與伺服器端入口一致。headers.Host 屬於 WebSocket 握手標頭,而 tlsSettings.serverName 用於 TLS 伺服器名稱驗證,兩者可能相同,也可能因部署結構而不同。將它們視為同一欄位同步替換,可能導致其中一層成功、另一層失敗。
伺服器位址 address 決定最初連線至哪台主機,TLS 名稱決定憑證與握手所針對的名稱,WebSocket Host 則由 HTTP 層處理。排查時應依連線建立順序理解三者。若位址可以建立 TCP 連線但 TLS 失敗,重點檢查系統時間、伺服器名稱與安全參數;若 TLS 成功後 WebSocket 被拒絕,則繼續檢查路徑與 Host。單純將憑證驗證選項改為寬鬆值會降低錯誤可見性,不應作為常規修復方式。
gRPC、mKCP 與傳輸專屬欄位
gRPC 設定通常需要準確的 serviceName,並依賴 HTTP/2 相關協商。服務名稱是設定值,不是節點備註,也不應自行加入 URL 形式的斜線。若中間層不支援所需連線方式,可能表現為握手後立即關閉。mKCP 屬於基於 UDP 的傳輸,除了雙方參數外,也取決於目前網路是否能穩定承載 UDP;TCP 可達不能證明 UDP 路徑同樣可達。
傳輸專屬參數數量較多時,應優先使用用戶端依節點資訊產生的結構,再針對明確需求修改。網路上跨核心、跨時期的範例,可能包含已經調整過的欄位名稱。v2rayN 通常搭配桌面端核心管理,v2rayNG 使用 Xray 核心路徑,v2flyNG 則面向 V2Fly 核心;同名傳輸的基礎概念相近,但擴充欄位未必完全一致。無法確認支援範圍時,先刪除非必要擴充,保留伺服器端要求的核心欄位。
security、TLS 與 Reality 的層級
security 決定啟用的安全層,對應設定物件必須與其一致。TLS 參數放在 tlsSettings,Reality 參數則使用核心規定的獨立設定物件。兩類設定不能只替換 security 字串,卻沿用全部舊欄位。伺服器名稱、公鑰類參數、短識別碼與指紋類選擇,都屬於特定安全方式的握手條件,必須來自同一份有效設定。
安全層錯誤與使用者識別碼錯誤在介面上都可能表現為連線測試失敗,因此需要依日誌判斷 DNS、TCP、TLS 或協定驗證發生在哪一步。若連伺服器連接埠都無法建立連線,繼續修改伺服器名稱沒有意義;若 TCP 已建立但安全握手失敗,則不要先修改路由規則。先將故障定位到具體層級,再修改參數,可避免某項改動暫時改變錯誤形式,卻沒有解決根本原因。
| 層級 | 代表欄位 | 需要與遠端一致的內容 |
|---|---|---|
| 目標連線 | address、port |
主機與監聽連接埠 |
| 傳輸 | network |
傳輸類型、路徑或服務名稱 |
| 安全層 | security |
伺服器名稱及對應握手參數 |
| 應用程式協定 | protocol、settings |
使用者識別碼與協定屬性 |
設定驗證與故障排查的分層方法
有效的故障排查不是連續更換參數,而是確認連線經過了哪一層、在哪一層停止。結構、監聽、解析、路由、出站與應用程式設定,應依固定順序檢查。
第一層:確認 JSON 可以讀取
啟動失敗時,先查看用戶端或核心日誌中的第一筆結構錯誤,記錄行號與欄位路徑。常見問題包括缺少逗號、括號類型不匹配、字串未閉合、欄位放錯物件、數字寫成字串,以及標準 JSON 中出現註解。編輯器提示的錯誤位置有時位於真正錯誤的下一行,因為解析器直到讀到後續字元,才確定前一項不完整。因此,也應檢查報錯行之前的物件結尾。
結構合法不代表欄位語意合法。拼寫正確的 JSON 仍可能包含核心不認識的欄位、錯誤的協定設定或不存在的標籤。此時應依照日誌中的物件路徑回到對應章節,核對該欄位屬於入站、出站還是傳輸設定。若用戶端每次啟動都會重新寫入設定,表示編輯的是產生後的檔案;應回到用戶端介面或其自訂設定入口修改來源設定。第一次使用用戶端的完整操作順序請見入門指南。
{
"log": {
"access": "",
"error": "",
"loglevel": "warning"
}
}
第二層:確認連線進入正確入站
設定載入後,檢查本機監聽位址與連接埠是否出現。應用程式的代理位址必須與入站一致,SOCKS 與 HTTP 類型也不能混用。系統代理已啟用但應用程式仍直接連線時,應確認該應用程式是否讀取系統設定;反過來,用戶端已關閉系統代理,但瀏覽器擴充功能仍保留獨立代理時,流量仍可能進入舊連接埠。排錯期間只保留一種入口方式,能大幅減少重複代理與路徑不明的問題。
若連接埠沒有監聽,先檢查是否被佔用、用戶端核心是否啟動,以及設定是否被另一個程序讀取。若連接埠存在但日誌完全沒有存取記錄,問題通常出在應用程式到入站之間。若日誌已記錄目標位址,表示入口成立,可以繼續檢查路由與出站。行動裝置還要確認 VPN 服務狀態與分應用程式代理範圍;被排除的應用程式不會經過 v2rayNG 或 v2flyNG 的核心路徑。
第三層:沿著 DNS、路由與出站標籤追蹤
針對一個固定測試網域名稱發起請求,依序記錄核心是否取得網域名稱、是否觸發解析、命中了哪條路由,以及選擇了哪個出站。只有網域名稱失敗而 IP 成功時,重點查看 DNS 與網域規則;所有目標都進入錯誤出站時,重點查看寬泛規則與預設路徑;特定應用程式失敗時,則比較其入站標籤、網路類型與嗅探結果。不要同時使用多個持續變動的測試網站,否則快取、位址族群與網域規則差異會引入額外變數。
若路由命中正確但遠端出站失敗,再檢查位址解析、連接埠可達性、協定使用者參數、傳輸類型與安全層。排錯期間可適度提高日誌等級,但完成記錄後應恢復到適合日常使用的等級,避免大量日誌掩蓋關鍵事件。日誌內容可能包含目標網域、本機位址與本機路徑,分享片段前應刪除與問題無關的個人設定資料。
第四層:區分用戶端狀態與核心狀態
v2rayN、v2rayNG 與 v2flyNG 都包含用戶端管理層,核心只是其中負責處理連線的一部分。訂閱更新成功表示用戶端已取得並解析訂閱,不代表其中每個節點都能連線;延遲測試失敗也不一定等同於所有應用程式連線失敗,因為測試方法、目標位址與實際應用程式協定可能不同。應分開判斷「訂閱是否更新」「節點是否被選取」「核心是否啟動」「系統或 VPN 入口是否啟用」「實際請求是否通過」。
v2rayN 的 Avalonia 桌面版支援 Windows、macOS 與 Linux,WPF 版僅支援 Windows,兩條發行線在介面與系統整合方面有所差異。需要選擇桌面版本時,可參考v2rayN 桌面版與 WPF 版對照。Linux 的安裝與登入工作階段啟動設定,則可查閱Linux 安裝 v2rayN 步驟。平台差異主要影響用戶端外層操作,不應據此任意修改節點協定參數。
建立可回復的修改記錄
每輪只修改一個邏輯層,並保存修改前的可用副本。可以依「結構整理、入站、DNS、路由、出站、傳輸、策略」的順序命名本機記錄,同時寫下預期結果與實際日誌。若一次修改包含多個欄位,即使連線恢復,也無法確認哪個欄位才是真正原因,後續移轉時容易再次出現同類問題。恢復設定時應完整恢復同一輪版本,避免混合舊路由與新標籤。
對於訂閱管理的節點,應優先在用戶端提供的編輯入口中調整,並了解訂閱更新是否會覆寫本機修改。需要長期保留的路由與 DNS 規則,宜放入用戶端支援的自訂設定層,而不是反覆修改暫時的執行檔案。設定規模增大後,也應定期刪除未被引用的標籤、重複規則與過期實驗入站,讓日誌中的每條路徑都能對應目前用途。
從參考設定回到用戶端操作
當最小設定可以正常運作後,再依序恢復網域規則、DNS 分流、多個出站與策略設定;每恢復一組,就重複固定測試。若問題只在恢復某組後出現,檢查範圍便可收斂到該組及其引用物件。需要重新安裝或切換用戶端時,請從用戶端下載頁依 Windows、macOS、Android、Linux 選擇對應入口;下載頁中的常見問題區也整理了安裝套件選擇、處理器架構與版本切換說明。
設定檔是一組彼此引用的宣告,不是互相孤立的參數集合。入站標籤會影響路由條件,路由策略可能觸發 DNS,DNS 查詢又需要出站,傳輸安全層最終決定遠端連線能否建立。依照相依鏈閱讀,可以將「無法連線」拆解為可驗證的結構問題、入口問題、解析問題、規則問題或握手問題。完成一次有記錄的分層排查後,同樣的方法也能套用到後續節點移轉與用戶端升級,不必重新從隨機修改開始。