OpenSSL *需要*申请 send/read non-application 数据吗?

Does OpenSSL *require* the application to send/read non-application data?

让我们假设有一个客户端和一个服务器,并且服务器发送一个 rekey 请求,或者任何其他 non-application 可能重要也可能不重要的数据(这里一般来说)。我想知道我是否绑定 发送和读取 OpenSSL 数据,以便我可以简化我的生活和代码。为了让你明白我的意思,我准备了这些例子:

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

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

以上两种场景都有一个共同的想法。问题是:OpenSSL 可以在没有 sending/receiving TLS 数据的情况下保留 sending/receiving 用户数据吗?还是要求应用程序满足 OpenSSL 的请求以保持健康 connection/encryption?

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

是的,我知道在握手和关机期间需要发送 non-application 数据。

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

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

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

TLS是严格的流式传输协议,所以如果有非应用数据,必须先读取,才能读取后续应用数据。您不能只跳过非应用程序数据。

I always want to read application data only when the application asks to do so

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

otherwise it is quite pointless, because we buffer data that we might not actually use and the peer will keep sending data, because the TCP congestion window will not shrink (since we read the data).

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

Is there any flag or a way of processing ONLY non-application data?

无法只读取非应用程序数据,因为必须从 TCP 套接字读取数据才能知道它是否是应用程序数据。但这有什么关系呢?

Is there any other cool solution to this?

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