【问题标题】:TCP socket used in a TLS Openssl connection becomes readable after Openssl call returned WANT_WRITE在 Openssl 调用返回 WANT_WRITE 后,TLS Openssl 连接中使用的 TCP 套接字变得可读
【发布时间】:2014-01-15 22:34:23
【问题描述】:

我正在尝试使用 Openssl 在 C++ 中通过 TCP 套接字创建通用 TLS。套接字将用于运行选择循环并利用非阻塞 I/O 的程序中。

我担心在上一个 SSL_get_error 调用返回 SSL_ERROR_WANT_WRITE 之后底层 TCP 套接字变得可读的情况。我可以想到两种可能发生这种情况的情况:

  • 本地应用程序和远程应用程序同时决定发送大量数据。两个应用程序同时调用SSL_write,随后对两个应用程序的SSL_get_error 调用返回SSL_ERROR_WANT_WRITE。从两个应用程序发送的 TCP 数据包在线路上交叉。在之前的 SSL_get_error 调用返回 SSL_ERROR_WANT_WRITE 之后,本地应用程序的 TCP 套接字现在可以读取。
  • 如上所述,除了远程 Openssl 库决定在写入任何应用程序数据之前在 SSL_write 调用中执行 SSL 重新协商。这只是将本地应用程序的 TCP 套接字上接收到的数据的含义从加密的应用程序数据更改为会话重新协商数据。

本地应用程序应该如何处理这些数据?应该:

  • 调用SSL_write,因为它目前正在编写中?
  • 如果套接字空闲,调用SSL_read 会发生什么情况?

【问题讨论】:

标签: ssl openssl


【解决方案1】:

SSL_ERROR_WANT_READ 和 SSL_ERROR_WANT_WRITE 可能由(重新)协商或完整的套接字缓冲区引起,不仅可以在 SSL_read 和 SSL_write 中发生,而且在非阻塞套接字上也可以发生 SSL_connect 和 SSL_accept。您所要做的就是等待想要的套接字状态(例如可读或可写),然后重复相同的操作。例如。如果您从 SSL_write 获得 SSL_ERROR_WANT_READ,则等待套接字可读(使用 select、poll 或类似方法),然后再次调用 SSL_write。与 SSL_read 相同。

将 SSL_CTX_set_mode 与 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER|SSL_MODE_ENABLE_PARTIAL_WRITE 一起使用可能也很有用。

【讨论】:

  • 谢谢。在我的问题的场景中,本地应用程序的 TCP 套接字上收到的数据应该怎么办?
  • SSL 以帧为单位读取/写入数据,例如每个 SSL_write 的数据在至少一个以大小为前缀的帧中一起打包(最大 16k)。如果由于内核中的套接字缓冲区已满而无法在 SSL_write 中发送完整帧,它将发送尽可能多的数据,保持其余的缓冲并返回 SSL_ERROR_WANT_WRITE。如果它返回错误是因为它需要数据来完成握手(例如(重新)协商),它不会在握手完成之前发送任何数据。
  • 谢谢史蒂芬。这种解释是有道理的,但是,它并没有回答我的问题。如果应用程序在SSL_write 之后收到TCP 数据,例如返回SSL_ERROR_WANT_WRITE,应该怎么办?有关何时可能发生这种情况的示例,请参阅开放问题。
  • 如果套接字是可读的(并且 SSL 连接已经建立),您应该调用 SSL_read,除非最后一次调用 SSL_write 返回 SSL_ERROR_WANT_READ。只有在后一种情况下,您才应该重试 SSL_write。
  • 如果我正确理解您的意思,可以在有一个未完成的、部分完成的写入操作时调用SSL_read。例如,以下是有效的:1)调用SSL_write,恰好部分完成,返回SSL_ERROR_WANT_WRITE,2)Socket变得可读,所以调用SSL_read,3)Socket变得可写,所以调用SSL_write . SSL_read 调用不会干扰部分完成的写入操作吗?
猜你喜欢
  • 2013-04-18
  • 2013-04-29
  • 2014-08-31
  • 1970-01-01
  • 2015-08-09
  • 2016-05-14
  • 2015-02-03
  • 2013-12-20
相关资源
最近更新 更多