OpenSSL *要求*应用程序发送/读取非应用程序数据吗?

问题描述

让我们假设有一个客户端和一个服务器,服务器发送一个重新生成密钥的请求,或任何其他可能重要或不重要的非应用程序数据(这里一般来说)。我想知道我是否绑定为 OpenSSL 发送和读取数据,以便我可以让我的生活和代码更简单。为了让你明白我的意思,我准备了这些例子:

假设我们通过 TLS 握手成功,现在准备交换数据。客户端向服务器发送 HTTP 请求,Connection 标头设置为 close,这意味着它不会再发送任何请求。现在 OpenSSL 想在幕后做一些事情,因此要求发送。也许我们做了 shutdown(SHUT_WR) 而不能那样做,或者内核缓冲区永久满了。

假设一个游戏需要交换大量数据——服务器向客户端发送有关游戏的信息,客户端向服务器发送有关鼠标和键盘的信息。通常,在数据交换期间,OpenSSL 将有足够多的机会做任何想做的事情,因此实际上不需要显式监听它的 WANTS_something 请求。现在,如果客户端变为 AFK,因此它不发送任何键盘和鼠标信息,但 OpenSSL 想做一些需要我们发送某些内容的事情(如果可能有这样的事件),该怎么办?

以上两种情况都有一个共同的想法。问题是:OpenSSL 可以在不发送/接收 TLS 数据的情况下继续发送/接收用户数据吗?或者应用程序是否需要满足 OpenSSL 的请求以保持健康的连接/加密?

如果需要满足它的要求,我在编码时可能会遇到另一个问题。假设它要求读取来处理非应用程序数据,但队列中的第一个实际上是应用程序数据。我总是想只在应用程序要求时才读取应用程序数据,否则这是毫无意义的,因为我们缓冲了我们可能不会实际使用的数据,而对等方将继续发送数据,因为 TCP 拥塞窗口不会缩小(因为我们读取数据)。或者,OpenSSL 将在内部缓冲应用程序数据,这是相同的场景,因为最终我将需要从中刷新数据以处理更多非应用程序数据。是否有任何标志或仅处理非应用程序数据的方法?有没有其他很酷的解决方案?

是的,我知道在握手和关闭期间需要发送非应用程序数据。

解决方法

除了初始握手和关闭序列外,TLS 仅在应用程序请求时发送消息。如果您没有做任何特别的事情并且您从 OpenSSL 收到 WANT_READWANT_WRITE 错误(或来自任何 TLS 库的类似指示),这意味着您需要继续读取或写入以完成发送您自己的数据,或从您的对等方接收数据。

任何一方都可以发送重新加密请求,但它只会这样做,因为它在传输更多数据之前需要这样做。

如果启用了相应的扩展,任何一方都可以发送 heartbeat。如果您不想要心跳,则不必启用它们。如果你已经表明你接受心跳,你不需要立即阅读它们,但如果你延迟阅读它们太久,你的对等方可能会断开连接。但是,再次重申,这是一项可选功能,如果您不想要它,请不要启用它。

TLS 是一个严格的流协议,所以如果有任何非应用数据,你必须先读取它,然后才能读取后续的应用数据。您不能只是跳过非应用程序数据。

我总是想在应用程序要求时才读取应用程序数据

网络应用程序通常不是这样工作的。通常您无法预测您的对等方何时将发送数据,因此您不会在不读取应用程序数据的情况下无限期阻塞。无论数据是否通过 TLS,这都类似:您在网络套接字和其他文件描述符上select(或 poll 或等效物),如果网络套接字上有可用数据,您阅读从中。与 TLS 的不同之处在于您从 SSL 套接字读取而不是直接从网络套接字读取; OpenSSL 将负责从网络套接字读取数据。

否则它毫无意义,因为我们缓冲了我们可能不会实际使用的数据,而对等方将继续发送数据,因为 TCP 拥塞窗口不会缩小(因为我们读取了数据)。

如果您不想在应用程序尚未准备好处理数据时无限期地缓冲数据,请不要继续阅读它。数据是直接来自 TCP 还是通过 TLS 没有任何区别。

是否有任何标志或方法可以仅处理非应用程序数据?

没有办法只读取非应用程序数据,因为必须从 TCP 套接字读取数据才能知道它是否是应用程序数据。但为什么这很重要?

还有其他很酷的解决方案吗?

我无法确定我的答案是否“酷”,或者就此而言它是否是“解决方案”,因为我没有看到问题所在。据我所知,您正在想象一个实际上并不存在的定义不清的问题。