如何通过Nginx模块实现国产SM算法支持,构建金融级Web网关合规化全流程?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1032个文字,预计阅读时间需要5分钟。
目前+Nginx官方主线不支持SM2/SM3/SM4,直接编译或配置ssl_protocols或ssl_ciphers无法启用国密算法;必须依赖第三方模块(如nginx_gm)并替换底层OpenSSL为支持国密的分支(如gmssl或openssl-gm)。
确认底层 OpenSSL 是否已替换为国密支持版本
很多团队卡在第一步:以为装了国密模块就万事大吉,结果 nginx -V 显示仍链接着系统默认 OpenSSL(OpenSSL 1.1.1w 或 3.0.x),这类版本原生不认 SM2 密钥或 SM4-CBC 密码套件。
- 运行
nginx -V 2>&1 | grep -i openssl,检查输出中的built with OpenSSL路径是否指向你编译安装的gmssl(例如/usr/local/gmssl) - 进入该路径,执行
bin/openssl version -a,确认输出含GMSSL字样且版本号 ≥3.1.1 - 若显示
OpenSSL 1.1.1或无GMSSL,说明 Nginx 编译时未指定--with-openssl=指向国密 OpenSSL 源码,需重编译
编译 Nginx 时正确加载 nginx_gm 模块
nginx_gm 是目前最稳定的国密模块(维护活跃、适配 Nginx 1.18–1.25),但它不是 --add-module 单步能搞定的——它强依赖 GMSSL 的头文件和符号导出,且部分版本需 patch Nginx 源码。
- 下载与你的 Nginx 版本匹配的
nginx_gm分支(如 Nginx 1.22 → 用nginx_gm的v1.22tag) - 编译前先在 GMSSL 源码根目录执行
make install_dev(否则./configure会报gmssl.h: No such file) -
./configure必须显式指定:--with-openssl=/path/to/gmssl/src --add-module=/path/to/nginx_gm - 若遇到
undefined reference to `EVP_sm4_cbc',说明链接时未带-lgmssl,需修改objs/Makefile中NGX_RPATH和LIBS行补全
配置 server 块启用 SM2+SM4 双向认证
国密合规不止是“能用 SM4 加密”,金融场景要求 TLS 层级的双向认证(mTLS),且证书链、密钥格式、密码套件必须严格匹配 GMSSL 规范。
- 私钥必须为 SM2 格式(PEM 中含
-----BEGIN EC PRIVATE KEY-----且曲线为sm2p256v1),不可用 RSA 私钥混用 - 证书需由国密 CA 签发,且
subjectAltName必须包含域名,否则现代浏览器拒绝建立连接 - 关键配置项:
ssl_certificate /etc/nginx/certs/server.crt; ssl_certificate_key /etc/nginx/certs/server.key; ssl_client_certificate /etc/nginx/certs/ca.crt; ssl_verify_client on; ssl_protocols TLSv1.2; ssl_ciphers ECDHE-SM2-SM4-CBC-SM3:SM2-SM4-CBC-SM3;
- 注意:
ssl_ciphers中不能混入非国密套件(如ECDHE-RSA-AES256-GCM-SHA384),否则协商失败返回no suitable cipher
验证连接是否真正走国密协议栈
浏览器地址栏显示锁图标 ≠ 国密生效;Chrome/Firefox 默认禁用国密套件,必须用国密浏览器(如红莲花、零信)或命令行工具验证。
- 用
openssl s_client -connect example.com:443 -cipher 'SM2-SM4-CBC-SM3' -tls1_2,成功时输出应含New, TLSv1.2, Cipher is SM2-SM4-CBC-SM3 - 抓包看 ClientHello 的
cipher_suites字段是否含0xc0,0x9f(即SM2-SM4-CBC-SM3的 IANA ID) - Nginx error log 出现
SSL_do_handshake() failed (SSL:) ... no ciphers available,大概率是ssl_ciphers写错、证书非 SM2、或客户端不支持 - 别忽略 OCSP Stapling:国密证书的 OCSP 响应也需用 SM2 签名,否则
ssl_stapling on会导致 handshake hang
真正的难点不在编译或配置,而在于整条信任链的国产化闭环:从 CA 根证书、中间证书、终端证书的签发算法,到 OCSP 响应签名、CRL 分发点证书,全部必须是 SM2;漏掉任意一环,TLS 握手就在某个环节静默失败。
本文共计1032个文字,预计阅读时间需要5分钟。
目前+Nginx官方主线不支持SM2/SM3/SM4,直接编译或配置ssl_protocols或ssl_ciphers无法启用国密算法;必须依赖第三方模块(如nginx_gm)并替换底层OpenSSL为支持国密的分支(如gmssl或openssl-gm)。
确认底层 OpenSSL 是否已替换为国密支持版本
很多团队卡在第一步:以为装了国密模块就万事大吉,结果 nginx -V 显示仍链接着系统默认 OpenSSL(OpenSSL 1.1.1w 或 3.0.x),这类版本原生不认 SM2 密钥或 SM4-CBC 密码套件。
- 运行
nginx -V 2>&1 | grep -i openssl,检查输出中的built with OpenSSL路径是否指向你编译安装的gmssl(例如/usr/local/gmssl) - 进入该路径,执行
bin/openssl version -a,确认输出含GMSSL字样且版本号 ≥3.1.1 - 若显示
OpenSSL 1.1.1或无GMSSL,说明 Nginx 编译时未指定--with-openssl=指向国密 OpenSSL 源码,需重编译
编译 Nginx 时正确加载 nginx_gm 模块
nginx_gm 是目前最稳定的国密模块(维护活跃、适配 Nginx 1.18–1.25),但它不是 --add-module 单步能搞定的——它强依赖 GMSSL 的头文件和符号导出,且部分版本需 patch Nginx 源码。
- 下载与你的 Nginx 版本匹配的
nginx_gm分支(如 Nginx 1.22 → 用nginx_gm的v1.22tag) - 编译前先在 GMSSL 源码根目录执行
make install_dev(否则./configure会报gmssl.h: No such file) -
./configure必须显式指定:--with-openssl=/path/to/gmssl/src --add-module=/path/to/nginx_gm - 若遇到
undefined reference to `EVP_sm4_cbc',说明链接时未带-lgmssl,需修改objs/Makefile中NGX_RPATH和LIBS行补全
配置 server 块启用 SM2+SM4 双向认证
国密合规不止是“能用 SM4 加密”,金融场景要求 TLS 层级的双向认证(mTLS),且证书链、密钥格式、密码套件必须严格匹配 GMSSL 规范。
- 私钥必须为 SM2 格式(PEM 中含
-----BEGIN EC PRIVATE KEY-----且曲线为sm2p256v1),不可用 RSA 私钥混用 - 证书需由国密 CA 签发,且
subjectAltName必须包含域名,否则现代浏览器拒绝建立连接 - 关键配置项:
ssl_certificate /etc/nginx/certs/server.crt; ssl_certificate_key /etc/nginx/certs/server.key; ssl_client_certificate /etc/nginx/certs/ca.crt; ssl_verify_client on; ssl_protocols TLSv1.2; ssl_ciphers ECDHE-SM2-SM4-CBC-SM3:SM2-SM4-CBC-SM3;
- 注意:
ssl_ciphers中不能混入非国密套件(如ECDHE-RSA-AES256-GCM-SHA384),否则协商失败返回no suitable cipher
验证连接是否真正走国密协议栈
浏览器地址栏显示锁图标 ≠ 国密生效;Chrome/Firefox 默认禁用国密套件,必须用国密浏览器(如红莲花、零信)或命令行工具验证。
- 用
openssl s_client -connect example.com:443 -cipher 'SM2-SM4-CBC-SM3' -tls1_2,成功时输出应含New, TLSv1.2, Cipher is SM2-SM4-CBC-SM3 - 抓包看 ClientHello 的
cipher_suites字段是否含0xc0,0x9f(即SM2-SM4-CBC-SM3的 IANA ID) - Nginx error log 出现
SSL_do_handshake() failed (SSL:) ... no ciphers available,大概率是ssl_ciphers写错、证书非 SM2、或客户端不支持 - 别忽略 OCSP Stapling:国密证书的 OCSP 响应也需用 SM2 签名,否则
ssl_stapling on会导致 handshake hang
真正的难点不在编译或配置,而在于整条信任链的国产化闭环:从 CA 根证书、中间证书、终端证书的签发算法,到 OCSP 响应签名、CRL 分发点证书,全部必须是 SM2;漏掉任意一环,TLS 握手就在某个环节静默失败。

