websocket代理无内置鉴权,需在nginx握手阶段(get请求)拦截校验:支持ip/geoip限制、请求头或参数预检、auth_request动态鉴权,以及limit_conn/limit_req防滥用。

WebSocket 代理本身不内置用户鉴权或细粒度访问控制,Nginx 的访问控制需结合 HTTP 层机制实现——在 WebSocket 握手阶段(即 GET 请求)拦截并校验,未通过则拒绝升级,从而阻止连接建立。
基于 IP 或地理位置的访问限制
适用于内网服务暴露、测试环境隔离等场景。可在 location 块中直接使用 allow/deny 指令:
- 只允许公司办公网段访问:
allow 192.168.10.0/24;,末尾加deny all; - 配合 GeoIP 模块可按国家/地区屏蔽(如禁用高风险区域 IP),需提前编译或启用
ngx_http_geoip2_module - 注意:该策略作用于握手请求,不影响已建立的 WebSocket 连接;连接建立后流量不再经过 Nginx 的 access 阶段
基于请求头或参数的身份预检
WebSocket 握手是标准 HTTP 请求,可利用 $arg_token、$http_authorization 等变量做初步校验:
- 检查 URL 中是否携带有效 token:
if ($arg_token = "") { return 403; } - 验证 Bearer Token(需配合后端签发和校验逻辑):
if ($http_authorization !~ "^Bearer [a-zA-Z0-9\-\._~\+/]+=*$") { return 401; } - 更安全的做法是将鉴权逻辑下沉到后端服务,Nginx 仅透传关键头(如
X-Forwarded-User),由后端完成 session 或 JWT 校验
结合 auth_request 模块实现动态鉴权
这是最灵活、生产推荐的方式:Nginx 将握手请求转发给一个独立的鉴权服务(如轻量 API),根据其返回状态码决定是否放行:
- 在
http块中定义鉴权 upstream:upstream auth_backend { server 127.0.0.1:8081; } - 在 WebSocket location 中添加:
auth_request /auth;和location = /auth { proxy_pass http://auth_backend; proxy_pass_request_body off; proxy_set_header Content-Length ""; } - 鉴权服务返回
200 OK则继续代理,返回401/403则直接拒绝握手 - 优势:支持数据库查询、Redis 缓存、OAuth2 introspection 等复杂逻辑,且与业务解耦
防止滥用的连接数与频率限制
WebSocket 是长连接,需防范恶意高频建连或连接堆积:
- 使用
limit_conn控制单个 IP 并发连接数:limit_conn addr 5;(需先定义limit_conn_zone $binary_remote_addr zone=addr:10m;) - 用
limit_req限制握手请求频次(防暴力探测):limit_req zone=ws_handshake burst=3 nodelay; - 注意:这些限制仅对握手阶段生效;已建立的连接不受影响,但可配合
proxy_read_timeout主动断开空闲连接











