互联网工程任务组 (IETF) M. Thomson
请求注释: 8470 Mozilla
类别:标准轨道 M. Nottingham
ISSN: 2070-1721 Fastly
W. Tarreau
HAProxy Technologies
2018年9月

在 HTTP 中使用早期数据


摘要

在 TLS 中使用早期数据会带来可能遭受重放攻击的风险。本文档定义了允许客户端就以早期数据发送的 HTTP 请求与服务器进行沟通的机制,并描述了利用这些机制来减轻重放风险的技术。

本备忘录的状态

这是一个互联网标准轨道文档。

本文档是互联网工程任务组 (IETF) 的产物。它代表了 IETF 社区的共识。它已接受公开审查并已获互联网工程指导小组 (IESG) 批准发布。有关互联网标准的更多信息,请参见 RFC 7841 第 2 节

有关本文档的当前状态、任何勘误以及如何提供反馈的信息,可在 https://www.rfc-editor.org/info/rfc8470 获取。

Copyright Notice

Copyright (c) 2018 IETF Trust and the persons identified as the document authors. All rights reserved.

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Simplified BSD License.

1. 引言

TLS 1.3 [TLS13] 引入了早期数据(也称为零往返时间 (0-RTT) 数据)的概念。如果客户端最近与同一服务器有过通信,早期数据允许客户端在连接的第一次往返中向服务器发送数据,而无需等待 TLS 握手完成。

当与 HTTP 一起使用时 [HTTP], 早期数据允许客户端立即发送请求,从而避免 TLS 握手所需的一到两个往返延迟。这是一个显著的性能改进;但它也存在重大限制。

使用早期数据的主要风险是攻击者可能捕获并重放其中包含的请求。TLS [TLS13] 描述了可减少攻击者成功重放请求可能性的一些技术,但这些技术部署起来可能困难,且仍然存在成功攻击的可能性。

请注意,这不同于自动或用户发起的重试;重放是由攻击者在客户端不知情的情况下发起的。

为帮助在 HTTP 中减轻重放风险,本文档概述了服务器端用于控制这些风险的技术,并定义了客户端在发送早期数据时的要求。

本文档中的建议同样适用于在 HTTP over QUIC 中使用 0-RTT [HQ] 的情况。

1.1. 约定与定义

本文档中关键字 “MUST”、“MUST NOT”、“REQUIRED”、“SHALL”、“SHALL NOT”、“SHOULD”、“SHOULD NOT”、“RECOMMENDED”、“NOT RECOMMENDED”、“MAY” 和 “OPTIONAL” 应当按 BCP 14 中的定义来解释 [RFC2119] [RFC8174],仅当这些单词全部使用大写时才适用,如此处所示。

2. HTTP 中的早期数据

概念上,早期数据与其他应用数据串联为单一流。这可能意味着请求完全包含在早期数据中,或只有请求的一部分属于早期数据。在像 HTTP/2 [RFC7540] 或 HTTP/QUIC [HQ] 这样的多路复用协议中,多个请求可能部分地在早期数据中被传送。

本文件假定的模型是,一旦 TLS 握手完成,该 TLS 连接上接收到的早期数据就被认为不是该数据的重放副本。然而,重要的是要注意,这并不意味着早期数据不会或尚未在另一个连接上被重放。

3. 在 HTTP 服务器中支持早期数据

服务器在发送 TLS 会话票证(session ticket)时决定是否向客户端提供在将来连接中发送早期数据的能力。

TLS [TLS13] 强制使用重放检测策略以降低攻击者成功重放早期数据的能力。这些防重放技术可以减少但不能完全消除数据被重放的可能性,并能确保重放次数有一个固定的上限。

当服务器启用早期数据时,它可以使用多种技术来减轻重放风险:

  1. 服务器可以在 TLS 层拒绝早期数据。服务器不能对早期数据进行选择性拒绝,因此这会导致所有以早期数据发送的请求被丢弃。
  2. 服务器可以选择在 TLS 握手完成之前延迟处理早期数据。通过延迟处理,它可以确保只有在连接成功完成后才对其中的请求进行处理。这为服务器提供了一定程度的保证,认为早期数据未被重放。如果服务器在早期数据中收到多个请求,它可以决定是否对每个请求分别延迟 HTTP 处理。
  3. 服务器可以在评估重放风险过大时,通过返回 425 (Too Early) 状态码(见 第 5.2 节)来要求客户端对单个请求重试,从而不使用早期数据。

以上这些技术同样有效;服务器可选择最适合其需求的方法。

对于给定请求,可容忍的重放风险级别取决于该请求所操作的资源(因此仅由源服务器知道)。使用早期数据的主要风险在于服务器在处理请求时采取的动作;处理重复请求可能导致重复的效果和副作用。RFC 8446 附录 E.5 也描述了处理重复请求可能产生的其他影响。

请求方法的安全性(见 [RFC7231], 第 4.2.1 节)是确定的一个方式。然而,有些资源即便使用安全方法也会产生副作用,因此该方法并不能被普遍依赖。

建议源服务器允许资源显式配置是否在请求中适合使用早期数据。在缺乏此类显式信息的情况下,源服务器必须要么拒绝早期数据,要么实施本文档中所述的在 TLS 握手完成前不处理请求的技术。

一个请求可能部分地在早期数据中发送,而请求的其余部分在握手完成后发送。这并不必然影响该请求的处理;关键在于服务器何时开始对请求内容采取行动。任何一个服务器实例在握手完成前可能开始处理该请求时,所有服务器实例都需要考虑早期数据被重放的可能性以及这可能如何影响处理(另见 第 6.2 节)。

服务器可以对不完整的请求进行部分处理。解析头字段——但不对其值采取动作——并确定请求路由通常不会产生副作用,但其它操作可能会。

中间服务器没有足够的信息来决定是否可以处理早期数据,因此 第 5.2 节 描述了源服务器如何向它们标示某个请求不适合早期数据。接受早期数据的中间服务器必须实现该机制。

注意服务器不能在 TLS 层选择性地拒绝早期数据。TLS 只允许服务器要么接受全部早期数据,要么全部拒绝。一旦服务器决定接受早期数据,它必须处理所有早期数据中的请求,即使服务器随后用 425 (Too Early) 响应拒绝该请求。

服务器可以使用 TLS 扩展 early_datamax_early_data_size 字段来限制早期数据的量。这可用于避免为可能被延迟处理的请求分配任意数量的内存。

4. 在 HTTP 客户端中使用早期数据

希望使用早期数据的客户端在发送 TLS ClientHello 后立即开始发送 HTTP 请求。

客户端本身可以控制某个请求是否作为早期数据发送,从而使客户端能够控制重放风险。在缺乏其它信息的情况下,客户端可以在可用时将安全的 HTTP 方法 [RFC7231], 第 4.2.1 节 中定义的那些方法以早期数据方式发送,但必须不要将不安全的方法(或其安全性未知的方法)在早期数据中发送。

如果服务器在 TLS 层拒绝早期数据,客户端必须像新建连接那样重新开始发送。这可能意味着使用与为早期数据乐观选择的不同的 ALPN 协商出的协议。任何早期数据中发送的请求都需要重发,除非客户端决定放弃这些请求。

自动重试会导致重放攻击的潜在风险。攻击者拦截使用早期数据的连接并把早期数据复制到另一个服务器实例上。第二个服务器实例接受并处理该早期数据,即便它不会完成 TLS 握手。随后攻击者允许原始连接完成。即便早期数据被检测为重复并被拒绝,第一台服务器实例仍可能允许连接完成。如果客户端随后重试早期数据中发送的请求,请求就可能被处理两次。

如果存在多个会接受早期数据的服务器实例,或者同一服务器多次接受早期数据(尽管后者将违反 RFC 8446 第 8 节 的要求),也可能发生重放。

接收 425 (Too Early) 响应状态码的客户端在使用早期数据时必须重试请求;参见 第 5.2 节

中间服务器在转发请求时不得使用早期数据,除非该请求在前一跳已使用早期数据,或它知道该请求可以安全地重试而不会产生后果(通常通过带外配置)。在缺乏更多信息的情况下,中间服务器只有在请求本身为早期数据到达,或请求包含 Early-Data 头字段且其值为 “1” 时,才能使用早期数据(见 第 5.1 节)。

5. HTTP 早期数据的扩展

由于 HTTP 请求可以跨越多个“跳”(hop),因此有必要明确地传达请求是否在先前跳中以早期数据发送。同样,当不希望使用早期数据时,需要有某种显式触发重试的手段。最后,也需要知道客户端是否会实际执行这样的重试。

为满足这些需求,定义了两种信令机制:

  • Early-Data 头字段用于那些可能在 TLS 握手完成前被中间件转发的请求中,指示该请求可能已被转发过。
  • 定义了 425 (Too Early) 状态码,供服务器在由于可能的重放攻击而无法处理请求时使用。

这些机制旨在在用户代理与源服务器之间以及在存在网关(反向代理、CDN 或 surrogate)时更好地协调早期数据的使用。

网关通常没有关于某个请求在早期数据中发送时是否可以安全处理的具体信息。在许多情况下,只有源服务器具有决定重放风险是否可接受的必要信息。这些扩展允许网关与其源服务器之间进行协调。

5.2. 425 (Too Early) 状态码

425 (Too Early) 状态码表示服务器不愿冒处理可能被重放的请求的风险。

以早期数据发送请求的用户代理在收到 425 (Too Early) 响应状态码时应重试该请求。用户代理应当自动重试,但任何重试都不得在早期数据中发送。

在所有情况下,中间服务器可以转发 425 (Too Early) 状态码。如果中间服务器收到并转发的请求包含 Early-Data 头字段,则它必须转发 425 (Too Early) 状态码。否则,收到早期数据请求的中间服务器在收到 425 (Too Early) 状态码时可以自动重试该请求,但它必须等待在其接收该请求的连接上 TLS 握手完成后再进行重试。

服务器不能假定客户端能够重试请求,除非该请求是在早期数据中接收的或 Early-Data 头字段被设置为 “1”。除非满足这些条件之一,服务器不应发出 425 状态码。

425 (Too Early) 状态码默认不可缓存。其载荷并不是任何已识别资源的表示。

6. 安全性考虑

使用早期数据会使客户端面临请求被重放的风险。重试或重放的请求可能在服务器上产生不同的副作用。除了这些副作用之外,重放和重试可能被用于流量分析,从而恢复关于请求或这些请求目标资源的信息。特别地,被重放的请求可能产生不同的响应,即使内容保持机密,也可能通过受保护数据的长度被观察到。

6.1. 网关与早期数据

网关不得转发那些在早期数据中接收到的请求,除非它知道它将要转发到的源服务器理解 Early-Data 头字段并会正确生成 425 (Too Early) 状态码。对于不确定源服务器是否支持某请求的网关,应该延迟转发该请求直到与其客户端的 TLS 握手完成,或直接响应 425 (Too Early)。

如果没有至少一个潜在的源服务器支持 Early-Data 头字段,则网关为启用早期数据而付出的努力通常不会带来显著的性能收益。如果没有源服务器支持早期数据,则更有效的做法是完全禁用早期数据。

6.2. 一致地处理早期数据

对以早期数据到达或部分以早期数据到达的请求进行一致处理,对于避免不当处理被重放请求至关重要。如果某请求在 TLS 握手完成之前不安全,则所有服务器实例(包括网关)需要达成一致,要么拒绝该请求,要么延迟处理。

禁用早期数据、延迟请求或用 425 (Too Early) 拒绝请求都是缓解可能被重放的请求的有效措施。服务器实例可以实现上述任一措施,并被认为是一致的,即使不同实例使用不同的方法。这一点至关重要:这意味着可以根据其它条件(例如服务器负载)采用不同的缓解措施。

如果服务器实例和其他服务器实例对如何处理相同数据可能做出不同决定,则该服务器不得在握手完成前对早期数据采取行动。

6.3. 拒绝服务

接受早期数据会使服务器面临通过重放那些处理代价高的请求而产生的拒绝服务风险。在负载较高时,服务器应优先考虑拒绝 TLS 早期数据整体,而不是接受早期数据后选择性地处理请求。返回 503 (Service Unavailable) 或 425 (Too Early) 状态码通常会导致客户端重试请求,这可能导致负载增大。

6.4. 乱序交付

在那些支持乱序交付的协议(例如 QUIC [HQ])中,早期数据可能在握手完成之后才到达。只有当服务器能依赖其他实例正确处理同一请求的重放时,它才能在握手完成后处理在早期数据中收到的请求。

7. IANA 注意事项

本文档在 “Permanent Message Header Field Names” 注册表中注册了 Early-Data 头字段,注册页面位于 <https://www.iana.org/assignments/message-headers>。

Header field name:
Early-Data
Applicable protocol:
http
Status:
standard
Author/Change controller:
IETF
Specification document(s):
This document
Related information:
(empty)

本文档在 “HTTP Status Codes” 注册表中注册了 425 (Too Early) 状态码,注册页面位于 <https://www.iana.org/assignments/http-status-codes>。

Value:
425
Description:
Too Early
Reference:
This document

8. 参考文献

8.2. 补充参考文献

[ALPN]
Friedl, S., Popov, A., Langley, A., and E. Stephan, “Transport Layer Security (TLS) Application-Layer Protocol Negotiation Extension”, RFC 7301, DOI 10.17487/RFC7301, July 2014, <https://www.rfc-editor.org/info/rfc7301>.
[HQ]
Bishop, M., “Hypertext Transfer Protocol (HTTP) over QUIC”, Work in Progress, draft-ietf-quic-http-14, August 2018.
[RFC7540]
Belshe, M., Peon, R., and M. Thomson, Ed., “Hypertext Transfer Protocol Version 2 (HTTP/2)”, RFC 7540, DOI 10.17487/RFC7540, May 2015, <https://www.rfc-editor.org/info/rfc7540>.

致谢

撰写本文件并不容易。以下人员对文档的质量和完整性作出了重要贡献:David Benjamin、Subodh Iyengar、Benjamin Kaduk、Ilari Liusavaara、Kazuho Oku、Eric Rescorla、Kyle Rose 和 Victor Vasiliev。

作者地址

Martin Thomson
Mozilla
EMail: martin.thomson@gmail.com
Mark Nottingham
Fastly
EMail: mnot@mnot.net
Willy Tarreau
HAProxy Technologies
EMail: willy@haproxy.org