您的位置:首页 - 教程 - IIS服务器 - 正文
IIS8支持SNI(Server Name Indication)
SNI(Server Name Indication)

用来解决一个服务器拥有多个域名的情况

之前的 SSL 握手信息中并没有携带客户端要访问的目标地址。这样会导致一个问题,如果一台服务器有多个虚拟主机,且每个主机的域名不一样,使用了不一样的证书,该返回哪一个给客户端?

做法就是在 Client Hello 中补上 Host 信息,SNI 在 TLSv1.2 开始得到协议的支持,当然还需要服务端和客户端都支持。

比如抓的一个 Client Hello 包中有这样的信息:

Extension: server_name
Type: server_name (0x0000)
Length: 16
Server Name Indication extension
Server Name list length: 14
Server Name Type: host_name (0)
Server Name length: 11
Server Name: hewnqi.com


这个扩展信息就指定了该 SSL 握手信息的目标域名为 hewenqi.com 。

有了它,拥有多域名的服务器就不用再迷茫了。

从 OpenSSL 0.9.8 版本开始支持。

IIS 7 是不支持 SNI的,升级到IIS 8 才可以

Server Name Indication(SNI)
SNI (Server Name Indication)是用来改善服务器与客户端 SSL (Secure Socket Layer)和 TLS (Transport Layer Security) 的一个扩展。主要解决一台服务器只能使用一个证书(一个域名)的缺点,随着服务器对虚拟主机的支持,一个服务器上可以为多个域名提供服务,因此SNI必须得到支持才能满足需求。

SNI产生背景
SSL以及TLS(SSL的升级版)为客户端与服务器端进行安全连接提供了条件。但是,由于当时技术限制,SSL初期的设计顺应经典的公钥基础设施 PKI(Public Key Infrastructure)设计,PKI 认为一个服务器只为一个域名提供服务,从而一个服务器上也就只能使用一个证书。这样客户端在发送请求的时候,利用DNS域名解析,只要向解析到的IP地址(服务器地址)发送请求,然后服务器将自身唯一的证书返回回来,交给客户端验证,验证通过,则继续进行后续通信。然后通过协商好的加密通道,获得所需要的内容。这意味着服务器可以在 SSL 的启动动阶段发送或提交证书,因为它知道它在为哪个特定的域名服务。

随着HTTP 服务器开启虚拟主机支持后,每个服务器通过相同的IP地址可以为很多域名提供服务。这种为虚拟主机提供通信安全的简单途径,却经常导致使用了错误的数字证书,因为服务器端无法知道客户端到底请求的是哪个域名下的服务,从而导致浏览器对用户发出警告。

不幸的是,当设置了 SSL加密,服务器在读取HTTP请求里面的域名之前已经向客户端提交了证书,也就是已经为默认域提供了服务。但是,一个服务器可能为上千个域名提供服务,不可能将所有证书都发送给客户端,让客户端一一验证,找到与请求域名对应的证书。SNI的设计目的是为了让服务器根据请求来决定为哪个域服务,这个信息通常从HTTP请求头获得。


Server Name Indication是用来改善SSL(Secure Socket Layer)和TLS(Transport Layer Security)的一项特性。它允许客户端在服务器端向其发送证书之前请求服务器的域名。这对于在虚拟主机模式使用TLS是必要的。

TLS背景

加密一个面向流的通讯会话最常用的方法之一就是使用TLS协议。比如,当用户在浏览器的地址栏里面输入https时就是在使用这个协议。

为了确认用户想要连接的站点就是浏览器实际连接到的站点,TLS使用包含站点域名的数字签名证书。客户端软件(比如浏览器)通常信任这个证书,如果这个证书是由其内置信任的认证机构签发的。
在TLS启动阶段,客户端软件比较用户输入的URI的域名部分与在服务器证书里面找到的域名部分,如果比较失败,浏览器会提示用户,这个站点的证书存在问题。

缺点

SSL v2的设计顺应经典的公钥基础设施PKI(public key infrastructure)设计,后者认为一个服务器只提供一个服务从而也就只使用一个证书。这意味着服务器可以在TLS启动的早期阶段发送或提交证书,因为它知道它在为哪个域服务。

HTTP服务器开启虚拟主机支持后,每个服务器通过相同的地址可以为很多域提供服务。服务器检查每一个请求来决定它在为哪个域服务。这个信息通常从HTTP请求头获得。不幸的是,当设置了TLS加密,服务器在读取HTTP请求里面的域名之前已经向客户端提交了证书,也就是已经为默认域提供了服务。

因此,这种为虚拟主机提供安全的简单途径经常导致使用了错误的数字证书,从而导致浏览器对用户发出警告。

钓鱼连接

实际上,这意味着每一个HTTP服务器只能为一个域提供安全浏览。而事实上每一个web服务器都为很多域提供服务,结果就是其他的域无法使用安全通信,从而处于危险境地。此外,安全浏览的缺乏使浏览器无法认证服务器,亦即它无法校验站点是否真的是属于宣称它的那个人或实体。钓鱼的一个重要因素是他们企图通过虚假站点来获取用户的信息。使用SSL或者TLS安全连接,浏览器可以基于它的证书来认证站点。钓鱼站点不会作为一个欺骗性的站点得到认证,浏览器会警告这个安全风险。然而,没有安全HTTP就没有标准的方法去认证服务器,使这种钓鱼的企图很容易就能实现。

修正

一个叫做SNI的TLS扩展通过发送虚拟域的名字做为TSL协商的一部分修正了这个问题。这会使服务器更早的切换到正确的虚拟域,并且发送给浏览器包含正确名字的数字证书。

行动

在2005年,人们意识到从SSL v2到TLS没有很容易的升级路径,并且站点不得不升级他们的软件来。为了尽快的推进,Mozilla宣告完全抛弃对SSL v2的支持。Firefox社区确信其余的站点会升级他们的服务器到SSL v3或TLS v1。

从2005年开始,CAcert在虚拟服务器上用不同的方法使用TLS来进行试验,大部分试验是不满意并且不实际的。比如,可以使用subjectAltName在一个数字证书中包含多个域,但是这是一个证书,意味着所有的域必须被一个人拥有并控制,并且每次域列表发生变化,证书必须重新发放。

2004年,EdelKey project为OpenSSL里面的TLS/SNI开发了一个补丁。2006年这个补丁进入OpenSSL的开发分支,2007年,它被向后移植到了OpenSSL 0.9.8,也就是当前的发行版本。

支持状况

支持SNI的浏览器

* Mozilla Firefox 2.0 or later
* Opera 8.0 or later (the TLS 1.1 protocol must be enabled)
* Internet Explorer 7 or later on Windows Vista or higher
* Google Chrome (Vista, not XP)
* Safari 3.2.1 Mac OS X 10.5.6

支持SNI的服务器

* Apache 2.2.12 or later using mod_ssl (or alternatively with experimental mod_gnutls)
* Cherokee if compiled with TLS support
* Versions of lighttpd 1.4.x and 1.5.x with patch
* Nginx with an accompanying OpenSSL built with SNI support
* acWEB with OpenSSL 0.9.8j and later (on Windows)

支持SNI的库

* Mozilla NSS 3.11.1 client side only
* OpenSSL
0.9.8f (released 11 Oct 2007) – not compiled in by default, can be compiled in with config option ‘–enable-tlsext’.
0.9.8j (released 07 Jan 2009) – now compiled in by default
Unreleased 0.9.9 is likely to include SNI compiled in by default.
* GNU TLS

不支持SNI的操作系统,浏览器和库

客户端

* Internet Explorer 6 or earlier and any IE version on Windows XP , windows 2003 or earlier
* Konqueror/KDE in any version

服务器端

* Microsoft Internet Information Server IIS (As of 2009).
* Apache Tomcat 8 or earlier



* Qt
* Mozilla NSS server side
* Python

windows和IE

可以看得出,windows XP和windows 2003 server系统上的任何IE版本浏览器都是不支持SNI的, vista及以后系统上的IE 7及更高版本的IE浏览器支持SNI。IE6及更早版本的IE浏览器在任何系统上都是不支持SNI的。

tomcat

tomcat当前的稳定版8尚不支持SNI,tomcat 9才会支持,以后可能会backport到tomcat 8和7。可以使用nginx反向https代理后端的tomcat,参见[2]

SNI测试

用浏览器或其他https客户端比如wget等访问SNI测试站点即可以知道浏览器或客户端是否支持SNI。

评论: