如何在一个进程中接受 SSL 连接并在另一个进程中重用相同的 SSL 上下文

sse*_*sen 5 c sockets linux ssl openssl

我花了相当多的时间研究如何解决这个问题,但还没有找到可行的解决方案。

问题: 我正在使用 OpenSSL 库和 linux。我有一个服务器进程 P1 接受来自 SSL 客户端的 SSL 连接。P1 执行 tcp_accept() 然后 SSL_accept() 并使用 SSL_read/SSL_write() 与客户端交换一些协议数据。到目前为止一切都很好。现在按照设计,P1 需要分叉一个子进程 C1 来为客户端提供服务。C1 使用 execve 调用来重新映像自身并生成不同的二进制文件。C1 仍然需要通过在 P1 中使用的相同 SSL 连接与 SSL 客户端通信。问题是因为 C1 是一个完全不同的过程,现在它如何为该客户端重新使用现有的 SSL 连接?我能够将底层 TCP 套接字描述符从 P1 传递到 C1,因为它在内核中维护,但我无法传递 SSL 上下文,因为它在 Openssl 库中维护。

我在 stackoverflow 上看到了这个步骤,但不幸的是没有提到解决方案。 OpenSSL:接受 TLS 连接,然后转移到另一个进程

可能的解决方案: 我不确定是否有人已经解决了此类问题,但我尝试了以下操作。

  1. 我以为我可以创建一个新的 SSL 上下文并在新的子进程中进行 SSL 重新协商。因此,在 C1 中,我在相同的底层 tcp 套接字 fd 上创建了一个新的 SSL 上下文,并尝试进行 SSL 重新协商。这是我所做的(省略 SSL_ctx 初始化部分)

    ssl = SSL_new(ctx) // ctx 的初始化与在 P1 服务器中完成的相同
    SSL_set_fd(ssl, fd); // fd 是底层 tcp socket fd 从 P1 传递到 C1
    SSL_set_accept_state(ssl);
    SSL_set_verify(ssl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0);
    SSL_renegotiate(ssl);
    SSL_do_handshake(ssl);
    ssl->状态=SSL_ST_ACCEPT;
    SSL_do_handshake(ssl);

但是重新协商没有成功,并且从第一个 SSL_do_handshake() 调用返回一个 Openssl 内部错误。我什至不确定这是否真的可以做到。我能想到的另一个解决方案如下。

  1. 以某种方式将该客户端的整个 SSL 上下文从 P1 传输到 C1。这样做的效率如何?我可以为此考虑共享内存,但不太确定 OpenSSL 维护的所有内部状态需要复制到共享内存中。这似乎是最合乎逻辑的解决方案,但我对 OpenSSL 代码没有太多了解来做到这一点。

有没有人遇到过类似的问题并解决了它?我将非常感谢任何有关这方面的帮助。

非常感谢

Rem*_*eau 3

网上搜索发现这样的讨论:

在程序之间传递 TLS 会话

获得 SSL_SESSION 后,将其转换为 ASN1(通过 i2d_SSL_SESSION)并将其转储到文件中。使用第二个程序读取该文件,并将其从 ASN1 转换回 SSL_SESSION(通过 d2i_SSL_SESSION),并将其添加到 SSL_CTX 的 SSL_SESSION 缓存(通过 SSL_CTX_add_session)。

我在 doc/ssleay.txt 中找到:
[...]
PEM_write_SSL_SESSION(fp,x) 和 PEM_read_SSL_SESSION(fp,x,cb) 将以 Base64 编码写入文件指针。您可以用它做的就是在不同的进程之间传递会话信息。
[...]

因此,您需要序列化来自 P1 的 SSL 会话数据,并将其与套接字描述符一起传递到 C1 进行反序列化。然后,您可以在 C1 中创建新的SSLSSL_CTX对象,并将它们与套接字和反序列化会话数据相关联,以便 C1 可以接管对话。