如何实现服务器名称指示(SNI)
在客户端,您在启动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_set_SSL_CTX()
将SSL
对象切换为SSL_CTX
。
的s_client.c
和s_server.c
文件在apps/
目录OpenSSL的源代码分发的实现这个功能,所以他们是一个很好的资源,看看它应该怎么做。
s_client.c和s_server.c就是很好的例子。我试图在充当负载生成器(网络)的客户端上实施SNI,并使用http/https请求来破坏服务器。而服务器已经实现了服务器端SNI。 – 2011-02-28 07:09:30
服务器调用是否保持在多线程上下文中?看起来SSL_set_SSL_CTX天生就不是线程安全的(即如果你有两个不同的入站连接和两个不同的证书,你会遇到问题)。 – chacham15 2014-05-11 18:57:22
@chacham15:让线程安全的一种方法是为每个线程分配一个SSL_CTX(),每个线程总是处理同一个线程中的SSL和SSL_CTX对象。另一种方法是用'CRYPTO_set_id_callback()'和'CRYPTO_set_locking_callback()'设置线程回调,在这种情况下,OpenSSL将对锁定回调进行正确的调用,以使'SSL_set_SSL_CTX()'线程安全。 – caf 2014-05-17 07:42:18
另请参阅[为SNI提供一个框中的多个域](http://*.com/questions/22373332/serving-multiple-domains-in-one-box-with-sni),了解一些代码示例并使用's_client'来测试你的服务器。 – jww 2014-03-13 15:48:49