必须同时验证编译时和运行时OpenSSL版本均≥1.1.1,且server块中启用ssl_early_data on、TLSv1.2+TLSv1.3协议、session复用,并由后端识别$ssl_early_data做幂等处理,否则0-RTT静默失效。

确认 Nginx 与 OpenSSL 版本是否真正支持 0-RTT
光看版本号不够,必须验证编译时链接的 OpenSSL 和运行时加载的 OpenSSL 是否都 ≥ 1.1.1。很多系统(如 Ubuntu 22.04 默认源)装的 OpenSSL 是 3.0.x,但旧版 Nginx 编译时可能仍绑着 1.1.1f —— 这种“混合状态”会导致 ssl_early_data on 静默失效。
执行这两条命令缺一不可:
-
nginx -V 2>&1 | grep -i openssl—— 看 configure 参数里--with-openssl=指向哪,或是否用了系统 OpenSSL; -
openssl version—— 看当前ldd $(which nginx) | grep ssl实际加载的是哪个 so,再比对该 so 的版本。
若两者不一致,或任一低于 1.1.1,0-RTT 不会启用,且无任何错误日志提示。
server 块内必须显式开启并约束协议栈
ssl_early_data on 是个局部指令,只作用于它所在的 server 块,全局配置无效。更关键的是:它只在 TLS 1.3 握手路径下生效,而 TLS 1.3 要求严格匹配 cipher suite 和协议协商机制。
- 必须写
ssl_protocols TLSv1.2 TLSv1.3(不能只写TLSv1.3,否则老客户端直连失败); - 推荐加
ssl_conf_command Options -PrioritizeChaCha,因为 ChaCha20-Poly1305 是 TLS 1.3 中 0-RTT 数据加密的默认 cipher,优先级高能减少客户端 fallback 延迟; - 务必启用 session 复用:
ssl_session_cache shared:SSL:10m和ssl_session_timeout 4h,否则 PSK 无法生成/恢复,0-RTT 直接退化为 1-RTT。
后端必须识别 $ssl_early_data 并做幂等性决策
Nginx 不拦截、不校验 early data,只负责透传 Early-Data: 1 header 或通过变量暴露给后端。如果你用 FastCGI(如 PHP),得显式传递:
fastcgi_param TLS_EARLY_DATA $ssl_early_data;
如果你用 proxy_pass,则:
proxy_set_header Early-Data $ssl_early_data;
后端逻辑必须检查这个值:
- 值为
1→ 请求走 0-RTT → 视为“可能被重放”,禁止任何非幂等操作(如 POST 转账、PUT 更新用户资料); - 可直接响应 GET /account/balance 这类只读请求;
- 敏感接口建议返回
425 Too Early,并由前端自动重发(注意:Chrome 当前对 425 的自动重试行为不稳定,生产环境建议搭配前端 JS 判断 header 后手动重发)。
验证时别被 HTTP/2 或浏览器缓存干扰
curl 默认启用 HTTP/2,而某些版本(如 curl 7.81)在 HTTP/2 下会隐藏 Early-Data header,导致你以为没生效。抓包也容易误判:Wireshark 中 tls.handshake.type == 1(ClientHello)需带 early_data 扩展,且 ServerHello 后紧跟着 application_data(不是 finished)才算成功。
可靠验证步骤:
- 首次访问后,用
curl -v --http1.1 -k https://yoursite.com/,观察响应头是否有Early-Data: 1; - 同时跑
tshark -i any -Y "tls.handshake.type == 1 || tls.handshake.type == 2" -T fields -e tls.handshake.extensions.supported_group -e tls.handshake.extensions.early_data,确认 ClientHello 包含early_data扩展; - 禁用浏览器缓存测试,Chrome 开无痕窗口 + Network 面板勾选 “Disable cache” —— 否则可能复用旧 session,掩盖配置问题。
真正难调的点不在 Nginx 配置本身,而在后端如何安全区分“可放行的 early data”和“必须阻断的重放风险”。漏掉这一层,0-RTT 不是加速,是开后门。


















