SSL握手中win xp和SNI的那点事

一、背景需求
server1-3使用不同的域名对外提供https服务,用nginx作为前端负载均衡器并负责https集中解密工作(以用户访问的域名为依据进行流量分配,同样的也是以域名为依据来判断应该将哪张证书丢给用户。即:SNI(Server Name Identification)功能),用户为WIN XP和WIN 7(都使用IE8浏览器)。

1 [root@localhost ~]$ nginx -V
2 nginx version: nginx/1.14.2
3 built by gcc 4.8.5 20150623 (Red Hat 4.8.5-28) (GCC) 
4 built with OpenSSL 1.0.2k-fips  26 Jan 2017
5 TLS SNI support enabled        ===> 查看SNI状态

二、工作原理
1、用户(WIN XP、WIN 7)通过DNS解析获知"a.test.com"、"b.test.com"、"c.test.com"三个域名对应的IP都为"192.168.178.154"
2、用户(WIN XP、WIN 7)与"192.168.178.154"进行SSL握手,获取相应域名证书后再次向"192.168.178.154"发起真正的http(已加密)请求
3、"192.168.178.154"收到加密后的http请求后先进行解密,然后再根据相应的策略向后端服务器server1-3发起http请求(未加密)
4、后端服务器server1-3进行处理后将回应的包发送给nginx,nginx将该数据进行加密后再次封装然后发送给用户

三、出现的问题:
就在大家都觉得这个逻辑十分顺畅的时候问题来了,我们发现WIN XP用户使用IE浏览器不能正常访问,其他系统均可以正常访问

四、排障:
1、WIN XP访问同样域名的80端口是否正常? 结果:正常。 说明问题出在SSL握手上了
2、将WIN XP和WIN 7访问443端口的流量进行抓包分析(可以看到WIN7的SSL握手成功,而WINXP第一次使用TLSv1握手失败,然后自动换用SSLv3进行握手,但依然失败)

3、为什么WIN7发hello的时候的nginx就会回应hello,而WINXP发hello时nginx就会回Alert呢? 我们来展开WIN7和WINXP的hello包来仔细看下。(可以看到WIN7的hello包中携带了Extension:server_name字段,并且里面包含了要访问的域名信息。而反观WINXP则没有该字段)

4、那WINXP换用其他浏览器能不能解决这个问题呢?(换用搜狗浏览器试下,结果发现可以访问了。抓包发现搜狗浏览器在发送SSL的hello包时会携带Extension:server_name字段,并且还附带了一大堆其他参数)

五、总结:

WINXP在使用IE访问https网站时,对方服务器不能使用SNI方式进行分流,不然会因为不能建立SSL握手而访问失败

附:解决方案

1、WINXP换用其他浏览器(对于公网服务不现实)

2、服务端通过IP地址颁发证书(WINXP虽不携带访问的域名信息,但它总有三层包头吧!)(推荐)

3、服务端全站只用一张大通配证书,无论用户访问哪个域名都将该证书丢给它(不推荐)

原文地址:https://www.cnblogs.com/guanshan/p/guan2019-8-28_001.html