multithreading - 来自多个线程的 OpenSSL SSL_read 和 SSL_write

标签 multithreading ssl openssl

我知道 OpenSSL API 中禁止从同一 SSL 上下文中的两个不同线程调用 SSL_readSSL_write,但它是在我的应用程序中,安全的全双工通信很重要。我想到了一些解决方案,但没有一个是我真正喜欢的:

  1. 每个连接使用两个 SSL 上下文。我不喜欢这样做,因为它使用更多资源,并且会使我的实现变得复杂。不过,如果我可以“复制”现有的 SSL 上下文而不是从头开始创建一个全新的连接,那么我会很好地使用它。
  2. 使用带有互斥锁的非阻塞套接字来控制对 SSL 上下文的访问。这需要占用资源的轮询,而且我听说非阻塞实现不太好。

这似乎是一件相当常见的事情,那么这个问题的公认解决方案是什么?

最佳答案

Use non-blocking sockets with a mutex controlling access to an SSL context.

使用单线程内的非阻塞套接字,您将不需要互斥体,因为您只能读取或写入(因为单线程)。

This would require resource-hogging polling, ...

您不需要“占用资源”轮询。我假设您在这里指的是忙轮询,而不是使用系统的常用功能(例如 select)来等待(而不是循环)直到数据可用或可以发送数据。但与普通套接字上的读/写相反,SSL 套接字如果想写则需要读,如果想读则需要写,并且即使套接字不可读,内部也可能有数据。请留意 SSL_WANT_READSSL_WANT_WRITESSL_pending

...and I heard the non-blocking implementation is just not very good.

如果您习惯使用线程,它看起来会更复杂。但是你有没有想过为什么像 nginx 这样的高性能服务器不使用线程而是使用非阻塞 I/O?这是因为它需要更少的资源,并且没有与线程相关的问题,例如需要在关键部分(开销)周围进行互斥,并且在忘记互斥某些内容时会出现奇怪和零星的错误。 nginx 还使用具有非阻塞 I/O 的 openssl。

我个人一直使用非阻塞 I/O,虽然由于协议(protocol)本身而不是 OpenSSL 实现而很难正确使用 SSL,但它是可行且快速的。

这意味着,单线程内的非阻塞 I/O 是解决问题的一种方法。另一种方法是让 SSL 只与内存 BIO 一起工作,而不是真正的文件描述符,并自行完成所有读写操作。但这可能比非阻塞 I/O 更复杂。

顺便说一句,通常SSL上下文表示可以在多个SSL连接之间共享的SSL_CTX对象,并且对于多线程来说可能没有问题。您的意思是,不应从多个线程使用同一个 SSL 连接(SSL 对象)。

关于multithreading - 来自多个线程的 OpenSSL SSL_read 和 SSL_write,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25392494/

相关文章:

java - 具有 Java 应用程序和 SSL 的 Web 服务客户端

c - 试验 SSL 连接

C++:std::atomic<bool> 和 volatile bool

c++ - 运行新线程 Qt C++

c# - 为每个单独的线程记录到单独的日志文件

c# - 使用在主线程中创建的 COM 对象无阻塞地运行一段代码

c# - 在 Sql Server 连接字符串中使用 Encrypt=yes -> "provider: SSL Provider, error: 0 - The certificate' s CN 名称与传递的值不匹配。”

security - 在防火墙中只允许 IPv4 和 HTTPS

python - 从 PKCS7 (signature&data) 中提取分离的 PKCS7 签名

ios - PKCS12_newpass 中的内存泄漏