在 Nginx 中配置 WebSocket 支持 wss 协议,核心是正确转发 Upgrade 和 Connection header,并将 HTTP 协议版本设为 1.1,同时需在 Nginx 侧终止 SSL 连接。
该方案适用于需要加密传输的实时通信场景,配置错误会导致握手失败返回 400 或 502 状态码。
先说结论:Nginx 原生支持 WebSocket 反向代理,但必须显式设置协议升级头并启用 HTTP 1.1 才能维持长连接。
- 适合:需要透过 Nginx 转发 ws 或 wss 流量的反向代理场景
- 先准备:确保证书有效且后端服务支持 WebSocket 握手
- 验收:通过浏览器控制台或 curl 命令确认握手状态码为 101
命令速用版
以下是 Nginx configuration 中 location 块的核心配置片段,直接替换原有 proxy 设置:
location /ws/ {
proxy_pass http://backend_server;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 86400s;
}若需支持 wss,需在 server 块中配置 ssl_certificate 和 ssl_certificate_key,并监听 443 端口。
为什么会这样
WebSocket 握手基于 HTTP 协议升级机制,默认 HTTP 1.0 不支持长连接升级。
Nginx 默认 proxy_http_version 为 1.0,会关闭 Connection 头,导致握手中断。WSS 本质是 WebSocket over TLS,通常由 Nginx 处理 SSL 解密后以 ws 协议转发给后端,因此必须配置 SSL 证书。
分步处理
第一步:配置 SSL 证书(仅 wss 需要)。
在 server 块中监听 443 ssl,指定证书路径,确保 openssl 生成的证书有效。
第二步:编写 location 反向代理规则。
添加 proxy_set_header Upgrade 和 Connection 字段,强制 proxy_http_version 为 1.1。
第三步:调整超时时间。
WebSocket 是长连接,需增大 proxy_read_timeout 和 proxy_send_timeout,避免连接被主动切断。
第四步:重载配置。
执行 nginx -t 检查语法,执行 nginx -s reload 应用配置。
怎么验证是否生效
使用 curl 命令模拟握手请求,检查返回状态码是否为 101 Switching Protocols。
命令示例:curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" -H "Host: your_domain" https://your_domain/ws/。
或在浏览器开发者工具 Network 面板查看 WebSocket 请求状态,确认 Status 为 101 且数据能正常收发。
常见坑
坑一:忘记设置 proxy_http_version 1.1,导致后端收不到 Upgrade 头。
坑二:SSL 证书配置错误,导致 wss 握手在 TLS 阶段失败,浏览器报 ERR_SSL_VERSION_OR_CIPHER_MISMATCH。
坑三:超时时间过短,长连接空闲时被 Nginx 主动断开,表现为连接意外丢失。
常见问题
ws 和 wss 配置有什么区别?
wss 需要在 Nginx 侧配置 SSL 证书并监听 443 端口,ws 仅需监听 80 端口。
为什么握手返回 400 Bad Request?
通常是 Upgrade 或 Connection 头未正确转发,或者 Host 头不匹配后端预期。
后端服务需要配置 SSL 吗?
不需要,Nginx 终止 SSL 后通常以明文 ws 协议向内网后端转发,除非要求全链路加密。
参考来源
- Nginx Official Documentation, "Nginx WebSocket Proxying", https://nginx.org/en/docs/http/websocket.html
- Nginx Official Documentation, "HTTP ngx_http_proxy_module", https://nginx.org/en/docs/http/ngx_http_proxy_module.html