0-RTT (TLS 1.3 早期数据(Early Data))
定义
0-RTT 是 TLS 1.3 和 QUIC 的特性,允许回访的客户端用上一次会话留下的密钥,在第一个数据包里就发送应用数据。
0-RTT 在 TLS 1.3 规范(RFC 8446,现为 RFC 9846)中称为 early data,只能用在会话恢复的连接上。上一次连接时,服务器下发了 Session Ticket,对应一个 PSK;下一次连接时,客户端发送 ClientHello 的同时,就附带用该 PSK 派生密钥加密的应用数据,不必等服务器回应。QUIC 也有同样的机制。
为什么重要
它为回访用户省掉一个完整往返,在高延迟的移动网络上效果明显。代价是早期数据的安全性较弱:它没有防重放保护,攻击者截获后可以原样再发给服务器一次;它相对于 PSK 也不具备前向保密。因此服务器只应对可以安全重复执行的请求接受 0-RTT,例如没有副作用的 GET。RFC 8470 定义了 Early-Data: 1 请求头和 425(Too Early)状态码,后端可以借此拒绝无法安全处理的早期数据。
例子
Nginx 开启早期数据并把标记传给后端:
ssl_protocols TLSv1.2 TLSv1.3;
ssl_early_data on;
proxy_set_header Early-Data $ssl_early_data;
后端对带有 Early-Data: 1 的下单、支付等写操作返回 425,客户端会在握手完成后重新发送。
常见误区
- 0-RTT 能加快首次访问。 首次连接没有 PSK,必须走完整握手,只有恢复的连接才能用 0-RTT。
- 0-RTT 数据和普通 TLS 1.3 数据一样安全。 只有早期数据缺少防重放和前向保密,握手完成后发送的数据仍受 TLS 1.3 完整保护。
- 开启它就是白赚的性能。 如果应用层不处理重放,可能导致重复下单、重复扣款等问题。