一、常见国密错误类型速查
1. 基础配置错误
错误现象 日志关键线索 根本原因 快速解决
Nginx 启动失败,报 `unknown cipher` `unknown cipher "TLS_SM4_GCM_SM3"` 未加载国密模块,或 `ssl_ciphers` 中写了国密套件但底层密码库不支持 换用 Tengine+Tongsuo 或 openresty-gm 等支持国密的版本
`ssl_certificate` 或 `ssl_certificate_key` 报错 `cannot load certificate "xxx"`, `PEM_read_bio_X509_AUX() failed` 证书路径错误、文件权限不足或证书格式不正确 | 检查路径,确保私钥权限为 600,属主为 Nginx 运行用户
SM2 私钥加载失败 无明确错误,但 `nginx -t` 通过后握手直接断连 证书 OID 不是国密标准 OID(`id-sm2`),或私钥非 GmSSL 工具链生成 使用 `gmssl genpkey -algorithm sm2 -out sm2.key` 重新生成私钥和证书
`ssl_reject_handshake on` 导致国密无法使用 配置该指令后国密握手全部失败 该指令被设置为 `on` 时,Nginx 会在 SSL 握手阶段直接拒绝所有连接,包括国密握手 将该指令显式设置为 `off`,或在单独 server 块中按域名正确处理 SNI
2. 握手协商错误
错误日志中的关键信息 含义 常见于国密场景的原因 排查方向
`no shared cipher` | 客户端与服务端没有共同的密码套件 ① `ssl_ciphers` 中未配置国密套件(如 `TLS_SM4_GCM_SM3`);② 客户端浏览器不支持国密算法 检查 `ssl_ciphers` 是否正确包含国密套件;换用奇安信、360 国密版等支持国密的浏览器访问
`version too low` 客户端 TLS 版本低于服务端允许的最低版本 国密双证书场景中,客户端与服务端 GmSSL 版本差异较大,导致握手版本协商失败 统一客户端与服务端的 GmSSL 版本;确保 `ssl_protocols` 包含了客户端所使用的 TLS 版本
`tlsv1 alert unknown ca` 客户端不信任服务端证书链中的 CA 国密证书链不完整,中间证书或根证书缺失 检查证书链拼接:`cat server_sm2.crt intermediate_sm2.crt root_sm2.crt > fullchain_sm2.crt`
`tlsv1 alert decrypt error` 握手过程中的解密错误 GmSSL 版本不一致导致密钥交换或证书验证环节出错;也可能与证书链问题或密码套件不匹配有关 统一 GmSSL 版本;验证证书与私钥是否匹配;确保协议套件配置正确
3. 证书与文件错误
错误日志关键词 含义 国密场景常见原因 解决方法
`SSL_do_handshake() failed` 无其他详细错误 Nginx 未记录详细握手失败原因 ① 国密模块编译时未启用 debug 支持;② 默认 `error_log` 级别(如 warn)太低,未输出底层错误细节 ① 启用 `debug` 日志级别;② 确保编译时包含 `--with-debug` 参数;③ 重新编译时添加国密扩展支持
`peer closed connection in SSL handshake` 对端在握手阶段关闭了连接 ① 客户端国密浏览器与服务器国密算法实现不兼容;② 使用了自签名证书但客户端未信任该 CA | 检查证书链完整性;使用可信 CA 签发的证书或配置客户端信任自签名 CA;使用奇安信/360 国密版浏览器测试
`cannot load certificate` 无法加载 SSL 证书 ① 证书文件损坏或格式不支持(SM2 证书需要使用带正确 OID 的 PEM 格式);② Nginx 用户无读取权限 使用 `gmssl x509 -in` 检查证书格式;确保 Nginx 进程用户(如 `www-data`)有读取权限
客户端提示 `ERR_CERT_AUTHORITY_INVALID` 浏览器提示证书颁发机构无效 国密证书链不完整,中间证书未正确配置到 `fullchain` 文件中 按正确顺序拼接证书链;确保 `ssl_certificate` 指向包含完整链的 PEM 文件
二、Error.log 配置调优(让日志“说话”)
Nginx 默认的 `error_log` 级别几乎不记录握手细节,必须显式开启才能捕捉到真实的国密握手错误。
第一步:启用 debug 日志
nginx
# 在 main(全局)或至少 http 块中添加
error_log /var/log/nginx/ssl_debug.log debug;
注意事项:
debug 日志量极大(可能每秒数千行),仅用于**临时排查**,生产环境问题定位后必须调回 `info` 或 `warn`
若启动时报 `unknown log level "debug"`,说明 Nginx 未带 debug 支持,需重新编译并加上 `--with-debug`,或换用已包含 debug 的二进制包
第二步:验证编译参数是否包含 debug
bash
nginx -V 2>&1 | grep -o with-debug
# 若有输出,说明 debug 支持已启用
第三步:确认国密模块是否已正确集成
bash
nginx -V 2>&1 | grep -- Tongsuo
# 或
nginx -V 2>&1 | grep -- gmssl
# 若输出中包含 --add-module=../tongsuo-nginx 或类似内容,说明已集成
第四步(可选):在 access_log 中增加 TLS 细节,辅助快速定位
nginx
log_format tls_detail '$remote_addr [$time_local] "$request" $status '
'$ssl_protocol $ssl_cipher $ssl_server_name $http_user_agent';
access_log /var/log/nginx/access_tls.log tls_detail;
配置后,每条访问日志会附带:实际协商的 TLS 版本(`$ssl_protocol`)、所选密码套件(`$ssl_cipher`)、客户端发送的 SNI 域名(`$ssl_server_name`)——可快速发现 SNI 不匹配或协议版本不对的问题。
第五步:配合关键配置确保握手能“走到”日志
确认监听端口启用了 SSL:`listen 443 ssl http2;`
显式指定 TLS 版本和加密套件,避免协商失败静默降级
若代理 HTTPS 上游,务必打开 SNI 并指定域名:`proxy_ssl_server_name on;`
如需验证上游证书,必须配置可信 CA:`proxy_ssl_verify on; proxy_ssl_trusted_certificate ...;`
三、常见国密错误码解读表
错误码 / 关键日志 国密专属解读 排查优先级
`no shared cipher` 服务端国密套件与客户端(浏览器)支持的套件无交集——通常是因为客户端不支持国密 高
`version too low` TLS 版本协商失败,常见于国密双证书场景中 GmSSL 版本差异过大 高
`tlsv1 alert unknown ca` 国密证书链不完整 中
`tlsv1 alert decrypt error` 与国密双证书加密证书/签名证书配对失败或 GmSSL 版本不匹配高度相关 中
`peer closed connection in SSL handshake` 自签名国密证书未在客户端配置信任 低
`PEM_read_bio_X509_AUX() failed` 国密证书文件不是标准 PEM 格式,或 OID 不是 `id-sm2` 中
四、国密专属配置与排查建议
1. 确认国密运行环境完整性
国密不是通过简单配置就能启用的功能。原生 Nginx + 普通 OpenSSL 不可能支持 SM2/SM3/SM4。正确的国密环境应该满足:
使用 Tengine + Tongsuo,或 openresty-gm(OpenResty 国密分支)
密码库必须使用 GmSSL 而非标准 OpenSSL(`openssl version` 输出应包含 `GmSSL` 字样)
国密证书必须通过 GmSSL 工具链生成,证书中 Subject Public Key Info 必须为 `sm2` OID
2. 快速定位思路(按日志排查优先级)
第一层:配置加载阶段错误
Nginx 启动失败 → 检查配置文件语法(`nginx -t`)
报 `unknown cipher` → 确认已集成国密模块,且 `ssl_ciphers` 中包含国密套件
报证书加载失败 → 检查文件路径、权限、格式(PEM)、OID
第二层:握手阶段错误(需开启 debug 日志)
日志中只有 `SSL_do_handshake() failed` 无细节 → debug 日志未开启或 Nginx 未编译 debug 支持
`no shared cipher` → 客户端浏览器不支持国密,换用奇安信/360 国密版测试
`tlsv1 alert unknown ca` → 证书链不完整,重新拼接 fullchain
`tlsv1 alert decrypt error` → 证书与私钥不匹配,或 GmSSL 版本不一致
第三层:客户端访问失败但服务端无任何日志
检查 `listen` 是否包含 `ssl` 参数
检查防火墙是否放行 443 端口
确认客户端确实是国密浏览器(普通 Chrome/Firefox 不支持国密)
3. 典型配置对照
nginx
# 国密服务端配置示例(Tengine + Tongsuo)
server {
listen 443 ssl;
server_name gm.example.com;
# 国密证书配置
ssl_certificate /etc/nginx/certs/fullchain_sm2.crt;
ssl_certificate_key /etc/nginx/certs/server_sm2.key;
# 协议与套件
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-SM2-WITH-SM4-SM3:TLS_SM4_GCM_SM3;
# 调试用(生产环境及时移除)
error_log /var/log/nginx/gm_ssl_debug.log debug;
# 必须关闭硬拒绝模式,按 SNI 正确处理
ssl_reject_handshake off;
# SNI 相关配置
proxy_ssl_server_name on;
proxy_ssl_name "gm.example.com";
}
注意:
使用国密证书时,需确保`ssl_certificate`指向包含完整证书链的PEM文件
私钥文件权限应设置为`600`,属主为Nginx运行用户(如`www-data`)
若使用自签名证书进行测试,需要将根证书手动导入到客户端信任库
五、常用诊断命令速查
目的 命令
查看 Nginx 错误日志 `sudo tail -f /var/log/nginx/error.log` 或 `/var/log/nginx/ssl_debug.log`
验证配置文件语法 `sudo nginx -t`
检查证书与私钥是否匹配 `openssl x509 -noout -modulus -in cert.crt \ openssl md5`<br>`openssl rsa -noout -modulus -in key.key \ openssl md5`
查看证书详细信息 `openssl x509 -in cert.crt -text -noout`
检查国密模块是否集成 `nginx -V 2>&1 \ grep -E "(Tongsuo\|gmssl)"`
模拟国密客户端测试 使用奇安信可信浏览器或 360 安全浏览器(国密版)访问
在线深度检测 [SSL Labs SSL Server Test](https://www.ssllabs.com/ssltest/
总结
国密故障排查的核心要点:
1. 日志级别是关键:默认 error_log 级别太低,必须启用 debug 级别并确保编译时包含 `--with-debug`,否则国密握手失败的详细信息不会被记录。
2. 原生 Nginx 不支持国密:必须换用 Tengine+Tongsuo 或 openresty-gm 等专门改造过的版本。
3. 先判断错误发生的阶段:是配置加载失败、握手协商失败,还是证书信任问题?不同阶段的日志线索不同,针对性排查效率更高。
4. 注意浏览器兼容性:普通 Chrome/Firefox 不支持国密,必须使用奇安信可信浏览器、360 安全浏览器(国密版)等专用浏览器测试。
5. 排查后及时关闭 debug 日志:避免磁盘空间耗尽或性能下降。
如果某条具体报错日志仍无法定位,可将完整的错误信息(含时间戳和前后文)提交至国密社区或相关技术支持渠道进一步分析。