OpenSSL是否允许每个进程多个SSL_CTX,一个SSL_CTX用于服务器会话,另一个SSL_CTX用于客户端会话?

per*_*xed 3 client openssl simultaneous server

我有一个Linux进程需要充当SSL服务器(接受和服务来自其他客户端的连接),但也需要 - 在同一个进程中 - 启动与其他SSL服务器的客户端会话.

我打算使用两个SSL_CTX_new()函数调用创建两个单独的SSL_CTX句柄,一个调用服务器方法,另一个调用客户端方法.是否支持在单个进程中双重使用OpenSSL?我希望OpenSSL使用SSL_CTX句柄 - 并且不依赖于全局或静态局部变量 - 来创建和服务新会话可能需要的所有上下文信息.这是一个很好的假设吗?

jww*_*jww 6

OpenSSL是否允许每个进程多个SSL_CTX,一个SSL_CTX用于服务器会话......

是的,这很常见.使用服务器名称指示时很常见.在SNI的情况下,您有一个默认值SSL_CTX,然后是SSL_CTX每个服务器的a.然后,如果客户端在其中包含服务器名称扩展,则返回默认值SSL_CTXSSL_CTXSNI回调中的专用.ClientHello

SSL_CTX由库引用计数,因此在其中一个SSL_CTX_free调用中引用计数降为0之前,它们不会被真正释放.

以下是关于SNI的一些相关问题,如果有兴趣:

第一个甚至为您提供回调代码.GetServerContext根据服务器名称返回新的(或现有的)上下文:

/* Need a new certificate for this domain */
SSL_CTX* ctx = GetServerContext(servername);
if(ctx == NULL) handleFailure();
...

/* Set new context */
SSL_CTX* v = SSL_set_SSL_CTX(ssl, ctx); 
Run Code Online (Sandbox Code Playgroud)

OpenSSL是否允许每个进程多个SSL_CTX,...其他SSL_CTX用于客户端会话?

是的,但你通常不使用它.客户端也没有通常会改变它SSL_CTX像服务器一样.

如果客户端连接到多个服务器,通常会设置通道参数,SSL_CTX_set_options并将其用于每个服务器的连接(甚至是不同的服务器).参数可以是协议(TLS 1.1,TLS 1.2),密码套件(删除匿名密码套件)和压缩等.有关详细信息,请参阅下面有关SSL/TLS客户端的讨论.

客户端确实需要设置服务器的主机名,但这是在SSL*使用时完成的SSL_set_tlsext_host_name,而不是SSL_CTX*.

或者,如果您使用BIO的是,它看起来像这样.注意BIO有效地包装a SSL*,所以你不是修改SSL_CTX*:

BIO* web = BIO_new_ssl_connect(ctx);
if(web == NULL) handleFailure();

res = BIO_set_conn_hostname(web, HOST_NAME ":" HOST_PORT);
if(res != 1) handleFailure();
Run Code Online (Sandbox Code Playgroud)

...一个用服务器方法调用,另一个用客户端方法调用

不需要.它们之间的唯一区别(比如SSLv23_client_methodSSLv23_server_method)是一些函数指针,用于函数connectaccept看不见的结构.客户端呼叫connect和服务器呼叫accept.

相反,只需使用通用SSLv23_method,一切都会好的.您仍然需要调整上下文,SSL_CTX_set_options因为默认上下文SSL_CTX_new包括弱/受伤/损坏的协议和密码.

OpenSSL的Wiki页面SSL/TLS Client向您展示如何调整SSL_CTX对象.它执行以下操作,客户端和服务器都可以使用它:

  • 禁用SSLv2
  • 禁用SSLv3
  • 禁用压缩
  • 禁用匿名协议
  • 使用"强"密码

使用自定义密码列表"HIGH: ... : !SRP:!PSK"可以删除许多弱/受损密码,并删除服务器可能不支持的一堆密码套件(因此客户端没有理由通告它们).SRP是Thomas Wu的安全远程密码,PSK是预共享密钥.IANA基于它们保留了87个密码套件,因此它可以节省近180个字节ClientHello.


是否支持在单个进程中双重使用OpenSSL?

是.


我希望OpenSSL使用SSL_CTX句柄 - 而不依赖于全局或静态局部变量

好吧,那里你运气不好.有很多全局变量,其中一些是动态分配的,其中一些不会被释放.

如果您使用的是Java或C#,则每次加载/卸载共享对象时都会泄露它们.因此,您的Java或C#程序会随着时间的推移积累越来越多的内存.OpenSSL开发人员并不觉得自己值得花时间.例如,请参阅OpenSSL邮件列表上多线程服务器上的小内存泄漏.


Vla*_*kov 1

根据我的经验:只要正确初始化 OpenSSL 库,您就可以自由创建多个上下文。按照 OpenSSL 手册页中所述设置线程锁后,我在同一应用程序中使用了两个不同的上下文,没有出现任何问题:http://www.openssl.org/docs/crypto/threads.html。如果您的应用程序不使用线程,则根本不需要这样的设置。