在 Web 实时通信场景中(聊天、推送、直播弹幕、设备心跳),WS(WebSocket) 明文传输会被现代浏览器拦截,生产环境必须使用 WSS(WebSocket Secure) 加密长连接。
本文提供一套 可直接上线的 Nginx WSS 标准配置,同时详解原理、关键参数、常见报错与解决方案,彻底解决 WSS 握手失败、自动断线、超时断开等问题。
一、WSS 核心原理
WSS = WebSocket + SSL/TLS,基于 HTTPS 443 端口传输,是 WS 的加密版本。
浏览器同源安全策略强制要求:HTTPS 页面不允许调用明文WS 接口,必须使用 WSS。
Nginx 实现 WSS 的核心逻辑:
- Nginx 承接 SSL 解密,对外提供
wss://加密连接; - 通过 HTTP 1.1 Upgrade 协议升级,将请求转发给后端
ws://明文服务; - 保持长连接通道,实现双向实时通信。
关键前提:WebSocket 握手必须依赖 HTTP/1.1 协议,且必须传递 Upgrade、Connection 请求头,否则会直接握手失败。
二、生产级完整配置(推荐)
该配置支持 SSL 加密、优雅连接升级、长连接保活、HTTP 强制跳转 HTTPS,适配绝大多数生产场景。
# 全局配置:优雅处理 WebSocket 连接升级
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
# 后端 WebSocket 服务集群
upstream ws_backend {
server 127.0.0.1:8080; # 替换为你的后端 WS 服务地址
# ip_hash; # 如需会话粘滞(同一用户固定后端)开启此行
}
# WSS 加密服务 443 端口
server {
listen 443 ssl;
server_name your-domain.com; # 替换为自己的域名
# SSL 证书配置(可使用 Let's Encrypt 免费证书)
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
# 安全 SSL 协议配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
# WSS 接口路由
location /ws {
proxy_pass http://ws_backend;
# 核心配置:支持 WebSocket 协议升级
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
# 透传真实客户端信息
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 长连接超时配置,解决自动断线问题
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_connect_timeout 10s;
}
}
# HTTP 80 端口强制跳转 HTTPS
server {
listen 80;
server_name your-domain.com;
return 301 https://$host$request_uri;
}
三、极简单服务配置(测试/单机使用)
如果无需负载均衡,仅单机测试使用,可使用精简版配置,足够满足个人项目、小型服务需求。
server {
listen 443 ssl;
server_name your-domain.com;
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
location /ws {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
}
四、核心参数详细解析
1. 协议升级必备参数
proxy_http_version 1.1:Nginx 默认使用 HTTP/1.0,必须开启 1.1 才支持协议升级;Upgrade + Connection:WebSocket 握手核心请求头,缺失直接报 101 握手失败。
2. 长连接保活参数(解决自动断线)
proxy_read_timeout 3600s:Nginx 最长空闲读取超时,默认 60s,超时自动断开连接;聊天、设备心跳场景建议设置为 1 小时;proxy_send_timeout:写入超时,与读取超时配套配置,避免单向阻塞断线。
3. map 模块作用
map $http_upgrade $connection_upgrade 是生产最优写法:有协议升级请求时开启 upgrade,普通 HTTP 请求自动 close 连接,兼顾兼容性与安全性。
五、前端连接示例
配置完成后,前端直接使用 wss:// 域名连接,无需处理证书逻辑。
// WSS 前端连接代码
const socket = new WebSocket("wss://your-domain.com/ws");
// 连接成功回调
socket.onopen = function () {
console.log("WSS 连接成功");
};
// 接收服务端消息
socket.onmessage = function (e) {
console.log("收到消息:", e.data);
};
// 连接关闭回调
socket.onclose = function () {
console.log("WSS 连接断开");
};
// 错误监听
socket.onerror = function (err) {
console.error("WSS 连接异常:", err);
};
六、配置校验与上线命令
# 检查 Nginx 配置语法是否正确
nginx -t
# 平滑重载配置(不中断现有长连接)
nginx -s reload
七、在线测试 WSS 连接
推荐使用 wscat 命令行工具快速验证连接是否正常。
1. 安装工具
npm install -g wscat
2. 测试连接
wscat -c wss://your-domain.com/ws
能正常收发数据即代表配置完全生效。
八、常见问题与解决方案(避坑指南)
1. 101 Switching Protocols 握手失败
大概率原因:缺失 Upgrade、Connection 配置,或未开启 HTTP/1.1。
解决:核对核心升级配置,确保参数完整。
2. 连接几十秒自动断开
原因:默认 proxy_read_timeout 60s 超时断开,无心跳包时触发。
解决:调大超时时间,前端/后端增加心跳保活机制。
3. HTTPS 页面无法连接 WS
浏览器安全策略限制,HTTPS 域名禁止请求明文 WS。
解决:统一使用 WSS 加密连接。
4. 负载均衡后用户频繁掉线
原因:Nginx 默认轮询策略,长连接切换后端节点。
解决:upstream 中开启 ip_hash 会话粘滞。
5. 端口不通、连接超时
解决:服务器防火墙、云服务器安全组放行 443 端口。
九、负载均衡拓展说明
多节点部署 WebSocket 服务时,直接在 upstream 中添加多台后端节点即可实现负载均衡:
upstream ws_backend {
server 127.0.0.1:8080;
server 127.0.0.1:8081;
server 127.0.0.1:8082;
ip_hash; # 固定用户节点,避免断线重连
}
总结
1. 生产环境必须使用 WSS,规避浏览器跨域与安全拦截问题;
2. Nginx WSS 配置核心:HTTP/1.1 + 协议升级头 + 超长连接超时;
3. 绝大多数断线、握手失败问题,均是配置缺失或超时时间过短导致;
4. 支持单机、负载均衡两种模式,可直接复制上线使用。