本文详细阐述了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。具体支持清单如下所示:
Software | Type | Supported | Notes | Supported since |
---|---|---|---|---|
Internet Explorer | Web browser | Yes | Since version 7 on Vista (not supported on XP) | 2006 |
Mozilla Firefox | Web browser | Yes | Since version 2.0 | 2006 |
cURL | Command-line tool and library | Yes | Since version 7.18.1 | 2008 |
Safari | Web browser | Yes | Not supported on Windows XP | |
Google Chrome | Web browser | Yes | Since 6.0[7] | 2010 |
BlackBerry 10 | Web browser | Yes | Supported in all BB10 releases | 2013 |
BlackBerry OS | Web browser | No | Not supported in 7.1 or earlier | |
elinks | Web browser | No | Not supported in 0.12pre6 or earlier | |
Windows Mobile | Web browser | Yes | Some time after 6.5 | |
Android default browser | Web browser | Yes | Honeycomb (3.x) for tablets and Ice Cream Sandwich (4.x) for phones | 2011 |
Firefox for Android | Web browser | Partial | Supported for browsing, Sync and other services don't support SNI[8][9] | |
wget | Command-line tool | Yes | Since version 1.14 | 2012 |
Nokia Browser for Symbian | Web browser | No | ||
Opera Mobile for Symbian | Web browser | No | Not supported on Series60 | |
IBM HTTP Server | Web server | Yes | Since version 9.0.0[10][11] | |
Apache Tomcat | Web server | Yes | Not supported before 8.5 (backport from 9) | |
Apache HTTP Server | Web server | Yes | Since version 2.2.12 | 2009 |
Microsoft IIS | Web server | Yes | Since version 8 | 2012 |
nginx | Web server | Yes | Since version 0.5.23 | 2007 |
Jetty | Web server | Yes | Since version 9.3.0 | 2015 |
Qt | Library | Yes | Since version 4.8 | 2011 |
Mozilla NSS server side | Library | No | [12] | |
4th Dimension | Library | No | Not supported in 15.2 or earlier | |
Java | Library | Yes | Since version 1.7 | 2011 |
ColdFusion / Lucee | Library | Yes | ColdFusion since Version 10 Update 18, 11 Update 7, Lucee since Version 4.5.1.019, Version 5.0.0.50 | 2015 |
Erlang | Library | Yes | Since version r17 | 2013 |
Go | Library | Yes | Since version 1.4 | 2011 |
Perl | Library | Yes | Since Net::SSLeay version 1.50 and IO::Socket::SSL version 1.56 |
2012 |
PHP | Library | Yes | Since version 5.3 | 2014 |
Python | Library | Yes | Supported in 2.x from 2.7.9 and 3.x from 3.2 (in ssl , urllib[2] and httplib modules) |
2011 for Python 3.x and 2014 for Python 2.x |
Ruby | Library | Yes | Since version 2.0 (in net/http ) |
2011 |
如何检验是否支持SNI
通过工具(如: Client Hello )抓取SSL握手协议过程中的报文,如果在Client Hello抓取的报文显示SNI扩展内容,表示此客户端支持SNI。这里以Google Chrome浏览器访问亚洲诚信的SSL握手过程为例:
注意:对于不支持SNI的客户端,选择以下任一方法并再次检验:
- 升级或使用新版本的浏览器(如: Chrome、Firefox等)。
- 如果是微信、支付宝第三方回调,需要让其调用源站IP。