防火墙(含waf、云安全组、系统防火墙)是websocket在nginx代理下中断的最隐蔽原因。需分层排查:先用curl直连ip验证是否被waf拦截,再检查云安全组、系统防火墙端口及waf协议识别规则,最后通过nginx日志和tcpdump确认upgrade头是否被篡改或清除。

WebSocket连接在Nginx代理下中断,若已排除Nginx配置、证书、超时等常见原因,防火墙(含WAF、云安全组、系统防火墙)就是最隐蔽也最常被忽略的一环。排查要分层推进,不能只盯着Nginx日志。
先确认是否真被防火墙拦截
很多问题表面是“连接失败”,实则是握手请求在抵达Nginx前就被静默丢弃。关键判断依据是:前端控制台报错为 net::ERR_CONNECTION_REFUSED、net::ERR_SSL_PROTOCOL_ERROR 或完全无响应(非101状态码),且Nginx访问日志里根本查不到该请求记录——说明请求没进Nginx,卡在了更外层。
- 用 curl 模拟握手并绕过域名解析:直接用服务器公网IP访问,跳过DNS和WAF
curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" http://[SERVER_IP]:80/ws/
如果返回101,说明WAF或CDN在中间干扰;如果仍失败,再查系统防火墙或端口 - 改用 hosts本地映射:把域名指向源站IP,浏览器访问同一页面,测试WebSocket能否连通。能通即锁定WAF/CDN
- 检查WAF控制台的实时访问日志,筛选目标路径(如
/ws、/socket),看是否有403、444、502响应且无后端日志——这是典型WAF拦截特征
逐层检查防火墙策略
防火墙不是单一层级,需从外到内排查:
-
云厂商安全组:确认入方向规则放行了WebSocket服务实际监听的端口(如8586、8282),协议选TCP,源地址建议设为
0.0.0.0/0(测试期)或精确到前端CDN/IP段 -
系统防火墙(firewalld/ufw):运行
sudo firewall-cmd --list-ports或sudo ufw status,确认对应端口已开放且为永久规则;用telnet [IP] [PORT]从客户端机器直连测试,能通说明网络层通畅 -
WAF自定义规则:重点检查是否启用了“Websocket协议识别”开关(阿里云、腾讯云均有);若未开启,需手动添加放行策略——匹配条件为
URI包含 /ws 或 /socket且请求头包含 Upgrade: websocket,动作设为“放行”,并禁用SQL注入、CC防护等关联规则
验证握手请求是否完整抵达Nginx
即使连接能建立,防火墙也可能篡改或截断关键头部,导致后端无法完成升级。必须验证原始请求头是否干净到达:
- 在Nginx的location块中临时加日志:
log_format ws_log '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_upgrade" "$http_connection"';,再配合access_log /var/log/nginx/ws_access.log ws_log; - 触发一次WebSocket连接,立刻查看日志:
✅ 正常应看到"websocket" "upgrade"
❌ 若$http_upgrade为空或为"",说明WAF或CDN清除了该头 - 用Wireshark或tcpdump在Nginx服务器上抓包:
sudo tcpdump -i any -A 'port 80 or port 443' | grep -i -E 'upgrade|connection',直接观察原始HTTP请求头内容











