WSS 與安全性防禦:TLS 加密與 CSWSH 攻擊防止
當我們離開實驗室,將 WebSocket 部署到公網時,安全性就成了生死攸關的大事。
WebSocket 的握手基於 HTTP,這意味著它繼承了 HTTP 的所有漏洞,同時又因為其「持久連線」的特性,衍生出了特有的安全風險:CSWSH (跨站 WebSocket 劫持)。本章我們將學習如何建立銅牆鐵壁。
一、 第一道防線:WSS (WebSocket Secure)
正如 HTTPS 之於 HTTP,WSS 是在 WebSocket 之上加上了 TLS/SSL 加密層。
為什麼一定要用 WSS?
- 防止中間人攻擊 (MITM):加密數據,讓駭客無法在網路節點竊聽通訊內容。
- 穿透代理伺服器:許多公司防火牆或代理(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 中加入一次性的 Ticket 或 JWT。 |
| 速率限制 (Rate Limiting) | 防止單一 IP 建立過多連線,造成伺服器資源耗盡 (DoS)。 |
| 數據長度限制 | 在伺服器端設置 maxPayload,防止遭受超大 Frame 的攻擊。 |
總結
安全性沒有終點,只有層層堆疊的防禦。透過 WSS 加密與嚴格的來源檢查,我們能有效抵禦絕大多數的網路威脅。
下一章,我們將探討高性能數據策略:Protocol Buffers 與 MessagePack 整合。
️ 進階挑戰
- 實驗室任務:嘗試在本地搭建一個測試 Server,並觀察當你從不同 Port 的網頁發起連線時,
Origin標頭的變化。 - 架構思考:如果你的 API 和 WebSocket Server 分佈在不同子域名,你的
allowedOrigins應該如何配置才能兼顧安全與彈性?
延伸閱讀與資源
- OWASP:WebSocket Security Cheat Sheet
- Node.js ws library:Security Documentation