【问题标题】:How does the TLS Record Protocol reassemble received data?TLS 记录协议如何重组接收到的数据?
【发布时间】:2019-03-27 07:30:31
【问题描述】:

我找不到有关 TLS 记录协议如何重新组合接收到的数据的详细信息。在 RFC 5246 中:

接收到的数据经过解密、验证、解压、重组、 然后交付给更高级别的客户。

但是怎么做?这是记录层数据的样子:

struct {
    ContentType type;
    ProtocolVersion version;
    uint16 length;
    opaque fragment[TLSPlaintext.length];
} TLSPlaintext;

长度字段就是片段的长度:

以下 TLSPlaintext.fragment 的长度(以字节为单位)

我希望在 Record Protocol Header 中看到完整的长度。谷歌几乎没有给出任何结果,这让我觉得我错过了一些明显的东西......

【问题讨论】:

  • 该文本具有误导性。解压后TLS记录层没有重新组装,只是交付给应用程序。这在描述的其他部分中已明确说明。

标签: ssl cryptography protocols tls1.2


【解决方案1】:

TLS 在流上执行,并且这些流中的数据被放入一个或多个片段(最大 2^14 字节)。这称为碎片。

规范本身的内容如下:

客户 记录层中不保留消息边界(即, 相同 ContentType 的多个客户端消息可以合并 到单个 TLSPlaintext 记录中,或者单个消息可能是 分散在多个记录中)。

这与将它们放入流中,然后再次将流分解为单独的片段相同。

如果您通过 TLS 接收数据,则必须从单独的片段重新创建该流。因此,发生的“重组”是将片段简单地串联成一个流。

一个套接字包含一个输出和输入流。输出流需要分片,输入流需要重组。

没有什么神奇的事情发生,这可能就是你找不到太多东西的原因。


然而,应用层通常会被赋予一个到 TLS 层的相对较低级别的接口,这将允许它包装或发送自己的片段。例如,这个API by IBM 表明它允许用户包装和发送或接收和解包每条消息本身。在这种情况下,库的用户需要处理任何消息碎片/重组。

由于 TLS 未指定分段/组装的实际方法,因此应将其视为特定于实现。

【讨论】:

    【解决方案2】:

    我也有同样的疑问,通过一些研究,我得出以下结论:如果您在可靠协议(例如 TCP)之上使用 TLS,那么重组只是接收到的连接的结果记录协议片段。由于这样一个可靠的协议保证数据按照发送的顺序被接收(当然,不会损坏),接收到的字节的简单连接就足以重新组装,并且由客户端知道如何解释那些接收到的字节。但是,当 TLS 不是通过像 TCP 这样的可靠协议运行时会发生什么?有一个名为Datagram Transport Layer Security 的协议可以做到这一点。直接引用维基百科:

    因为它使用 UDP 或 SCTP,应用程序必须处理数据包重新排序、数据报丢失和大于数据报网络数据包大小的数据

    在这种情况下它究竟是如何工作的?我从 IETF 找到了这个draft,它概述了 DTLS 的工作原理。包含应用程序数据的消息的问题通过以下约束得到解决:

    每个 DTLS 消息必须适合单个传输层数据报

    但是,握手消息是另一回事:

    但是,握手消息可能大于最大记录大小。因此,DTLS 提供了一种将握手消息分片到多个记录上的机制,每条记录都可以单独传输,从而避免了 IP 分片

    特别是握手消息的格式如下:

    struct {
          HandshakeType msg_type;    /* handshake type */
          uint24 length;             /* bytes in message */
          uint16 message_seq;        /* DTLS-required field */
          uint24 fragment_offset;    /* DTLS-required field */
          uint24 fragment_length;    /* DTLS-required field */
          select (HandshakeType) {
              case client_hello:          ClientHello;
              case server_hello:          ServerHello;
              case end_of_early_data:     EndOfEarlyData;
              case hello_retry_request:   HelloRetryRequest;
              case encrypted_extensions:  EncryptedExtensions;
              case certificate_request:   CertificateRequest;
              case certificate:           Certificate;
              case certificate_verify:    CertificateVerify;
              case finished:              Finished;
              case new_session_ticket:    NewSessionTicket;
              case key_update:            KeyUpdate; /* reserved */
          } body;
      } Handshake;
    

    如您所见,它包括一个序列号、一个片段偏移量和一个片段长度。这些也是我希望在 TLS 的记录协议的消息头中看到的字段,但在使用 TCP 时它们不是必需的。

    我希望你会觉得这很有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-05-18
      • 1970-01-01
      • 2015-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-08
      相关资源
      最近更新 更多