https中关于sni的问题

二维码
| Dec 23, 2018 | 原创

这又是一个历史性的问题,sni 全称:Server Name IndicationTLS/SSL协议是基于TCP协议之上,但又何HTTP协议没半点关系的协议,该协议在和服务端建立握手(handshake)的时候,需要获取服务端证书(单向验证)验证,在HTTP协议中使用了host字段定义了当前请求的具体server_name,服务端当存在多个虚拟机共享一个ip时也能区分具体要进入那一个配置项,如:

# 俩站点部署在一台机器上,共享一个IP
server {
    listen 80;
    server_name demoA.com;
    ...
}

server {
    listen 80;
    server_name demoB.com;
}

然而,TLS/SSL协议里(早期,2006年之前)却没有提供这么一个字段的来让服务器连接的时候返回正确的域名证书给客户端,对于服务端来说,不支持sni扩展的协商握手,它也是一脸懵逼的,于是它就把服务器默认的第一个站点的证书返回给客户端,但造成的影响是,有可能它给的是一个错误的证书,直接导致握手失败,凉凉了。

不过好在这之后,定义了一个扩展字段:server_name, 在TLS握手协商的时候,客户端会带上这个参数,告诉服务端具体需要的是哪一个证书(下图,绿色部分):

但这个亡羊补牢的扩展还是让早期的一部分操作系统无法支持未适配上,比如winows XP系统下的 IE6IE7IE8, 倘若你的站点还需要考虑这部分用户,那么你得评估这部分用户是否支持HTTPS了,该参数的浏览器兼容性可参考:https://caniuse.com/#search=sni