Nginx国密SSL双轨制配置实战:从编译到部署全流程详解 📅 2026/6/24 22:21:44 1. 项目概述为什么国密SSL证书不再是“可选项”最近给一个金融行业的客户做安全加固对方技术负责人上来就问“咱们的系统能不能支持国密SSL” 我当时心里咯噔一下知道这事儿已经从一个技术选型问题变成了一个必须完成的合规任务。如果你还在用RSA算法的国际标准SSL证书觉得“能用就行”那可能很快就要面临类似的情况了。国密SSL或者说基于SM2椭圆曲线密码算法的SSL/TLS协议已经不再是政府、金融、能源等关键领域的“加分项”而是正在快速成为“准入项”。简单来说SSL证书就像是你网站的“数字身份证”它保证了用户浏览器和你服务器之间通信的加密和身份可信。我们过去十几年用的都是RSA、ECC国际ECC非SM2这套国际算法体系。而国密SSL则是用我国自主设计的SM2、SM3、SM4等密码算法重新构建了这套信任体系。它的核心价值有两个第一是自主可控规避潜在的国际算法后门风险第二是合规性满足《网络安全法》、《密码法》以及金融、政务等行业监管的硬性要求。所以这篇实战教程的目标非常明确不是探讨国密好不好而是手把手带你走通从零开始为一个Web服务以最常用的Nginx为例配置并启用国密SSL证书的全过程。你会看到它和配置一个RSA证书的流程既有相似之处又有几个关键的不同点而这些不同点正是最容易踩坑的地方。无论你是运维工程师、开发人员还是系统架构师掌握这套流程都将是未来几年一项非常实用的技能。2. 核心概念与准备工作理解国密SSL的“双轨制”在动手之前我们必须先理清一个关键概念双轨制。这是国密SSL推广初期一个非常重要的过渡方案理解了它你就能明白为什么我们接下来的配置看起来有点“复杂”。2.1 什么是双轨制所谓双轨制是指服务器同时支持两套SSL/TLS协议栈国际算法协议栈继续使用传统的RSA证书服务于主流浏览器如Chrome、Firefox和客户端保证全球通用性。国密算法协议栈使用SM2证书服务于支持国密的浏览器如360安全浏览器、红莲花浏览器或客户端满足合规要求。形象点说你的服务器就像一家支持两种支付方式的商店既收Visa/Mastercard国际算法也收银联国密算法。客户用哪种卡你就走哪套流程。在现阶段绝大多数用户仍使用不支持国密的浏览器因此保留国际算法通道是保证业务可访问性的前提。而政务、金融等内网或特定场景则可能强制要求使用国密浏览器访问这时国密通道就必须畅通。2.2 准备工作清单工欲善其事必先利其器。配置国密SSL需要一些特定的工具和材料和配置RSA证书有所不同。1. 支持国密的软件环境这是最核心的一点。你常用的OpenSSL默认不支持国密算法。方案一推荐使用国密OpenSSL分支。例如Tongsuo铜锁原BabaSSL这是阿里云开源的一个强大分支完整支持国密算法和双轨制。我们将以此为例。# 从GitHub克隆并编译安装Tongsuo git clone https://github.com/Tongsuo-Project/Tongsuo cd Tongsuo ./config --prefix/usr/local/tongsuo make -j$(nproc) sudo make install方案二使用集成国密算法的其他库如GmSSL。但就与Nginx等软件的集成成熟度而言Tongsuo目前是社区最活跃的选择。2. 国密SSL证书你需要从获得国家密码管理局许可的电子认证服务机构申请国密SSL证书。常见的提供商有数安时代、天威诚信、上海CA等。申请流程和DV/OV证书类似需要生成SM2算法的证书签名请求文件去提交。这里有一个关键区别注意生成CSR时必须使用支持SM2的软件如刚才安装的Tongsuo而不是普通的OpenSSL。因为密钥对生成和签名算法完全不同。3. 支持双轨制的Web服务器Nginx本身不支持国密需要重新编译加入对国密算法和双轨制的支持。同样我们需要使用nginx-with-tongsuo这样的补丁或直接使用集成了Tongsuo的Nginx发行版。本文将演示从源码编译的方式。4. 测试浏览器为了验证国密通道是否生效你需要一个支持国密的浏览器。360安全浏览器的“国密专版”模式是最容易获取的测试工具。准备好以上四点我们就可以开始动手了。整个过程可以概括为编译国密库 - 编译Nginx - 配置双证书 - 测试验证。3. 实战演练编译支持国密双轨制的Nginx这是整个过程中技术含量最高的一步。别担心只要跟着步骤走就能成功。我们假设你的服务器是CentOS 7或Ubuntu 20.04这类常见的Linux发行版。3.1 第一步编译安装Tongsuo国密库首先确保系统有基本的编译工具。# CentOS/RHEL sudo yum groupinstall -y Development Tools sudo yum install -y wget git perl perl-IPC-Cmd # Ubuntu/Debian sudo apt update sudo apt install -y build-essential wget git perl然后我们编译安装Tongsuo。这里我建议使用一个特定的稳定版本避免最新版可能存在的兼容性问题。wget https://github.com/Tongsuo-Project/Tongsuo/archive/refs/tags/8.3.2.tar.gz -O tongsuo-8.3.2.tar.gz tar -zxvf tongsuo-8.3.2.tar.gz cd Tongsuo-8.3.2在配置时我们开启enable-ntls选项这是实现双轨制N代表National的关键。./config --prefix/usr/local/tongsuo --shared --openssldir/usr/local/tongsuo/ssl enable-ntls make -j$(nproc) sudo make install安装完成后需要让系统找到这个新库。echo /usr/local/tongsuo/lib64 | sudo tee /etc/ld.so.conf.d/tongsuo.conf sudo ldconfig验证安装是否成功/usr/local/tongsuo/bin/openssl version # 应该输出 OpenSSL 3.0.0 等信息并且支持NTLS /usr/local/tongsuo/bin/openssl s_client -ntls -connect 127.0.0.1:443 -servername localhost 21 | head -5 # 虽然会连接失败但如果没有“Invalid command”错误说明ntls选项已支持。3.2 第二步编译集成Tongsuo的NginxNginx的编译需要一些额外的依赖并且我们要下载一个使Nginx支持国密双轨制的补丁。安装Nginx依赖# CentOS/RHEL sudo yum install -y pcre-devel zlib-devel # Ubuntu/Debian sudo apt install -y libpcre3-dev zlib1g-dev下载Nginx源码和国密补丁wget http://nginx.org/download/nginx-1.24.0.tar.gz tar -zxvf nginx-1.24.0.tar.gz cd nginx-1.24.0 # 下载国密补丁这个补丁通常由社区维护例如来自Tongsuo项目或云厂商 # 这里以一个常见的补丁地址为例实际操作时请寻找最新稳定的补丁 wget -O nginx.patch https://gist.githubusercontent.com/someuser/xxxxxx/raw/xxxx/nginx_sm2.patch # 注意请务必从可靠来源如Tongsuo项目Wiki获取正确的补丁文件。打补丁并编译# 应用补丁 patch -p1 nginx.patch # 配置编译选项关键是指定我们刚才安装的Tongsuo路径 ./configure --prefix/usr/local/nginx \ --with-http_ssl_module \ --with-openssl/usr/local/tongsuo \ --with-openssl-optenable-ntls \ --with-http_v2_module # 建议也开启HTTP/2 make -j$(nproc) sudo make install实操心得./configure这一步最容易出错。如果提示找不到Tongsuo的库或头文件请检查--with-openssl的路径是否正确并确认/usr/local/tongsuo/include和.../lib64目录存在。有时需要手动指定--with-cc-opt和--with-ld-opt来包含库路径。验证Nginx是否支持国密/usr/local/nginx/sbin/nginx -V 21 | grep -i ntls如果输出中包含ntls字样恭喜你编译成功。4. 核心配置在Nginx中部署双证书软件准备好后接下来就是核心的配置环节。你需要准备两个证书文件server.rsa.crt和server.rsa.key你的国际算法RSA证书及私钥。server.sm2.crt和server.sm2.key你的国密算法SM2证书及私钥。4.1 Nginx SSL基础配置打开Nginx的配置文件通常位于/usr/local/nginx/conf/nginx.conf在对应的server块中我们先配置国际算法部分这和普通SSL配置无异server { listen 443 ssl http2; server_name yourdomain.com; # 国际算法RSA证书配置 ssl_certificate /path/to/your/server.rsa.crt; ssl_certificate_key /path/to/your/server.rsa.key; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; ... # 其他location等配置 }启动Nginx此时你的网站应该已经可以通过国际标准SSL访问了。4.2 启用国密双轨制配置关键步骤来了我们需要在同一个server块中添加国密证书的监听和配置。Nginx国密补丁引入了新的指令ssl_ntls和新的监听选项ntls。server { # 原有443监听保持不变用于国际算法 listen 443 ssl http2; # 新增一个监听端口专门用于国密算法。通常使用8443端口也可以复用443但需要更复杂配置。 listen 8443 ssl http2 ntls; server_name yourdomain.com; # 国际算法RSA证书配置不变 ssl_certificate /path/to/your/server.rsa.crt; ssl_certificate_key /path/to/your/server.rsa.key; # 国密算法SM2证书配置 ssl_ntls on; ssl_sign_certificate /path/to/your/server.sm2.crt; ssl_sign_certificate_key /path/to/your/server.sm2.key; ssl_enc_certificate /path/to/your/server.sm2.crt; ssl_enc_certificate_key /path/to/your/server.sm2.key; # 密码套件配置为国密连接指定专用的密码套件 ssl_ciphers ECC-SM2-WITH-SM4-SM3:ECDHE-SM2-WITH-SM4-SM3; ssl_ntls_ciphers ECC-SM2-WITH-SM4-SM3; ... # 其他配置 }配置解析listen 8443 ssl http2 ntls;这行告诉Nginx在8443端口上启用SSL并且启用国密NTLS模式。ntls参数是关键。ssl_ntls on;启用国密SSL功能。ssl_sign_certificate和ssl_enc_certificate在国密SSL中理论上签名证书和加密证书可以不同但实践中通常使用同一套SM2证书。这里需要同时配置。ssl_ntls_ciphers指定国密连接使用的密码套件如ECC-SM2-WITH-SM4-SM3表示使用SM2算法进行密钥交换SM4算法进行对称加密SM3算法进行消息摘要。4.3 重载配置与防火墙保存配置文件后测试语法并重载Nginx。/usr/local/nginx/sbin/nginx -t /usr/local/nginx/sbin/nginx -s reload别忘了在服务器防火墙和安全组中放行你新配置的国密端口例如8443。5. 测试与验证如何确认国密SSL生效配置完成后如何验证国密通道真的在工作呢我们需要从国际和国密两个通道分别测试。5.1 测试国际算法通道443端口使用任何主流浏览器Chrome/Firefox或命令行工具访问https://yourdomain.com。这应该和配置任何普通SSL证书一样显示为安全连接。你可以点击浏览器地址栏的小锁查看证书详情确认使用的是你的RSA证书。用OpenSSL命令测试openssl s_client -connect yourdomain.com:443 -servername yourdomain.com 2/dev/null | openssl x509 -noout -text | grep -i signature algorithm输出应该是Signature Algorithm: sha256WithRSAEncryption或类似证明是RSA证书在提供服务。5.2 测试国密算法通道8443端口这是重点。你需要使用支持国密的客户端。使用360安全浏览器测试打开360安全浏览器在地址栏输入https://yourdomain.com:8443。如果连接成功浏览器地址栏会显示安全锁标志。关键验证点点击小锁 - “连接安全” - “证书信息”。在证书详情中你应该能看到“签名算法sm2-with-sm3”以及“公钥算法id-ecPublicKey”等信息。这明确表明浏览器是通过国密算法套件与服务器建立的连接。使用Tongsuo的s_client命令测试 这是最可靠的命令行验证方式因为它直接使用我们编译的、支持国密的OpenSSL。/usr/local/tongsuo/bin/openssl s_client -ntls -connect yourdomain.com:8443 -servername yourdomain.com 21 | grep -A5 -B5 Cipher如果国密连接成功建立命令输出中会包含类似Cipher : ECC-SM2-WITH-SM4-SM3的字样并且会完整地显示SM2证书的详细信息。5.3 双轨制自动协商测试高级更优雅的双轨制实现是让服务器在同一个端口如443上自动识别客户端能力。如果客户端支持国密就用国密算法通信如果不支持就回落使用国际算法。这需要更复杂的Nginx配置和Tongsuo库的支持通常涉及在listen 443 ssl后也加上ntls参数并精细配置ssl_protocols和ssl_ciphers的优先级。对于初次配置我建议先使用不同端口443和8443的方案更清晰也更容易排查问题。6. 常见问题与深度排查指南在实际部署中你几乎一定会遇到一些问题。下面是我总结的几个最常见故障及其排查思路。6.1 编译阶段失败问题./configure时报错提示找不到OpenSSL或特定文件。排查确认--with-openssl指向的是Tongsuo的源码目录顶层路径即包含Configure、Makefile的目录而不是安装目录。检查Tongsuo是否已成功编译安装。可以进入Tongsuo目录手动执行make test进行测试。确保系统已安装所有依赖如perl这是配置脚本所必需的。6.2 Nginx启动失败问题执行nginx -t或启动时报错unknown directive “ssl_ntls”或类似。排查这几乎100%说明Nginx没有正确编译进国密支持。重新检查编译步骤确认./configure的输出中是否有关于ntls的提示。确保应用补丁 (patch) 时没有失败。可以检查nginx -V的输出。可能是补丁版本与Nginx版本不兼容。尝试更换更匹配的补丁或调整Nginx版本。6.3 国密端口无法连接或握手失败问题浏览器访问8443端口超时或提示“安全连接失败”。排查网络层面用netstat -tlnp | grep 8443检查Nginx是否在监听8443端口。如果没有检查配置语法和错误日志error.log。检查服务器防火墙和云服务商安全组规则。SSL握手层面使用Tongsuo的s_client命令进行详细诊断/usr/local/tongsuo/bin/openssl s_client -ntls -connect yourdomain.com:8443 -servername yourdomain.com -debug -state这个命令会输出非常详细的握手过程。关注错误信息常见的比如no ciphers available可能是ssl_ntls_ciphers配置的密码套件名称错误或不支持。certificate verify failed可能是证书链不完整。SM2证书也需要配置中间CA证书使用ssl_sign_certificate和ssl_enc_certificate时需要将证书文件拼接为服务器证书 中间CA证书的形式。wrong signature type证书算法不匹配。确保你使用的确实是SM2证书而不是误用了RSA证书。6.4 性能与兼容性考量性能SM2算法在相同安全强度下计算速度通常比RSA更快尤其是私钥解密操作。但SM4算法与AES相比在部分硬件未优化的情况下软件实现可能略有开销。总体而言性能差异在日常Web应用中感知不明显无需过度担心。兼容性这是目前最大的挑战。除了少数国产浏览器和特定客户端主流环境移动端App、curl命令、各种SDK默认都不支持国密。因此双轨制在很长一段时间内都是必须的。在架构设计时需要考虑如何优雅地将支持国密的客户端引导至国密端口或协议。配置国密SSL证书尤其是实现双轨制初看步骤繁多但本质上是一个“替换密码学套件”的过程。一旦你成功走通一次流程理解了其中几个关键节点编译支持国密的库、打补丁、配置双证书和双监听就会发现它并没有那么神秘。这项技能的价值正在于它连接了当下的通用互联网生态与未来自主可控的安全规范。从今天开始动手实践当合规要求到来时你就能从容应对而不是临阵磨枪。