本文详细阐述了Server Name Indication(SNI)的概念、产生背景、兼容性、以及检验是否支持SNI的方法。

什么是SNI

SNI是为了解决一个服务器使用多个域名和证书的Secure Socket Layer(SSL)/Transport Layer Security(TLS)的一个扩展。它允许服务器在同一IP地址和TCP端口数下支持多张证书,从而允许多个HTTPS网站,或其他服务在TLS的网站,被同一个IP地址而不需要所有的网站使用相同的证书。

SNI产生背景

SSL初期设计是一台服务器只能为一个域名服务。当客户端访问站点时,利用DNS域名解析,向解析到的IP地址(服务器地址)发送请求服务器的证书,然后服务器将自身唯一的证书返回回来,交给客户端验证。通过验证后,按照协商好的加密通道,进行后续通信。这意味着服务器可以在SSL的启动动阶段发送或提交证书。

但随着服务器支持虚拟主机的出现,一台服务器要为多个域名提供服务。继续沿用之前的工作原理,会经常导致服务器端无法知道与客户端所请求域名对应的证书,从而使用错误的数字证书,导致浏览器对用户发出警告。

SNI的设计目的是为了让服务器根据请求来决定为哪个域服务,这个信息通常从HTTP请求头获得。

SNI应用场景

当服务器解析到同一个IP(如:192.168.10.3)下的多个域名(如:domain1.com、domain2.com)在使用默认端口时,你可以安装不同的SSL证书。否则,服务端不能针对不同的域名安装不同的SSL证书。

注意:针对无法支持SNI的服务器,我们推荐安装多域名SSL证书通配符SSL证书

SNI的兼容性

SNI兼容TLS 1.0及以上协议,但不兼容SSL。具体支持清单如下所示:

SOFTWARETYPESUPPORTEDNOTESSUPPORTED SINCE
Internet ExplorerWeb browserYesSince version 7 on Vista (not supported on XP)2006
Mozilla FirefoxWeb browserYesSince version 2.02006
cURLCommand-line tool and libraryYesSince version 7.18.12008
SafariWeb browserYesNot supported on Windows XP
Google ChromeWeb browserYesSince 6.0[7]2010
BlackBerry 10Web browserYesSupported in all BB10 releases2013
BlackBerry OSWeb browserNoNot supported in 7.1 or earlier
elinksWeb browserNoNot supported in 0.12pre6 or earlier
Windows MobileWeb browserYesSome time after 6.5
Android default browserWeb browserYesHoneycomb (3.x) for tablets and Ice Cream Sandwich (4.x) for phones2011
Firefox for AndroidWeb browserPartialSupported for browsing, Sync and other services don't support SNI[8][9]
wgetCommand-line toolYesSince version 1.142012
Nokia Browser for SymbianWeb browserNo

Opera Mobile for SymbianWeb browserNoNot supported on Series60
IBM HTTP ServerWeb serverYesSince version 9.0.0[10][11]
Apache TomcatWeb serverYesNot supported before 8.5 (backport from 9)
Apache HTTP ServerWeb serverYesSince version 2.2.122009
Microsoft IISWeb serverYesSince version 82012
nginxWeb serverYesSince version 0.5.232007
JettyWeb serverYesSince version 9.3.02015
QtLibraryYesSince version 4.82011
Mozilla NSS server sideLibraryNo[12]
4th DimensionLibraryNoNot supported in 15.2 or earlier
JavaLibraryYesSince version 1.72011
ColdFusion / LuceeLibraryYesColdFusion since Version 10 Update 18, 11 Update 7, Lucee since Version 4.5.1.019, Version 5.0.0.502015
ErlangLibraryYesSince version r172013
GoLibraryYesSince version 1.42011
PerlLibraryYesSince Net::SSLeay version 1.50 and IO::Socket::SSL version 1.562012
PHPLibraryYesSince version 5.32014
PythonLibraryYesSupported in 2.x from 2.7.9 and 3.x from 3.2 (in sslurllib[2]and httplib modules)2011 for Python 3.x and 2014 for Python 2.x
RubyLibraryYesSince version 2.0 (in net/http)2011

如何检验是否支持SNI

通过工具(如: Client Hello )抓取SSL握手协议过程中的报文,如果在Client Hello抓取的报文显示SNI扩展内容,表示此客户端支持SNI。这里以Google Chrome浏览器访问Gworg的SSL握手过程为例:
006tNc79gy1fow6errznlj30o10fd404.jpg

注意:对于不支持SNI的客户端,选择以下任一方法并再次检验:

  • 升级或使用新版本的浏览器(如: Chrome、Firefox等)。

  • 如果是微信、支付宝第三方回调,需要让其调用源站IP。