TLS 1.1+ ClientHello 消息中版本字段的意义是什么?

信息安全 tls 协议
2021-09-09 07:45:35

我正在尝试将 TLS 1.1 和 1.2 支持添加到已经支持 TLS 1.0 的数据包捕获产品中。

我使用 Wireshark 来捕获我的浏览器和 openssl 服务器之间的流量以生成一些测试用例。我在我创建的所有跟踪中看到了一个意外的 TLS 版本。

Secure Sockets Layer
    TLSv1.2 Record Layer: Handshake Protocol: Client Hello
        Content Type: Handshake (22)
        Version: TLS 1.0 (0x0301)
        Length: 105
        Handshake Protocol: Client Hello
            Handshake Type: Client Hello (1)
            Length: 101
            Version: TLS 1.2 (0x0303)

以上是 Wireshark 报告的 TLS 1.2 跟踪之一的摘录。在 ClientHello 中给出的版本是 TLS 1.0,在所有后续消息中是 1.2。这发生在 TLS 1.1 和 1.2 跟踪中。

附录 E.1。(与 TLS 1.0/1.1 和 SSL 3.0 的兼容性)来自 TLS 1.2 RFC 说:

Earlier versions of the TLS specification were not fully clear on
what the record layer version number (TLSPlaintext.version) should
contain when sending ClientHello (i.e., before it is known which
version of the protocol will be employed).  Thus, TLS servers
compliant with this specification MUST accept any value {03,XX} as
the record layer version number for ClientHello.

这本身对我来说也有点模棱两可。

所以我的问题是:

  • 这个字段可以是一个完全任意的值(只要它是 SSLv3 或更高版本)?
  • 行为是否会根据此字段中给出的版本而改变?
  • 浏览器选择 TLS 1.0 而不是 SSLv3 有什么意义吗?

有关的:

1个回答

版本字段出现在三个地方:

  • 作为客户端和服务器发送的每条记录的标头的一部分;
  • 作为ClientHello来自客户端的消息的一部分;
  • 作为ServerHello来自服务器的消息的一部分。

协议版本协商

中的版本字段ClientHello是客户端实现支持的最大版本。例如,当客户端在此字段中输入 0x0302(这是常规值,意思是“TLS 1.1”)时,客户端会告诉服务器:“我已准备好处理最高 TLS 1.1 的所有协议版本”。来自服务器的消息中的版本字段ServerHello指定将用于此连接的协议版本。服务器使用客户端和服务器都支持的最高协议版本。

客户端不应该宣布支持它实际上不支持的协议版本,以免服务器会选择这样的版本,错误地认为客户端确实支持它。

关于记录

来自ClientHello客户端的发送包装成一条或多条记录,每条记录也包含协议版本。记录就像信封周围的信封。对这些记录使用版本 0x0300 (SSLv3) 是安全的,无论ClientHello; 这就像在 SSLv3 信封中发送一封信,但信中说“顺便说一句,我也支持 TLS 1.0 和 TLS 1.1”。使用 SSLv3 记录可以最大限度地与只知道 SSLv3 并且会拒绝更高版本的记录的旧的和有缺陷的实现的互操作性。

服务器的响应说明将使用的协议版本,并且应该作为带有该版本的记录出现。例如,如果服务器在其中显示“TLS 1.1”,ServerHelloServerHello应该将其包装到也标记为“TLS 1.1”的记录中;来自客户端和服务器的所有后续记录都应使用该版本。

互操作性

从理论上讲,服务器应该在版本字段中接受任何大于或等于 0x0300 的值,并且如果它包含例如 0xA7C0(意思是“TLS 165.193”,一个可能永远不会定义的虚构版本),则不应抱怨。这适用于ClientHello消息和记录标题。协议版本会影响记录的编码,但第一个记录是明文(无加密),对于它们来说,可以忽略版本,因为明文是明文(SSL 3.0、TLS 1.0、TLS 1.1 和 TLS 1.2 明文记录的区别仅在于标头中指定的版本,但其他方面相同)。

在实践中,有报告称广泛部署的实现不允许第一个字节不是 0x03 的“版本”字段。甚至有些实现不支持ClientHello指定高于 0x0301(又名 TLS 1.0)的版本。

为了尽量减少问题,客户:

  • 应在记录中使用 SSL 3.0 ClientHello
  • 应在ClientHello; 中指定其支持的最高版本
  • 如果失败,可能会退回到ClientHello再次尝试,这次声称支持的最大版本较低(以适应在看到“TLS 1.1”或“TLS 1.2”时中风的旧服务器)。