9. HTTP/2 Connections (HTTP/2连接)
HTTP/2 连接是应用层协议,运行在可靠的传输层之上 [TCP],它使用传输层安全性 (TLS) [TLS13] 来保护通过网络交换的数据。
HTTP/2 使用与 HTTP/1.1 相同的 "http" 和 "https" URI 方案。HTTP/2 共享相同的默认端口号:80 端口用于 "http" URI,443 端口用于 "https" URI。因此,实现需要处理对目标资源 URI(如 http://example.org/foo 或 https://example.com/bar)的请求,方法是首先发现上游服务器(客户端希望建立连接的直接对等方)是否支持 HTTP/2。
9.1. Connection Management (连接管理)
HTTP/2 连接是持久的。为了获得最佳性能,期望客户端不要关闭连接,直到确定不再需要与服务器进一步通信(例如,当用户离开特定网页时),或者直到服务器关闭连接。
客户端不应该 (SHOULD NOT) 打开到给定主机和端口对的多个 HTTP/2 连接,其中主机由 URI、选定的备用服务 [ALT-SVC] 或配置的代理派生。
客户端可以创建额外的连接作为替代,以替换即将耗尽可用流标识符空间 (Section 5.1.1) 的连接,以刷新用于 TLS 连接的密钥材料,或以替换遇到错误 (Section 5.4.1) 的连接。
客户端可以 (MAY) 出于以下原因打开到同一目标的多个连接:创建新连接以尝试原子请求(见 Section 9.1.2),或者替换在 GOAWAY 帧中接收到的任何流标识符大于 0 且处于 "活动" 或 "闲置" 状态的流(见 Section 6.8)。
服务器鼓励尽可能长时间地维护打开的连接,但如果必要,允许终止空闲连接。当任一端点选择关闭传输层 TCP 连接时,终止端点应该 (SHOULD) 首先发送 GOAWAY 帧 (Section 6.8),以便两个端点能可靠地确定先前发送的帧是否已被处理并正常完成或终止任何必要的剩余任务。
9.1.1. Connection Reuse (连接重用)
直接或通过使用 CONNECT 方法的隧道 (Section 8.5) 建立到源服务器的连接可以重用于具有多个不同 URI 权限组件的请求。只要源服务器具有权威性 (Section 10.1),连接就可以重用。对于没有 TLS 的 TCP 连接,这取决于已解析为相同 IP 地址的主机。
对于 "https" 资源,连接重用还依赖于拥有对 URI 中的主机有效的证书。服务器提供的证书必须 (MUST) 通过客户端在原始连接上建立的任何检查。
源服务器可能为多个源提供证书,每个源都对使用连接具有权威性。例如,证书可能在主题备用名称 (subjectAltName) 字段中包含多个主机名。或者,可以使用包含通配符的主机名,该通配符也适用于其他源。
在某些情况下,URI 权限可能与证书中标识的一组源不同(例如,一些部署使用 URI 来携带在其他地方建立的身份断言),而权限的其他属性也不匹配。客户端可以 (MAY) 尝试使用现有连接,但必须 (MUST) 使用其认为权威的 URI 发送请求。如果服务器不希望接受该请求,它应该 (SHOULD) 产生 421 (Misdirected Request) 状态码,这将导致客户端重试请求。
如果客户端发现它尝试重用的连接不再可用,则可以在新连接上重试不安全的请求。
代理可以 (MAY) 重用到同一源服务器的连接。
9.1.2. The 421 (Misdirected Request) Status Code (421(错误定向请求)状态码)
421 (Misdirected Request) 状态码表示请求被定向到无法生成响应的服务器。这可能由未配置为为请求 URI 中包含的方案和权限组合生成响应的服务器发送。
客户端在接收到 421 (Misdirected Request) 响应时可以 (MAY) 重试请求,无论请求方法如何,在不同的连接上。这是可能的,因为只有在服务器选择不提供权威响应之前才允许生成 421 响应码。
此状态码不得 (MUST NOT) 由代理生成。421 响应是可缓存的;除非响应中另有指示(参见 [HTTP-CACHING] 的 Section 4.2.2),否则默认情况下是启发式可缓存的。
9.2. Use of TLS Features (TLS功能的使用)
HTTP/2 的实现必须 (MUST) 为 "https" URI 使用 TLS 版本 1.2 [TLS12] 或更高版本。TLS 实现的一般指导在 [TLSBCP] 中给出。
TLS 实现必须 (MUST) 支持 Server Name Indication (SNI, 服务器名称指示) [TLS-EXT] 扩展。HTTP/2 客户端必须 (MUST) 在 TLS 握手期间指示目标域名,除非提供了指示不需要的替代机制。
对于客户端和服务器,部署 HTTP/2 取决于 TLS 1.3 [TLS13] 或更高版本的部署应该 (SHOULD) 支持和使用 TLS 的应用层协议协商 (ALPN) 扩展 [TLS-ALPN]。这样做会在不消耗往返行程的情况下在 TLS 握手期间识别使用 HTTP/2。
虽然连接级选项对于 HTTP 的使用不是特定的,但使用 HTTP/2 的服务器可以传达它们对连接的首选项。TLS 提供了加密,可以最大程度地减少窃听者学习到客户端和服务器之间交换的信息的能力。TLS 还提供了完整性保护,确保信息不会在传输过程中被修改,无论是通过无意的网络污染还是通过主动攻击者。
在协商使用 HTTP/2 后必须 (MUST) 执行 [TLS12] 的 Section 7.4.1.4 中的规则。这些规则使用服务器证书来建立标识;客户端证书不能用于此目的。证书链和证书颁发机构 (CA) 的检查也是必需的。
如果 HTTP/2 是在 TLS 1.2 上协商的,则必须 (MUST) 提供 TLS 1.2 加密套件黑名单 (Section 9.2.2)。
建议不要使用压缩的 TLS 证书;除非客户端明确请求,否则客户端和服务器在 HTTP/2 中使用的证书不应该 (SHOULD NOT) 被压缩。
9.2.1. TLS 1.2 Features (TLS 1.2功能)
本节介绍了 TLS 1.2 中特定于 HTTP/2 的使用限制。由于这些限制主要在 TLS 1.3 中得到解决,因此鼓励实现使用 TLS 1.3 或更高版本。仅使用 TLS 1.2 的实现必须 (MUST) 符合本节的要求。
9.2.1.1. TLS 1.2 Features for HTTP/2 Clients (HTTP/2客户端的TLS 1.2功能)
HTTP/2 客户端实现必须 (MUST) 支持在握手中通过扩展字段发送 TLS 服务器名称指示 (SNI) [TLS-EXT]。
HTTP/2 客户端必须 (MUST) 支持 TLS 应用层协议协商 (ALPN) [TLS-ALPN]。
9.2.1.2. TLS 1.2 Features for HTTP/2 Servers (HTTP/2服务器的TLS 1.2功能)
如果服务器通过 ALPN 或 NPN 以外的方式协商 HTTP/2,则必须 (MUST) 为客户端提供机会来指示是否愿意使用 HTTP/2。
HTTP/2 服务器应该 (SHOULD) 发送扩展 master secret 扩展 [RFC7627]。如果客户端不支持此扩展,则服务器不得 (MUST NOT) 恢复先前建立的会话。如果协商了扩展 master secret,则服务器可以 (MAY) 恢复先前建立的会话。
9.2.2. TLS 1.2 Cipher Suites (TLS 1.2加密套件)
在 TLS 1.2 上的 HTTP/2 部署必须 (MUST) 支持 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 [TLS-ECDHE],并具有 secp256r1 [RFC8422] 椭圆曲线。注意,客户端在 TLS ClientHello 消息中通过 supported_groups 扩展 [TLS13] 指示对其支持的曲线的支持,服务器通过选择该扩展提供的任何列出的曲线来表明对曲线的支持。
客户端可以 (MAY) 在使用 HTTP/2 的 TLS 1.2 上通告对任何密码套件的支持。然而,下面列出的密码套件具有已知质量不佳的特性,因此被禁止在 TLS 1.2 上的 HTTP/2 中使用。这些套件具有以下一个或多个属性:
- NULL 加密套件,不提供加密。
- 基于流密码的套件,在 TLS 中的使用容易受到攻击。
- 基于 RC4 的套件,有严重的安全问题。
- 基于 3DES 的套件,其实际提供的安全性少于 112 位。
- 基于 CBC 模式的块密码,在 TLS 中对攻击敏感,特别是在 TLS 1.2 及更早版本中。
- 基于 RSA 密钥交换的套件,不提供前向保密性。
- 使用不建议用于 TLS 的 Diffie-Hellman 参数的套件。
- 使用对 AEAD 算法的支持不佳的 SHA-1 摘要的套件。
完整的被禁止密码套件列表在 Appendix A 中提供。
9.3. Connection Preface (连接前言)
在 HTTP/2 中,每个端点都需要发送一个连接前言作为所使用协议的最终确认,并建立 HTTP/2 连接的初始设置。客户端和服务器各自发送不同的连接前言。
客户端连接前言以 24 个八位字节的序列开始,十六进制表示法为:
0x505249202a20485454502f322e300d0a0d0a534d0d0a0d0a
也就是说,连接前言以字符串 PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n 开始。此序列后面必须 (MUST) 跟随一个 SETTINGS 帧 (Section 6.5),该帧可能为空。客户端在接收到服务器连接前言后立即发送客户端连接前言。
| 注意: 选择客户端连接前言以便最大程度地减少 HTTP/2 连接在处理其他 HTTP 协议的 | 服务器上被视为有效的 HTTP/1.1 请求的可能性。请注意,无论如何,任何 HTTP/1.1 | 请求都不能合理地包含 "PRI" 作为方法令牌。
服务器连接前言由可能为空的 SETTINGS 帧 (Section 6.5) 组成,该帧必须 (MUST) 是服务器在 HTTP/2 连接中发送的第一个帧。
收到需要 HTTP/1.1(或更早版本)的 101 (Switching Protocols) 响应后升级的客户端必须 (MUST) 立即发送客户端连接前言。
服务器接收客户端连接前言,客户端接收服务器连接前言。连接前言中的 SETTINGS 帧必须 (MUST) 被确认(见 Section 6.5.3),作为进一步连接建立的一部分(见 Section 3.4)。
为避免不必要的延迟,允许客户端在发送客户端连接前言后立即向服务器发送其他帧,而无需等待接收服务器连接前言。但是,重要的是要注意,服务器连接前言的 SETTINGS 帧可能包括必须遵守的参数,以便与服务器通信。在接收到 SETTINGS 帧后,客户端应该 (SHOULD) 遵守任何建立的参数。在某些配置中,服务器可能在客户端发送额外帧之前传输 SETTINGS,提供有机会避免此问题。
客户端和服务器必须 (MUST) 将无效的连接前言视为 PROTOCOL_ERROR 类型的连接错误 (Section 5.4.1)。在这种情况下可能省略 GOAWAY 帧 (Section 6.8),因为无效前言表明对等方未使用 HTTP/2。
第9章完成!
References
- [TCP] RFC 793
- [TLS13] RFC 8446
- [TLS12] RFC 5246
- [TLS-EXT] RFC 6066
- [TLS-ALPN] RFC 7301
- [TLSBCP] RFC 9325
- [TLS-ECDHE] RFC 5289
- [RFC8422] RFC 8422
- [RFC7627] RFC 7627
- [ALT-SVC] RFC 7838
- [HTTP-CACHING] RFC 9111