本文把 REALITY 與 XTLS Vision 拆成「握手」與「傳輸」兩段來說:REALITY 如何從目標網站取得憑證鏈完成握手、未授權的連線會被轉送到哪裡;XTLS Vision 如何辨識 TLS 記錄並直通轉送、省下的是哪一層加密。讀完之後,可以判斷自己的節點適合哪種組合,以及 CDN 中轉、WebSocket 傳輸、v2fly 核心這些情境為什麼用不上,並能在 v2rayN 與 v2rayNG 裡把 REALITY 欄位與 flow 參數填對。
結論:一個改握手,一個改傳輸
REALITY 是 VLESS 在傳輸安全層的一種實作方式,作用點在握手階段。伺服器不持有自有網域憑證,而是從目標網站(dest)取得憑證鏈用於握手;用戶端不用公開 CA 驗證伺服器,改用設定裡預先設定的公鑰驗證身分。未通過驗證的連線會被整條轉送到 dest,看到的是目標網站的實際頁面與真實憑證鏈。
XTLS Vision 作用在握手之後。代理 HTTPS 流量時,用戶端與目標網站之間本來就有一層 TLS;XTLS 讓用戶端在完成外層握手後,不再把內層 TLS 記錄塞進外層記錄層重複加密,而是直接轉送這些已經加密的記錄,伺服器辨識後同樣直接轉送給目標網站。省掉的是重複的那一層,不是僅有的那一層。
兩者都由 Xray 核心實作,可以單獨使用,也可以組合:VLESS + TCP + REALITY + flow=xtls-rprx-vision 是目前伺服器端常見的寫法。只開 REALITY 不開 flow,握手階段的偽裝效果不變,只是大流量下要多付一次加解密的 CPU 開銷。
TLS 握手階段:延遲與指紋出在哪裡
TLS 1.3 的完整握手需要 1 次來回,工作階段恢復可以做到 0-RTT。握手封包裡的 SNI、加密套件清單、擴充順序、金鑰共享群組共同構成用戶端指紋;伺服器回傳的憑證鏈、簽章演算法、工作階段票據構成伺服器指紋。任何一項與「一般 HTTPS 網站」不一致,都可能成為被區分的特徵。
傳統自建節點的做法,是用自有網域申請憑證,或是使用自簽憑證。前者的成本是網域與憑證續期,後者則容易出現憑證鏈不完整、SNI 與憑證不相符的情況,在沒有正確回落設定的情況下很容易被辨識出來。
| 觀察重點 | 自簽憑證 + 回落 | REALITY |
|---|---|---|
| 伺服器出示的憑證 | 自簽憑證,瀏覽器提示不受信任 | 目標網站的實際憑證鏈 |
| SNI 與憑證是否相符 | 常見的不相符情況 | 一致 |
| 未授權存取 443 連接埠 | 取決於回落設定,可能曝光代理行為 | 轉送到 dest,回傳實際頁面 |
| 用戶端身分驗證方式 | 憑證鏈驗證或略過驗證 | 預置公鑰 + X25519 金鑰交換 |
| 網域與憑證成本 | 需要網域,憑證需續期 | 不需要自有網域與憑證 |
表裡的差異集中在握手的前幾個封包。REALITY 的目標是讓這幾個封包與「直接存取該目標網站」無法區分,而不是把流量藏起來——流量本身仍是標準 TLS,記錄格式、版本號、擴充都與一般 HTTPS 一致,只是憑證來源與驗證方式換了一套。
REALITY:借用真實網站的憑證鏈
伺服器端設定 REALITY 需要四個關鍵值:dest(目標網站,例如 www.python.org:443)、serverNames(與 dest 相符的網域清單)、privateKey(伺服器私鑰,用 xray x25519 指令產生)、shortIds(短 ID 清單,用來區分不同用戶端)。用戶端持有對應的 publicKey、serverName 與 shortId,三項與伺服器端一一對應。
收到連線後,伺服器端用私鑰與 ClientHello 裡的臨時公鑰進行 X25519 運算,能得出預期結果就當作代理處理;得不出結果,就把整條連線轉送給 dest,由目標網站正常回應。這也是挑選目標網站的依據:真實存在、支援 TLS 1.3 與 X25519、有正常網頁,最好還支援 HTTP/2,回落時的表現才會自然。
REALITY + VLESS TCP
推薦不需要自有網域與憑證,單一 443 連接埠同時負責握手偽裝與代理;未授權的存取看到的是目標網站的實際頁面。
適合:直連環境、單機自建、需要抵抗主動探測
網域憑證 + TLS + WebSocket
設定直觀,憑證需要定期續期,傳輸層可以疊加 WebSocket,方便後續接入 CDN 中轉。
適合:已有網域、需要走標準 443 TLS
自簽憑證 + WebSocket + CDN
來源站台 IP 被 CDN 隱藏,但憑證鏈通常不完整,需要仔細設定回落,否則握手特徵依然明顯。
適合:需要隱藏來源站台 IP、可接受較多設定步驟
結論:先確定要不要走 CDN,再選握手方案
REALITY 與 XTLS Vision 都依賴 RAW(TCP)直連,一旦決定用 CDN 中轉,兩者都無法疊加,應該回到「網域憑證 + WebSocket」的組合;確定直連之後,REALITY 就是不用買網域也能取得真實憑證鏈的方案。
限制也要寫清楚:dest 與 serverNames 必須相符,填錯會出現握手能完成、但頁面回報憑證錯誤的情況;shortId 與 publicKey 必須成對派發,用戶端填錯會直接連不上;不能疊加 WebSocket、gRPC、HTTP/2 等傳輸方式,因此走不了 CDN;v2fly 核心(V2flyNG)對 VLESS 的支援完善,但不解析 REALITY 相關欄位,REALITY 節點需要在 Xray 核心上執行,v2rayNG 內建的就是 Xray 核心。
XTLS Vision:握手之後省掉一層加密
代理 HTTPS 時的資料路徑是:用戶端與目標網站之間一層 TLS,用戶端與代理伺服器之間再一層 TLS。外層 TLS 用來保護用戶端到代理伺服器這一段;內層 TLS 記錄在用戶端送出時已經加密過一次,一般實作會把它當成普通位元組流,再套進外層記錄層加密一遍。
XTLS 的做法是在外層握手完成後辨識第一筆應用資料:如果是 TLS ClientHello,代表這條連線上的資料本身已經加密,外層不再重複加密,直接轉送;如果不是 TLS 流量,例如明文 HTTP,仍照一般方式加密傳輸。判斷依據是首包內容,不需要額外開關。
Vision 是 XTLS 的改良實作,解決了早期 xtls-rprx-direct 在部分情境下的相容性問題,並加入 UUID 驗證與首包辨識。它在設定裡以 flow 欄位的形式出現:伺服器端 clients 寫 "flow": "xtls-rprx-vision",用戶端 outbound 填同一個值,兩端不一致時連線會失敗,或退回一般 VLESS。
- 效益:滿速下載時省掉一次對稱式加密與解密,CPU 佔用下降,在軟路由與低功耗裝置上最明顯;
- 效益:大流量情境下吞吐量更接近裸 TCP,首包直通後延遲抖動更小;
- 代價:只對 TLS 流量生效,明文 HTTP 仍走一般加密;
- 代價:兩端都必須填 flow,且用戶端核心需要支援 Vision;
- 代價:與 REALITY 一樣只能走 RAW 傳輸,不能疊加 WebSocket 與 gRPC。
設定重點:金鑰、flow 與回落驗證
產生金鑰對
伺服器端執行 xray x25519,取得私鑰與公鑰;私鑰只留在伺服器端設定裡,公鑰隨節點資訊派發給用戶端。
填寫入站設定
inbound 用 VLESS + TCP 監聽 443,streamSettings.security 設為 reality,填入 dest、serverNames、shortIds 與 privateKey。
用戶端填公鑰
在 v2rayN 的節點編輯裡填入位址、連接埠 443、UUID,flow 選 xtls-rprx-vision,再填 publicKey、serverName、shortId。
驗證回落行為
用瀏覽器直接存取該網域與連接埠,應該會看到 dest 網站的頁面;若出現憑證錯誤,代表 dest 與 serverNames 不相符。
查看核心日誌
連線失敗時,查看日誌裡 REALITY、invalid user、flow 相關的關鍵字,先確認公鑰與 shortId 是否成對派發。
{
"port": 443,
"protocol": "vless",
"settings": {
"clients": [
{ "id": "8f7a2c1e-5b3d-4a9f-9c21-7d6e4b0a1f33", "flow": "xtls-rprx-vision" }
],
"decryption": "none"
},
"streamSettings": {
"network": "tcp",
"security": "reality",
"realitySettings": {
"dest": "www.python.org:443",
"serverNames": ["www.python.org"],
"privateKey": "aP3nQ8vK2sL7dF9xR4tY6uW1zC5bN0mJ2hG8kD3sQ1E",
"shortIds": ["6ba85179e30d4fc2"]
}
}
}
範例片段裡 dest 與 serverNames 指向同一個網域,這是 REALITY 能正常握手的前提;shortIds 可以列出多筆,每個用戶端用一個,更換用戶端時不必重新產生伺服器端金鑰。用戶端這邊的 publicKey 是上面私鑰的配對公鑰,不是另一個隨機值,填錯會直接連不上。
常見問題:探測、相容性與核心差異
別人直接存取我的 443 連接埠會看到什麼?
沒有攜帶正確公鑰的連線會被轉送到 dest 網站,看到的是該網站的實際頁面與憑證鏈;前提是 serverNames 與 dest 相符、回落鏈路沒有被改壞。
REALITY 節點能套 CDN 嗎?
不行。REALITY 與 XTLS Vision 都依賴 RAW(TCP)直連,WebSocket、gRPC、HTTP/2 這些能由 CDN 承載的傳輸方式無法疊加,需要換回「網域憑證 + WebSocket」的組合。
用戶端填了 flow 卻連不上?
先確認伺服器端 clients 裡也寫了同一個 flow,再確認用戶端用的是 Xray 核心;v2fly 核心不解析 REALITY 欄位,節點參數裡填了也不會生效。
只開 REALITY 不開 Vision 行不行?
可以。REALITY 解決握手偽裝,Vision 解決傳輸層重複加密,兩者相互獨立;不開 flow 時握手效果不變,只是大流量下 CPU 佔用會高一些。
dest 一定要選大站嗎?
選支援 TLS 1.3 與 X25519、有正常網頁、且與自己節點不同網域的網站即可;dest 與 serverNames 必須相符,不要填自己的網域,也不要用只回傳 API 資料的網域。
情境組合:直連、CDN 與核心選擇
單機自建、有獨立 IP、不需要隱藏來源站台:VLESS + TCP + REALITY + xtls-rprx-vision。一個 443 連接埠同時負責握手偽裝與傳輸最佳化,不需要網域與憑證,設定項目最少,用戶端用 v2rayN 或 v2rayNG 都可以。
已有網域與憑證、需要走 CDN:VLESS + WebSocket + TLS。這時候 REALITY 與 Vision 都用不上,最佳化方向在 CDN 端與傳輸方式的選擇,而不是握手與傳輸層。兩條路線的分歧點在「來源站台 IP 要不要曝光」,先回答這個問題,後面的參數才有意義。
結論:先定傳輸方式,再定握手方案
有 CDN 需求時,REALITY 與 Vision 都不在可選範圍內;確定直連後,再依「要不要維護自有網域」二選一:不想維護就用 REALITY,已有網域且習慣標準 TLS 就用網域憑證。兩種方案的握手來回都是 1-RTT,差距不在延遲,而在憑證來源與探測特徵。