原生 Nginx 并不支持国密算法。因此,配置负载均衡的首要前提是使用一款支持国密的 Nginx 衍生版或进行定制编译。
常用的选择有以下几种:
Tengine + Tongsuo:阿里开源的 Tengine 服务器集成了铜锁(Tongsuo,原 BabaSSL)密码库,是目前最成熟、文档最丰富的选择之一。
nginx-tongsuo:一个专门集成了 Tongsuo 的 Nginx 官方维护版本,被认为是生产环境就绪的。
nginx-gm:由社区维护的支持国密的 Nginx 分支。
Nginx + GMSSL:使用 GMSSL 替换系统自带的 OpenSSL,并重新编译 Nginx。
介绍完底层前提,接下来的重点是上游服务器的国密 SSL 配置,核心在于**同时处理好国密客户端和国际客户端,并为上游服务器启用国密安全通道(通常是 HTTPS)**。
一、上游服务器的国密 SSL 配置要点
1. 部署双证书 (SM2 + RSA)
这是最关键的步骤,必须同时配置国密 SM2 证书和用于兼容的 RSA 证书。
国密证书:包含 SM2 签名证书和 SM2 加密证书。配置时需通过 `ssl_certificate` 和 `ssl_certificate_key` 指令依次指明。
国际证书:包含 RSA 证书和私钥,同样是分开配置。
nginx
# 在 upstream 的 server 或一个专门的 location 块中
server {
# 1. 配置国密 SSL 证书(签名证书+加密证书)
ssl_certificate /path/to/sm2_sign.crt;
ssl_certificate_key /path/to/sm2_sign.key;
ssl_certificate /path/to/sm2_encrypt.crt;
ssl_certificate_key /path/to/sm2_encrypt.key;
# 2. 配置国际 RSA SSL 证书(用于兼容性)
ssl_certificate /path/to/rsa.crt;
ssl_certificate_key /path/to/rsa.key;
# ... 其他配置
}
2. 锁定国密协议与密码套件
编辑 Nginx 配置文件,严格限制 TLS 协议版本和密码套件。
优先国密协议:确保优先使用国密协议(如 `GMv1`),同时为了兼容,可包含 TLSv1.2 和 TLSv1.3。
优先国密套件:将国密加密套件(如 `ECC-SM2-WITH-SM4-SM3` 或 `ECDHE-SM4-SM3`)置于列表最前。
服务端优先:开启 `ssl_prefer_server_ciphers on;`,让服务器主导加密套件的选择,确保国密套件生效。
nginx
# 在 server 块内
ssl_protocols GMv1 TLSv1.2 TLSv1.3;
ssl_ciphers ECC-SM2-WITH-SM4-SM3:ECDHE-SM4-SM3:TLS_SM4_SM3:ECDHE-RSA-AES128-GCM-SHA256:...;
ssl_prefer_server_ciphers on;
3. 可选但建议:启用双向认证 (mTLS)
对于支付接入、身份验证等安全敏感的上游服务,可以通过注解或特定配置为后端服务器启用双向认证。
yaml
# 使用 nginx.org/redirect-to-https 注解为后端服务开启 TLS 重定向,再通过类似方式要求客户端证书
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
# 类似思路,要求上游服务器验证负载均衡器提供的证书
二、负载均衡层面的配置要点
在 Upstream 块中配置上游服务器
在 `upstream` 块中定义后端服务器组时,如果上游服务器本身是支持国密的 HTTPS 服务,务必声明使用 `https` 协议。
nginx
upstream backend_servers {
# 健康检查(推荐)
health_check interval=5s fails=3 passes=2;
server backend1.example.com:443 weight=3 max_fails=3 fail_timeout=30s;
server backend2.example.com:443 weight=2 max_fails=3 fail_timeout=30s;
server backend3.example.com:443 backup; # 备用服务器
}
server {
listen 443 ssl;
server_name your-domain.com;
# ... SSL 配置(双证书、协议、加密套件等,此处省略)
location / {
proxy_pass https://backend_servers; # 注意使用 https
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
三、关于监控和健康检查
确保配置的健康检查机制能够正确处理 TLS 情况【13†L14-L15】:
HTTPS 健康检查:使用 `health_check` 指令时,确保它能正确处理上游服务器的国密 SSL/TLS 握手。
日志记录:在 `log_format` 中添加 `$ssl_protocol` 和 `$ssl_cipher`,用于审计和监控国密协商情况。
四、验证与常见问题
配置完成后,务必进行验证,不能仅依赖配置语法检查。
使用国密工具测试:
使用 国密浏览器(如红莲花、360安全浏览器国密版) 访问,观察浏览器地址栏是否能正常显示安全锁标。
使用 gmssl 命令行工具测试: `gmssl s_client -connect your-domain.com:443 -cipher ECC-SM2-WITH-SM4-SM3`。
检查 Nginx 错误日志:查看是否存在 `SSL_do_handshake() failed` 或 `no suitable key share` 等错误,常见原因是证书链不完整或曲线不匹配。
网络抓包分析:使用 `tcpdump` 或 Wireshark 抓包,分析 ClientHello 和 ServerHello 消息,确认协商的协议版本是否为国密协议(如 GMv1),加密套件是否为已配置的国密套件。
常见错误及解决:
`unknown directive "ssl_protocols GMv1"`:**原因** Nginx 未使用支持国密的版本。解决 请使用文章开头推荐的国密定制版 Nginx。
`no appropriate protocol (offending protocol: GMv1, ...)`:原因 通常是编译时 OpenSSL 库未正确链接或版本不支持。解决 检查编译过程,确保 OpenSSL 库支持 GMv1 协议,并正确链接。
国密改造是一个系统性工程,覆盖了从底层密码库到上层应用的全链路。如果能告诉我你更倾向使用哪种国密方案(比如 Tengine + Tongsuo,还是 Nginx + GMSSL),我可以为你提供更具针对性的配置示例。