背景
用户经常在首次访问后的短时间内重新访问网页。
0-RTT 连接恢复背后的基本理念是,如果客户端和服务器之间之前已经建立了 TLS 连接,那么它们就可以使用缓存的会话信息建立新的连接,而无需重新协商连接参数。
0-RTT 的工作原理
初次连接:
- 当客户端第一次与服务器建立 QUIC 连接时,它会经历完整的握手过程,这通常涉及 1-RTT(一次往返时间)。在此过程中,客户端会从服务器获取必要的加密信息(如 TLS 证书)并完成加密会话的建立。
- 在这个过程中,服务器会向客户端提供一个 Session Ticket,用于后续的 0-RTT 连接。
后续连接(0-RTT):
- 当客户端再次与同一服务器连接时,它可以使用之前收到的 Session Ticket,直接发起一个 0-RTT 连接请求。客户端使用预先协商好的密钥和协议版本加密并发送数据,无需等待服务器的响应。
- 服务器收到 0-RTT 请求后,可以直接处理并解密数据,从而实现更快的数据传输。
0-RTT 和前向保密
前向保密(Forward Secrecy)
Forward Secrecy(前向安全性) 是一种密码学特性,确保即使长期使用的密钥(例如服务器的私钥)被泄露,之前的通信内容仍然无法被解密。这种安全特性是通过在每次会话中使用临时会话密钥来实现的,即便攻击者获得了长期密钥,也无法回溯性地解密以前的通信内容。
在 0-RTT 场景中,客户端使用的是之前会话中协商的预共享密钥(PSK),而不是每次重新生成的临时密钥。这和前向保密冲突。
解决
- 缩短 Session Ticket 有效期
为了减小 PSK 泄露带来的风险,服务器通常会设置 Session Ticket 的短生命周期,确保 PSK 只在有限的时间窗口内有效。
- 更换长期密钥
客户端使用 0-RTT 请求与服务器建立连接后,长期密钥会在随后的握手过程中被更换。
0-RTT 阶段:
- 在 0-RTT 阶段,客户端使用之前从服务器获得的 Session Ticket 和相应的密钥进行加密通信。这些密钥是在之前的会话中通过完整的 TLS 1.3 握手生成的,并且允许客户端立即发送数据而无需等待新的握手完成。
1-RTT 阶段:
- 即使客户端在 0-RTT 阶段开始发送数据,QUIC 协议仍然要求双方完成一个完整的 TLS 1.3 握手,以建立一个新的加密上下文。这个完整的握手称为 1-RTT 握手。
- 在 1-RTT 握手中,客户端和服务器将协商新的加密密钥,并且所有后续的数据传输都将使用这些新的密钥进行加密。
0-RTT 放大攻击
0-RTT 放大攻击是一种利用 QUIC 或 TLS 1.3 协议中的 0-RTT 特性来对目标服务器进行的攻击。此类攻击旨在通过发送小量请求,诱使服务器发送大量数据到目标受害者,从而实现流量放大。
放大攻击
- 伪造源地址:
- 攻击者伪造客户端 IP 地址,使其看起来像是来自受害者的请求。
- 攻击者向服务器发送一个 0-RTT 请求,这个请求通常是一个很小的数据包。
- 服务器的响应:
- 服务器会认为这个请求是合法的,并根据 0-RTT 请求生成一个可能非常大的响应数据包。
- 由于攻击者伪造了客户端 IP 地址,这些大量的响应数据将会被发送到受害者的 IP 地址。
- 放大效果:
- 攻击者发送的小量请求导致服务器生成大量的响应数据,从而放大了流量。这种流量放大会使受害者的网络带宽被消耗,造成拒绝服务(DoS)攻击效果。
防御 0-RTT 放大攻击
为了应对 0-RTT 放大攻击,协议设计和实现中引入了多个防御措施:
限制 0-RTT 数据的大小:
- 服务器可以限制在 0-RTT 阶段允许传输的数据量。如果数据量较小,即使发生放大攻击,造成的影响也会受到控制。
地址验证:
- 在 QUIC 协议中,服务器可以要求在 0-RTT 阶段进行地址验证,例如通过发送验证令牌(Token)来确认客户端的 IP 地址。只有在验证通过后,服务器才会发送大数据量的响应。
- 如果客户端无法提供有效的验证令牌,服务器可以选择缓冲响应或限制响应的大小,直到握手完成并验证地址。
限制未验证客户端的响应数据量:
- 服务器可以对未完成握手的客户端设定严格的响应数据量上限,防止大量数据被发送到未经验证的 IP 地址。
总结
在 QUIC 协议中,0-RTT 阶段使用旧的密钥来加密初始数据,以实现低延迟连接。
然而,在 0-RTT 之后,协议要求客户端和服务器在 1-RTT 握手完成后使用新密钥进行后续的数据加密。这样做是为了确保通信的安全性,同时最大限度地减少延迟。
QUIC 在回复 0-RTT 请求时必须保守,限制它发送的响应数据量,直到客户端被验证为真实客户端而不是受害者。