Nginx 配置 WSS 完整教程(解决断线、101 握手失败、超时断开)

10次阅读
没有评论

在 Web 实时通信场景中(聊天、推送、直播弹幕、设备心跳),WS(WebSocket) 明文传输会被现代浏览器拦截,生产环境必须使用 WSS(WebSocket Secure) 加密长连接。

本文提供一套 可直接上线的 Nginx WSS 标准配置,同时详解原理、关键参数、常见报错与解决方案,彻底解决 WSS 握手失败、自动断线、超时断开等问题。


一、WSS 核心原理

WSS = WebSocket + SSL/TLS,基于 HTTPS 443 端口传输,是 WS 的加密版本。

浏览器同源安全策略强制要求:HTTPS 页面不允许调用明文WS 接口,必须使用 WSS。

Nginx 实现 WSS 的核心逻辑:

  1. Nginx 承接 SSL 解密,对外提供 wss:// 加密连接;
  2. 通过 HTTP 1.1 Upgrade 协议升级,将请求转发给后端 ws:// 明文服务;
  3. 保持长连接通道,实现双向实时通信。

关键前提: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. 支持单机、负载均衡两种模式,可直接复制上线使用。

正文完
可以使用微信扫码关注公众号(ID:xzluomor)
post-qrcode
 0
评论(没有评论)
验证码