线上业务遇到了一个奇怪的事情,服务访问https域名有问题,日志里报错大量的connection reset 。之前一直都好着啊,怎么突然就报这个错。浏览器访问了一下https的网站发现没问题啊。怎么java服务访问就有问题了。
报错日志
抓包
遇到这种网络上的问题,就不要猜了,先tcpdump一下,再wireshark分析下吧。
抓到的网络包如下:
wireshark抓包
分析tcp stream 发现,emmm,为什么只发了一个client hello 就给我reset了。这是什么操作?让我们来看一下我的打招呼的方式有问题吗?
tls client hello阶段
点开,似乎没啥问题啊,这里是TLS 1.0。反正问题已经定位了,首先这是服务端问题,不是我客户端问题。因为我就发了一个client hello,服务端就reset我。这明显不是我客户端的锅啊,而且问题还是再TLS握手阶段出的问题。因为连 TLS 过程都还没有建立好呢。
好吧,问题是服务端,而且是nginx这块,因为TLS的加解密是nginx这块在做的。
分析
难道是nginx的配置没写支持TLS 1.0 。因为前段时间对nginx做了一次迁移,但似乎我也没改域名的配置啊。看看配置。
nginx ssl 配置
对啊。server 块中 ssl_protocols TLSv1 ,这不就是TLS1.0 么。怎么回事。。。
算了,那就nginx这块再抓包吧。。。在nginx这块抓包发现,数据包是TLS1.0 全部被reset了。好吧,应该就是nginx这块不支持TLS1.0 的问题。但是我配置文件明明是写的支持啊???
杀手锏
看来要第三方分析一下该域名了。
https://www.ssllabs.com/ssltest
用ssl test 测试一下 我们这个网站支持什么样的客户端。
这里是我已经更正nginx后的截图,源截图是TLS 1.0 显示的是No
好吧,果然不支持。靠~ 那就是nginx不支持 TLS1.0 的事实铁定了。
回到问题源点,nginx到底是出了什么问题?最后想到了http块。
问题解决
原来是http块也配置了 ssl_protocols TLSv1.1 TLSv1.2; 单单忘了TLSv1 。这导致了 http块 覆盖了 server 块的内容,所以TLS1 nginx不支持。导致的reset。
使用opensll 测试一下:
$ openssl s_client --connect xxx.xxx.mi.com:443 -showcerts -tls1
CONNECTED(00000003)
depth=2 C = US, ST = Arizona, L = Scottsdale, O = "GoDaddy.com, Inc.", CN = Go Daddy Root Certificate Authority - G2
verify return:1
depth=1 C = US, ST = Arizona, L = Scottsdale, O = "GoDaddy.com, Inc.", OU = http://certs.godaddy.com/repository/, CN = Go Daddy Secure Certificate Authority - G2
verify return:1
.....
通了。。。
网友评论