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

我花了一段时间来研究如何解决这个问题,但还找不到一个可行的解决scheme。

问题:我正在使用OpenSSL库和Linux。 我有一个服务器进程P1接受来自SSL客户端的SSL连接。 P1执行tcp_accept()和SSL_accept(),并用SSL_read / SSL_write()与客户端交换一些协议数据。 一切都很好,直到这一点。 现在deviseP1需要从这一点开始分叉一个subprocessC1来为客户端服务。 C1使用execve调用重新映像自己并产生一个不同的二进制文件。 C1仍然需要通过与P1中使用的相同的SSL连接与SSL客户端通信。 问题是因为C1是一个完全不同的过程,现在它是如何重新使用现有的SSL连接的客户端? 我能够将底层的TCP套接字描述符从P1传递到C1,因为它是在内核中维护的,但是由于它是在Openssl库中维护的,所以我无法传递SSL上下文。

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

可能的解决scheme:我不确定是否有人已经解决了这样的问题,但我试图追踪。

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

    ssl = SSL_new(ctx)// ctx的初始化与在P1服务器中完成的一样
    SSL_set_fd(ssl,fd); // fd是从P1传递给C1的底层TCP套接字fd
    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内部错误。 我甚至不确定这是否真的可以做到。 我能想到的另一个解决scheme如下。

  1. 以某种方式将该客户端的整个SSL上下文从P1转移到C1。 这可以做多高效? 我可以为此共享内存,但不确定所有内部状态OpenSSL需要复制到共享内存中的内容。 这似乎是最合乎逻辑的解决scheme,但我对OpenSSL代码没有太多的了解。

有没有人遇到类似的问题并解决了它? 我真的很感谢这方面的帮助。

非常感谢

Solutions Collecting From Web of "如何在一个进程中接受SSL连接,并在另一个进程中重用相同的SSL上下文"

网上搜索发现这个讨论:

在程序之间传递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可以接管对话。

我做了一个“tls内核模式”的搜索,发现一个内核补丁为TLS连接提供正常的fd。 因此,fd可以作为普通套接字传递给其他进程。

该页面在lwn.net上标题为“ 内核中的TLS ”。 对底部有一些有趣的讨论。 希望它能进入内核主线。 否则希望有人可以拿出一个生产质量补丁集,以便人们可以真正使用它。

如果你知道一些真正的产品正在使用它,可能在这里分享是一个好主意。

更新: 这个开放源代码项目“TLSe”作为openssh的替代品,专门用于将上下文导出到另一个进程。