CentOS 7部署国密HTTPS:GmSSL编译与Nginx双证书配置实战

发布时间:2026/6/24 19:28:39
CentOS 7部署国密HTTPS:GmSSL编译与Nginx双证书配置实战 1. 项目概述为什么要在CentOS 7上折腾国密HTTPS最近几年但凡和“安全”、“信创”沾边的项目国密算法SM2/SM3/SM4的集成几乎成了硬性要求。作为一名常年和服务器打交道的运维我手头就接到过不少这样的任务把现有的Web服务从国际通用的RSA/SHA256迁移到国密体系。一开始我也头疼国际标准的OpenSSL用得好好的为啥要换但深入了解后才发现这不仅是合规要求更是技术自主可控的必然趋势。简单来说国密HTTPS就是用我们自己的密码算法套件替换掉TLS/SSL协议中那些由国外制定的算法。核心是三个“SM”SM2用于非对称加密和签名替代RSA/ECDSASM3用于摘要替代SHA256SM4用于对称加密替代AES。在CentOS 7这个依然广泛存在于企业内网和传统业务环境中的稳定系统上实现它GmSSL是目前最成熟、最受社区认可的开源工具箱。这个项目就是带你从零开始在一台干净的CentOS 7服务器上用GmSSL编译、配置、签发证书最终搭建一个支持国密双证书体系的HTTPS服务。我会把每一步的操作意图、背后的原理以及我踩过的所有坑都摊开来讲清楚。无论你是为了满足项目验收还是单纯想学习国密技术的实操这篇手记都能给你一份能“抄作业”的指南。2. 环境准备与GmSSL源码编译工欲善其事必先利其器。在开始编译之前我们需要一个干净、标准的CentOS 7环境。2.1 系统基础环境配置首先确保你的CentOS 7系统是最小化安装并且网络通畅。第一步永远是更新系统并安装必要的开发工具链。# 1. 更新系统到最新状态 sudo yum update -y # 2. 安装编译所需的开发工具和库 sudo yum groupinstall -y Development Tools sudo yum install -y wget openssl openssl-devel perl perl-IPC-Cmd这里安装openssl和openssl-devel并不是为了用它而是因为一些Perl脚本和系统工具可能会依赖OpenSSL的头文件和库路径提前安装可以避免一些诡异的编译依赖错误。perl是GmSSL配置脚本所必需的。接下来我们创建一个独立的工作目录避免文件散落各处。mkdir -p ~/gmssl_build cd ~/gmssl_build2.2 获取与验证GmSSL源码GmSSL的主仓库在GitHub上。我们直接克隆最新的稳定版本。这里有一个关键点GmSSL 3.x版本是一个重要的里程碑它实现了对国密双证书签名证书和加密证书的完整支持与《GB/T 38636-2020》标准对齐。因此我们优先选择3.x的版本。# 克隆GmSSL官方仓库 git clone https://github.com/guanzhi/GmSSL.git cd GmSSL # 查看并切换到最新的稳定标签例如 3.1.1 git tag -l | grep ^3. | sort -V | tail -5 # 查看最新的3.x版本 git checkout gmssl_3.1.1 # 以实际最新稳定版为准注意直接从master分支编译有时会碰到正在开发中的特性可能导致不稳定。始终建议切换到带有版本号的标签Tag进行编译这是生产环境部署的黄金法则。源码下载后我强烈建议你花一分钟时间验证一下文件的完整性。虽然从GitHub克隆通常很安全但这是一个培养好习惯的机会对比官方发布的校验和如果提供的话。2.3 编译安装GmSSL详解GmSSL的编译采用了经典的configure、make、make install三部曲但其中有一些针对国密和安装路径的关键配置。# 1. 运行配置脚本指定安装前缀 ./config --prefix/usr/local/gmssl3 --openssldir/usr/local/gmssl3/ssl # 2. 编译源码-j参数根据你的CPU核心数设定可以加快速度 make -j$(nproc) # 3. 以root权限安装到系统目录 sudo make install现在我们来拆解一下这几个命令背后的“为什么”--prefix/usr/local/gmssl3这是最关键的参数。它指定了GmSSL的安装根目录。将其安装在/usr/local下是一个标准做法与系统自带的/usr/bin/openssl完全隔离避免文件冲突。命名为gmssl3可以清晰区分版本。--openssldir这个目录用于存放默认的配置文件openssl.cnf、证书、私钥等。将其放在前缀目录下保持所有相关文件的集中管理。make -j$(nproc)$(nproc)命令会自动获取你CPU的逻辑核心数然后启动并行编译任务能极大缩短编译时间。如果你的服务器核心数较少如1核直接使用make即可。编译安装完成后GmSSL的可执行文件位于/usr/local/gmssl3/bin/gmssl。为了能在任何地方方便地使用它我们需要将其路径加入到系统的PATH环境变量中并更新动态链接库的缓存。# 将GmSSL的bin目录添加到PATH echo export PATH/usr/local/gmssl3/bin:$PATH ~/.bashrc source ~/.bashrc # 更新系统的动态库搜索路径 echo /usr/local/gmssl3/lib | sudo tee /etc/ld.so.conf.d/gmssl3.conf sudo ldconfig最后验证安装是否成功gmssl version你应该能看到类似GmSSL 3.1.1 - ...的输出。同时运行which gmssl应该显示/usr/local/gmssl3/bin/gmssl。这一步成功标志着我们的“武器”已经锻造完毕。3. 国密数字证书的生成与管理有了GmSSL接下来就要打造HTTPS的“身份证”——数字证书。国密体系与RSA体系一个显著不同是双证书机制一份是签名证书用于身份认证一份是加密证书用于密钥交换。我们需要依次生成根CA、服务端的签名证书和加密证书。3.1 创建私有根证书颁发机构CA在内部测试或开发环境中我们不需要向公共CA购买证书可以自己扮演CA。这需要先创建一个自签名的根证书。首先为我们的CA创建工作目录并初始化mkdir -p ~/sm2_ca/{certs, private, newcerts} cd ~/sm2_ca touch index.txt echo 1000 serialindex.txt是证书数据库serial文件提供下一个证书的序列号。接下来生成根CA的私钥和自签名证书。这里使用SM2算法。# 生成根CA的SM2私钥使用素数域参数-param sm2p256v1 gmssl ecparam -genkey -name sm2p256v1 -out private/ca.key # 为私钥加上密码保护可选但推荐 gmssl ec -aes256 -in private/ca.key -out private/ca_encrypted.key # 使用私钥生成自签名的根证书 gmssl req -new -x509 -days 3650 -key private/ca.key -out certs/ca.crt \ -subj /CCN/STBeijing/LBeijing/OMyOrg/OUDev/CNMy SM2 Root CA参数解析与注意事项-param sm2p256v1指定使用国密SM2的椭圆曲线参数。这是标准参数必须指定。-aes256用AES-256加密私钥文件这样私钥本身会受密码保护。生产环境中务必使用执行命令后会提示你输入密码。-subj指定证书主题信息。C是国家ST是省L是城市O是组织OU是部门CN是通用名称对于CA通常是一个描述性名称。-days 3650证书有效期10年。根CA通常设置较长的有效期。实操心得私钥文件.key是最高机密。生成后立即将其权限设置为仅所有者可读chmod 400 private/ca.key。加密后的私钥在每次使用时都需要输入密码虽然麻烦但安全。3.2 生成服务器双证书服务器需要一对证书签名证书和加密证书。它们使用同一个SM2密钥对但在证书的“密钥用法”扩展上有所不同。第一步生成服务器SM2密钥对gmssl ecparam -genkey -name sm2p256v1 -out server.key第二步创建证书签名请求CSRCSR包含了公钥和主体信息需要为签名和加密用途各生成一份。关键在于配置文件中的扩展项。首先准备一个配置文件server.cnf[ req ] default_bits 256 distinguished_name req_distinguished_name req_extensions v3_req [ req_distinguished_name ] countryName CN stateOrProvinceName Beijing localityName Beijing organizationName MyServer Inc. commonName server.example.com # 你的服务器域名或IP [ v3_req ] basicConstraints CA:FALSE keyUsage digitalSignature, keyCertSign # 签名证书用法 # 对于加密证书keyUsage应为 keyEncipherment, dataEncipherment extendedKeyUsage serverAuth subjectAltName alt_names [ alt_names ] DNS.1 server.example.com IP.1 192.168.1.100 # 你的服务器IP然后分别生成两个CSR。注意我们通过命令行临时覆盖keyUsage来区分它们# 1. 生成用于签名的CSR gmssl req -new -key server.key -out server_sign.csr -config server.cnf \ -subj /CCN/STBeijing/LBeijing/OMyServer Inc./CNserver.example.com # 2. 生成用于加密的CSR。这里通过-addext参数动态添加加密用途的扩展项。 gmssl req -new -key server.key -out server_enc.csr -config server.cnf \ -subj /CCN/STBeijing/LBeijing/OMyServer Inc./CNserver.example.com \ -addext keyUsage keyEncipherment, dataEncipherment第三步使用根CA签发证书现在用我们自己的根CA来签署这两个CSR。# 签发签名证书 gmssl ca -config /usr/local/gmssl3/ssl/openssl.cnf -in server_sign.csr \ -out server_sign.crt -days 365 -extensions v3_req \ -cert certs/ca.crt -keyfile private/ca.key # 签发加密证书 gmssl ca -config /usr/local/gmssl3/ssl/openssl.cnf -in server_enc.csr \ -out server_enc.crt -days 365 \ -cert certs/ca.crt -keyfile private/ca.key执行ca命令时可能会提示你输入根CA私钥的保护密码如果你之前加密了的话。还会提示你是否确认签发证书输入y即可。至此你得到了以下关键文件server.key服务器SM2私钥。server_sign.crt服务器签名证书。server_enc.crt服务器加密证书。certs/ca.crt根CA证书。你可以使用以下命令查看证书的详细信息验证其类型和有效期gmssl x509 -in server_sign.crt -text -noout | grep -A 1 Key Usage gmssl x509 -in server_enc.crt -text -noout | grep -A 1 Key Usage签名证书的Key Usage应包含Digital Signature而加密证书应包含Key Encipherment。4. 在Nginx上配置国密HTTPS服务证书齐备现在让我们在Web服务器上启用它们。这里以最流行的Nginx为例。4.1 安装与编译支持GmSSL的NginxCentOS 7默认的yum仓库里的Nginx不支持国密。我们需要下载Nginx源码并动态链接到我们刚安装的GmSSL库进行编译。# 回到工作目录下载Nginx稳定版源码 cd ~/gmssl_build wget https://nginx.org/download/nginx-1.24.0.tar.gz tar -zxvf nginx-1.24.0.tar.gz cd nginx-1.24.0 # 配置编译选项关键是指定GmSSL的路径 ./configure --prefix/usr/local/nginx_gmssl \ --with-http_ssl_module \ --with-openssl/usr/local/gmssl3 \ --with-openssl-opt--prefix/usr/local/gmssl3 \ --with-stream \ --with-stream_ssl_module # 编译并安装 make -j$(nproc) sudo make install配置参数解读--with-http_ssl_module启用HTTP SSL模块这是HTTPS的基础。--with-openssl指定OpenSSL/GmSSL源码路径。这里指向GmSSL的安装目录Nginx的编译脚本会自动查找其中的头文件和库。--with-stream_ssl_module启用TCP流SSL模块方便后续扩展如国密TCP代理等。安装完成后Nginx的可执行文件位于/usr/local/nginx_gmssl/sbin/nginx。同样建议将其软链接到/usr/sbin/或将路径加入PATH。4.2 Nginx国密SSL深度配置接下来是核心步骤配置Nginx使用SM2双证书。将之前生成的证书和私钥文件server.key,server_sign.crt,server_enc.crt,ca.crt拷贝到一个安全的目录例如/usr/local/nginx_gmssl/conf/sm2_certs/。然后编辑Nginx的主配置文件/usr/local/nginx_gmssl/conf/nginx.conf在http块内添加一个server配置http { ... server { listen 443 ssl; server_name server.example.com; # 你的域名或IP # 国密双证书配置 ssl_certificate /usr/local/nginx_gmssl/conf/sm2_certs/server_sign.crt; ssl_certificate_key /usr/local/nginx_gmssl/conf/sm2_certs/server.key; ssl_enc_certificate /usr/local/nginx_gmssl/conf/sm2_certs/server_enc.crt; ssl_enc_certificate_key /usr/local/nginx_gmssl/conf/sm2_certs/server.key; # 指定国密密码套件优先级从高到低 ssl_ciphers ECDHE-SM2-WITH-SM4-SM3:ECDHE-SM2-WITH-SM4-128-SM3; ssl_prefer_server_ciphers on; # 协议版本设置建议禁用不安全的旧协议 ssl_protocols TLSv1.2 TLSv1.3; # 会话缓存优化 ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; # 其他安全头部可选但推荐 add_header Strict-Transport-Security max-age63072000; includeSubdomains; preload; location / { root html; index index.html index.htm; } } }配置关键点解析双证书指令这是国密配置的核心。ssl_certificate和ssl_certificate_key对应签名证书ssl_enc_certificate和ssl_enc_certificate_key对应加密证书。注意它们使用的是同一个私钥server.key。密码套件ssl_ciphers这里指定了国密的密码套件。ECDHE-SM2-WITH-SM4-SM3是使用SM2进行密钥交换SM4进行对称加密SM3进行消息认证的完整国密套件。ssl_prefer_server_ciphers on;确保服务器端的套件优先级更高。协议版本TLSv1.2是支持国密算法的最低安全版本TLSv1.3也已被GmSSL支持。务必禁用SSLv3和TLSv1.0/1.1。权限确保Nginx进程用户通常是nginx或nobody有权限读取证书和私钥文件。4.3 启动、验证与防火墙配置配置完成后启动或重载Nginx# 测试配置文件语法 sudo /usr/local/nginx_gmssl/sbin/nginx -t # 如果测试成功启动Nginx sudo /usr/local/nginx_gmssl/sbin/nginx # 如果Nginx已在运行则重载配置 sudo /usr/local/nginx_gmssl/sbin/nginx -s reload接下来我们需要验证服务是否真的在国密算法下工作。由于主流浏览器如Chrome, Firefox默认不支持国密套件我们需要使用GmSSL自带的s_client工具进行测试。# 使用GmSSL的s_client连接本地服务指定国密套件 echo -n | /usr/local/gmssl3/bin/gmssl s_client -connect localhost:443 \ -cipher ECDHE-SM2-WITH-SM4-SM3 \ -sign_cert server_sign.crt -sign_key server.key \ -enc_cert server_enc.crt -enc_key server.key \ -CAfile ca.crt如果连接成功你会在输出中看到详细的握手信息包括“Cipher is ECDHE-SM2-WITH-SM4-SM3”这样的字样以及证书链的验证结果。最后别忘了配置服务器的防火墙开放443端口sudo firewall-cmd --permanent --add-port443/tcp sudo firewall-cmd --reload5. 客户端适配与国密浏览器测试服务端搭好了但用户怎么访问呢这就需要国密浏览器。常见的如“赢达信”国密浏览器、“红莲花”浏览器等。它们内置了国密算法支持。客户端测试步骤导入根CA证书这是最关键的一步。你必须将自签名的根CA证书ca.crt导入到国密浏览器的“受信任的根证书颁发机构”存储中。否则浏览器会因不信任你的CA而显示连接不安全。访问HTTPS站点在浏览器地址栏输入https://你的服务器IP或域名。查看证书详情点击地址栏的锁图标查看证书信息。你应该能看到证书的签名算法是sm2sign-with-sm3公钥算法是SM2。这证明你成功建立了国密HTTPS连接。注意事项在真实的生产环境中如果是对公网提供服务你需要向国家认可的商用CA机构如CFCA申请签发的国密服务器证书。自签名证书仅用于测试和内部环境。商用CA的根证书已经预置在国密浏览器中无需手动导入。6. 实战排坑指南从编译失败到连接超时在这一部分我汇总了从编译GmSSL到配置Nginx过程中最可能遇到的几个“坑”及其解决方案。这些都是我亲身踩过或者社区里反复出现的问题。6.1 编译与安装类错误问题1configure时提示perl: command not found或缺少编译器。原因系统是最小化安装缺少必要的开发工具。解决确保已执行sudo yum groupinstall -y Development Tools和sudo yum install -y perl。问题2make编译时失败报错涉及-m64或某些汇编文件。原因常见于32位与64位环境混用或者某些依赖的汇编代码对特定CPU架构支持不佳。解决尝试在./config时添加no-asm参数禁用汇编优化./config --prefix... no-asm。这可能会降低性能但能提高兼容性。问题3安装后运行gmssl version提示libgmssl.so.x: cannot open shared object file。原因系统没有找到GmSSL的动态链接库。解决确保已执行sudo ldconfig并且/etc/ld.so.conf.d/gmssl3.conf文件内容正确指向了/usr/local/gmssl3/lib。6.2 证书生成与签发错误问题4使用gmssl ca命令时报错提示找不到./demoCA/index.txt或无法创建新证书。原因openssl.cnf配置文件中的CA路径设置与你的实际目录不符或者你没有初始化CA目录结构。解决仔细检查你执行gmssl ca命令时使用的-config参数指向的配置文件路径。确保你在正确的目录下创建了index.txt和serial文件。最稳妥的方法是像我之前那样创建一个独立的CA目录如~/sm2_ca并在其中初始化所有文件然后在该目录下执行签发命令。问题5生成的证书在浏览器中提示“证书密钥用法不符合要求”。原因签名证书和加密证书的Key Usage扩展项设置错误。签名证书必须包含digitalSignature加密证书必须包含keyEncipherment。解决严格按照3.2节中的步骤通过-addext参数或不同的配置文件为两种CSR明确指定正确的keyUsage。使用gmssl x509 -in cert.crt -text -noout仔细核对生成证书的“X509v3 Key Usage”字段。6.3 Nginx配置与连接错误问题6Nginx启动失败报错SSL_CTX_use_enc_certificatefailed。原因这是最典型的国密双证书配置错误。Nginx在编译时没有正确链接到支持国密双证书接口的GmSSL库或者配置文件中的ssl_enc_certificate指令写错了路径。解决确认Nginx编译链接正确运行/usr/local/nginx_gmssl/sbin/nginx -V查看输出中是否包含--with-openssl/usr/local/gmssl3。如果没有说明编译时未链接GmSSL需要重新编译。检查证书路径和权限确保ssl_enc_certificate指令指向的server_enc.crt文件存在且Nginx进程用户有读取权限。验证证书格式使用gmssl x509 -in server_enc.crt -text确认这是一个有效的X.509证书。问题7GmSSLs_client测试能通但国密浏览器无法连接或显示“不安全的连接”。原因根证书未导入这是99%的原因。自签名的CA证书必须手动导入到浏览器的信任库。证书主题不匹配浏览器访问的域名或IP与证书中的Common Name (CN)或Subject Alternative Name (SAN)不匹配。防火墙/安全组服务器的443端口未对客户端开放。解决将ca.crt文件安全地传输到客户端机器并详细按照国密浏览器的帮助文档将其导入到“受信任的根证书颁发机构”。检查服务器证书的SAN字段是否包含了客户端使用的访问地址DNS名或IP。可以使用gmssl x509 -in server_sign.crt -text -noout | grep -A 5 Subject Alternative Name查看。在服务器上使用sudo ss -tlnp | grep :443确认Nginx正在监听443端口并使用curl -I https://localhost在服务器本地或从客户端网络使用telnet命令测试端口连通性。问题8性能问题HTTPS连接速度慢。原因SM2算法在某些硬件上的计算效率可能不如优化多年的RSA。此外没有启用会话复用Session Resumption或OCSP装订OCSP Stapling也会导致每次握手都进行完整的密钥交换。解决启用会话缓存如配置中所示ssl_session_cache和ssl_session_timeout已经配置这能显著提升重复连接的速度。考虑硬件加速如果对性能要求极高可以调研支持国密算法硬件加速的SSL加速卡或支持相关指令集的服务器CPU。优化Nginx配置调整工作进程数worker_processes、连接数worker_connections等参数匹配服务器硬件。整个搭建过程从环境准备到最终浏览器访问是一个环环相扣的系统工程。最容易出问题的环节往往不是编译而是证书链的信任建立CA导入和Nginx与GmSSL的兼容性配置。按照上述步骤耐心排查你一定能成功搭建起属于自己的国密HTTPS服务。这不仅是完成一个技术任务更是对国密标准和技术栈一次深入的理解和实践。