当前位置: 首页 > news >正文

国密 TLCP 实战:GmSSL / OCL / Nginx 版本选型与全部调试修改说明

本文面向发布到 CSDN,汇总本人在 Windows + WSL2 编译、Docker 部署、CentOS 生产环境跑通Nginx 国密 HTTPS(TLCP)时使用的源码版本目录布局,以及为调通而做的全部修改(含配置、脚本、证书处理;不含对 Nginx 核心 C 源码的 patch)。

参考博文:基于 GmSSL 搭建 Nginx 国密反代(流程可参考,但部分写法如ssl_protocols GMTLS与当前 OCL/Nginx 行为不完全一致,下文会说明)。


一、环境与目录布局

环境说明
开发机Windows 10/11 +WSL2 Ubuntu 24.04
生产机CentOS 7 系(10.131.111.250),Docker 运行
源码根目录/mnt/d/codes/(Windows 对应D:\codes\

推荐三仓库并列:

/mnt/d/codes/ ├── GmSSL/ # 国密算法库 ├── OpenSSL-Compatibility-Layer/ # OpenSSL 兼容层(OCL) └── nginx/ # Nginx 1.25.3 源码 + Docker 工程

证书调试目录(与仓库分离,便于拷到生产机):

/mnt/d/nginx_gm/certs/ # 自建 CA + 服务器 TLCP 证书 /opt/nginx/certs/ # 生产机挂载进容器 /opt/nginx/conf/nginx.conf # 生产机自定义主配置

二、引用的三个项目及版本(务必对齐)

2.1 版本总表

项目仓库推荐 Tag / 版本用途
GmSSLhttps://github.com/guanzhi/GmSSLv3.1.1OCL 依赖;gmssl命令行生成证书
OpenSSL-Compatibility-Layerhttps://github.com/GmSSL/OpenSSL-Compatibility-Layerv0.8.1提供libssl.so/libcrypto.so,伪装 OpenSSL API
Nginxhttps://nginx.org 或本仓库release-1.25.31.25.3OCL README 明确测试过的版本
运行环境版本
WSL 编译Ubuntu24.04,gcc13.3.0
Docker 基础镜像Ubuntu24.04
Docker 镜像标签nginx-gmssl:1.25.3

2.2 版本不对齐时的典型现象

错配现象
GmSSL 用master,Nginx/OCL 用 v3.1.1 编译WSL 上gmssl tlcp_clienttls.c:2829:tls_init(): error(见下文 §5.3)
Nginx 1.31+ 未在 OCL 列表中编译或握手阶段未知问题,不建议生产首选用
系统 OpenSSL 3.x 未被子替换nginx -V显示 SSL 但握手仍是国际算法
gmssl与链接进 Nginx 的libgmssl不是同一次编译证书工具能生成,运行时库行为不一致

2.3 编译安装顺序(固定)

① GmSSL (v3.1.1) → sudo make install → /usr/local/lib/libgmssl.so ② OCL (v0.8.1) → sudo make install → /usr/local/lib/libssl.so, libcrypto.so ③ Nginx (1.25.3) → ./configure && make → objs/nginx

安装 OCL 后必须确认默认头文件/库来自 OCL,而不是系统 OpenSSL:

grep-iOPENSSL /usr/local/include/openssl/opensslv.h ldd /usr/local/lib/libcrypto.so|grepgmssl

三、各组件编译参数(最终调通版)

3.1 GmSSL v3.1.1

cd/mnt/d/codes/GmSSLgitfetch--tagsgitcheckout v3.1.1mkdirbuild&&cdbuild cmake..make-j$(nproc)sudomakeinstall# 命令行工具whichgmssl# 期望 /usr/local/bin/gmssl

说明:证书在/mnt/d/nginx_gm/certsgmssl sm2keygen/certgen/reqgen/reqsign生成;口令示例Ilove@cn123签名私钥与加密私钥必须相同(OCL 硬性要求)。

对 GmSSL 源码的修改(仅git checkout v3.1.1,避免使用 master 做客户端测试)。


3.2 OpenSSL-Compatibility-Layer v0.8.1

cd/mnt/d/codes/OpenSSL-Compatibility-Layergitfetch--tagsgitcheckout v0.8.1mkdirbuild&&cdbuild cmake..make-j$(nproc)sudomakeinstall

安装结果:

  • 头文件:/usr/local/include/openssl/(OCL 头文件)
  • 库:/usr/local/lib/libssl.solibcrypto.so(底层依赖libgmssl

对 OCL 源码的修改(生产调通路径)无 patch
理解其行为即可,不必改代码(见 §5.1pem.c逻辑)。

社区可选 patch(浏览器访问报错时)
OCL Issue #13 提到在 GmSSL 的src/tlcp.ctlcp_do_accept中注释客户端扩展校验,以兼容部分国密浏览器。本人生产调通未改此文件;若奇安信/360 握手失败可再评估。


3.3 Nginx 1.25.3

第一次 configure(踩坑,缺 PCRE)
./configure\--prefix=/usr/local/nginx\--with-http_ssl_module\--with-stream\--with-stream_ssl_module\--without-http_rewrite_module

objs/ngx_auto_config.hNGX_PCRE,配置里写location ~* \.(js|css|...)$会报:

nginx: [emerg] using regex "..." requires PCRE library
最终 configure(调通版)
sudoaptinstall-ylibpcre3-dev ./configure\--prefix=/usr/local/nginx\--with-http_ssl_module\--with-stream\--with-stream_ssl_module\--with-pcre\--with-pcre-jitmake-j$(nproc)

当前工程内记录的编译参数(objs/ngx_auto_config.h):

#defineNGX_CONFIGURE" --prefix=/usr/local/nginx --with-http_ssl_module --with-stream --with-stream_ssl_module --without-http_rewrite_module --with-pcre --with-pcre-jit"

验证:

objs/nginx-V# 应含 openssl 相关信息,且 ldd objs/nginx | grep -E 'ssl|crypto|gmssl'

对 Nginx 官方源码src/的修改。国密能力完全来自链接 OCL 的 libssl,不是 nginx 补丁模块。


四、Docker 工程修改(本仓库nginx/docker/

采用「WSL 编好二进制 + 拷贝 .so → 镜像只打包」策略,不在镜像内重编三件套。

4.1docker/prepare.sh(打包动态库)

将 sibling 目录编译产物拷入vendor/lib

../GmSSL/build/bin/libgmssl.so* ../OpenSSL-Compatibility-Layer/build/libssl.so* ../OpenSSL-Compatibility-Layer/build/libcrypto.so*

4.2Dockerfile要点

  • 基础镜像:ubuntu:24.04
  • 安装运行时依赖:libpcre3zlib1g在镜像里装开发包)
  • COPY objs/nginx/usr/local/nginx/sbin/nginx
  • ENV LD_LIBRARY_PATH=/usr/local/lib
  • EXPOSE 80 4443(生产映射-p 443:443时由宿主机nginx.conf决定 listen)

4.3docker-entrypoint.sh修改(重要)

修改前(旧镜像逻辑,导致容器秒退)

if[!-f/certs/tlcp_server_certs.pem]||[!-f/certs/tlcp_server_keys.pem];thenecho"error: TLCP certs required under /certs (see docker/README.md)"exit1fi

生产挂载为/etc/nginx/certs/,文件名也可能是sign-fullchain.pem等,与/certs/tlcp_server_*.pem不一致 →entrypoint 直接 exit 1

修改后(当前文件)

#!/bin/shset-eNGINX=/usr/local/nginx/sbin/nginx ldconfig2>/dev/null||trueif["$1"="$NGINX"]||["$(basename"$1"2>/dev/null)"="nginx"];then"$NGINX"-tfiexec"$@"

仅做nginx -t不再硬编码证书路径。

4.4docker/default.conf修改

修改前

ssl_certificate /certs/tlcp_server_certs.pem; ssl_certificate_key /certs/tlcp_server_keys.pem; ssl_password_file /certs/tlcp_server_password.txt;

修改后

ssl_certificate /etc/nginx/certs/tlcp_server_certs.pem; ssl_certificate_key /etc/nginx/certs/tlcp_server_keys.pem; ssl_password_file /etc/nginx/certs/tlcp_server_password.txt;

docker-compose.yml挂载./certs:/etc/nginx/certs:ro一致。

4.5 生产docker run(相对最初命令的修正)

dockerrun-d\--namenginx-gm\-p443:443\-v/opt/nginx/certs:/etc/nginx/certs:ro\-v/opt/nginx/conf/nginx.conf:/usr/local/nginx/conf/nginx.conf:ro\-v/opt/nginx/html:/etc/nginx/html:ro\-v/opt/nginx/logs:/usr/local/nginx/logs\nginx-gmssl:1.25.3
最初写法问题
--name nginx-gm重复命令非法或覆盖
logs/var/log/nginx:ro前缀应为/usr/local/nginx/logs,且不能只读
cache无关只读挂载与 nginx 无关,易误导
旧 entrypoint + 旧镜像证书未放到/certs/tlcp_server_*.pem即退出

五、生产nginx.conf与证书(运维侧修改)

5.1 证书文件(OCL 要求,非 Nginx 官方格式)

服务器侧三个文件(/opt/nginx/certs/):

文件内容顺序
tlcp_server_certs.pem终端签名证→ 终端加密证中间 CA(不要根证)
tlcp_server_keys.pem签名加密私钥加密加密私钥(两段ENCRYPTED PRIVATE KEY
password.txt一行口令,无\r

生成示例(与 OCL README 一致):

catsigncert.pem enccert.pem cacert.pem>tlcp_server_certs.pemcatsignkey.pem enckey.pem>tlcp_server_keys.pemprintf'%s\n''Ilove@cn123'>password.txt

证书处理上的“修改”(非改 C 代码):

  1. 厂商未加密私钥BEGIN PRIVATE KEY)→ 用gmssl pkcs8 -topk8加密后再合并。
  2. 厂商分体 fullchainsign-fullchain.pem+enc-fullchain.pem)→ 改为 OCL 推荐的单证链 + 双钥文件
  3. password.txt与密钥口令不一致(曾用12345678而密钥为Ilove@cn123)→ 统一口令并cat -A检查无^M

5.2 生产server块(最终)

server { listen 443 ssl; server_name 10.131.111.250; ssl_certificate /etc/nginx/certs/tlcp_server_certs.pem; ssl_certificate_key /etc/nginx/certs/tlcp_server_keys.pem; ssl_password_file /etc/nginx/certs/password.txt; ssl_ecdh_curve sm2p256v1; ssl_ciphers ECDHE-SM2-WITH-SMS4-SM3:ECDHE-SM2-WITH-SMS4-GCM-SM3; ssl_prefer_server_ciphers on; location / { root /etc/nginx/html; index index.html index.htm; } }

相对 CSDN 参考文/初稿删除或禁止的项

# 错误 — Nginx 配置解析不认 GMTLS ssl_protocols GMTLS TLSv1.2; # 错误 — OCL 双钥加密场景不要删 # ssl_password_file ...

说明:TLCP 由 GmSSL 在libssl内完成,不需要也不能在ssl_protocols里写GMTLS

5.3 OCL 读私钥逻辑(理解即可,解释为何必须加密+口令)

OCLsrc/pem.cPEM_read_bio_PrivateKey核心逻辑(v0.8.1 / main 同类):

// 必须有 password 回调if(!bio||!cb||!u){error_print();returnNULL;}cb(pass,sizeof(pass),0,u);// 同一 BIO 连续读两把 SM2 私钥sm2_private_key_info_decrypt_from_pem(&pkey->signkey,pass,bio);sm2_private_key_info_decrypt_from_pem(&pkey->kenckey,pass,bio);

因此:

  • 必须配置ssl_password_file
  • tlcp_server_keys.pem必须是PKCS#8 加密格式(BEGIN ENCRYPTED PRIVATE KEY);
  • 两把钥同一口令

六、GmSSL 命令行版本问题(WSL 调试)

6.1 现象

gmssl tlcp_client-get/-host10.131.111.250-port443-cacertrootcacert.pem# /mnt/d/codes/GmSSL/src/tls.c:2829:tls_init():# tlcp_client: error

此时服务器docker exec nginx-gm nginx -tsuccessfulnc443 通。

6.2 原因

WSL 中/usr/local/bin/gmssl若来自GmSSL mastertls_init()会检查key_exchange_modes != 0,而tlcp_client未设置 supported_groups / signature_algorithms,导致客户端在握手前就失败

v3.1.1tls_init无此检查,且会正确设置conn->is_client = ctx->is_client

6.3 处理(版本切换,非改 tls.c)

cd/mnt/d/codes/GmSSLgitcheckout v3.1.1rm-rfbuild&&mkdirbuild&&cdbuild&&cmake..&&make-j$(nproc)sudomakeinstall

6.4 不要用这些方式判断服务是否存活

工具结果原因
curl https://IP:443PR_END_OF_FILE_ERROR国际 TLS vs TLCP
openssl pkey -in tlcp_server_keys.pemunable to load key系统 OpenSSL 不支持 SM2

七、修改项汇总表(便于 CSDN 读者对照)

序号对象是否改上游 C 源码修改内容
1GmSSL固定tag v3.1.1,不用 master 跑tlcp_client
2OCL否(可选 tlcp.c 见 Issue #13)固定tag v0.8.1;理解pem.c双钥+解密
3Nginxconfigure 增加--with-pcre --with-pcre-jit
4docker-entrypoint.sh项目脚本去掉/certs/tlcp_server_*.pem强校验,仅nginx -t
5docker/default.conf项目配置证书路径/certs/etc/nginx/certs
6生产nginx.conf运维配置listen 443;删GMTLS;OCL 三件套路径
7证书文件运维合并证链/双钥;加密私钥;password.txt去 CRLF
8docker run运维日志可写、去掉错误 volume、更新镜像

八、验证通过标准(本环境)

# 1. 编译链ldd /usr/local/nginx/sbin/nginx|grepgmssl objs/nginx-V# 2. 容器dockerexecnginx-gm /usr/local/nginx/sbin/nginx-t# configuration file ... test is successful# 3. 监听(镜像可能无 ss)dockerexecnginx-gmsh-c'cat /proc/net/tcp'|grep01BB# 443# 4. 客户端(GmSSL v3.1.1)gmssl tlcp_client-get/-host10.131.111.250-port443-cacertrootcacert.pem# 5. 浏览器# 国密浏览器 + 导入 rootcacert.pem → https://10.131.111.250/

九、发布 CSDN 时的建议标签

Nginx国密GmSSLTLCPOpenSSL-Compatibility-LayerSM2DockerHTTPS


十、参考链接

  • GmSSL/OpenSSL-Compatibility-Layer README
  • guanzhi/GmSSL(Tagv3.1.1
  • GmSSL Issue #1156 - invalid value GMTLS
  • OCL Issue #13 - 浏览器访问国密 nginx
  • 本人部署踩坑合集:同目录nginx-gmssl-部署总结.md

版权声明:版本号与修改记录基于 2026 年 5 月实际调试环境整理;若上游 tag 更新,请以各项目 Release 说明为准,并重新做nginx -ttlcp_client回归。

http://www.jsqmd.com/news/859694/

相关文章:

  • 百度文库核心功能全解析(教育博主实操版)
  • AI设计泳装,能颠覆今夏潮流?
  • 2026宁波PLC培训标杆名录:实训能力与就业资源双维度盘点 - 互联网科技品牌测评
  • Wordpress网站使用siteground security optimizer 及 translatepress多语言插件的翻译问题
  • 为什么92%的ElevenLabs山东话项目上线失败?——5大隐性技术红线与3种合规替代方案(附GitHub可运行Demo)
  • 利用CDN进行首屏优化。能不能看CDN与本地服务器谁快用谁?
  • 2026 北京高端西装定制权威评测:国家中心城市的商务着装智慧 - 西装爱好者
  • RT-DETRv2训练自定义数据集的排坑全记录
  • 拒绝中间商赚差价!找接触角测量仪源头厂家,直奔广东北斗精密仪器有限公司 - 品牌推荐大师
  • 仅限首批50家申请者:ElevenLabs潮州话语音定制音色内测通道开放(含潮汕非遗传承人声纹授权协议模板)
  • 金融求职面试复盘资源哪家好:专业复盘实用指南分享 - 技研备忘录
  • 2026年深圳GEO优化公司靠谱推荐:口碑领先服务商选型对比 - 奔跑123
  • Windhawk终极指南:5分钟掌握Windows系统个性化定制
  • Midjourney范戴克印相避坑清单(11个致命错误):第9条导致90%用户输出褪色假象——附权威博物馆级比对图谱
  • 如何快速掌握uesave:Unreal引擎存档编辑的完整指南
  • 2026年企业礼品定制厂家最新推荐榜选择:江苏俭礼礼品有限公司 - 品牌推广大师
  • 2026企业网盘怎么选?十大产品深度测评:从合规到协作一次讲清
  • Ricon组态系统vs传统组态软件:为什么选择新一代Web组态平台
  • 【Flink学习】(五)Flink 并行度与任务链,任务运行核心原理
  • 2027精神病学主治医师考试听谁的课?过考考生口碑榜出炉 - 医考机构品牌测评专家
  • 如何用Python快速接入Taotoken平台调用多款大模型
  • 显卡驱动清理终极指南:如何彻底解决游戏卡顿和系统蓝屏问题?
  • 土方车远程监控智慧运维系统方案
  • 2026年十大品牌消泡剂厂家推荐指南:懂工艺、重安全的厂家 - 奔跑123
  • 开源数据库 TimescaleDB 2.27.1 发布:性能改进与多项错误修复,官方建议尽快升级
  • 泰州黄金回收实测:3个真实变现案例,哪家正规靠谱、价格透明? - 恒顺黄金回收
  • 老合兴洋服:贵阳西服定制的匠心之选,穿出绅士的体面与尊严 - 贵州服装测评君
  • 昆山奢侈品回收行业综合实力排名TOP6,2026年5月权威测评榜单 - 天天生活分享日志
  • 3个核心功能:用HSTracker将炉石传说数据转化为你的制胜优势
  • 【MATLAB源码-第442期】基于MATLAB的OFDM系统PAPR抑制算法仿真及限幅压扩SLM、PTS与TR性能对比