服务器名称指示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请求头获得。

SNI应用场景

当服务器上多个域名解析到同一IP且使用同一HTTPS端口时,若服务端支持SNI则可为不同域名安装不同SSL证书。否则服务端不能针对不同域名安装不同证书。对于不支持SNI的服务器推荐购买多域名SSL证书或通配符SSL证书。

SNI兼容性

说明 SNI兼容TLS1.0及以上协议,但不被SSL支持。

  • SNI支持以下桌面版浏览器
    • Chrome 5及以上版本
    • Firefox 2及以上版本
    • IE 7及以上版本(运行在Windows Vista/Server 2008及以上版本系统中,在XP系统中任何版本的IE浏览器都不支持SNI)
    • Opera 8及以上版本
    • Safari 3.0 on Windows Vista/Server 2008及以上版本,Mac OS X 10.5.6 及以上版本
  • SNI支持以下
    • GNU TLS
    • Java 7及以上版本,仅作为客户端
    • HTTP client 4.3.2及以上版本
    • libcurl 7.18.1及以上版本
    • NSS 3.1.1及以上版本
    • OpenSSL 0.9.8j及以上版本
    • OpenSSL 0.9.8f及以上版本,需配置flag
    • Qt 4.8及以上版本
    • Python3、Python 2.7.9及以上版本
  • SNI支持以下手机端浏览器
    • Android Browser on 3.0 Honeycomb及以上版本
    • iOS Safari on iOS 4及以上版本
    • Windows Phone 7及以上版本
  • SNI支持以下服务器
    • Apache 2.2.12及以上版本
    • Apache Traffic Server 3.2.0及以上版本
    • HAProxy 1.5及以上版本
    • IIS 8.0及以上版本
    • lighttpd 1.4.24及以上版本
    • LiteSpeed 4.1及以上版本
    • nginx 0.5.32及以上版本
  • SNI 支持以下命令行
    • cURL 7.18.1及以上版本
    • wget 1.14及以上版本