Nginx国密HTTPS部署实战:从算法原理到双证书配置

📅 2026/7/5 9:24:30
Nginx国密HTTPS部署实战:从算法原理到双证书配置
1. 项目概述为什么金融级HTTPS必须拥抱国密如果你负责过金融、政务或者大型国企的Web服务项目大概率遇到过“国密合规”这个硬性要求。这不仅仅是技术选型更是一项政策性任务。传统的HTTPS依赖RSA、ECC等国际通用算法而国密SSL则是基于我国自主密码算法标准SM2、SM3、SM4构建的安全通信体系。简单来说它用SM2非对称算法替代RSA/ECC用SM3哈希算法替代SHA用SM4对称算法替代AES实现了一套从底层算法到上层协议完全自主可控的安全链路。这次实战我们聚焦于最核心的Web服务入口——Nginx服务器使用阿里云签发的SM2双证书搭建一个支持国密算法的HTTPS站点。你可能会问为什么是“双证书”这正是国密改造初期为了兼容性而采取的经典方案一套SM2国密证书用于与支持国密的浏览器如360安全浏览器国密版、密信浏览器通信另一套传统的RSA/ECC国际证书用于保障其他主流浏览器的正常访问。Nginx国密版则是在原生Nginx基础上集成了对国密算法和双证书监听能力的特殊编译版本。整个过程从证书申请、Nginx国密版编译安装到复杂的双证书链合并与配置每一步都有坑。尤其是证书链合并阿里云下载的证书包往往需要手动拼接中间CA这一步没做对浏览器就会亮起刺眼的“证书链不完整”警告。接下来我会以一个完整的实操流程带你走通这条金融级HTTPS的部署之路。2. 核心需求解析与方案设计2.1 国密HTTPS的核心组件拆解要搭建一个完整的国密HTTPS服务我们需要四个核心部件协同工作国密SSL证书由权威的国密CA机构如沃通WoSign、上海CA签发证明服务器身份。阿里云作为证书服务商提供了便捷的申请入口。国密证书通常是“双证书”即一个用于数字签名的签名证书Signature Certificate和一个用于密钥交换的加密证书Encryption Certificate分别对应.pem和.key文件。支持国密的Web服务器原生Nginx使用的OpenSSL库不支持国密算法因此必须使用集成了国密算法库如wotrus_ssl即沃通国密SSL模块的Nginx或直接使用Tengine阿里基于Nginx的增强版内置国密支持。我们选择从源码编译Nginx并集成沃通模块以获得更灵活的控制。支持国密的客户端浏览器服务端部署好后普通Chrome、Firefox无法使用国密套件连接。需要使用内置了国密算法根的浏览器如360安全浏览器需开启国密支持、密信浏览器、红莲花浏览器等才能建立完整的国密HTTPS连接。双证书监听与智能选择服务器需要同时监听在同一个端口如443上根据客户端握手时声明的密码套件Cipher Suite来智能选择使用国密证书还是国际证书进行响应。这需要Nginx有相应的配置支持。2.2 阿里云SM2证书申请与下载要点在阿里云数字证书管理服务控制台申请国密证书时有几个关键选择直接影响后续部署证书类型选择“国密标准(SM2)”。注意它会自动包含双证书签名和加密。密钥算法选择“SM2”。生成CSR方式对于新手或快速部署强烈建议选择“系统生成”。阿里云会自动为你生成密钥对并将私钥包含在最终下载的证书包中。如果选择“手动生成”你需要用openssl gmssl等工具本地生成CSR和私钥私钥需自行保管证书包中不包含私钥遗失后证书将无法使用。域名验证根据你的域名管理方式选择DNS验证或文件验证。通常DNS验证添加一条TXT解析记录更为方便通用。证书签发后在控制台下载时服务器类型选择“Nginx”。下载的压缩包解压后你会看到类似以下结构的文件yourdomain.com/ ├── yourdomain.com_sm2_sign.pem # SM2签名证书 ├── yourdomain.com_sm2_sign.key # SM2签名证书私钥 ├── yourdomain.com_sm2_enc.pem # SM2加密证书 ├── yourdomain.com_sm2_enc.key # SM2加密证书私钥 └── yourdomain.com.pem # 国际证书RSA/ECC可选 └── yourdomain.com.key # 国际证书私钥可选这里有一个至关重要的细节下载的.pem证书文件可能只包含你的站点证书而不包含中间CA证书链。浏览器校验证书时需要构建从你的站点证书到根证书的完整信任链。如果中间CA证书缺失就会导致“证书链不完整”的错误。这就是我们后面要重点解决的“证书链合并”问题。2.3 Nginx国密版编译方案选型你有两个主流选择直接使用阿里云或社区提供的已编译好的Tengine/国密Nginx二进制包或者从源码编译。我推荐从源码编译理由有三1) 版本可控能与系统环境更匹配2) 编译参数可定制方便后续扩展模块3) 能更深入地理解其组成。我们选择稳定的Nginx 1.18.0与沃通国密模块wotrus_ssl进行编译。编译的核心思路是先准备好国密算法库wotrus_ssl然后在编译Nginx时通过--with-openssl参数指向这个国密库的源码目录让Nginx链接国密版本的SSL库而不是系统自带的OpenSSL。3. 环境准备与国密Nginx编译安装3.1 服务器基础环境配置假设我们使用一台全新的CentOS 8或AlmaLinux 8服务器。首先进行基础准备# 1. 更新系统并安装编译依赖 sudo yum update -y sudo yum groupinstall -y Development Tools sudo yum install -y gcc gcc-c pcre pcre-devel zlib zlib-devel wget tar # 2. 检查并开放443端口防火墙与安全组 # 查看防火墙状态如果使用firewalld sudo systemctl status firewalld # 如果防火墙开启放行443端口 sudo firewall-cmd --permanent --add-port443/tcp sudo firewall-cmd --reload # 对于云服务器如阿里云ECS务必在控制台的安全组规则中添加入方向允许TCP 443端口。3.2 下载源码与国密模块我们计划将软件安装在/usr/local/src目录下。cd /usr/local/src # 1. 下载Nginx 1.18.0源码包 sudo wget https://nginx.org/download/nginx-1.18.0.tar.gz sudo tar -zxvf nginx-1.18.0.tar.gz # 2. 下载沃通国密SSL模块 (wotrus_ssl) # 注意沃通官网下载链接可能变更如果失效需从其官网查找最新链接。 sudo wget https://www.wotrus.com/download/wotrus_ssl.tar.gz sudo tar -zxvf wotrus_ssl.tar.gz # 解压后通常得到一个名为 wotrus_ssl2.0 或类似的目录3.3 编译安装Nginx国密版进入Nginx源码目录进行配置。关键点在于--with-openssl参数必须指向我们刚解压的wotrus_ssl目录的上一层即包含include和lib目录的路径。cd nginx-1.18.0 # 配置编译参数 # 假设wotrus_ssl解压到了 /usr/local/src/wotrus_ssl2.0 # --prefix 指定安装目录 # --with-openssl 指向国密SSL库源码目录 sudo ./configure --prefix/usr/local/nginx \ --with-http_ssl_module \ --with-http_stub_status_module \ --with-stream \ --with-stream_ssl_module \ --with-openssl/usr/local/src/wotrus_ssl2.0 # 编译并安装 sudo make sudo make install踩坑记录编译错误Error 127如果编译过程中出现类似make[1]: *** [/usr/local/src/wotrus_ssl2.0/.openssl/include/openssl/ssl.h] Error 127的错误这是因为Nginx的编译脚本在国密模块的目录结构预期上出了问题。需要手动修复一个配置文件。 解决方法# 编辑Nginx的OpenSSL配置脚本 sudo vi /usr/local/src/nginx-1.18.0/auto/lib/openssl/conf找到以下四行内容CORE_INCS$CORE_INCS $OPENSSL/.openssl/include CORE_DEPS$CORE_DEPS $OPENSSL/.openssl/include/openssl/ssl.h CORE_LIBS$CORE_LIBS $OPENSSL/.openssl/lib/libssl.a CORE_LIBS$CORE_LIBS $OPENSSL/.openssl/lib/libcrypto.a将其修改为CORE_INCS$CORE_INCS $OPENSSL/include CORE_DEPS$CORE_DEPS $OPENSSL/include/openssl/ssl.h CORE_LIBS$CORE_LIBS $OPENSSL/lib/libssl.a CORE_LIBS$CORE_LIBS $OPENSSL/lib/libcrypto.a保存退出后重新执行sudo make clean然后再次sudo make sudo make install。安装完成后验证Nginx版本及其SSL支持cd /usr/local/nginx/sbin sudo ./nginx -V输出中应该能看到--with-openssl/usr/local/src/wotrus_ssl2.0以及TLS SM4-GCM-SM3等国密相关的密码套件这说明国密模块已成功集成。3.4 启动Nginx与初步测试# 启动Nginx sudo ./nginx # 检查进程 ps -ef | grep nginx # 测试默认HTTP页面 curl http://localhost如果看到Nginx的欢迎页面HTML代码说明服务已正常启动。4. 证书处理与配置合并证书链是关键4.1 上传证书文件在Nginx配置目录下创建一个专门存放证书的文件夹并将从阿里云下载的所有证书文件.pem和.key上传至此。sudo mkdir -p /usr/local/nginx/conf/cert # 使用scp、sftp或其他方式将本地证书文件上传到服务器的 /usr/local/nginx/conf/cert/ 目录下 # 例如scp yourdomain.com_sm2_sign.pem useryour_server_ip:/usr/local/nginx/conf/cert/4.2 合并国密证书链核心技巧这是整个部署中最容易出错的一步。阿里云下载的yourdomain.com_sm2_sign.pem通常只包含你的站点证书。浏览器需要完整的证书链站点证书 中间CA证书 根CA证书才能验证。如何获取完整的证书链从CA机构网站获取访问为你签发证书的CA机构如沃通的网站在其“技术支持”或“下载中心”页面查找“国密SM2中间证书”或“证书链”进行下载。通过浏览器导出推荐使用360安全浏览器国密版或密信浏览器访问一个已经正确部署了同CA国密证书的网站点击地址栏锁图标 - “证书” - “证书路径”你会看到从根证书到你的站点证书的完整链条。然后可以逐级导出中间CA和根CA的证书通常为.cer或.crt格式。假设我们获取到了两个中间CA文件WoSign SM2 OV SSL CA.crt和WoSign SM2 Root CA.crt。合并命令我们需要将站点证书、中间CA证书、根CA证书按顺序合并到一个文件中。顺序是你的站点证书在最前面然后是中间CA证书最后是根CA证书。cd /usr/local/nginx/conf/cert # 1. 合并SM2签名证书链 sudo cat yourdomain.com_sm2_sign.pem WoSign\ SM2\ OV\ SSL\ CA.crt WoSign\ SM2\ Root\ CA.crt yourdomain.com_sm2_sign_chain.pem # 2. 合并SM2加密证书链通常加密证书与签名证书使用相同的CA链但务必确认 # 如果加密证书的CA链不同需用对应的文件。这里假设相同。 sudo cat yourdomain.com_sm2_enc.pem WoSign\ SM2\ OV\ SSL\ CA.crt WoSign\ SM2\ Root\ CA.crt yourdomain.com_sm2_enc_chain.pem # 3. 可选合并国际证书链如果部署双证书 # 国际证书的中间CA通常不同例如可能是“R3”或“ISRG Root X1”。获取对应中间证书后合并。 sudo cat yourdomain.com.pem R3.crt ISRG\ Root\ X1.crt yourdomain.com_chain.pem重要提示合并后务必使用文本编辑器如vi或cat命令检查生成的*_chain.pem文件。一个正确的PEM格式证书链文件应该包含多个以-----BEGIN CERTIFICATE-----开头以-----END CERTIFICATE-----结尾的区块且顺序正确。4.3 配置Nginx支持国密双证书编辑Nginx的主配置文件/usr/local/nginx/conf/nginx.conf。我们需要在http块内配置一个监听443端口的server块。http { ... # 其他原有配置 server { listen 443 ssl; # 同时监听国密和国际SSL server_name yourdomain.com www.yourdomain.com; # 替换为你的域名 # 国密SM2证书配置 # 签名证书链和私钥 ssl_certificate /usr/local/nginx/conf/cert/yourdomain.com_sm2_sign_chain.pem; ssl_certificate_key /usr/local/nginx/conf/cert/yourdomain.com_sm2_sign.key; # 加密证书链和私钥 ssl_certificate /usr/local/nginx/conf/cert/yourdomain.com_sm2_enc_chain.pem; ssl_certificate_key /usr/local/nginx/conf/cert/yourdomain.com_sm2_enc.key; # 国际证书配置双证书方案必需 ssl_certificate /usr/local/nginx/conf/cert/yourdomain.com_chain.pem; ssl_certificate_key /usr/local/nginx/conf/cert/yourdomain.com.key; # SSL协议和密码套件配置 ssl_protocols TLSv1.2 TLSv1.3; # 建议禁用TLSv1.0/1.1 # 密码套件顺序优先国密套件其次国际强套件 ssl_ciphers ECC-SM4-SM3:ECDHE-SM4-SM3:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK; ssl_prefer_server_ciphers on; # 服务器优先选择密码套件 ssl_session_timeout 5m; ssl_session_cache shared:SSL:10m; # 网站根目录等其他配置 root /usr/local/nginx/html; index index.html index.htm; location / { try_files $uri $uri/ 404; } # 可选启用HSTS强制浏览器使用HTTPS add_header Strict-Transport-Security max-age63072000; includeSubDomains; preload always; } # 可选将HTTP请求重定向到HTTPS server { listen 80; server_name yourdomain.com www.yourdomain.com; return 301 https://$server_name$request_uri; } }配置要点解析ssl_certificate指令可以多次出现Nginx国密版能够识别并处理多套证书。当客户端握手时Nginx会根据客户端支持的密码套件列表自动选择对应的证书进行响应。ssl_ciphers列表中ECC-SM4-SM3和ECDHE-SM4-SM3是国密算法套件必须放在最前面以确保支持国密的浏览器优先使用国密算法连接。国际证书的密码套件如ECDHE-RSA-AES128-GCM-SHA256紧随其后保证兼容性。4.4 验证配置并重载Nginx# 1. 测试配置文件语法 sudo /usr/local/nginx/sbin/nginx -t # 预期输出nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful # 2. 如果测试成功重载Nginx使配置生效 sudo /usr/local/nginx/sbin/nginx -s reload # 3. 检查443端口是否在监听 sudo netstat -tlnp | grep :4435. 测试验证与问题排查5.1 使用浏览器测试国际浏览器测试使用Chrome、Firefox、Safari访问https://yourdomain.com。应该能正常打开网站并显示安全锁图标。点击锁图标查看证书详情应显示你部署的国际证书RSA/ECC。国密浏览器测试使用360安全浏览器需在设置中开启“国密算法支持”或密信浏览器访问同一地址。同样应显示安全锁。查看证书详情此时应显示SM2国密证书。这是验证国密部署是否成功的金标准。5.2 使用OpenSSL/GMSSL命令行测试服务器上可以使用链接了国密库的openssl实际上是gmssl命令进行测试。# 测试国际SSL连接 openssl s_client -connect yourdomain.com:443 -servername yourdomain.com # 测试国密SSL连接需要指定国密套件 # 首先找到gmssl命令通常在国密模块安装目录下或者系统PATH中 /usr/local/src/wotrus_ssl2.0/bin/gmssl s_client -connect yourdomain.com:443 -cipher ECC-SM4-SM3在s_client命令的输出中关注“Certificate chain”部分查看服务器发送的证书链是否完整以及“Cipher”部分是否使用了预期的密码套件。5.3 常见问题与排查技巧实录问题1浏览器提示“您的连接不是私密连接”NET::ERR_CERT_AUTHORITY_INVALID可能原因A证书链不完整。这是最常见的原因。使用浏览器检查证书路径如果只有你的站点证书缺少中间CA说明合并步骤有误。排查在服务器上执行sudo openssl x509 -in /usr/local/nginx/conf/cert/yourdomain.com_sm2_sign_chain.pem -text -noout | grep -A 1 Issuer查看颁发者信息。然后对比浏览器中缺失的中间CA信息。解决重新获取正确的中间CA证书并按正确顺序合并。可能原因B域名不匹配。证书绑定的域名与当前访问的域名不一致。排查检查证书的Subject Alternative Name (SAN) 字段sudo openssl x509 -in yourdomain.com_sm2_sign.pem -text -noout | grep -A 1 Subject Alternative Name。解决确保证书覆盖了所有需要访问的域名如带www和不带www。问题2国密浏览器无法建立国密连接自动降级到国际证书可能原因ANginx配置中国密密码套件顺序不对或未启用。排查检查nginx.conf中ssl_ciphers是否包含ECC-SM4-SM3等国密套件且是否放在靠前位置。解决调整ssl_ciphers顺序确保国密套件在前。可能原因BNginx未正确编译国密模块。排查执行sudo /usr/local/nginx/sbin/nginx -V查看输出中是否有国密相关模块和--with-openssl指向正确路径。解决重新编译安装Nginx国密版。问题3Nginx启动或重载报错提示证书或密钥文件找不到或格式错误可能原因A文件路径或权限错误。排查使用绝对路径并确保Nginx进程用户通常是nobody或www-data有读取证书和密钥文件的权限。解决sudo chmod 644 /usr/local/nginx/conf/cert/*.pem /usr/local/nginx/conf/cert/*.key。可能原因B证书或密钥文件格式错误如Windows换行符、多余空格。排查使用cat -A查看文件不应有^MWindows回车符。解决使用dos2unix命令转换或使用vi重新保存。问题4性能考虑与优化国密SM2算法的计算开销比RSA大在超高并发场景下可能成为瓶颈。建议启用ssl_session_cache和ssl_session_tickets来复用SSL会话减少握手开销。考虑使用硬件密码卡HSM来加速SM2运算这对于金融等高性能场景是必备选项。做好监控关注SSL握手时间、CPU使用率等指标。部署完成后一个稳固的监控策略是必不可少的。除了监控服务本身的可访问性更关键的是监控证书有效期。国密证书和国际证书都有过期时间一旦过期服务将立即中断。建议在阿里云控制台开启证书到期提醒同时也可以在自己的监控系统如Prometheus中通过定期抓取证书信息并解析notAfter字段来设置告警。