NGINX不生成或校验SCT,仅透传CA嵌入证书扩展或OCSP响应中的SCT;需确保OpenSSL≥1.1.1、正确配置ssl_stapling及ssl_trusted_certificate,并通过openssl s_client或Chrome安全标签验证SCT是否实际送达客户端。

NGINX 本身不直接生成或提交证书透明度(CT)日志条目,也不原生执行客户端对 SCT(Signed Certificate Timestamp)的强制校验。它主要通过 透传、暴露和配合外部机制 来支持 CT 生态——关键在于正确配置 TLS 握手行为,使浏览器能获取并验证 SCT,从而满足如 Chrome 的 CT 强制策略。
CT 是什么,为什么 NGINX 要“适配”而非“实现”?
证书透明度(Certificate Transparency)是一种防止恶意或错误签发 SSL/TLS 证书的安全机制。核心是:所有公开信任的证书必须被记录到公开、不可篡改的 CT 日志中,并附带由日志签名的 SCT(时间戳)。浏览器(尤其是 Chrome)会检查服务器是否在 TLS 握手中提供了有效 SCT,否则可能拒绝连接(如显示“NET::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED”)。
NGINX 不是 CA,不运行 CT 日志服务器,也不内置 SCT 签名或日志提交逻辑。它的角色是:
• 正确携带由 CA 或第三方服务提供的 SCT(通常嵌入在证书扩展或 OCSP 响应中)
• 在 TLS 握手时通过 signed_certificate_timestamp 扩展(RFC 6962)将 SCT 发送给客户端
• 配合上游(如 Let’s Encrypt、Sectigo)或工具链(如 ct-submit、certbot 插件)完成日志提交与证书打包
让 NGINX 正确传递 SCT 的两种主流方式
要使客户端(如 Chrome)收到 SCT,必须确保 SCT 以标准方式注入到 TLS 握手流程中。NGINX 支持以下两种兼容路径:
-
方式一:SCT 嵌入证书扩展(Embedded SCTs)
CA 在签发证书时,将一个或多个 SCT 直接写入证书的 X.509 扩展字段(OID1.3.6.1.4.1.11129.2.4.2)。只要使用该证书启动 NGINX(ssl_certificate),且 OpenSSL 版本 ≥ 1.0.2h(推荐 ≥ 1.1.1),NGINX 会自动在 TLS ServerHello 中携带这些 SCT。无需额外配置。 -
方式二:OCSP Stapling + SCT(Stapled SCTs)
部分 CA(如 Let’s Encrypt)或 CT 工具(如ct-submit+ocsp-responder)可生成包含 SCT 的 OCSP 响应。启用 OCSP Stapling 后(ssl_stapling on; ssl_stapling_verify on;),若响应中含 SCT(符合 RFC 9162),现代 OpenSSL 也会将其一并发送。需确保:
✓ OCSP 响应由可信 OCSP 签发者签名
✓ NGINX 可访问 OCSP 响应缓存(ssl_trusted_certificate指向根+中间证书)
✓ssl_stapling_file或动态 stapling 正常工作
验证 SCT 是否真正送达客户端
不能仅凭证书里有 SCT 就认为生效。需实测 TLS 握手是否携带了 SCT 扩展:
- 用
openssl s_client -connect example.com:443 -servername example.com -tlsextdebug 2>&1 | grep -i "signed certificate",若输出类似server extension 18 (signed_certificate_timestamp) length=65,说明 SCT 已成功发送。 - 在 Chrome 访问站点,按 F12 → Security → View certificate → Details → 找 “Signed Certificate Timestamp List” 扩展,展开后应可见至少一个有效 SCT(含 log ID、timestamp、signature)。
- 使用在线工具如 crt.sh 或 CT Logs Explorer,确认该证书确实出现在至少两个主流 CT 日志中(如 Google ‘Aviator’、‘Pilot’、DigiCert ‘Sawtooth’)。
常见问题与绕过误区
以下操作无法解决 CT 校验失败,反而可能掩盖根本问题:
-
禁用 OCSP Stapling 或忽略
ssl_stapling_verify:可能导致 SCT 丢失(尤其依赖 stapled SCT 场景),或引发其他证书信任问题。 - 用自签名或私有 CA 证书部署生产环境:这类证书不在公共 CT 日志中,Chrome 会直接拦截,NGINX 无权豁免。
- 手动修改证书扩展添加 SCT:X.509 签名会失效,导致证书不被信任;SCT 必须由对应 CT 日志签名,不可伪造。
- 依赖旧版 OpenSSL(:SCT 扩展支持不完整,即使证书含 SCT 也无法透传。
真正有效的做法是:选用支持 CT 的公共 CA(如 Let’s Encrypt、ZeroSSL)、确保证书含嵌入 SCT、使用较新 OpenSSL(≥1.1.1)与 NGINX(≥1.15.0)、定期用上述方法验证握手行为。


















