如何实现服务器名称指示 (SNI)
Posted
技术标签:
【中文标题】如何实现服务器名称指示 (SNI)【英文标题】:How to implement Server Name Indication (SNI) 【发布时间】:2011-07-04 01:20:06 【问题描述】:如何用 C 或 C++ 在 OpenSSL 上实现服务器名称指示(SNI)?
是否有任何现实世界的示例可用?
【问题讨论】:
另请参阅Serving multiple domains in one box with SNI 获取一些代码示例并使用s_client
测试您的服务器。
【参考方案1】:
在客户端,您在启动 SSL 连接之前使用SSL_set_tlsext_host_name(ssl, servername)
。
在服务器端,稍微复杂一点:
为每个不同的证书设置一个额外的SSL_CTX()
;
使用SSL_CTX_set_tlsext_servername_callback()
为每个SSL_CTX()
添加服务器名称回调;
在回调中,使用SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name)
检索客户端提供的服务器名称。找出正确的SSL_CTX
与该主机名一起使用,然后将SSL
对象切换到SSL_CTX
和SSL_set_SSL_CTX()
。
OpenSSL 源代码分发的apps/
目录中的s_client.c
和s_server.c
文件实现了此功能,因此它们是一个很好的资源来了解它应该如何完成。
【讨论】:
s_client.c 和 s_server.c 就是很好的例子。我正在尝试在充当负载生成器(网络)并使用 http/https 请求锤击服务器的客户端上实现 SNI。并且服务器已经实现了服务器端 SNI。 服务器调用在多线程上下文中是否成立?似乎 SSL_set_SSL_CTX 天生就不是线程安全的(即,如果您有两个不同的入站连接和两个不同的证书,您就会遇到问题)。 @chacham15:使其成为线程安全的一种方法是为每个证书、每个线程分配一个SSL_CTX()
(并且始终处理来自同一线程的相同SSL
和SSL_CTX
对象) .另一种方法是使用CRYPTO_set_id_callback()
和CRYPTO_set_locking_callback()
设置线程回调,在这种情况下,OpenSSL 将正确调用锁定回调以使SSL_set_SSL_CTX()
线程安全。
这是一篇非常好的高级文章,谢谢! jww 用another answer 中的代码示例准确地说明了这种方法。你们中的一个或两个可以用 cmets 中提出的关于多线程的问题来扩充这些答案吗?例如,SSL_set_SSL_CTX
天生就不是线程安全的?它似乎只影响第一个参数中指定的 SSL 连接。
你知道如何在服务器上使用 boost::asio 作为套接字实现 SNI 支持吗?我找不到任何示例。我也看不到如何添加多个 ssl 上下文,因为 ssl 套接字在构造函数中获取上下文以上是关于如何实现服务器名称指示 (SNI)的主要内容,如果未能解决你的问题,请参考以下文章
从 TLS 客户端 hello 中提取服务器名称指示 (SNI)