01 / JSON STRUCTURE
設定檔結構總覽
先依流量方向理解頂層物件
V2Ray 與 Xray 的設定檔通常是一個 JSON 物件。首先要記住的不是欄位數量,而是流量方向:應用程式先連線到本機的入站監聽,核心讀取路由規則、選擇一個出站,再透過目標出站建立連線。DNS 負責將網域解析為位址,policy 負責工作階段逾時、統計等執行策略,log 則決定記錄位置與紀錄等級。
inbounds 和 outbounds 都是陣列,因為同一個執行個體可以同時監聽多個本機連接埠,也可以準備多個出口。陣列中的每個物件通常使用 tag 命名,路由規則再透過標籤引用。標籤只是執行個體內部的識別名稱,不會傳送給遠端;名稱可自行決定,但應保持簡短、穩定且能看出用途,例如 socks-in、proxy、direct 和 block。
一個便於閱讀的設定順序是:先寫入日誌,再寫 DNS,接著是入站、出站、路由與策略。JSON 本身不要求這個順序,但固定排列能縮短排查時間。遇到啟動失敗時,可以從檔案開頭往下檢查;比較兩份設定時,也更容易找出變更。圖形用戶端產生的順序可能不同,只要層級與欄位有效,執行結果不會因物件鍵的排列順序而改變。
{
"log": {
"loglevel": "warning"
},
"dns": {},
"inbounds": [],
"outbounds": [],
"routing": {},
"policy": {}
}
JSON 語法與設定語意是兩層檢查
設定能被 JSON 解析,只代表括號、引號、逗號與資料型別符合語法,不表示目前核心會接受所有欄位。例如連接埠寫成字串,可能是合法 JSON,卻不符合該欄位需要整數的要求;出站標籤拼寫不一致,也可能直到套用路由時才暴露問題。排查時要分兩步:先確認 JSON 可以解析,再查看核心日誌中關於未知欄位、型別錯誤、標籤缺失或協定設定不完整的提示。
標準 JSON 不允許註解,也不允許在物件或陣列最後一項後保留多餘逗號。複製範例時尤其要注意這一點。文件為了說明經常展示片段,但片段本身只有放入正確的父層物件才有效。例如單獨複製 routing 物件時,必須將它作為頂層的 "routing" 值,而不是直接貼到檔案末尾。字串必須使用雙引號,布林值使用 true 或 false,不能加上引號。
| 欄位 | 資料型態 | 主要用途 | 常見檢查點 |
|---|---|---|---|
log |
物件 | 控制存取日誌、錯誤日誌與記錄等級 | 路徑權限、日誌等級是否過低 |
inbounds |
陣列 | 接收來自瀏覽器、系統或區域網路裝置的連線 | 監聽位址、連接埠占用、協定類型 |
outbounds |
陣列 | 定義代理、直連與阻擋等出口 | 伺服器參數、標籤、傳輸設定 |
routing |
物件 | 依網域、IP、連接埠或入站標籤選擇出口 | 規則順序、標籤引用、解析策略 |
dns |
物件 | 定義解析伺服器、靜態對映與查詢條件 | 查詢路徑、網域比對、回退行為 |
policy |
物件 | 控制工作階段逾時、流量統計等執行策略 | 策略層級、統計開關與統計模組的配合 |
修改前建立可回復的基準
開始調整前,先讓目前設定在不修改的情況下成功啟動一次,並記下正在使用的本機連接埠、系統代理模式與核心名稱。接著複製設定檔,為副本加上用途明確的檔名。每次只修改一個邏輯單元,例如先增加直連出站,驗證後再加入路由規則。一次改動多個區域雖然較快,但啟動失敗時很難判斷是語法、標籤還是協定參數造成的。
圖形用戶端可能在更新訂閱、切換節點或重新啟動核心時重新產生執行設定。此時直接編輯暫存檔,變更可能無法長期保留。v2rayN 中應優先使用用戶端提供的自訂設定、路由設定或進階選項;Android 用戶端則先確認目前設定來自訂閱節點還是手動設定。想了解某個術語的界線,可同時查看術語表,避免將「入站」、「系統代理」與「路由模式」理解成同一項功能。
02 / INBOUNDS
inbounds 入站設定
監聽位址決定誰能連線
入站是本機應用程式將流量交給核心的入口。最常見的本機入口是 SOCKS 與 HTTP 代理。listen 決定在哪個網路位址監聽,port 決定連接埠,protocol 決定應用程式應使用哪種代理協定。只供目前裝置使用時,建議將監聽位址寫成 127.0.0.1。這個位址只接受本機連線,瀏覽器、系統代理與同一裝置上的其他程式可以使用,區域網路中的其他裝置無法直接接入。
如果需要讓桌面用戶端提供給同一區域網路中的手機、電視或另一台電腦使用,入站通常會監聽 0.0.0.0 或特定的區域網路位址。這麼做還需要同時處理系統防火牆、網路類型與存取控制,不能只修改監聽位址。共用裝置填寫的是執行核心那台電腦的區域網路位址與入站連接埠,而不是 127.0.0.1。相關操作可參考v2rayN 允許區域網路連線設定教學。
{
"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 入站適合明確支援 SOCKS 代理的應用程式,可承載 TCP,並在設定允許時處理 UDP。HTTP 入站主要供使用 HTTP CONNECT 或一般 HTTP 代理的程式連線。兩者都要求應用程式或系統代理明確指向對應連接埠。程式設定為 HTTP 代理時,不能將位址指向 SOCKS 連接埠;連接埠雖然正確但協定類型選錯,常見表現是連線立即中斷、瀏覽器提示代理回應異常,或日誌中出現無法識別的握手資料。
TUN 模式與一般本機代理不同。它透過虛擬網路介面接收更廣泛的系統流量,用戶端還需要設定路由表、DNS 接管與權限。不要將 TUN 相關設定簡單理解成多加一個 SOCKS 入站。v2rayN 會依據介面中的 TUN 選項組織執行參數,通常應先透過用戶端介面啟用,再檢查日誌,而不是將其他環境中的完整 TUN 片段直接拼入目前設定。一般系統代理已能滿足瀏覽器與常見桌面程式時,沒有必要為了「涵蓋更多」而同時啟用多種接管方式。
sniffing 如何協助網域路由
sniffing 用來從連線中的協定特徵還原目標網域。某些應用程式會先自行解析網域,再將 IP 位址交給代理;如果 routing 只有網域規則,核心看到純 IP 時就無法依網域比對。啟用嗅探後,HTTP 請求中的主機資訊或 TLS 握手中的伺服器名稱,可以協助路由模組取得網域。範例中的 destOverride 表示允許使用辨識出的 HTTP 或 TLS 目標覆寫原始目的位址,讓後續規則進行判斷。
嗅探不是 DNS 的替代品,也不是所有連線都能還原網域。沒有可辨識主機資訊的協定仍然只會呈現 IP;加密握手方式與應用程式行為也會影響結果。排查路由未命中時,可以先查看存取日誌記錄的是網域還是 IP,再決定調整 domainStrategy、增加 IP 規則或檢查嗅探設定。不要在沒有觀察日誌的情況下反覆堆疊相同的網域與 IP 條件,這會讓規則難以維護。
連接埠、驗證與標籤的設定原則
同一個位址上的連接埠不能同時被兩個程序占用,也不能讓兩個入站監聽相同位址與連接埠。用戶端啟動後若立即回報位址已被占用,先關閉重複執行的執行個體,再檢查其他代理工具或舊核心程序。隨意修改連接埠只能解決一半衝突:系統代理、瀏覽器擴充功能與區域網路裝置中的連接埠也必須同步修改。為減少混淆,可以讓 SOCKS 與 HTTP 連接埠相鄰,但不要依賴固定數字判斷協定類型。
auth: "noauth" 適合只監聽回送位址的本機 SOCKS 入站。監聽區域網路位址時,應依用戶端支援情況評估驗證與防火牆限制,並只允許可信任的網路存取。標籤方面,每個入站使用獨立名稱,之後就能透過 inboundTag 為不同入口設定不同路由。例如本機流量使用一般分流,區域網路共用入口限制部分連接埠。修改標籤後,要全文檢查 routing 中的引用,避免規則仍指向舊名稱。
| 參數 | 建議理解方式 | 常見錯誤 |
|---|---|---|
listen |
決定連線來源範圍 | 共用時仍填寫回送位址,或本機使用時開放至所有網卡 |
port |
應用程式連線至核心的本機連接埠 | 與其他程式衝突,修改後未同步系統代理 |
protocol |
定義入站握手方式 | 應用程式選擇 HTTP,實際連線至 SOCKS 連接埠 |
tag |
供路由規則引用的內部名稱 | 更名後 routing 仍使用舊標籤 |
sniffing |
協助還原網域並參與分流 | 誤以為啟用後所有 IP 都能轉換成網域 |
03 / OUTBOUNDS
outbounds 出站設定
代理、直連與阻擋組成基礎出口
出站定義核心要將流量送往何處。完整設定通常至少包含代理出口與直連出口,需要明確拒絕某類連線時再增加阻擋出口。代理出口保存伺服器位址、連接埠、使用者識別碼、加密或傳輸設定;直連出口讓核心直接存取目標;阻擋出口則主動終止符合規則的連線。routing 不負責建立連線,只負責將目前請求交給某個出站標籤。
出站陣列的順序值得留意。當某條連線沒有命中任何路由規則時,常見實作會使用第一個出站作為預設出口。因此,將代理放在第一項,還是將直連放在第一項,會直接影響未命中流量的去向。不要只依賴預設順序表達重要策略,關鍵流量應明確寫出規則;同時仍要讓第一項符合整體預期,避免新增網域或遺漏條件時產生意外結果。
{
"outbounds": [
{
"tag": "proxy",
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "server.example.com",
"port": 443,
"users": [
{
"id": "11111111-2222-4333-8444-555555555555",
"encryption": "none"
}
]
}
]
},
"streamSettings": {
"network": "tcp",
"security": "tls",
"tlsSettings": {
"serverName": "server.example.com"
}
}
},
{
"tag": "direct",
"protocol": "freedom",
"settings": {}
},
{
"tag": "block",
"protocol": "blackhole",
"settings": {
"response": {
"type": "none"
}
}
}
]
}
協定身分參數與傳輸參數要分開檢視
排查代理出站時,先將欄位分成兩組。第一組是協定身分參數,例如伺服器位址、連接埠、使用者 ID 與協定要求的附加設定;第二組是 streamSettings 中的傳輸參數,例如 TCP、WebSocket、gRPC、TLS 或 REALITY。兩組參數各自正確但組合關係不一致,連線仍然無法建立。例如遠端使用 WebSocket,而本機設定成 TCP;伺服器憑證對應的名稱與 serverName 不同;使用者識別碼正確,但連接埠指向另一項服務。
訂閱匯入的價值之一,就是將服務提供者給出的協定、傳輸、安全層與主機參數一併寫入用戶端。手動遷移時不要只複製位址與連接埠。看到「節點能測試但網頁打不開」時,也不要立即認定出站身分參數全部正確:用戶端測試方法可能只涵蓋部分鏈路,實際應用還會涉及 DNS、UDP、路由與系統代理。應結合執行日誌判斷失敗發生在解析、連線至遠端、握手還是存取目標階段。
直連出口同樣會受到 DNS 與網路環境影響
freedom 表示由目前裝置直接建立目標連線。它不是繞過整個設定流程,而是仍經過入站與 routing 後,由核心執行直連。直連失敗時要檢查本機網路、系統 DNS、目標位址以及出站的網域策略。若規則依網域選擇 direct,但目標在建立連線前需要解析,解析結果與位址族會影響後續行為。某些環境中 IPv6 記錄存在但實際連線條件不完整,也可能表現為等待較久後逾時。
可以為 freedom 出站設定適當的網域解析策略,但不同核心支援的值與行為可能有差異。沒有明確需求時,先保留用戶端產生的預設值。除錯過程中若想判斷問題是否來自分流,可以暫時建立一條範圍很小、目標明確的規則送往 direct,而不是刪除全部規則。驗證完成後再復原,避免臨時測試改變其他應用程式的流量路徑。
代理鏈與多出口應從簡單結構開始
一個設定可以包含多個代理出站,並透過路由標籤選擇,也可以讓一個出口經由另一個出口建立底層連線。這種結構適合有明確鏈路需求的環境,但標籤依賴會迅速增加。開始設定前先畫出「入站 → 路由 → 第一出口 → 底層出口」的順序,確保不存在互相引用。若 proxy-a 依賴 proxy-b,而 proxy-b 又回到 proxy-a,核心便無法得到有效鏈路。
多節點選擇通常由 v2rayN、v2rayNG 或 v2flyNG 的設定管理功能完成。用戶端切換節點時,會調整目前使用的出站或重新產生執行設定。直接在產生檔案中塞入大量伺服器物件,不一定能配合用戶端的切換邏輯。桌面環境優先讓 v2rayN 管理節點,只將穩定的自訂路由與 DNS 需求放到用戶端支援的擴充位置,這比長期手動維護整份節點清單更容易復原。
| 標籤範例 | 協定 | 用途 | 排查重點 |
|---|---|---|---|
proxy |
依節點實際協定 | 連線至遠端伺服器並轉送目標流量 | 位址、連接埠、身分、傳輸與安全層必須成套一致 |
direct |
freedom |
從本機網路直接存取目標 | 本地網路、DNS、位址族與目標可達性 |
block |
blackhole |
終止符合規則的流量 | 規則範圍是否過寬,是否誤傷必要連線 |
04 / ROUTING
routing 路由規則
規則由上至下比對,第一個結果生效
路由模組會依連線的目標網域、IP、連接埠、網路類型、協定特徵或入站標籤選擇出站。最重要的行為是規則順序:規則通常由上至下檢查,一旦某條規則符合,就使用該規則指定的 outboundTag,後續規則不再參與。因此,較具體的規則應放在前面,較寬泛的規則放在後面。若將「所有 TCP 流量走代理」寫在第一條,後面的直連網域規則就沒有機會生效。
設計規則時,先寫出預設策略,再列出例外。如果預設出口是代理,可以優先放置阻擋條件與明確直連條件,其餘流量落到預設代理;如果預設出口是直連,則先列出需要代理的目標。不要同時依賴出站陣列順序、複雜網域清單與多條兜底規則來表達同一件事。選擇一種清楚的預設行為,規則只描述例外,之後維護時更容易判斷新增項目應放在哪裡。
{
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"protocol": [
"bittorrent"
],
"outboundTag": "direct"
},
{
"type": "field",
"domain": [
"domain:intranet.example.com",
"full:printer.example.net"
],
"outboundTag": "direct"
},
{
"type": "field",
"ip": [
"geoip:private"
],
"outboundTag": "direct"
},
{
"type": "field",
"network": "tcp,udp",
"outboundTag": "proxy"
}
]
}
}
網域比對方式決定規則界線
網域條件常見寫法包括完整比對、網域及其子網域比對、關鍵字比對與預設網域集合。full:printer.example.net 只比對完整主機名稱,適合界線明確的單一服務;domain:example.com 通常涵蓋該網域及其子網域,適合一組相關主機;沒有前綴的字串在不同情境下可能以特定方式解讀,維護時最好明確寫出比對類型,避免日後忘記原意。
關鍵字比對範圍較廣,一個短字串可能意外命中不相關網域。除非確實需要依名稱片段分類,否則優先使用 full 或 domain。規則未命中時,先確認核心看到的目標是不是網域。如果應用程式已將目標解析為 IP,而入站嗅探沒有還原網域,那麼再精確的網域規則也不會執行。此時可以檢查存取日誌、啟用適當的 sniffing,或為已知位址範圍補充 IP 條件。
domainStrategy 串連網域規則與 IP 規則
domainStrategy 控制路由模組在什麼情況下為了比對 IP 規則而解析網域。AsIs 強調依收到的目標形式判斷,網域不會僅為了路由比對而主動轉換成 IP;IPIfNonMatch 通常表示網域規則未命中後,再解析位址並嘗試比對 IP 規則;其他策略可能會更積極地進行解析。策略越積極,網域流量越可能參與 IP 分類,但也會增加 DNS 行為與路由結果之間的耦合。
選擇策略時要先問:目前規則主要依賴網域還是 IP?如果大部分規則是明確網域,只有少數網段需要補充判斷,IPIfNonMatch 會比較容易理解。如果所有網域都要先依位址分類,就必須確保 DNS 設定與預期出口一致。否則同一網域因解析伺服器、快取或位址族不同而得到不同結果,路由也會改變。修改 domainStrategy 後,應測試網域規則、IP 規則與未命中目標三種情況,而不是只開啟一個網頁判斷成功與否。
IP、連接埠、網路與入站標籤可以組合
IP 條件可以寫單一位址、CIDR 網段或核心支援的預設集合。私有位址通常應直連,避免存取路由器、印表機或區域網路服務時被送往遠端。連接埠條件適合限制明確的服務範圍,例如 53 或 80,443,也可以表示區間。網路條件常用 tcp、udp 或兩者組合。同一條規則中放入多個不同欄位時,通常需要同時符合;同一欄位陣列中的多個值則表示符合任一值。
inboundTag 很適合區分來源。例如 socks-in 走一般分流,lan-in 只允許使用指定出口。這樣不必為每種來源啟動多個核心執行個體。設定時應先確認入站標籤確實存在,並將來源限制寫在規則前段,避免被更寬泛的目標規則搶先比對。阻擋連接埠與協定時也要保守,範圍過寬會表現為部分應用程式能開啟首頁,卻無法播放、登入或同步。
用日誌驗證規則,不靠猜測
驗證路由最有效的方法,是準備幾個目標明確的測試項目:一個應直連的內部網域、一個應進入代理的目標,以及一個應被阻擋的條件,再查看存取日誌中的出站標籤。若日誌只顯示目標,未顯示預期標籤,可以暫時提高日誌詳細程度,測試完成後再恢復到較克制的等級,避免日誌持續增長。修改規則後要重新啟動或重新載入核心,確認用戶端沒有繼續使用舊的執行設定。
當規則數量變多時,為每組規則在設定檔外撰寫維護說明,記錄「為什麼需要這條」,比只記錄網域清單更有價值。標準 JSON 不能寫註解,可在獨立文件中保存說明。訂閱更新一般會影響節點與代理出站,不應順手覆蓋手動路由;如果用戶端每次更新後都遺失規則,表示編輯位置可能是暫存產生檔,應改用用戶端提供的路由設定入口。
05 / DNS
dns 解析設定
先分清系統解析與核心解析
DNS 設定容易出錯,是因為一台裝置上可能同時存在多條解析路徑。應用程式可以先呼叫系統 DNS 取得 IP,再將 IP 交給代理;核心也可以為了路由判斷主動解析網域;TUN 情境還可能由用戶端接管系統查詢。設定檔中的 dns 主要定義核心自身如何解析,並不會自動確保所有應用程式查詢都經過這裡。判斷問題前,先確認日誌中進入核心的是網域還是已解析好的 IP。
如果應用程式將網域直接交給 SOCKS 或 HTTP 代理,核心有機會依自己的 DNS 設定處理。若應用程式先在本地解析,routing 看到的可能只有位址,此時 DNS 設定對該次原始查詢不一定生效。sniffing 可以從部分連線中還原網域,但不能取代完整的查詢接管。因此,「已經寫了 dns 物件」與「所有程式都使用該 DNS」並不是同一回事。
{
"dns": {
"hosts": {
"router.home.arpa": "192.168.1.1"
},
"servers": [
{
"address": "1.1.1.1",
"domains": [
"domain:example.com"
],
"skipFallback": true
},
"localhost"
],
"queryStrategy": "UseIP"
}
}
servers 陣列既有順序,也可以附帶條件
servers 可以包含簡單位址,也可以使用物件為某個伺服器附加網域條件、預期位址範圍或回退行為。簡單設定從一至兩個穩定的解析來源開始即可。伺服器越多,不代表解析越可靠;如果各伺服器的使用條件不清楚,失敗時很難判斷查詢實際送往何處。物件中的 domains 用來讓指定網域優先交給該伺服器,適合內部網域或有明確解析來源的服務。
skipFallback 的用途,是控制符合目前伺服器條件的查詢是否還參與後續回退。啟用前要確認該伺服器確實能解析所列網域,否則查詢失敗後可能不會再嘗試其他來源。對於區域網路主機名稱,直接使用本地解析伺服器或 hosts 靜態對映通常更清楚。將內部名稱交給公共解析來源,不僅得不到結果,還可能讓排查方向偏離本地網路。
hosts 適合穩定對映,不適合維護動態位址
hosts 可以將網域對映至固定位址,也可以用於少量別名關係。它在測試新服務、覆寫區域網路主機名稱或暫時繞過錯誤解析時很方便。由於對映優先於一般查詢,寫錯後會持續將連線送往錯誤目標。使用 hosts 排錯時,要記錄新增項目,並在驗證後決定是否保留,避免數週後位址已經變更,設定卻仍固定在舊值。
對映值的資料型態要符合核心要求,網域鍵也應寫成預期的完整名稱。如果目標同時有 IPv4 與 IPv6,單一固定對映會改變正常的位址選擇。對於由服務提供者動態調度的網域,不建議使用 hosts 長期固定某個結果;看似縮短了一次查詢,實際上可能失去故障切換與位址更新能力。遇到偶發連線問題,應先比較解析結果與連線日誌,而不是立即將目前 IP 寫死。
queryStrategy 影響位址族選擇
queryStrategy 用來控制查詢 IPv4、IPv6 或兩類位址的傾向。不同核心支援的具體值可能有所差異,應以目前用戶端所使用核心的有效設定為準。裝置所在網路只有穩定 IPv4 時,強制只回傳 IPv6 會導致目標無法連線;網路具備 IPv6 並不表示每條遠端鏈路都適合優先使用它。選擇策略時要結合本地網路、代理伺服器位址與目標出站的能力。
典型現象是網域解析很快,但連線在某個位址族上持續等待,之後回退或逾時。此時可以分別查看解析得到的 A 與 AAAA 記錄,再觀察核心實際嘗試的目標位址。不要將所有 timeout 都歸咎於節點故障。若切換查詢策略後恢復,應繼續確認是本地 IPv6 路由、遠端伺服器監聽還是目標網路路徑的問題,而不是永久依賴一個偶然有效的設定。
DNS 與 routing 需要閉環檢查
當 domainStrategy 需要解析網域以比對 IP 規則時,routing 會呼叫 DNS;解析查詢本身又可能透過某個出站傳送。設計不當會出現循環依賴:為了決定網域應走哪個出口而先發起查詢,但查詢出口又依賴尚未完成的網域分類。簡單環境應避免為 DNS 設計過度複雜的路由鏈。先確保基本查詢可用,再為明確的解析伺服器位址新增直連或代理規則。
檢查閉環可以分四步進行:第一,看應用程式交給入站的是網域還是 IP;第二,看路由策略是否需要解析;第三,看查詢由哪個伺服器處理;第四,看查詢連線本身透過哪個出站。任何一步與預期不同,最終都會表現為網頁無法開啟或分流錯誤。v2rayN 的日誌可以協助定位查詢與連線階段,閱讀方法可參考V2Ray 執行日誌怎麼看。
| 現象 | 優先檢查 | 不要先做什麼 |
|---|---|---|
| 網域失敗,直接存取 IP 有回應 | 查詢伺服器、DNS 出站路徑、應用程式是否使用系統解析 | 一次加入許多解析伺服器 |
| 網域規則未命中 | 入站看到的是網域還是 IP、sniffing、domainStrategy | 重複新增相同網域關鍵字 |
| 區域網路主機名稱無法解析 | 本地 DNS、hosts 對映、搜尋網域 | 交給與區域網路無關的解析來源 |
| 解析成功但連線長時間等待 | 位址族、目標路由、出站實際嘗試的位址 | 只依解析速度判斷節點狀態 |
06 / POLICY
policy 策略與統計
policy 控制執行行為,不決定分流方向
policy 經常被誤認為 routing 的補充,實際上它主要控制連線工作階段的逾時、閒置判定與統計開關。流量走代理還是直連,仍由 routing 與出站決定。策略通常依使用者等級組織,出站使用者物件中的 level 可以關聯相應等級;沒有特別設定時,多數設定使用預設等級。只有明確需要不同工作階段行為時,才有必要增加多個等級。
逾時參數不是越短越好。短時間沒有資料傳輸,不代表連線已經失效。長輪詢、檔案傳輸間歇、遠端終端機與保持連線的應用程式都可能出現閒置階段。將閒置時間設得過低,會造成應用程式頻繁重新連線;設定過高則會讓失效連線更晚才清理。應從用戶端或核心的預設行為開始,只有在日誌與應用程式現象證明有需要時才調整。
{
"policy": {
"levels": {
"0": {
"handshake": 4,
"connIdle": 300,
"uplinkOnly": 2,
"downlinkOnly": 5,
"statsUserUplink": false,
"statsUserDownlink": false
}
},
"system": {
"statsInboundUplink": false,
"statsInboundDownlink": false,
"statsOutboundUplink": false,
"statsOutboundDownlink": false
}
}
}
handshake 與 connIdle 處理不同階段
handshake 限制連線建立階段允許等待的時間。它針對尚未完成握手的連線,不等同於整個網頁的載入時限。設定過短時,在網路波動或遠端回應稍慢的情況下會提前失敗;設定過長則會讓明顯無法建立的連線占用資源更久。看到握手逾時時,應先排查伺服器位址、連接埠、傳輸層與本地網路,而不是立即將數值調得很大。
connIdle 關注連線在沒有資料活動時保留多久。閒置連線關閉後,應用程式通常會重新建立,但某些程式會將它表現為工作階段中斷。除錯時可以比較問題發生的時間間隔是否穩定:如果每次都在相近的閒置時長後斷線,值得檢查策略;如果斷線時間隨機且日誌顯示遠端重設,則更可能是鏈路或伺服器行為。
uplinkOnly 與 downlinkOnly 用於處理只有單向資料活動的連線。它們不是上傳、下載速度限制,也不會為某個應用程式分配頻寬。不了解現有連線行為時,不建議為了「最佳化」而隨意縮短。圖形用戶端產生的預設策略通常適合一般使用,只有長時間連線、資源受限或明確的服務情境才需要單獨評估。
統計開關只負責採集許可
statsUserUplink、statsUserDownlink 以及 system 下的入站、出站統計欄位,用於允許核心記錄對應方向的流量資訊。開啟這些布林值不一定會自動出現可見圖表或介面數字,還需要設定受支援的統計模組與查詢方式。若用戶端沒有使用這些資料,單純開啟全部統計項目只會增加不必要的狀態維護。
不要將統計項目當作連線成功檢測。某個方向出現位元組變化,只表示曾有資料經過對應的計數範圍,無法單獨證明目標內容完整返回,也無法說明路由選擇符合預期。判斷連線品質仍應結合存取結果與錯誤日誌。用戶端介面顯示的流量統計可能來自系統介面、核心介面或自身計數,具體口徑未必與 policy 中每個開關完全一致。
多使用者等級需要明確的關聯關係
當設定包含多個使用者物件時,可以為使用者指定不同的 level,再於 policy 的 levels 中定義對應策略。等級鍵在 JSON 中以字串形式出現,例如 "0"、"1"。如果使用者引用了尚未設定的等級,核心可能採用預設行為或回報相關問題,具體取決於實作。維護時應將使用者等級與策略等級一起檢查,避免只複製其中一半。
一般用戶端出站通常不需要複雜的等級體系。節點訂閱提供的使用者身分主要用於遠端協定驗證,並不代表本機一定要為每個節點建立 policy 等級。只有作為入站服務、需要區分工作階段策略時,多等級才較常見。本頁聚焦於用戶端設定,因此建議保持單一預設等級,將精力放在入站安全、出站參數與路由可讀性上。
日誌等級與策略排查要互相配合
策略問題經常表現為「連線建立後又中斷」,需要日誌提供時間線。日常執行可使用 warning 等較克制的等級;排查期間再暫時提高詳細程度,並記錄開始時間與重現步驟。日誌路徑若寫入無權限的目錄,核心可能無法啟動或無法留下診斷資訊。圖形用戶端通常已處理日誌位置,手動設定獨立核心時才需要特別檢查檔案路徑。
重現後先比較三個時間點:連線開始、最後一次資料活動、連線關閉。若關閉時間緊接策略門檻,可調整一項後再次測試;若日誌明確顯示由遠端關閉或底層連線失敗,policy 並不是主要方向。完成除錯後恢復合理的日誌等級,並刪除僅為測試而開啟的統計項目,保持執行設定簡潔。
| 欄位 | 控制階段 | 不負責的事項 |
|---|---|---|
handshake |
連線握手等待 | 網頁完整載入時間 |
connIdle |
保留無資料活動的連線 | 網路速度限制 |
uplinkOnly |
僅上行活動後的連線處理 | 上傳頻寬分配 |
downlinkOnly |
僅下行活動後的連線處理 | 下載頻寬分配 |
statsInboundUplink |
允許記錄入站上行統計 | 自動產生視覺化報告 |
07 / ASSEMBLY
組合完整設定與啟動前檢查
先建立最小閉環,再逐層增加功能
組合設定時,最可靠的順序是先建立最小閉環:一個只監聽本機的 SOCKS 入站、一個有效的代理出站、一個直連出站,以及少量方向明確的路由規則。最小設定能夠啟動並完成連線後,再增加 HTTP 入站、DNS 條件、阻擋規則與 policy。這樣每次新增的範圍有限,出現問題時可以直接回復到上一份可用設定。
完整檔案中的每個標籤都要形成引用閉環。routing 使用的 outboundTag 必須能在 outbounds 中找到;inboundTag 必須與 inbounds 的標籤一致;使用者 level 若關聯 policy,也要存在對應策略。標籤區分大小寫時,Proxy 與 proxy 會被視為不同名稱。建議只使用小寫字母、數字與短橫線,減少輸入錯誤。
{
"log": {
"loglevel": "warning"
},
"dns": {
"servers": [
"localhost"
],
"queryStrategy": "UseIP"
},
"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": "vless",
"settings": {
"vnext": [
{
"address": "server.example.com",
"port": 443,
"users": [
{
"id": "11111111-2222-4333-8444-555555555555",
"encryption": "none"
}
]
}
]
},
"streamSettings": {
"network": "tcp",
"security": "tls",
"tlsSettings": {
"serverName": "server.example.com"
}
}
},
{
"tag": "direct",
"protocol": "freedom",
"settings": {}
},
{
"tag": "block",
"protocol": "blackhole",
"settings": {}
}
],
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"ip": [
"geoip:private"
],
"outboundTag": "direct"
},
{
"type": "field",
"network": "tcp,udp",
"outboundTag": "proxy"
}
]
},
"policy": {
"levels": {
"0": {
"handshake": 4,
"connIdle": 300
}
}
}
}
範例完整不代表節點參數可以直接使用
上面的 JSON 層級完整,可用於理解各部分如何組合,但其中的伺服器網域與使用者 ID 是文件範例。實際設定必須替換為自己的訂閱或服務資訊中的完整參數,並讓 streamSettings 與遠端一致。如果實際節點使用的不是範例中的協定或傳輸方式,應替換整個代理出站物件,而不是只修改協定名稱。協定物件內部結構不同,僅修改一個字串會留下不相容欄位。
使用 v2rayN、v2rayNG 或 v2flyNG 時,優先匯入節點後觀察用戶端產生的出站結構,再將需要的路由思路套用到用戶端支援的位置。不要為了使用本文範例而放棄用戶端已正確產生的節點參數。設定參考的用途是解釋結構與協助排錯,不是讓每位使用者都從空白檔案手動寫出全部連線資訊。
執行語法檢查與核心設定檢查
第一層檢查可以使用支援 JSON 的編輯器確認括號、引號與逗號。第二層需要讓實際核心讀取設定。獨立執行 Xray 時,常見測試方式是執行 xray run -test -config config.json;獨立執行 V2Ray 時,可依目前可執行檔支援的命令使用 v2ray test -c config.json。命令名稱與參數應以本機核心的說明輸出為準,因為用戶端封裝方式與可執行檔位置可能不同。
圖形用戶端使用者通常不需要手動開啟終端機測試暫存設定。重新啟動核心後查看用戶端日誌即可。若用戶端在啟動前會重新產生檔案,應在它提供的編輯入口中儲存變更。測試結果回報未知欄位時,先確認目前使用的是 V2Fly 還是 Xray 核心,再檢查該欄位屬於頂層、入站設定、協定設定還是 streamSettings。將正確欄位放錯層級,同樣會被判定為無效。
依資料流進行啟動後的四段驗證
設定通過讀取後,還要驗證執行鏈路。第一段檢查入站:確認連接埠正在監聽,應用程式的代理類型與連接埠相符。第二段檢查路由:存取一個目標,查看日誌選擇的是 proxy 還是 direct。第三段檢查出站:觀察遠端連線與握手是否完成。第四段檢查目標回應:確認應用程式取得實際內容,而不只是建立了本機代理連線。
如果第一段失敗,重點查看連接埠占用與監聽位址;第二段錯誤,檢查規則順序、目標形式與標籤;第三段失敗,檢查節點、網路與傳輸參數;前三段正常但第四段異常,再查看 DNS、目標服務與應用程式自身行為。這種分段方法比不停更換節點更有效,也能避免將本機連接埠問題誤判為遠端故障。
用戶端覆寫設定時如何保留變更
v2rayN 在切換伺服器、更新訂閱或變更代理模式後,可能重新組織核心執行設定。需要長期保留的內容,應放進用戶端支援的自訂路由、DNS 或自訂設定功能,而不是只編輯執行目錄中的暫存 JSON。修改前先匯出或記錄目前設定,更新後再確認自訂規則仍被合併。首次安裝與設定檔位置相關的注意事項,可查看v2rayN 首次安裝與初始設定完整流程。
Android 用戶端也可能將單節點設定、訂閱項目與執行設定分開儲存。編輯某個節點只會改變該節點的協定參數,不一定會改變全域路由。先確認目前頁面修改的是節點、路由還是應用程式設定,再進行測試。v2rayNG 首推使用 Xray 核心路徑,v2flyNG 則作為 v2fly 核心的備選;兩者擴充欄位存在差異時,不應直接互相複製完整 JSON。
08 / TROUBLESHOOTING
設定錯誤與連線故障排查
啟動立即失敗:先看第一個明確錯誤
核心啟動失敗時,日誌後面可能跟著多條連鎖訊息,真正原因通常出現在最早的一個明確錯誤附近。常見類型包括 JSON 解析失敗、未知欄位、資料型別不符、連接埠占用、檔案路徑無法存取,以及 routing 引用的標籤不存在。先處理第一處錯誤,再重新啟動;不要一次依據後續訊息修改多個區域,因為後續錯誤可能只是前一處失敗的結果。
JSON 解析錯誤通常會提供行號或字元位置。檢查該行前後是否少了逗號、多了尾逗號、引號未閉合,或複製時混入全形標點。錯誤位置有時指向解析器發現問題的地方,而真正遺漏的內容可能在上一行。若檔案很長,可以暫時移除最近新增的整個物件,確認基本設定恢復後,再逐層放回片段。
核心運作中但應用程式無法連線本機代理
這種情況先不要檢查遠端節點。確認應用程式代理位址是否為 127.0.0.1,連接埠是否與入站一致,代理類型是否相符。若使用系統代理,檢查用戶端是否已啟用相應模式;只啟動核心不一定會自動修改系統設定。瀏覽器擴充功能、應用程式內代理與系統代理同時存在時,可能形成重複代理或指向舊連接埠,測試時應保留一條清楚的路徑。
在 Windows、macOS 或 Linux 桌面環境中,連接埠被舊程序占用並不少見。退出用戶端後確認核心程序是否隨之結束,再重新開啟。若修改了入站連接埠,系統代理也要同步更新。Android 用戶端使用系統提供的網路介面接管應用程式流量,排查重點與桌面本機 SOCKS 連接埠不同,應先查看用戶端是否處於已連線狀態,以及執行日誌是否顯示核心成功啟動。
本機代理可連線,但遠端握手失敗
日誌出現連線遭拒、握手失敗或遠端提前關閉時,依「位址與連接埠 → 使用者身分 → 協定 → 傳輸 → 安全層」的順序檢查。網域能解析不代表連接埠對應正確服務,TCP 能建立也不代表 TLS 名稱與應用層傳輸一致。訂閱節點應先執行一次正常更新,確認目前項目沒有使用舊參數;手動節點則逐項與原始設定資訊比較。
系統時間明顯不正確會影響依賴時間的安全連線,應先讓裝置時間恢復正常。網路切換後若問題消失,表示還要檢查目前網路、DNS 或位址族,而不是只修改協定。節點逾時可以依節點逾時排查順序逐層驗證,避免跳過本地網路與系統時間,直接反覆修改出站物件。
只有部分網站或應用程式失敗
部分目標失敗通常表示基本入站與至少一個出站已可用,接下來應重點查看路由、DNS、UDP 與目標特徵。先比較成功目標與失敗目標分別使用哪個出站,再查看失敗項目進入核心時是網域還是 IP。如果錯誤規則將某個網域送往 direct,節點本身再正常也不會參與這次連線;如果 domainStrategy 觸發了不同的位址解析,結果也可能與預期的網域規則不一致。
應用程式的登入、語音、影片或同步功能可能使用不同網域、連接埠與網路類型。首頁能開啟,只能表示其中一部分請求成功。不要根據主頁結果將整個應用程式網域歸入一條過寬的規則。重現時記錄失敗功能對應的日誌目標,逐一補充必要條件。涉及 UDP 時,檢查 SOCKS 入站是否允許 UDP、代理協定與伺服器是否支援目前路徑,以及 routing 是否將 UDP 送往正確出口。
規則看似正確但始終未命中
先確認規則位置。前面是否存在更寬泛的 domain、IP、network 或 port 條件?其次確認目標形式:日誌看到的是完整網域、子網域、IP,還是透過 sniffing 還原的名稱?然後檢查比對前綴是否符合需求,full 不會自動涵蓋所有子網域,關鍵字又可能過寬。最後檢查 outboundTag 拼寫與目前執行檔案,避免修改的是備份檔,而用戶端實際載入的是另一份設定。
為了驗證某條規則,可以暫時將它移到前段,並將目標限制為一個明確網域。測試後查看日誌中的出站標籤。如果仍未命中,問題在目標形式或設定未載入;如果移到前段後命中,表示原本位置之前有規則攔截。確認原因後重新整理順序,不要長期依賴將所有新規則堆在最上方,否則具體規則之間也會逐漸互相覆蓋。
連線一段時間後中斷
先判斷中斷是否發生在固定時間間隔。若每次都接近 connIdle 或單向連線策略的時間,檢查 policy;若時間隨機,查看遠端重設、網路切換、裝置休眠與位址變化。筆記型電腦從一個網路切換到另一個網路後,舊連線失效是正常現象,用戶端通常需要重新建立鏈路。不要將一次睡眠喚醒後的中斷直接歸因於節點參數。
日誌中的 timeout、context canceled 或 connection reset 代表不同階段與觸發方,不能只看到「錯誤」就採用同一種處理方式。timeout 需要結合前一筆記錄判斷是 DNS、撥號還是握手;context canceled 可能來自上層請求主動結束;reset 表示連線被某一端重設。先找出時間線上最早的異常,再判斷後續錯誤是否只是取消與清理動作。
建立可重現的排查記錄
複雜設定最好保留一份簡短記錄,包含用戶端名稱、目前核心家族、入站連接埠、預設出站、最近修改區域與重現步驟。記錄不需要保存節點敏感資訊,只要能說明結構即可。每次測試寫下「修改了什麼、預期什麼、實際日誌是什麼」,兩三輪後通常就能排除大部分猜測。反覆切換多個選項卻不做記錄,容易在問題偶然消失後仍無法確認原因。
需要復原時,先回到最小可用設定,再逐項加入 DNS、分流與策略。如果最小設定仍然失敗,問題更可能位於用戶端安裝、本地網路或節點本身,可回到快速入門主線重新確認匯入與連線步驟。若只有自訂規則失敗,則保留已驗證的節點出站,集中檢查 routing 與目標日誌,不必重新安裝用戶端。
| 故障層級 | 典型現象 | 優先動作 |
|---|---|---|
| JSON 與欄位 | 核心無法啟動 | 處理第一個解析或欄位錯誤,檢查最近的變更 |
| 入站 | 應用程式無法連線本機代理 | 核對位址、連接埠、協定類型與連接埠占用 |
| 路由 | 目標走錯出口或規則未命中 | 查看目標形式、規則順序與實際出站標籤 |
| DNS | 網域失敗或解析結果異常 | 確認查詢路徑、伺服器條件與位址族 |
| 出站 | 遠端拒絕、握手失敗或逾時 | 成套核對位址、身分、協定、傳輸與安全層 |
| 策略與工作階段 | 連線在固定閒置時間後中斷 | 對照 policy 門檻與日誌時間線 |