应于Nginx入口层拦截非法WebSocket连接:先透传Upgrade/Connection头并设HTTP/1.1,再用Lua在access阶段校验协议、路径、token、Origin及限频,叠加IP限连、黑白名单、攻击载荷过滤与强制HTTPS。

限制非法 WebSocket 连接,关键不是等请求到了后端再拦,而是在 Nginx 入口层就识别、拦截、拒绝。核心思路是:用标准配置守住协议底线,再用 Lua 动态校验补充业务逻辑,最后叠加基础访问控制。
严格透传并校验握手头
90% 的非法连接其实连握手都通不过——因为 Nginx 默认丢弃 Upgrade 和 Connection 头,导致后端根本收不到升级意图,或被中间设备篡改。必须显式配置:
- proxy_http_version 1.1:HTTP/1.0 不支持协议升级,缺了这行,Nginx 会静默降级
- proxy_set_header Upgrade $http_upgrade:用变量转发原始值,兼容 websocket / h2c / mqtt 等多种升级场景
- proxy_set_header Connection "upgrade":必须是小写字符串 "upgrade",不能用 $http_connection(它常含 keep-alive,会覆盖升级信号)
用 Lua 在 access 阶段动态拦截
仅靠头透传不够,攻击者可能伪造 Origin、空 token、恶意 URI 或高频试探。在 location 块中嵌入 Lua 脚本,在请求进入内容处理前实时决策:
- 检查 ngx.var.http_upgrade == "websocket" 且 ngx.var.http_connection:lower():find("upgrade"),否则直接
ngx.exit(400) - 验证 URI 路径是否匹配白名单(如
/ws/、/api/v1/chat),禁止通配或敏感路径(如/admin/ws) - 提取查询参数 token=xxx,调用 HMAC 校验或查本地缓存白名单;无 token 或校验失败则
ngx.exit(403) - 用 lua_shared_dict 统计每个 IP 每分钟握手次数,超阈值(如 ≥5 次)返回
429 Too Many Requests - 对 Origin 做域名白名单比对,拒绝 localhost、127.0.0.1、非业务域名或空 Origin(生产环境必须)
叠加基础网络与行为防护
协议和业务层之外,还需防止扫描、泛洪和已知攻击特征:
- 在 server 或 http 块中启用 limit_conn perip 10(单 IP 最多 10 个并发 WebSocket 连接)
- 配合 allow/deny 限制来源 IP 段,例如只允许 CDN 或办公网段访问管理类 ws 接口
- 禁用目录浏览:autoindex off;隐藏版本号:server_tokens off
- 用正则过滤 URI 中的典型攻击载荷,如
%3Cscript%3E、javascript:、union select,匹配即ngx.exit(403)
HTTPS 强制与证书有效性保障
wss 不是可选项,而是安全前提。浏览器在 HTTPS 页面中会直接阻止 ws:// 连接:
- server 块必须监听 listen 443 ssl,且配置有效证书(
ssl_certificate+ssl_certificate_key) - 禁用老旧协议:ssl_protocols TLSv1.2 TLSv1.3;关闭不安全套件:ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
- 确保后端服务监听 HTTP(非 HTTPS),Nginx 完成 SSL 终结后以明文转发,避免证书链错乱


















