Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何在一个进程中接受SSL连接并在另一个进程中重用相同的SSL上下文_C_Linux_Sockets_Ssl_Openssl - Fatal编程技术网

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

C 如何在一个进程中接受SSL连接并在另一个进程中重用相同的SSL上下文,c,linux,sockets,ssl,openssl,C,Linux,Sockets,Ssl,Openssl,我花了相当长的时间研究如何解决这个问题,但还没有找到有效的解决办法 问题: 我正在使用OpenSSL库和linux。 我有一个从SSL客户端接受SSL连接的服务器进程P1。P1先执行tcp_accept(),然后执行SSL_accept(),并使用SSL_read/SSL_write()与客户端交换一些协议数据。到目前为止一切都很好。现在,根据设计,P1需要派生一个子进程C1,以便从此点开始为客户机提供服务。C1使用execve调用来重新映像自身并生成不同的二进制文件。C1仍然需要通过P1中使用

我花了相当长的时间研究如何解决这个问题,但还没有找到有效的解决办法

问题: 我正在使用OpenSSL库和linux。 我有一个从SSL客户端接受SSL连接的服务器进程P1。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上看到了这种情况,但不幸的是没有提到解决方案。

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

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

    ssl=ssl\u new(ctx)//ctx的初始化与P1服务器中的初始化相同
    SSL_set_fd(SSL,fd);//fd是从P1传递到C1的底层tcp套接字fd
    SSL设置接受状态(SSL)
    SSL设置验证(SSL、SSL验证对等方、SSL验证失败,如果没有对等方证书,0)
    SSL_重新协商(SSL)
    SSL_do_握手(SSL)
    ssl->state=ssl\u ST\u ACCEPT
    SSL_do_握手(SSL)

  • 但是重新协商没有成功,并从第一次SSL\u do\u handshake()调用返回一个Openssl内部错误。我甚至不确定这是否真的能做到。我能想到的另一个解决方案是:

  • 以某种方式将该客户端的整个SSL上下文从P1传输到C1。这项工作的效率如何?我可以为此想到共享内存,但并不确定OpenSSL维护的所有内部状态都需要复制到共享内存中。 这似乎是最符合逻辑的解决方案,但我对OpenSSL代码了解不多 有人遇到过类似的问题并解决了吗? 我真的非常感谢任何关于这方面的帮助


    非常感谢

    在线搜索可找到以下讨论:

    一旦有了SSL_会话,就将其转换为ASN1(通过i2d_SSL_会话),并将其转储到文件中。用第二个程序读入该文件,并将其从ASN1转换回SSL_会话(通过d2i_SSL_会话),然后将其添加到SSL_CTX的SSL_会话缓存(通过SSL_CTX_添加_会话)

    我在doc/ssleay.txt中找到:
    […]
    PEM_写SSL_会话(fp,x)和PEM_读SSL_会话(fp,x,cb)将 以base64编码写入文件指针。 你能做的就是在不同的服务器之间传递会话信息 过程
    [……]

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

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

    该页面在lwn.net上标题为“”。下面是关于它的有趣讨论。希望它能进入内核主线。或者希望有人能拿出一个生产质量的补丁集,让人们能够真正利用它

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


    更新:是专门为将上下文导出到另一个进程而设计的

    谢谢你的指点。我这样做了,但C1无法在恢复会话时发送数据。P1执行SSL_accept()、SSL_get_session()、i2d_SSL_session(),然后执行分叉C1。C1按顺序执行SSL_new()、SSL_set_fd()、d2i_SSL_SESSION()、SSL_CTX_add_SESSION()、SSL_set_SESSION()、SSL_set_accept_state()、SSL_write()。但数据并没有从系统中流出。我还遗漏了什么吗?OpenSSL是否报告了任何错误,特别是在
    SSL\u write()
    上?SSL\u write()不会报告任何错误。还有什么其他可能性?您确定底层套接字没有缓冲传出数据吗?您实际发送的是什么类型的数据?如何监控数据没有离开系统?我发送了一些约12字节长的协议数据。底层套接字没有缓冲(禁用了naggle算法)。我使用tcpdump在系统上捕获数据包,在系统中,只要数据包交换发生在P1的上下文中,所有数据包交换都会正常进行,但在C1中没有。我等了很久才证实这一点。我还在openssl手册页中读到,SSL_set_会话仅对SSL客户端有用。如果是这样,那么SSL服务器如何从会话缓存重用会话?我不确定我的API调用是否正确。你有这个问题的解决方案吗?如果有,请告诉我解决方案。这是一个安全工程师梦寐以求的事情。让我想起了Windows内核中的一些渲染字体,我想知道是否存在其他在进程之间传递TLS连接的方法。可能是一个活动的fd,通过它,进程可以成为管道中的一个阶段?共享内存似乎是显而易见的选择共享内存可以是数据部分。一个职业选手的扳机怎么样