用户要让 Nginx 支持国密算法,一个常见但容易出错的步骤是配置 `ssl_protocols` 指令。需要特别注意,原生 Nginx 本身不支持国密,必须替换底层密码库或使用经过改造的专用版本才行。
一、前置准备:构建国密环境
在开始配置前,你需要先准备一个支持国密的 Nginx 环境,主要有以下3种专业方案:
方案 说明 适用场景
使用 GMSSL 重编译 用支持国密的 GMSSL 3.1.1+ 库替换原生 OpenSSL,再重新编译 Nginx。 希望在不更换 Nginx 主版本的情况下,自行构建国密支持能力。
使用国密版 Tengine 以阿里系维护的开源 Web 服务器 Tengine 为基础,集成国密补丁或模块(如 BabaSSL/Tongsuo)。 寻求更稳定、社区支持更成熟的国密 Nginx 解决方案。
使用 nginx-with-openHiTLS 基于 openHiTLS 密码库的 Nginx 发行版,原生支持国密 TLCP 协议。 需要深度国密改造,对 TLCP 协议支持有强需求的高安全场景。
二、 `ssl_protocols` 配置说明
构建出国密环境后,典型的 `ssl_protocols` 配置会对比普通 HTTPS 和多了一种国密专属协议**GMv1**。
标准 HTTPS 配置
如果只需支持普通 HTTPS,配置如下:
nginx
server {
listen 443 ssl;
# 证书路径仅为示意,请替换为您自己的证书路径
ssl_certificate /path/to/server.crt;
ssl_certificate_key /path/to/server.key;
ssl_protocols TLSv1.2 TLSv1.3;
# ... 其他配置
}
Nginx 官方推荐的现代安全配置中,`ssl_protocols TLSv1.2 TLSv1.3;` 允许客户端使用 TLS 1.2 或更安全的 TLS 1.3 建立连接。
国密 HTTPS 配置
若需同时支持国密,配置文件会变为:
nginx
server {
listen 443 ssl;
# 双证书配置示例:签名证书与加密证书(高安全场景)
ssl_certificate /path/to/sign.crt;
ssl_certificate_key /path/to/sign.key;
ssl_certificate /path/to/encrypt.crt;
ssl_certificate_key /path/to/encrypt.key;
ssl_protocols GMv1 TLSv1.2 TLSv1.3;
# 密码套件强制国密优先
ssl_ciphers ECC-SM2-WITH-SM4-SM3:ECDHE-SM2-WITH-SM4-SM3:...:!aNULL:...;
ssl_prefer_server_ciphers on;
# ... 其他配置
}
与普通配置相比,有以下几个关键差异:
`GMv1` 协议参数:配置中新增的 `GMv1` 是国密 SSL 协议的专属标识,对国密握手至关重要。若 Nginx 版本不支持该参数,说明未正确安装国密版本。
必须优先国密套件(Cipher Suites):国密环境下 `ssl_ciphers` 指令必须强制优先配置 SM 系列算法套件(如 `ECC-SM2-WITH-SM4-SM3`),并禁用掉非国密的算法。
开启 `ssl_prefer_server_ciphers on`:建议开启此指令,让服务器端完全主导加密套件的协商顺序,确保国密套件能被优先使用。
三、双证书配置与认证
双证书部署 (Sign & Encrypt):在等保三级的金融级应用中,通常要求部署签名证书和加密证书(即双证书体系),需要如上例所示分别配置。
双向认证 (mTLS) 加强安全:在金融支付等安全等级极高的场景,还需要配置双向认证(mTLS):
nginx
server {
# ... 基础配置
ssl_client_certificate /path/to/gm-ca-chain.crt; # 信任的国密CA链
ssl_verify_client on; # 开启客户端证书验证
# ... 其他配置
}
四、配置步骤
1. 替换或编译 Nginx
根据“前置准备”表格,选择一种方案进行环境构建。
2. 修改 Nginx 配置文件
编辑 `conf/nginx.conf`,在 `server` 块中按上述示例修改 SSL 配置。
3. 测试并重载配置
bash
nginx -t # 测试配置语法是否正确
systemctl reload nginx # 重载配置,或重启Nginx服务
五、故障排查
如果配置后国密功能异常,可以尝试以下排查方法:
现象 可能原因 排查步骤
启动报错 "unknown cipher" `ssl_ciphers` 配置的国密套件名不被 Nginx 识别。 | 确认 Nginx 是否为国密版本,并检查 GMSSL 或国密模块是否安装正确。
配置了 `ssl_protocols GMv1` 导致 Nginx 不识别启动失败 Nginx 原生版本不识别 `GMv1` 等参数。 检查 Nginx 安装版本是否为上述三种之一。
握手失败,浏览器报错 国密证书加载错误或底层库不匹配。 确认证书格式正确,并使用 `nginx -V 2>&1 \ grep -o 'OpenSSL [^ ]*'` 命令,检查使用的 OpenSSL 版本是否为支持国密的 GMSSL 等。
审计发现协商使用了国际算法 国密套件优先级不是最高,导致协议降级。 `ssl_ciphers` 行必须将国密套件写在最前面,并开启 `ssl_prefer_server_ciphers on` 让服务器端主导协商。
总结
想让 Nginx 支持国密,最关键的一步是用 GMSSL 或 openHiTLS 等支持国密的密码库替换掉 Nginx 依赖的底层 OpenSSL 库,或者在国密版 Tengine 等专用版本上做二次开发。之后的 `ssl_protocols GMv1 TLSv1.2 TLSv1.3;` 和配套的国密 `ssl_ciphers` 配置,都是为了真正驱动国密功能的专门设置。