在 linux 中结合 ssl 证书实现 nginx 代理 websocket 的双向认证,核心在于配置 ssl_verify_client on 并指定 ca 证书路径。nginx 会在建立 tls 握手时验证客户端证书的有效性,只有验证通过的连接才会被转发到后端 websocket 服务。这种做法确保了通信双方的身份可信,防止未授权客户端接入。

Nginx 如何配置双向认证的 SSL 参数
Nginx 通过 ssl_certificate、ssl_certificate_key 和 ssl_client_certificate 三个指令完成双向认证配置。其中 ssl_client_certificate 用于存放签发客户端证书的 CA 证书,ssl_verify_client 设置为 on 强制要求客户端提供有效证书。WebSocket 升级请求必须包含正确的 Upgrade 和 Connection 头,否则 Nginx 不会将连接升级为 WebSocket 协议。

server {
listen 443 ssl;
server_name ws.example.com;
# 服务端证书与私钥
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
# 客户端认证:CA 证书
ssl_client_certificate /etc/nginx/ssl/ca.crt;
ssl_verify_client on;
# WebSocket 支持
location /ws {
proxy_pass http://backend_ws;
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_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
}
}
upstream backend_ws {
server 127.0.0.1:8080;
}
上述配置中,ssl_verify_client on 是开启双向认证的关键。如果客户端不提供证书或证书无效,Nginx 会直接返回 400 Bad Request,不会转发到后端。WebSocket 相关的头部设置确保连接能正确升级。超时时间设置为 86400 秒(一天),适合长连接场景。
客户端如何生成证书并连接
客户端需要拥有由 Nginx 配置的 CA 签发的证书才能成功连接。通常使用 OpenSSL 生成客户端密钥和证书请求,然后用 CA 私钥签名生成客户端证书。连接时使用 wss:// 协议,并在客户端代码中加载客户端证书和私钥。不同编程语言库的 API 略有差异,但核心都是提供证书文件路径。

# 生成客户端私钥 openssl genrsa -out client.key 2048 # 生成客户端证书请求 openssl req -new -key client.key -out client.csr -subj "/CN=client" # 用 CA 私钥签名生成客户端证书 openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 365
在 Python 中使用 websockets 库连接时,需创建 ssl.SSLContext 并加载客户端证书。Node.js 使用 tls 模块或第三方库如 ws 时,同样需要在选项对象中指定 cert 和 key。如果证书过期或被吊销,连接会被拒绝。
客户端证书缺失时 Nginx 返回什么状态码
当客户端未提供证书或证书无效时,Nginx 会返回 HTTP 400 Bad Request 状态码。这是因为 ssl_verify_client on 模式下,TLS 握手阶段就会失败,Nginx 无法获取有效的客户端身份信息,因此直接终止连接。此时后端 WebSocket 服务完全不会收到请求,日志中会记录 SSL 验证失败的错误信息。











