如何在一个进程中接受 SSL 连接并在另一个进程中重用相同的 SSL 上下文 [英] How to accept SSL connection in one process and reuse the same SSL context in another process

查看:45
本文介绍了如何在一个进程中接受 SSL 连接并在另一个进程中重用相同的 SSL 上下文的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have spent quite some time doing my research on how to tackle this problem but could not find a working solution yet.

问题:我正在使用 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 库中维护.

Problem: I am using OpenSSL library and linux. I have a server process P1 accepting SSL connection from SSL client. P1 does tcp_accept() and then SSL_accept() and exchanges some protocol data with client with SSL_read/SSL_write(). Everything is fine till this point. Now by design P1 needs to fork a child process C1 to serve the client from this point onwards. C1 uses execve call to re-image itself and spawn a different binary. C1 still needs to talk to the SSL client over the same SSL connection that was used in P1. The problem is since C1 is a completely different process now how it can re-use the existing SSL connection for that client? I am able to pass the underlying TCP socket descriptor from P1 to C1 as it is maintained in kernel but I can not pass the SSL context since it's maintained in the Openssl Library.

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

I saw this tread on stackoverflow but unfortunately no solution is mentioned. OpenSSL: accept TLS connection and then transfer to another process

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

Possible Solution: I am not sure if anybody has already solved this kind of problem but I tried following.

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

  1. I thought I can just create a new SSL conctext and do SSL renegotiation in the new child process. So in C1 I created a new SSL context over the same underlying tcp socket fd and tried to do SSL renegotiation. Here is what I did (Omiting the SSL_ctx initialization part)

ssl = SSL_new(ctx)//ctx 的初始化与在 P1 服务器中的初始化相同
SSL_set_fd(ssl, fd);//fd 是从 P1 传递给 C1 的底层 tcp socket 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->state=SSL_ST_ACCEPT;
SSL_do_handshake(ssl);

ssl = SSL_new(ctx) // ctx is initialized the same as it was done in P1 server
SSL_set_fd(ssl, fd); // fd is the underlying tcp socket fd passed from P1 to 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->state=SSL_ST_ACCEPT;
SSL_do_handshake(ssl);

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

But the renegotiation does not succeed and returns me an Openssl Internal error from first SSL_do_handshake() call. I am not even sure if this can really be done. The other solution that I can think of is following.

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

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

Has anybody faced similar problem and solved it? I will really appreciate any help regarding this.

非常感谢

推荐答案

网上搜索发现这个讨论:

A search online finds this discussion:

在程序之间传递 TLS 会话

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

Once you have the SSL_SESSION, convert it to ASN1 (via i2d_SSL_SESSION) and dump it to a file. Read that file in with your second program and convert it back from ASN1 to SSL_SESSION(via d2i_SSL_SESSION) and add it to the SSL_SESSION cache of the SSL_CTX (via SSL_CTX_add_session).

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

I found in doc/ssleay.txt :
[...]
The PEM_write_SSL_SESSION(fp,x) and PEM_read_SSL_SESSION(fp,x,cb) will write to a file pointer in base64 encoding. What you can do with this, is pass session information between separate processes.
[...]

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

So you need to serialize the SSL session data from P1 and pass it to C1 to deserialize, along with the socket descriptor. You can then create new SSL and SSL_CTX objects in C1 and associate them with the socket and deserialized session data so C1 can take over the conversation.

这篇关于如何在一个进程中接受 SSL 连接并在另一个进程中重用相同的 SSL 上下文的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆