在 TLS 协议中解析扩展问候消息的正确方法是什么?

What is the correct way to parse extended hello messages in TLS protocol?

根据RFC 5246(定义 TLS 协议版本 1.2)

第 18 页:

The record layer fragments information blocks into TLSPlaintext records carrying data in chunks of 2^14 bytes or less. Client message boundaries are not preserved in the record layer (i.e., multiple client messages of the same ContentType MAY be coalesced into a single TLSPlaintext record, or a single message MAY be fragmented across several records).

第 40 页上写着:

TLS allows extensions to follow the compression_methods field in an extensions block. The presence of extensions can be detected by determining whether there are bytes following the compression_methods at the end of the ClientHello. Note that this method of detecting optional data differs from the normal TLS method of having a variable-length field, but it is used for compatibility with TLS before extensions were defined.

我从这段话中了解到的是,当我解析完一个ClientHello消息后,我应该将它的大小与封装记录层消息的TlsPlaintext.length字段进行比较,看是否有记录层消息末尾的任何额外字节,如果有,将它们解释为 Extension 结构。

这对于我测试我的应用程序的一些 TLS 流量样本实际上工作正常,但对于其他一些则失败(即它无法检测 wireshark 可以检测的消息)。当我使用 wireshark 查看有问题的数据包时,它看起来像是几个握手消息组合成一个握手消息。这些是带有扩展名的 ServerHello(看起来完全像 ClientHello),CertificateServerHelloDone 消息。

当 Hello 消息被封装在单个握手消息中时,检测 Hello 扩展很容易,但我不明白当存在其他握手消息时,如何在 hello 消息之后检测扩展部分的存在和边界他们之后是相同的消息。

任何关于如何解析这些数据包的帮助或建议将不胜感激。

属于(hanshake 协议、更改密码规范协议、警报协议、其他协议)的每个 TLS 消息都在记录层协议内(或之上)发送。看看这个:https://technet.microsoft.com/en-us/library/cc767139.aspx

记录层协议将提供:

  • 内容类型(1 个八位字节)
  • 版本(2 个八位字节)
  • 长度(2 个八位字节)

每条 TLS 消息都将以这些字段开头,即使您在同一 TCP 段的负载中看到许多 SSL 消息也是如此。您可以将这些消息解析为单独的 TLS 消息。

SSL Record Protocol中的Length会给你上层协议报文的总长度。如果它是作为握手协议一部分的 Hello 消息,它将包含扩展。该字段还可以让您确定边界或许多 TLS 消息聚集在一起。

在 Hello 消息的情况下,在压缩方法字段之后,您有 2 个八位字节指示扩展长度。扩展包含在包含 Hello 消息的 SSL 记录协议的长度字段中。它们也包含在同一 Hello 消息的长度中。

在 SSL 记录层之后,不同协议的每条消息都以自己的方式解析:

  • 更改密码规范协议:始终为 1 个八位字节
  • 握手协议:TLV(类型、长度、值)
  • 警报协议:2 个八位字节(级别、警报)
  • HTTP 或其他...

因此,当您有许多 TLS 消息聚集在同一个 TCP 段中时,您总是:

Offset = 0
While more data (based on TCP payload length):
    Read first 5 octets at Offset
        Obtain Length field (Assign to MessageLength, Offset += 5)
            Process first TLS message from Offset, with length MessageLength
            Offset += MessageLength

希望我能正确解决您的问题...