ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Nginx换证书后部分客户端仍显示旧证书:RSA与ECDSA双证书排查

Nginx换证书后部分客户端仍显示旧证书:RSA与ECDSA双证书排查 同一个域名证书明明换了有的客户端看到新证书有的却还拿到旧证书。先别清缓存Nginx 同时配置 RSA 和 ECDSA 证书却只更新一组就可能出现这种分裂。本文固定地址、端口和 SNI用两次不同认证类型的握手检查是不是漏换了另一张。一、一次握手不是整站证书盘点一个站点不一定只有一张服务端证书。Nginx 可以同时加载 RSA、ECDSA 证书再根据客户端能力和服务端配置选择合适的一组。普通客户端可能同时支持两者并不存在永远固定的“RSA 浏览器”和“ECDSA 浏览器”。因此一次 openssl s_client 成功只能说明这次握手拿到的证书如何。-showcerts 展示的是该次服务端发送的证书列表不会把服务器上所有备选证书都翻出来。就像检查了一扇门不能顺手给整栋楼盖验收章。二、先找同一 server 中的两组配置Nginx 官方文档说明从 1.11.0 起ssl_certificate 可以重复出现用于加载不同类型的证书。下面是配置片段路径需要替换成自己的文件不是可直接覆盖生产的完整配置。server { listen 443 ssl; server_name dual.example.test; ssl_certificate /etc/nginx/tls/rsa-fullchain.pem; ssl_certificate_key /etc/nginx/tls/rsa.key; ssl_certificate /etc/nginx/tls/ec-fullchain.pem; ssl_certificate_key /etc/nginx/tls/ec.key; }先确认两组证书与各自私钥配对fullchain 中叶证书在前、中间证书在后再检查 SAN 是否都覆盖访问名。官方提到的 OpenSSL 1.0.2 及以上要求在这段文档中指的是不同证书使用各自独立证书链别简化成一句含糊的“双证书最低版本”。本机查看生效配置时留意 include 和符号链接不要把完整配置或私钥贴进工单。三、固定终点再分别探测 RSA 与 ECDSA两次探针固定同一地址、端口和 SNI避免负载均衡、IPv4/IPv6 干扰判断。Bash 模板中的文档地址、域名和 CA 文件需要替换。私有站点用受控 CA 包公网用合适的系统 CA 包不能随手信任未知证书。IP192.0.2.10 NAMEdual.example.test CAFILE/path/to/trusted-ca.pem for ALG in RSA ECDSA; do openssl s_client -connect ${IP}:443 \ -servername $NAME -tls1_2 \ -cipher ECDHE-${ALG}-AES128-GCM-SHA256 \ -CAfile $CAFILE -no-CApath \ -verify_hostname $NAME -verify_return_error \ -showcerts -no_ticket /dev/null \ ${ALG}.txt 21 RC$? printf %s 握手退出码%s\n $ALG $RC done这里限定 TLS 1.2是为了利用两个套件明确区分 RSA 与 ECDSA 认证。两个名字中的 ECDHE 都是临时密钥交换后面的 RSA/ECDSA 才是此处关注的认证区别不能看到 ECDHE 就认定用了 EC 证书。-servername 发送 SNI-verify_hostname 校验访问名两者不是同义词。-verify_return_error 要求遇到验证错误就中断否则诊断工具可能继续握手让人误以为验证成功。四、比较公钥类型和完整指纹先查退出码、协议、套件和主机名验证再将成功握手中的第一段完整 PEM 证书分别存为 rsa-leaf.pem、ec-leaf.pem不要把整个日志当证书。for F in rsa-leaf.pem ec-leaf.pem; do openssl x509 -in $F -noout \ -sha256 -fingerprint -serial -dates -ext subjectAltName openssl x509 -in $F -noout -text done重点看 Subject Public Key Info 下的 Public Key Algorithm以及 SHA-256 指纹。证书的 Signature Algorithm 是签发者对证书的签名算法不等于叶证书公钥类型RSA CA 签出的证书叶子公钥仍可以是 EC。不同证书可能有效期相同别只截图日期线上指纹要与预期新证书逐张对应。五、隔离实验只换 RSA 会发生什么为避免把猜测写成结论我用临时 CA、同一 SAN 和四张仍有效的测试证书做了回环实验。Nginx 为 1.26.3构建信息报告 OpenSSL 1.1.1w命令行是 OpenSSL 1.1.1k FIPS。两者版本分开记录不能拿 CLI 版本替服务端作证。每个阶段都停止并重新启动独立测试实例再分别建立两次全新握手。这样排除了旧 worker、旧内存和会话恢复的干扰不是生产 reload 实验。阶段RSA 探针ECDSA 探针初始两张旧证书RSA 旧指纹EC 旧指纹只更新 RSARSA 新指纹EC 指纹不变再更新 ECRSA 指纹不变EC 新指纹六次正例均通过 CA、主机名、套件和指纹检查错误主机名负例被拒绝。这里的“旧”只是未替换并没有过期。实验结束已关闭独立监听、清理临时私钥没有改系统信任库、时钟或生产服务。六、握手失败别立刻判断证书缺失如果一个探针成功另一个握手失败先看服务端是否允许 TLS 1.2 和指定套件。只支持 TLS 1.3、禁用了该套件或者签名算法约束不兼容都可能失败不能单凭结果认定没配置 EC 证书。不要为跑通命令修改生产安全策略现有策略不允许上述 TLS 1.2 套件时按实际协议另做探针。本机负例还提醒了一个坑错误主机名时退出码已经是 1日志也有 Hostname mismatch末尾却仍出现 Verify return code: 0。不要只搜一行“0 (ok)”就宣布成功更不要用管道最后一个命令的退出码遮住握手失败。七、TLS 1.3 不照搬这套选择方法OpenSSL 官方说明-cipher 控制 TLS 1.2 及更早版本TLS 1.3 使用 -ciphersuites。TLS 1.3 套件名称不再承担 RSA/ECDSA 认证类型选择单纯更换套件名不能复刻这里的分组。TLS 1.3 需结合签名算法协商与服务端策略另查。本文未实测 TLS 1.3 或 -sigalgs不将其写成万能命令。八、修复后验收两张而不是一张确认漏更后按现有部署流程补齐对应证书和私钥保留回滚材料配置校验通过后再执行获授权的加载操作。不要直接把 RSA 文件复制到 EC 路径两种公钥类型不是换个文件名就能互相代替。同一地址、端口和 SNI 下分别记录两类探针结果。两张叶证书的 SAN、有效期、指纹与预期一致。分别验证证书链和主机名不只检查文件可解析。结合真实客户端复测多节点部署要逐节点验收。监控分别覆盖两组证书避免只盯默认协商结果。两类探针都拿到新证书再查连接复用、CDN 或节点分发。先回答这次握手选中了哪张证书官方参考Nginx ssl_certificateOpenSSL s_client 参数OpenSSL 套件定义。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进