【问题标题】:Slow DTLS handshake in case of packet loss在丢包的情况下缓慢的 DTLS 握手
【发布时间】:2020-07-10 12:50:37
【问题描述】:

我使用 openssl 实现了一个 DTLS 服务器。 (我有一个 udp 套接字,我正在使用内存 bio 与 openssl 通信。)但是,如果丢包,DTLS 握手可能需要 1-2 秒,这在我的情况下很多。

没有丢包时的正常流程:(几毫秒)

Client Hello ------------------------->
             <------------------------- Server Hello
Rest of the handshake ---------------->
                      <---------------- Rest of the handshake

我正在经历的流程:(几秒钟)

Client Hello ------------------------->
             <-------(lost)------------ Server Hello
Client Hello ------------------------->
Client Hello ------------------------->
Client Hello ------------------------->
             <------------------------- Server Hello
Rest of the handshake ---------------->
                      <---------------- Rest of the handshake

即使在本地环境中直接丢弃第一个 Server Hello,我也可以轻松重现它。

我很好奇为什么服务器不响应一些即将到来的客户端问候。 如果它会回答握手可能会在 1 秒以下完成,但这样它会占用 1-2 秒,当它最终再次回答以后的客户问候时。

如何使 DTLS 握手更快完成? (例如,通过启用所有 Client Hello 的回答,有没有办法?)

【问题讨论】:

  • 这可能取决于重传的客户端 hello(记录号 - 握手序列号)。如果可能,请提供wireshark日志。 (我不确定 Stackoverflow 是否支持附加文件。如果不只是在 github.com/eclipse/californium/issues 中打开一个新问题并通过“拖放”将其附加到那里。)
  • 感谢您的帮助,我使用随附的 Wireshark 捕获文件创建了一个 GitHub 问题:github.com/eclipse/californium/issues/1267

标签: ssl networking openssl udp dtls


【解决方案1】:

在 OpenSSL 中,默认的 DTLS 重新传输计时器从 1 秒开始,如果没有收到响应,它会定期加倍。在您的情况下,服务器已经发送了它的 ServerHello (并且可能是 ServerHelloDone 和其他消息 - 但您没有显示)并且现在正在等待 ClientKeyExchange 消息。从同一对等方接收到的任何后续 ClientHello 都被假定为过时的重传并被忽略。

您可以使用 DTLSv1_listen() 让服务器无状态运行,这意味着服务器将侦听来自任何对等方的连接并假设任何进入的 ClientHello 来自新对等方并立即响应它 - 尽管在这种情况下它添加额外的往返,因为所有 ClientHello 都需要在其中包含“cookie”。它也不会解决握手后丢包的任何问题 - 所以在这里它并不能真正解决您的问题。

从 OpenSSL 1.1.1 开始,您可以使用自定义 DTLS 计时器回调来通过 DTLS_set_timer_cb() 控制计时器的超时:

https://www.openssl.org/docs/man1.1.1/man3/DTLS_set_timer_cb.html

这是一个示例,它将初始计时器设置为 50 毫秒并定期将其加倍(对于基于网络的实现来说,50 毫秒可能太短了 - 但这个特定示例是一个“内存中”测试):

https://github.com/openssl/openssl/blob/20c98cd45399423f760dbd75d8912769c6b7b10e/test/dtlstest.c#L45-L53

注意不要将超时设置太低,因为您可能会开始用大量虚假重传来淹没您的网络。

【讨论】:

  • 感谢您的回答!让我引用 RFC 6347(数据报传输层安全版本 1.2)第 3.2.1 节:“当服务器收到重传时,它知道要重传。”第 4.2.4 节:“实现从对等方读取重新传输的航班:实现转换到 SENDING 状态,在此它重新传输航班,重置重新传输计时器,并返回到 WAITING 状态。”这不是在 openssl 中实现的吗?
  • 我相信 OpenSSL 只会丢弃这些陈旧的重传:github.com/openssl/openssl/blob/…
猜你喜欢
  • 2011-03-24
  • 1970-01-01
  • 1970-01-01
  • 2012-03-12
  • 1970-01-01
  • 2014-12-14
  • 2015-03-13
  • 2022-11-30
  • 2020-11-10
相关资源
最近更新 更多