OpenSSL 是否允许每个进程使用多个 SSL_CTX,一个用于服务器会话的 SSL_CTX ...
是的,而且这种情况很常见。使用服务器名称指示时很常见。对于 SNI,您有一个默认值SSL_CTX
然后一个SSL_CTX
对于每个服务器。然后返回默认值SSL_CTX
或专门的SSL_CTX
在 SNI 回调中if客户端将服务器名称扩展包含在其ClientHello
.
SSL_CTX
被库引用计数,因此只有在其中一个引用计数降至 0 时,它们才真正被释放。SSL_CTX_free
calls.
以下是一些关于 SNI 的相关问题,有兴趣的话:
- 使用 SNI 在一个盒子中为多个域提供服务
- 如何实现服务器名称指示(SNI)
- SSL_CTX_set_tlsext_servername_callback 回调函数未被调用
第一个甚至为您提供了回调代码。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);
OpenSSL 是否允许每个进程使用多个 SSL_CTX,...其他 SSL_CTX 用于客户端会话?
是的,但你通常不会使用它。客户确实not通常改变它的SSL_CTX
就像服务器一样。
在客户端连接到多个服务器的情况下,通常您可以使用以下命令设置通道参数SSL_CTX_set_options并将其用于与每个服务器(甚至不同的服务器)的每个连接。参数可以是协议(TLS 1.1、TLS 1.2)、密码套件(删除匿名密码套件)和压缩等内容。请参阅下面的讨论SSL/TLS 客户端更多细节。
客户端确实需要设置服务器的主机名,但这是在服务器上完成的SSL*
using SSL_set_tlsext_host_name
,而不是SSL_CTX*
.
或者,如果您正在使用BIO
的,它看起来像这样。注意BIO
有效地包裹了一个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();
...一个使用服务器方法调用,另一个使用客户端方法调用
不需要。它们之间唯一的区别(比如SSLv23_client_method
and SSLv23_server_method
),是几个函数指针,例如connect
and accept
在看不见的结构中。客户来电connect
和服务器调用accept
.
相反,只需使用通用的SSLv23_method
一切都会好起来的。你仍然需要调整上下文SSL_CTX_set_options因为默认上下文由SSL_CTX_new
包括弱/受伤/损坏的协议和密码。
OpenSSL 的 wiki 页面SSL/TLS 客户端向您展示如何调整SSL_CTX
目的。它执行以下操作,并且可由客户端和服务器使用:
- 禁用 SSLv2
- 禁用 SSLv3
- 禁用压缩
- 禁用匿名协议
- 使用“强”密码
使用自定义密码列表,例如"HIGH: ... : !SRP:!PSK"
删除许多弱/受伤的密码,并删除一堆服务器可能不支持的密码套件(因此客户端没有理由宣传它们)。 SRP 是 Thomas Wu 的安全远程密码,PSK 是预共享密钥。IANA 保留 87 个密码套件基于它们,因此节省了近 180 个字节ClientHello
.
是否支持在单个进程中双重使用 OpenSSL?
Yes.
我希望 OpenSSL 使用 SSL_CTX 句柄 - 并且不依赖全局或静态局部变量
好吧,你运气不太好。全局变量有很多,有些是动态分配的,有些是没有释放的。
如果您使用 Java 或 C# 工作,则每次加载/卸载共享对象时它们都会泄漏。因此,随着时间的推移,您的 Java 或 C# 程序会积累越来越多的内存。 OpenSSL 开发人员觉得它不值得他们花时间。例如,参见多线程服务器上的小内存泄漏在 OpenSSL 邮件列表中。