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

时间:2014-05-20 18:41:06

标签: c linux sockets 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: accept TLS connection and then transfer to another process

可能的解决方案: 我不确定是否有人已经解决了这类问题,但我试过了。

  1. 我想我可以创建一个新的SSL conctext并在新的子进程中进行SSL重新协商。所以在C1中我在相同的底层tcp套接字fd上创建了一个新的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);

  2. 但是重新协商没有成功,并从第一次SSL_do_handshake()调用返回一个Openssl Internal错误。我甚至不确定这是否真的可以做到。我能想到的另一个解决方案是:

    1. 以某种方式将该客户端的整个SSL上下文从P1传输到C1。这样做有多高效?我可以为此考虑共享内存,但不能确定所有内部状态OpenSSL维护需要复制到共享内存中的内容。 这似乎是最合理的解决方案,但我不太了解OpenSSL代码来做到这一点。
    2. 有没有人遇到类似的问题并解决了? 我真的很感激任何有关这方面的帮助。

      非常感谢

2 个答案:

答案 0 :(得分:2)

在线搜索找到了这个讨论:

Passing TLS sessions between programs

  

获得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可以接管对话。

答案 1 :(得分:1)

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

该页面标题为" TLS in the kernel"在lwn.net上。在底部有一些有趣的讨论。希望它可以进入内核主线。或者希望有人可以提出一个生产质量的补丁集,以便人们可以真正使用它。

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

更新:This open source project "TLSe" as a replacement to openssh专门用于将上下文导出到另一个进程。