互联网工程任务组 (IETF) M. Nottingham
请求评注: 8336 E. Nygren
类别: 标准轨道 Akamai
ISSN: 2070-1721 2018年3月

ORIGIN HTTP/2 帧


摘要

本文档定义了 HTTP/2 的 ORIGIN 帧,用于指示在给定连接上可用的 origin。

本备忘录的状态

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

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

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

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. 介绍

HTTP/2 [RFC7540] 允许在满足特定条件时将不同的 origin [RFC6454] 在同一连接上合并(coalesce)。然而,在某些情况下,连接对被合并的 origin 并不可用,因此定义了 421(Misdirected Request)状态码([RFC7540],第 9.1.2 节)。

以这种方式使用状态码可以让客户端从错误定向的请求中恢复,但代价是增加了延迟。为了解决该问题,本规范定义了一种新的 HTTP/2 帧类型 “ORIGIN”,允许服务器指示某个连接对哪些 origin 是可用的。

此外,实践表明 HTTP/2 要求使用 DNS 与服务器证书共同建立服务器权威性的做法较为繁重。使用 ORIGIN 帧时,本规范放宽了对 DNS 检查的要求。这样做还有额外好处,例如消除某些 DNS 查询带来的延迟。

1.1. 表示约定

本文档中的关键词 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", 和 "OPTIONAL" 应当在全部大写出现时,按 BCP 14 中的描述解释,参见 [RFC2119][RFC8174] 的说明,仅在全部大写时适用。

2. ORIGIN HTTP/2 帧

本文档定义了一种新的 HTTP/2 帧类型(参见 [RFC7540] 第 4 节),称为 ORIGIN,允许服务器指示其希望客户端在所在连接中将哪些 origin [RFC6454] 视为 Origin Set(第 2.3 节)的成员。

2.1. 语法

ORIGIN 帧类型的代码为 0xc(十进制 12),包含零个或多个 Origin-Entry 字段实例。

+-------------------------------+-------------------------------+
|         Origin-Entry (*)                                    ...
+-------------------------------+-------------------------------+

Origin-Entry 是一个长度限定的字符串:

+-------------------------------+-------------------------------+
|         Origin-Len (16)       | ASCII-Origin?               ...
+-------------------------------+-------------------------------+

具体而言:

Origin-Len:
一个无符号的 16 位整数,指示 ASCII-Origin 字段的长度(以八位字节计)。
Origin:
一个可选的字符序列,包含 origin 的 ASCII 序列化形式(参见 [RFC6454] 第 6.2 节),发送者断言该连接可对其进行权威或可能对其进行权威。

ORIGIN 帧未定义任何标志;不过,未来对本规范的更新可能会定义标志。参见 第 2.2 节

2.2. 处理 ORIGIN 帧

ORIGIN 帧是对 HTTP/2 的非关键扩展。不支持该帧的端点在接收时可以安全地忽略它。

当由实现了该规范的客户端接收时,它用于初始化和操纵 Origin Set(参见 第 2.3 节),从而改变客户端为 origin 服务器建立权威性的方式(参见 第 2.4 节)。

ORIGIN 帧 MUST 在流 0 上发送;在任何其他流上的 ORIGIN 帧都是无效的并 MUST 被忽略。

同样,ORIGIN 帧仅在标识为 "h2" 的连接上有效,或在该协议定义中特别指定时有效;在标识为 "h2c" 的连接上接收时 MUST 被忽略。

本规范未为 ORIGIN 帧定义任何标志,但通过 IETF 共识对本规范的未来更新可能使用标志来改变其语义。前四个标志位(0x1、0x2、0x4 和 0x8)为向后不兼容更改保留;因此,当设置了其中任何一个时,包含这些标志的 ORIGIN 帧在客户端未理解其语义时 MUST 被忽略。其余标志为向后兼容更改保留,不会影响符合本规范的客户端的处理。

ORIGIN 帧描述的是连接的属性,因此按逐跳处理。中间节点 MUST NOT 转发 ORIGIN 帧。配置为通过代理使用连接的客户端 MUST 忽略该代理发送的任何 ORIGIN 帧。

帧载荷中的每个 ASCII-Origin 字段 MUST 解析为 origin 的 ASCII 序列化形式(参见 [RFC6454] 第 6.2 节)。如果解析失败,则该字段 MUST 被忽略。

注意 ORIGIN 帧不支持通配符名称(例如 "*.example.com")作为 Origin-Entry。因此,当使用通配符证书时发送 ORIGIN 实际上会在客户端理解 ORIGIN 时禁用未在 ORIGIN 帧中明确列出的任何 origin。

参见 附录 A,其中给出了处理 ORIGIN 帧的示例性算法。

2.3. Origin 集合

在本规范中,给定连接可能用于的 origin 集合(参见 [RFC6454])称为 Origin Set。

默认情况下,连接的 Origin Set 为未初始化。未初始化的 Origin Set 意味着客户端适用 [RFC7540] 第 9.1.1 节中的合并规则。

当客户端首次成功接收并处理 ORIGIN 帧时,该连接的 Origin Set 将被定义为包含一个初始 origin。初始 origin 由以下内容组成:

  • Scheme: "https"
  • Host: 在 Server Name Indication (SNI) 中发送的值(参见 [RFC6066] 第 3 节)转换为小写;如果 SNI 不存在,则使用连接的远端地址(即服务器的 IP 地址)
  • Port: 连接的远端端口(即服务器的端口)

该 ORIGIN 帧(以及后续的 ORIGIN 帧)的内容允许服务器按 第 2.2 节 所述逐步将新的 origin 添加到 Origin Set 中。

Origin Set 也会受 421(Misdirected Request)响应状态码的影响,如在 [RFC7540] 第 9.1.2 节中定义。接收到带此状态码的响应时,实现该规范的客户端 MUST 为相应请求构造 origin 的 ASCII 序列化形式(参见 [RFC6454] 第 6.2 节),并在存在时将其从连接的 Origin Set 中移除。

注意:
当向已作为替代服务初始化的连接发送 ORIGIN 帧时(参见 [RFC7838]),初始 Origin Set(第 2.3 节)将包含具有适当方案和主机名的 origin(因为 RFC 7838 指定了在 SNI 中发送 origin 的主机名)。然而,端口可能与目标 origin 的端口不同,因为初始 Origin Set 是使用实际使用的端口计算的,该端口可能与替代服务的端口不同。在这种情况下,目标 origin 需要在 ORIGIN 帧中显式发送。
例如,客户端对 "https://example.com" 发起请求但被定向到替代服务 ("h2", "x.example.net", "8443")。如果该替代服务发送 ORIGIN 帧,则初始 origin 将为 "https://example.com:8443"。除非该 origin 在 ORIGIN 帧中被显式包含,否则客户端不能使用该替代服务来对 "https://example.com" 发出请求。

2.4. 与 ORIGIN 相关的权威、推送与合并

[RFC7540] 的第 10.1 节使用 DNS 与呈现的传输层安全 (TLS) 证书来建立连接对哪些 origin 具有权威性,就像 HTTP/1.1 在 [RFC7230] 中所做的那样。

此外,[RFC7540] 第 9.1.1 节明确允许在连接被认为具有权威性的情况下将该连接用于多个 origin 服务器。这会影响哪些响应可以被视为权威响应,无论是对请求的直接响应还是服务器推送(参见 [RFC7540] 第 8.2.2 节)。间接地,这也影响了哪些请求将被发送到该连接,因为客户端通常只会在其认为对目标 origin 具有权威性的连接上发送请求。

一旦为连接初始化了 Origin Set,实现本规范的客户端将使用其来帮助确定该连接的权威范围。具体而言,此类客户端 MUST NOT 将连接视为对不在 Origin Set 中的 origin 具有权威性,并且 SHOULD 将该连接用于 Origin Set 中且连接对其具有权威性的所有请求,除非存在出于操作原因需要打开新连接的情况。

注意,要将连接视为对某给定 origin 具有权威性,服务器仍需使用能够通过适当检查的证书进行认证;更多信息见 [RFC7540] 第 9.1.1 节。这包括验证主机名是否与证书的 subjectAltName 字段中的 dNSName 值匹配(使用 [RFC2818] 定义的规则;另见 [RFC5280] 第 4.2.1.6 节)。

此外,客户端可以选择在对 Origin Set 中的新 origin 发起新请求时避免查询 DNS 来建立连接的权威性;但这样做会带来新的风险,详见 第 4 节

由于 ORIGIN 可以随时间改变连接所使用的 origin 集合,客户端可能在任意时刻对某个 origin 同时保持多个可用连接。当发生这种情况时,客户端 SHOULD NOT 在任何 Origin Set 是另一个连接 Origin Set 的真子集的连接上发出新请求,并且在所有未完成请求完成后 SHOULD 关闭该连接。

Origin Set 不受服务器所做的任何替代服务 [RFC7838] 通告的影响。通告替代服务并不会影响服务器是否具有权威性。

3. IANA 注意事项

本规范向 “HTTP/2 Frame Type” 注册表添加一项条目。

  • Frame Type: ORIGIN
  • Code: 0xc
  • Specification: RFC 8336

4. 安全注意事项

盲目信任 ORIGIN 帧内容的客户端将容易受到大量攻击。关于缓解措施,请参见 第 2.4 节

放宽在确定 origin 的权威性时咨询 DNS 的要求意味着,拥有有效证书的攻击者不再需要在路径上以重定向流量;他们无需修改 DNS,只需说服用户访问另一个网站,就可以将连接与目标的合并到他们现有的连接上。

因此,选择不咨询 DNS 的客户端应采用某些替代方法来建立对证书合法性的高度信心。例如,客户端可能仅在收到证书透明日志(Certificate Transparency)中的包含证明 [RFC6962],或拥有最近的在线证书状态协议(OCSP)响应 [RFC6960](可能使用 TLS 的 "status_request" 扩展 [RFC6066])表明证书未被吊销时,才跳过 DNS 查询。

Origin Set 的大小并未被本规范限制,因此可能被攻击者用于耗尽客户端资源。为缓解此风险,客户端可以监控其状态承诺并在过高时关闭连接。

5. 参考文献

5.2. 信息性参考文献

[RFC6960]
Santesson, S., Myers, M., Ankney, R., Malpani, A., Galperin, S., and C. Adams, “X.509 Internet Public Key Infrastructure Online Certificate Status Protocol - OCSP”, RFC 6960, DOI 10.17487/RFC6960, June 2013, <https://www.rfc-editor.org/info/rfc6960>.
[RFC6962]
Laurie, B., Langley, A., and E. Kasper, “Certificate Transparency”, RFC 6962, DOI 10.17487/RFC6962, June 2013, <https://www.rfc-editor.org/info/rfc6962>.
[RFC7230]
Fielding, R., Ed. and J. Reschke, Ed., “Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing”, RFC 7230, DOI 10.17487/RFC7230, June 2014, <http://www.rfc-editor.org/info/rfc7230>.
[RFC7838]
Nottingham, M., McManus, P., and J. Reschke, “HTTP Alternative Services”, RFC 7838, DOI 10.17487/RFC7838, April 2016, <http://www.rfc-editor.org/info/rfc7838>.
[RFC8288]
Nottingham, M., “Web Linking”, RFC 8288, DOI 10.17487/RFC8288, October 2017, <https://www.rfc-editor.org/info/rfc8288>.

附录 A. 非规范性处理算法

下面的算法示例说明了客户端如何处理接收到的 ORIGIN 帧:

  1. 如果客户端被配置为对该连接使用代理,则忽略该帧并停止处理。
  2. 如果该连接未被标识为 "h2" 协议标识符或未明确选择加入本规范的其他协议,则忽略该帧并停止处理。
  3. 如果该帧出现在除流 0 以外的任何流上,则忽略该帧并停止处理。
  4. 如果设置了任何标志 0x1、0x2、0x4 或 0x8,则忽略该帧并停止处理。
  5. 如果之前在该连接上没有任何 ORIGIN 帧达到此步骤,则按 第 2.3 节 初始化 Origin Set。
  6. 对于帧载荷中的每个 Origin-Entry
    1. ASCII-Origin 解析为 origin 的 ASCII 序列化形式(参见 [RFC6454] 第 6.2 节),令结果为 parsed_origin。如果解析失败,则跳到下一个 Origin-Entry
    2. parsed_origin 添加到 Origin Set。

附录 B. 服务器的操作注意事项

ORIGIN 帧允许服务器指示某个连接应被用于哪些 origin。使用该机制通告的 origin 集由服务器控制;服务器既不必使用该机制,也不必通告它们可能能够响应请求的所有 origin。

例如,可通过发送一个空的 ORIGIN 帧告知客户端该连接仅用于基于 SNI 的 origin。或者,可以通过包含载荷来指示更多的 origin。

通常,这些信息在发送任何可能引发新连接的响应部分之前发送最为有用;例如,“Link” 响应头字段 [RFC8288],或响应主体中的链接。

因此,ORIGIN 帧应尽早在连接上发送,理想情况下在任何 HEADERS 或 PUSH_PROMISE 帧之前发送。

然而,如果希望将大量 origin 与连接关联,可能会因其大小而引入用户感知的延迟。因此,可能需要选择一个“核心” origin 集合作为初始发送,并在随后(例如连接空闲时)通过后续 ORIGIN 帧扩展该集合。

尽管如此,建议发送者在单个 ORIGIN 帧中包含尽可能多的 origin;客户端需要在运行时对是否创建连接作出决策,如果 Origin Set 分散在许多帧中,其行为可能并非最优。

发送者应注意,如 [RFC6454] 第 4 节第 5 步所述,ORIGIN 头字段中的值在序列化之前需要进行大小写归一化。

最后,承载替代服务的服务器(参见 [RFC7838])在发送 ORIGIN 时需要显式通告它们的 origin,因为 Origin Set 的默认内容(参见 第 2.3 节)不包含任何替代服务的 origin,即使这些替代服务之前在连接上被使用过。

作者地址

Mark Nottingham
EMail: mnot@mnot.net
URI: https://www.mnot.net/
Erik Nygren
Akamai
EMail: nygren@akamai.com