Upon receiving an "encrypted_client_hello" extension in an initial ClientHello, the client-facing server determines if it will accept ECH, prior to negotiating any other TLS parameters. Note that successfully decrypting the extension will result in a new ClientHello to process, so even the client's TLS version preferences may have changed.¶
在初始 ClientHello 中收到 "encrypted_client_hello" 扩展后, 面向客户端的服务器在协商任何其他 TLS 参数之前确定是否接受 ECH. 请注意, 成功解密扩展将导致要处理的新 ClientHello, 因此甚至客户端的 TLS 版本偏好也可能已更改.¶
First, the server collects a set of candidate ECHConfig values. This list is determined by one of the two following methods:¶
首先, 服务器收集一组候选 ECHConfig 值. 此列表由以下两种方法之一确定:¶
Compare ECHClientHello.config_id against identifiers of each known ECHConfig and select the ones that match, if any, as candidates.¶
将 ECHClientHello.config_id 与每个已知 ECHConfig 的标识符进行比较, 并选择匹配的 (如果有) 作为候选.¶
Collect all known ECHConfig values as candidates, with trial decryption below determining the final selection.¶
收集所有已知的 ECHConfig 值作为候选, 下面的试验解密确定最终选择.¶
Some uses of ECH, such as local discovery mode, may randomize the ECHClientHello.config_id since it can be used as a tracking vector. In such cases, the second method SHOULD be used for matching the ECHClientHello to a known ECHConfig. See Section 10.4. Unless specified by the application profile or otherwise externally configured, implementations MUST use the first method.¶
ECH 的某些用途, 如本地发现模式, 可能会随机化 ECHClientHello.config_id, 因为它可以用作跟踪向量. 在这种情况下, 必须使用第二种方法将 ECHClientHello 匹配到已知的 ECHConfig. 参见 Section 10.4. 除非由应用程序配置文件指定或以其他方式外部配置, 实现必须使用第一种方法.¶
The server then iterates over the candidate ECHConfig values, attempting to decrypt the "encrypted_client_hello" extension as follows.¶
然后服务器遍历候选 ECHConfig 值, 尝试按如下方式解密 "encrypted_client_hello" 扩展.¶
The server verifies that the ECHConfig supports the cipher suite indicated by the ECHClientHello.cipher_suite and that the version of ECH indicated by the client matches the ECHConfig.version. If not, the server continues to the next candidate ECHConfig.¶
服务器验证 ECHConfig 支持由 ECHClientHello.cipher_suite 指示的密码套件, 并且客户端指示的 ECH 版本与 ECHConfig.version 匹配. 如果不匹配, 服务器继续到下一个候选 ECHConfig.¶
Next, the server decrypts ECHClientHello.payload, using the private key skR corresponding to ECHConfig, as follows:¶
接下来, 服务器使用对应于 ECHConfig 的私钥 skR 解密 ECHClientHello.payload, 如下所示:¶
context = SetupBaseR(ECHClientHello.enc, skR,
"tls ech" || 0x00 || ECHConfig)
EncodedClientHelloInner = context.Open(ClientHelloOuterAAD,
ECHClientHello.payload)
¶ClientHelloOuterAAD is computed from ClientHelloOuter as described in Section 5.2. The info
parameter to SetupBaseR is the concatenation "tls ech", a zero byte, and the serialized ECHConfig. If decryption fails, the server continues to the next candidate ECHConfig. Otherwise, the server reconstructs ClientHelloInner from EncodedClientHelloInner, as described in Section 5.1. It then stops iterating over the candidate ECHConfig values.¶
ClientHelloOuterAAD 从 ClientHelloOuter 计算, 如 Section 5.2 中所述. SetupBaseR 的 info
参数是连接 "tls ech"、零字节和序列化的 ECHConfig. 如果解密失败, 服务器继续到下一个候选 ECHConfig. 当解密成功, 服务器从 EncodedClientHelloInner 重构 ClientHelloInner, 如 Section 5.1 中所述. 然后它停止遍历候选 ECHConfig 值.¶
Once the server has chosen the correct ECHConfig, it MAY verify that the value in the ClientHelloOuter "server_name" extension matches the value of ECHConfig.contents.public_name, and abort with an "illegal_parameter" alert if these do not match. This optional check allows the server to limit ECH connections to only use the public SNI values advertised in its ECHConfigs. The server MUST be careful not to unnecessarily reject connections if the same ECHConfig id or keypair is used in multiple ECHConfigs with distinct public names.¶
一旦服务器选择了正确的 ECHConfig, 它可以验证 ClientHelloOuter "server_name" 扩展中的值是否与 ECHConfig.contents.public_name 的值匹配, 如果这些不匹配, 则以 "illegal_parameter" 警报中止. 此可选检查允许服务器将 ECH 连接限制为仅使用其 ECHConfigs 中公布的公共 SNI 值. 如果在具有不同公共名称的多个 ECHConfigs 中使用相同的 ECHConfig id 或密钥对, 服务器必须小心不要不必要地拒绝连接.¶
Upon determining the ClientHelloInner, the client-facing server checks that the message includes a well-formed "encrypted_client_hello" extension of type inner
and that it does not offer TLS 1.2 or below. If either of these checks fails, the client-facing server MUST abort with an "illegal_parameter" alert.¶
确定 ClientHelloInner 后, 面向客户端的服务器检查消息是否包含格式良好的类型为 inner
的 "encrypted_client_hello" 扩展, 以及它是否不提供 TLS 1.2 或以下版本. 如果这些检查中的任何一个失败, 面向客户端的服务器必须以 "illegal_parameter" 警报中止.¶
If these checks succeed, the client-facing server then forwards the ClientHelloInner to the appropriate backend server, which proceeds as in Section 7.2. If the backend server responds with a HelloRetryRequest, the client-facing server forwards it, decrypts the client's second ClientHelloOuter using the procedure in Section 7.1.1, and forwards the resulting second ClientHelloInner. The client-facing server forwards all other TLS messages between the client and backend server unmodified.¶
如果这些检查成功, 面向客户端的服务器然后将 ClientHelloInner 转发给适当的后端服务器, 后端服务器按照 Section 7.2 中的方式进行. 如果后端服务器响应 HelloRetryRequest, 面向客户端的服务器转发它, 使用 Section 7.1.1 中的过程解密客户端的第二个 ClientHelloOuter, 并转发结果的第二个 ClientHelloInner. 面向客户端的服务器在客户端和后端服务器之间未修改地转发所有其他 TLS 消息.¶
Otherwise, if all candidate ECHConfig values fail to decrypt the extension, the client-facing server MUST ignore the extension and proceed with the connection using ClientHelloOuter, with the following modifications:¶
否则, 如果所有候选 ECHConfig 值都无法解密扩展, 面向客户端的服务器必须忽略扩展并使用 ClientHelloOuter 继续连接, 但有以下修改:¶
If sending a HelloRetryRequest, the server MAY include an "encrypted_client_hello" extension with a payload of 8 random bytes; see Section 10.10.4 for details.¶
如果发送 HelloRetryRequest, 服务器可以包含一个带有8个随机字节载荷的 "encrypted_client_hello" 扩展;详见 Section 10.10.4.¶
If the server is configured with any ECHConfigs, it MUST include the "encrypted_client_hello" extension in its EncryptedExtensions with the "retry_configs" field set to one or more ECHConfig structures with up-to-date keys. Servers MAY supply multiple ECHConfig values of different versions. This allows a server to support multiple versions at once.¶
如果服务器配置了任何 ECHConfigs, 它必须在其 EncryptedExtensions 中包含 "encrypted_client_hello" 扩展, 将 "retry_configs" 字段设置为一个或多个具有最新密钥的 ECHConfig 结构. 服务器可以提供不同版本的多个 ECHConfig 值. 这允许服务器同时支持多个版本.¶
Note that decryption failure could indicate a GREASE ECH extension (see Section 6.2), so it is necessary for servers to proceed with the connection and rely on the client to abort if ECH was required. In particular, the unrecognized value alone does not indicate a misconfigured ECH advertisement (Section 8.1.1). Instead, servers can measure occurrences of the "ech_required" alert to detect this case.¶
请注意, 解密失败可能表示(客户端提供了) GREASE ECH 扩展 (参见 Section 6.2) , 因此服务器有必要继续连接并依赖客户端在需要 ECH 时中止. 特别是, 仅仅无法识别的值并不表示 ECH 公布配置错误 (Section 8.1.1) . 相反, 服务器可以测量 "ech_required" 警报的出现次数来检测这种情况.¶
After sending or forwarding a HelloRetryRequest, the client-facing server does not repeat the steps in Section 7.1 with the second ClientHelloOuter. Instead, it continues with the ECHConfig selection from the first ClientHelloOuter as follows:¶
在发送或转发 HelloRetryRequest 后, 面向客户端的服务器不会使用第二个 ClientHelloOuter 重复 Section 7.1 中的步骤. 相反, 它会继续使用第一个 ClientHelloOuter 中的 ECHConfig 选择, 如下所述:¶
If the client-facing server accepted ECH, it checks the second ClientHelloOuter also contains the "encrypted_client_hello" extension. If not, it MUST abort the handshake with a "missing_extension" alert. Otherwise, it checks that ECHClientHello.cipher_suite and ECHClientHello.config_id are unchanged, and that ECHClientHello.enc is empty. If not, it MUST abort the handshake with an "illegal_parameter" alert.¶
如果面向客户端的服务器接受了 ECH, 它会检查第二个 ClientHelloOuter 是否也包含 "encrypted_client_hello" 扩展. 如果没有, 它必须使用 "missing_extension" 警报中止握手. 否则, 它会检查 ECHClientHello.cipher_suite 和 ECHClientHello.config_id 是否未发生变化, 并且 ECHClientHello.enc 是否为空. 如果不是, 它必须使用 "illegal_parameter" 警报中止握手.¶
Finally, it decrypts the new ECHClientHello.payload as a second message with the previous HPKE context:¶
最后, 它使用之前的 HPKE 上下文将新的 ECHClientHello.payload 作为第二条消息解密:¶
EncodedClientHelloInner = context.Open(ClientHelloOuterAAD,
ECHClientHello.payload)
¶ClientHelloOuterAAD is computed as described in Section 5.2, but using the second ClientHelloOuter. If decryption fails, the client-facing server MUST abort the handshake with a "decrypt_error" alert. Otherwise, it reconstructs the second ClientHelloInner from the new EncodedClientHelloInner as described in Section 5.1, using the second ClientHelloOuter for any referenced extensions.¶
ClientHelloOuterAAD 的计算如 Section 5.2 中所述, 但使用第二个 ClientHelloOuter. 如果解密失败, 面向客户端的服务器必须使用 "decrypt_error" 警报中止握手. 否则, 它会根据 Section 5.1 中所述, 从新的 EncodedClientHelloInner 重建第二个 ClientHelloInner, 使用第二个 ClientHelloOuter 来处理任何引用的扩展.¶
The client-facing server then forwards the resulting ClientHelloInner to the backend server. It forwards all subsequent TLS messages between the client and backend server unmodified.¶
然后, 面向客户端的服务器将结果 ClientHelloInner 转发给后端服务器. 它会将客户端和后端服务器之间所有后续 TLS 消息不经修改地转发.¶
If the client-facing server rejected ECH, or if the first ClientHello did not include an "encrypted_client_hello" extension, the client-facing server proceeds with the connection as usual. The server does not decrypt the second ClientHello's ECHClientHello.payload value, if there is one. Moreover, if the server is configured with any ECHConfigs, it MUST include the "encrypted_client_hello" extension in its EncryptedExtensions with the "retry_configs" field set to one or more ECHConfig structures with up-to-date keys, as described in Section 7.1.¶
如果面向客户端的服务器拒绝了 ECH, 或者第一个 ClientHello 未包含 "encrypted_client_hello" 扩展, 则面向客户端的服务器会像往常一样继续连接. 服务器不会解密第二个 ClientHello 的 ECHClientHello.payload 值 (如果存在) . 此外, 如果服务器配置了任何 ECHConfig, 它必须在其 EncryptedExtensions 中包含 "encrypted_client_hello" 扩展, 并将 "retry_configs" 字段设置为一个或多个带有最新密钥的 ECHConfig 结构, 如 Section 7.1 中所述.¶
Note that a client-facing server that forwards the first ClientHello cannot include its own "cookie" extension if the backend server sends a HelloRetryRequest. This means that the client-facing server either needs to maintain state for such a connection or it needs to coordinate with the backend server to include any information it requires to process the second ClientHello.¶
请注意, 转发第一个 ClientHello 的面向客户端的服务器不能在后端服务器发送 HelloRetryRequest 时包含自己的 "cookie" 扩展. 这意味着面向客户端的服务器要么需要为此类连接维护状态, 要么需要与后端服务器协调, 以包含处理第二个 ClientHello 所需的信息.¶