如何实现服务器名称指示 (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_CTXSSL_set_SSL_CTX()

OpenSSL 源代码分发的apps/ 目录中的s_client.cs_server.c 文件实现了此功能,因此它们是一个很好的资源来了解它应该如何完成。

【讨论】:

s_client.c 和 s_server.c 就是很好的例子。我正在尝试在充当负载生成器(网络)并使用 http/https 请求锤击服务器的客户端上实现 SNI。并且服务器已经实现了服务器端 SNI。 服务器调用在多线程上下文中是否成立?似乎 SSL_set_SSL_CTX 天生就不是线程安全的(即,如果您有两个不同的入站连接和两个不同的证书,您就会遇到问题)。 @chacham15:使其成为线程安全的一种方法是为每个证书、每个线程分配一个SSL_CTX()(并且始终处理来自同一线程的相同SSLSSL_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)

SNI协议分析

服务器名称指示(SNI)是什么东东?

使用 SNI 通过 HTTPS 提供服务时出现 CloudFront 错误

IIS 8.5 上的 SNI 和 SSL

在 AFNetworking 中支持 SNI