wss配置的核心就一句话:用Nginx做SSL终结,再把流量反向代理到WebSocket服务端口,客户端用wss://协议连接即可。这里的难点不在Nginx的proxy_pass,而在证书链完整性、Upgrade请求头透传这两件事上,下面我会按真实踩坑顺序,把从零到能跑通的全过程拆给你看。
wss和ws区别是什么?为什么生产环境必须用wss
很多新手第一次接触wss时,会把它当作一个单独的协议,其实它和ws的关系就是HTTP与HTTPS的关系,ws的默认端口是80,wss是443;ws走明文,wss走TLS加密,这段加密不是说“加个密码”那么简单,它意味着数据在传输过程中即使被截获,对方看到的也是一堆密文。
行业共识认为,任何暴露在公网的WebSocket服务都必须启用wss。 尤其当你做的业务涉及登录态、用户ID、聊天记录或支付回调时,明文传输等于把用户数据裸奔在互联网上,你可能觉得自己的服务只是个小工具,不会有黑客盯上,但现实是扫描全网开放端口的爬虫比你的用户还勤劳,它们发现你有一个ws端口,几十秒内就可能发起恶意请求。
从浏览器层面看,事情更严格。主流浏览器在HTTPS页面下会直接拦截ws://请求。 比如你在https://example.com上线了一个功能,页面里的JS却用ws://api.example.com去连WebSocket,浏览器会报Mixed Content错误,代码一个字母不用改,但就是连不上,这也就是为什么微信小程序这类强约束环境里,几乎只能见到wss,因为平台方直接封死了ws的入口。
另外要说清楚,wss和ws的握手过程、心跳机制、数据帧格式完全一致,唯一变的是传输层套了一层TLS,所以你的后端业务逻辑不用做任何改动,唯一要动手的就是网关层的配置,搞清楚这点,后面排错时会少走很多弯路。
wss配置nginx完整步骤,从生成证书到流量转发
具体到“wss配置nginx”这一步,我假设你已经有了一台公网服务器、一个解析好的域名、一个跑在8080端口的WebSocket后端,以及一个Nginx环境(1.18以上版本即可),现在要做的事分三步走。
第一步:准备SSL证书
证书有两类选择:付费的商业证书,以及免费的Let’s Encrypt,个人项目或中小站点选免费的就够用,配置起来也不复杂,如果你是简米云或酷番云用户,控制台里能直接申请免费DV证书,有效期一年,下载Nginx版压缩包,里面会有.pem和.key两个文件,把它们传到服务器上的/etc/nginx/cert/目录下。
用certbot自动申请的方式也很常见,命令大致是:
sudo apt install certbot python3-certbot-nginx sudo certbot --nginx -d yourdomain.com

整个过程是交互式的,按提示填入邮箱、同意条款、选择是否强制HTTPS跳转即可,申请成功后,certbot会自动帮你改Nginx配置,证书会续期,基本是零维护,不过它自动生成的SSL配置只能保证HTTPS能跑,对于wss还差关键几行,需要手动补上。
第二步:配置Nginx的47层代理
这里给出一个直接可用于生产环境的server块配置,每一行都有它的用途,不要乱删:
server {
listen 443 ssl;
server_name yourdomain.com;
ssl_certificate /etc/nginx/cert/yourdomain.pem;
ssl_certificate_key /etc/nginx/cert/yourdomain.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
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_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 3600s;
}
}
其中的关键操作是proxy_set_header Upgrade和Connection这两行。 WebSocket协议从HTTP/1.1的Upgrade机制演化而来,Nginx默认配置不会保留这两个请求头,没有它们的话客户端握手直接失败,表现通常是浏览器控制台报101切换协议请求被拒,或者反复刷新重连。
proxy_read_timeout这里设置的3600秒,指后端没有发送数据时,Nginx等待多久才断开连接,默认60秒,对聊天类应用来说太短了,客户端一会儿就被动断线,如果你的业务有心跳机制,这个值可以适度下调,比如300秒,配合后端的心跳包一起工作。
这里多提一句,很多人会踩的一个坑:Nginx配置了SSL后,浏览器直接访问https://你的域名/ws会返回404或502,但这不代表你的wss不通。 wss连接是普通HTTP请求携带Upgrade头发起的,你用浏览器地址栏访问时根本不会带上这个头,所以看到的响应没有参考意义,判断通不通,要用前端代码或命令行工具去试。
第三步:改前端连接地址
后端代码不用动,但前端所有连WebSocket的地方,要把地址从ws://yourdomain.com/ws改成wss://yourdomain.com/ws,就这么一个字符串的变更,但漏了的话浏览器会一直报错,而且报错信息有时并不直观,容易让人怀疑是后端问题。
改完以后,如果是网页端,记得在Nginx里补跳转配置,把原来的ws://请求也指到443端口:
server {
listen 80;
server_name yourdomain.com;
return 301 https://$host$request_uri;
}
这个301跳转对WebSocket连接没有什么直接帮助,因为握手时不一定走80,但对于那些不小心用了ws://的老用户,能起到一个缓冲提示的作用。
wss连接失败怎么回事?常见原因排查清单

这个疑问基本是每个配置过wss的人都会遇到的问题,我自己也卡过好几个晚上,繁多的失败原因里,概率最高且最容易误判的是下面几种。
| 现象 | 可能原因 | 处理方式 |
|---|---|---|
| 连接Error in connection establishment | 证书链不完整 | 检查证书文件是否包含完整中间证书 |
| 101状态但立即断开 | 心跳超时或后端主动断开 | 调整Nginx的proxy_read_timeout |
| 404/400响应 | location路径不匹配 | 确认前端连接的/ws与Nginx配置一致 |
| Mixed Content | 页面是HTTPS但代码写成ws | 前端字符串改为wss |
| ERR_CERT_COMMON_NAME_INVALID | 证书域名不匹配 | 证书必须绑定你的连接域名 |
证书链不完整这个坑值得单独拿出来说一说,你用后端的wss://地址连时,如果浏览器报NET::ERR_CERT_REVOKED或类似提示,多半是证书链少了中间证书,免费DV证书通常会把站点证书和中间证书放在同一个.pem文件里,但有些厂商下载下来是两个独立的文件,你只配了站点证书就会出问题。正确处理方式是把站点证书和中间证书按顺序拼接成一个文件,方式是用文本编辑器打开,站点证书内容在上,中间证书在下,保存为fullchain.pem,然后在Nginx里指向这个拼接文件。
还有一类问题出在端口上。wss默认走443,但如果你的Nginx监听的不是443而是别的端口,则wss地址里必须显式带端口, 比如wss://yourdomain.com:8443/ws,有些云厂商的安全组规则默认只放行80和443,你用其他端口时防火墙可能静默丢包,表现为连接超时或长时间pending,连报错都不给。
拼接证书和检查安全组这两件事,排查时优先级最高,把这两项确认完,剩下的问题通常都能在前端控制台的报错信息里找到线索。
把ws升级到wss时,你需要处理的三个细节
通过ip_hash或相同域名解决负载均衡会话保持
如果你不止一台后端服务器,Nginx层做了upstream负载均衡,那么需要留意:WebSocket连接建立后是长连接,前面几台机器轮询分发没有关系,但是连接一旦建立,后续所有数据帧都必须由同一台机器处理。 解决方式是在upstream块加上ip_hash;,这样同一个客户端的请求会固定转发到同一台后端机器上。
upstream websocket_backend {
ip_hash;
server 192.168.1.2:8080;
server 192.168.1.3:8080;
}
同时代理配置里的proxy_pass要改成http://websocket_backend,和upstream定义的名称对应上,这种模式在多数业务场景下都没有问题,但如果你的用户量大且通过网络出口动态变化IP,则可能需要改用Redis Pub/Sub或消息队列做跨节点消息同步,那是另一个话题了。

证书通用性与域名选择
有一类业务场景比较特殊有些App或小程序不允许你动态配置请求域名,必须绑定一个固定域名,这要求你在规划wss的时候就把域名想清楚,域名一旦在生产环境用了几个月,再想换新域名不是只改前端地址那么简单,证书要重新申请,旧用户你就没有更匹配的方式覆盖了。所以先定域名再做证书,这一点值得投入点时间规划。
端口与外网访问策略
还是有不少人图省事,直接用8080、8081这类端口开wss,技术上完全可行,只要在Nginx把443换成对应端口,再把证书配置上去,其他逻辑不变,但实际使用中,非标准端口的wss在部分企业网络或校园网环境下容易被封,因为很多防火墙默认只放行80和443,行业实践里,几乎所有公共WebSocket服务都跑在443,这个端口有兼容性上的不可替代性,另一个问题是,你如果用非标端口,wss地址里要写明端口号,写代码时漏掉端的概率远超你想象。
关于wss配置,开发者常问的三个问题
wss配置里需要用HTTP/2吗?
不需要,HTTP/2和WebSocket是完全独立的两套机制,Nginx开启HTTP/2只影响普通的HTTPS请求,WebSocket连接走的还是HTTP/1.1的Upgrade流程,所以很多教程里说的“开启HTTP/2后WebSocket更快”,其实没有逻辑依据。
wss连接在移动端会额外耗电吗?
能耗主要取决于心跳策略,而不在于是否使用TLS加密,手机端弱网环境下频繁掉线重连的功耗,远大于TLS加解密带来的开销。多数情况下建议前端采用自适应心跳:网络正常时30秒发一次ping,弱网时自动缩短到15秒,这样既能保持连接活跃,又不会在锁屏时白白耗电。
一台Nginx能同时代理多个wss业务吗?
能,用不同的location路径区分业务,各自指向不同的后端端口即可,证书配置在server块之下,这些location共用同一个证书,有一点要注意:如果两个业务所在的父级域名相同,比如example.com/app1和example.com/app2,证书可以直接共用;若它们属于完全不同的域名,则需要额外配置多证书或通配符证书。
wss配置不是一件需要复杂脑力的事,它更像是按图索骥证书链完整、Upgrade头透传、路径匹配,这三点完全落实,连接自然就通了,哪怕中途遇到报错,按上面的排查表逐项比对,绝大多数问题都能在半小时内定位,真正让你头疼的往往不是配置本身,而是那些看起来像“玄学”的小细节,其实都是基础设施层面的硬道理。
