Featured image of post 建立高隱蔽性與低延遲的家網代理隧道:基於 Xray (VLESS) + WebSocket + TLS 的部署指南

建立高隱蔽性與低延遲的家網代理隧道:基於 Xray (VLESS) + WebSocket + TLS 的部署指南

透過 Xray (VLESS) + WebSocket + TLS 架構,將代理流量偽裝成標準 HTTPS,搭配 Traefik 進行 SSL 終止與反向代理,以雙路由設計分離管理面板與代理節點流量,解決企業 RBI 畫面卡頓問題。

1. 簡介

傳統的遠端瀏覽器方案將畫面轉為影片串流,在受限的辦公室網路中極易產生延遲。本方案採用 Xray (VLESS) + WebSocket + TLS 架構。其核心邏輯是將代理流量偽裝成標準的 HTTPS (Port 443) 流量,透過家中的 Traefik 進行 SSL 終止,並以雙路由設計分別處理 X-ui 管理面板與 VLESS 代理節點,確保兩者的安全政策互不干擾。

方案優勢

  • 低延遲:本地瀏覽器負責渲染,反應速度極快。
  • 高隱蔽性:流量特徵與標準 WebSocket (如 Slack、Teams) 一致,能有效穿透防火牆。
  • 免安裝驅動:用戶端僅需執行綠色免安裝軟體,無需系統管理員權限。

2. 先決條件

在開始部署前,請確保具備以下環境:

  • 已安裝 Docker 與 Docker Compose 的 Linux 主機 (位於家中)。
  • 已部署完成並可正常運作的 Traefik,且設定好 websecure 入口點、憑證解析器 (myresolver) 以及 sec-strict@filesec-normal@file 兩組 middleware。
  • 一個可用的網域,並已將子網域 (如 proxy.example.com) 指向家中 IP。
  • 公司電腦具備執行自定義 .exe 檔案與修改瀏覽器代理設定的權限。

3. 全量參數提取清單

以下為本架構中涉及的核心參數,請根據實際需求進行調整。部署時統一以環境變數注入,避免將敏感資訊直接寫入設定檔。

參數名稱建議值 / 範例說明
APP_DOMAINproxy.yourdomain.com對外公開的子網域
ROUTER_NAMEx-uiTraefik 路由與服務的命名前綴
PANEL_PORT2053X-ui 管理面板的容器內部埠口
NODE_PORT2054VLESS 代理節點的容器內部埠口
NODE_PATH/ (或自訂如 /chat)WebSocket 路徑,須與 X-ui 入站設定一致
用戶端 SOCKS 埠口10808v2rayN 在本地端開啟的代理埠口

路由分離設計說明:面板 (Route A) 使用嚴格安全標頭 (sec-strict@file);代理節點 (Route B) 使用一般安全標頭 (sec-normal@file),避免嚴格的 HSTS 與 CSP 標頭干擾 WebSocket 握手與 VLESS 連線。


4. 逐步教學

第一階段:服務端 (Server) 部署

步驟 1:配置 Docker Compose

建立新的 Stack 並填入以下設定。本設定採雙路由架構,管理面板與代理節點分別對應不同的內部埠口與安全政策。

version: '3.8'

networks:
  traefik_network:
    external: true
  default:
    driver: bridge

services:
  x-ui:
    image: ghcr.io/mhsanaei/3x-ui:latest
    container_name: x-ui
    restart: unless-stopped
    environment:
      XRAY_VMESS_AEAD_FORCED: "false"
    volumes:
      - /mnt/cloud1/dockerData/x-ui/db:/etc/x-ui/
      - /mnt/cloud1/dockerData/x-ui/cert:/root/cert
    tty: true
    networks:
      - default
      - traefik_network
    labels:
      - "traefik.enable=true"

      # ==========================================
      # 路由 A:X-ui 管理面板 (PANEL_PORT)
      # ==========================================
      - "traefik.http.routers.${ROUTER_NAME}-panel.rule=Host(`${APP_DOMAIN}`)"
      - "traefik.http.routers.${ROUTER_NAME}-panel.entrypoints=websecure"
      - "traefik.http.routers.${ROUTER_NAME}-panel.tls.certresolver=myresolver"
      - "traefik.http.routers.${ROUTER_NAME}-panel.service=${ROUTER_NAME}-panel-svc"
      - "traefik.http.services.${ROUTER_NAME}-panel-svc.loadbalancer.server.port=${PANEL_PORT}"
      # 嚴格安全防護,適合管理介面
      - "traefik.http.routers.${ROUTER_NAME}-panel.middlewares=sec-strict@file"

      # ==========================================
      # 路由 B:VLESS 代理節點 (NODE_PORT + NODE_PATH)
      # ==========================================
      # PathPrefix 規則優先級較高,Traefik 會自動處理路由匹配順序
      - "traefik.http.routers.${ROUTER_NAME}-node.rule=Host(`${APP_DOMAIN}`) && PathPrefix(`${NODE_PATH}`)"
      - "traefik.http.routers.${ROUTER_NAME}-node.entrypoints=websecure"
      - "traefik.http.routers.${ROUTER_NAME}-node.tls.certresolver=myresolver"
      - "traefik.http.routers.${ROUTER_NAME}-node.service=${ROUTER_NAME}-node-svc"
      - "traefik.http.services.${ROUTER_NAME}-node-svc.loadbalancer.server.port=${NODE_PORT}"
      # 一般安全防護:避免嚴格標頭干擾 WebSocket 握手
      - "traefik.http.routers.${ROUTER_NAME}-node.middlewares=sec-normal@file"

      - "traefik.docker.network=traefik_network"

在 Portainer Stack 的 Environment variables 區塊填入對應變數:APP_DOMAINROUTER_NAMEPANEL_PORTNODE_PORTNODE_PATH

步驟 2:Traefik WebSocket 支援說明

Traefik 預設即支援 WebSocket 連線升級,無需額外設定。本方案的關鍵在於路由 B 套用 sec-normal@file 而非 sec-strict@file,確保 Traefik 不會移除 UpgradeConnection 標頭,讓 VLESS over WebSocket 的握手得以正常完成。

步驟 3:配置 X-ui 面板入站規則

X-ui 需要設定兩個入站:管理面板使用預設埠口,代理節點需額外新增一個獨立入站。

  1. 訪問 http://家裡內網IP:2053 並登入。

  2. 進入「入站列表」 -> 「添加入站」,設定代理節點:

    • 協議:vless
    • 埠口${NODE_PORT} (與 Docker Compose 中一致,例如 2054)
    • 傳輸:ws (WebSocket)
    • 路徑${NODE_PATH} (與 Docker Compose 中一致,例如 /)
    • TLS:關閉 (SSL 終止由外部 Traefik 負責)
  3. 儲存後點擊「查看」並「複製連結」。

[圖片說明:X-ui 面板中入站設定的截圖,重點標注 vless、ws 傳輸、埠口與路徑,以及關閉 TLS 的位置]


第二階段:用戶端 (Client) 配置

步驟 1:匯入代理設定

  1. 在公司電腦啟動 v2rayN
  2. 點選「伺服器」 -> 「從剪貼簿匯入批次網址」。
  3. 雙擊該伺服器進行細節修正:
    • 地址 (Address):填入網域 proxy.yourdomain.com
    • 埠口 (Port):修改為 443
    • 傳輸層安全 (TLS):選擇 tls

步驟 2:Firefox 代理設定

  1. 開啟 Firefox 設定,搜尋「代理」。
  2. 選擇「手動設定代理」:
    • SOCKS 主機127.0.0.1
    • 埠口10808
    • 類型:SOCKS v5
    • 勾選:使用 SOCKS v5 時代理 DNS。

5. 故障排除紀錄 (Troubleshooting Log)

問題 A:連線成功但無法解析網頁

  • 現象:v2rayN 顯示已連線,但瀏覽器出現 DNS 解析錯誤。
  • 原因:公司網路環境可能攔截了非授權的 DNS 查詢。
  • 解決方法:務必在瀏覽器設定中勾選「使用 SOCKS v5 時代理 DNS」,強制讓遠端的家網主機代為解析網域。

問題 B:Traefik 轉發失敗 (Error 502)

  • 現象:Traefik 回傳 502 Bad Gateway。
  • 嘗試過的無效方法:在 X-ui 面板開啟 TLS。
  • 最終解決邏輯:X-ui 內部必須維持明文 (TLS off),SSL 終止由 Traefik 負責。同時確認容器已正確加入 traefik_network,且 Label 中的 traefik.docker.network 與實際網路名稱一致,避免 Traefik 取錯容器 IP。

問題 C:WebSocket 連線握手失敗

  • 現象:連線建立後立即斷開,日誌顯示 WebSocket handshake 失敗。
  • 原因:路由套用了 sec-strict@file,其中的嚴格安全標頭 (如 CSP、HSTS) 干擾了 WebSocket 的 Upgrade 握手流程。
  • 解決方法:代理節點路由 (Route B) 必須改用 sec-normal@file,確保握手標頭不被覆蓋或移除。

問題 D:面板與節點路由衝突

  • 現象:訪問管理面板被導向代理節點,或兩者路由不如預期。
  • 原因:Traefik 依路由規則的「精確度」決定優先順序,包含 PathPrefix 的規則 (Route B) 優先級自動高於純 Host 規則 (Route A)。
  • 解決方法:確認節點的 NODE_PATH 與面板路徑不衝突;若仍有問題,可透過 priority 標籤手動指定路由優先順序。

6. 進階優化:自動化切換 (SwitchyOmega)

為了避免手動開關 Firefox 代理設定,建議安裝 Proxy SwitchyOmega 擴充功能。

  • 建立一個專屬情境模式 (如「Home-Proxy」),協定選 SOCKS5,地址 127.0.0.1:10808
  • 利用「自動切換」功能,設定特定內部網址直接連線,其餘網址走「Home-Proxy」。

7. 結論

本架構成功將複雜的 VPN 驅動安裝需求轉化為單純的 HTTPS 流量轉發,以 Traefik 作為統一的反向代理閘道,透過 Docker Labels 與環境變數即可完成雙路由設定。面板與代理節點分離的設計確保了管理安全性與連線穩定性不互相妥協,是一套針對「流量代理」而非「畫面傳送」的高效優化方案。