跳至主要內容
Skip to content

WSS 與安全性防禦:TLS 加密與 CSWSH 攻擊防止

當我們離開實驗室,將 WebSocket 部署到公網時,安全性就成了生死攸關的大事。

WebSocket 的握手基於 HTTP,這意味著它繼承了 HTTP 的所有漏洞,同時又因為其「持久連線」的特性,衍生出了特有的安全風險:CSWSH (跨站 WebSocket 劫持)。本章我們將學習如何建立銅牆鐵壁。


一、 第一道防線:WSS (WebSocket Secure)

正如 HTTPS 之於 HTTP,WSS 是在 WebSocket 之上加上了 TLS/SSL 加密層。

為什麼一定要用 WSS?

  1. 防止中間人攻擊 (MITM):加密數據,讓駭客無法在網路節點竊聽通訊內容。
  2. 穿透代理伺服器:許多公司防火牆或代理(Proxy)會因為看不懂原始的 ws 流量而直接斷線。

實務建議:在生產環境,請絕對不要使用非加密的 ws://


二、 核心攻防:CSWSH (Cross-Site WebSocket Hijacking)

這是 WebSocket 最臭名昭著的攻擊方式。

攻擊原理

由於 WebSocket 握手時會自動攜帶瀏覽器的 Cookie,當受害者訪問釣魚網站時,駭客的程式碼可以發起一個指向你伺服器的 WebSocket 連線。 由於瀏覽器會自動補上受害者的 Session Cookie,你的伺服器會認為這是合法的請求,從而建立雙向通道。

恐怖之處:WebSocket 握手不受 CORS (跨來源資源共享) 的限制!


三、 實戰防禦:Origin 檢查機制

防範 CSWSH 最有效、最簡單的方法就是強制驗證 Origin 標頭。

javascript
const ws = require("ws");
const http = require("http");

const server = http.createServer();
const wss = new ws.Server({ noServer: true });

server.on("upgrade", (request, socket, head) => {
  const origin = request.headers.origin;

  // 1. 嚴格驗證來源域名
  const allowedOrigins = ["https://hirimu.blog", "http://localhost:5183"];

  if (!allowedOrigins.includes(origin)) {
    console.warn(`🛑 拒絕非授權來源的握手請求: ${origin}`);
    socket.destroy(); // 直接切斷 TCP 連線
    return;
  }

  // 2. 驗證通過,執行升級
  wss.handleUpgrade(request, socket, head, (ws) => {
    wss.emit("connection", ws, request);
  });
});

wss.on("connection", (ws) => {
  console.log("✅ 合法來源連線已建立");
});

server.listen(8080);

四、 深度防禦:其他安全策略

策略說明
Token 認證除了 Cookie,建議在握手 URL 中加入一次性的 TicketJWT
速率限制 (Rate Limiting)防止單一 IP 建立過多連線,造成伺服器資源耗盡 (DoS)。
數據長度限制在伺服器端設置 maxPayload,防止遭受超大 Frame 的攻擊。

總結

安全性沒有終點,只有層層堆疊的防禦。透過 WSS 加密與嚴格的來源檢查,我們能有效抵禦絕大多數的網路威脅。

下一章,我們將探討高性能數據策略:Protocol Buffers 與 MessagePack 整合。


️ 進階挑戰

  1. 實驗室任務:嘗試在本地搭建一個測試 Server,並觀察當你從不同 Port 的網頁發起連線時,Origin 標頭的變化。
  2. 架構思考:如果你的 API 和 WebSocket Server 分佈在不同子域名,你的 allowedOrigins 應該如何配置才能兼顧安全與彈性?

延伸閱讀與資源