记录一次的https网络协议握手失败的原因

本文正在参与 “网络协议必知必会”征文活动

问题描述

今天遇到一个报错:

http: TLS handshake error from *

整个时间的经过是这样的:今天先以容器的形式在测试环境部署了一个云服务,测试后没有问题。然后,以相同的方式在公网上也部署了一个服务却出现了问题,导致 https 网络协议握手失败。

具体报错信息如下:

2021/11/09 07:15:58 http: TLS handshake error from 125.64.94.138:34428: remote error: tls: bad certificate
2021/11/09 07:15:58 http: TLS handshake error from 125.64.94.138:41490: EOF
2021/11/09 07:15:58 http: TLS handshake error from 125.64.94.138:42006: read tcp 172.17.0.79:9443->125.64.94.138:35318: read: connection reset by peer
2021/11/09 15:51:50 http: TLS handshake error from 165.227.163.245:38494: EOF

通过上述报错信息,我们可以大致猜测是证书原因导致的握手失败,但是具体原因还不是很清楚,至少也为我们提供了一个分析和思考的方向。

进一步分析报错日志可以发现握手过程中,IP 地址为 125.64.94.138 的机器不断尝试切换其他端口,但是每次都被重置连接,最终导致 https 连接失败。

解决方法

网上搜索了很多资料,但是介绍的方法都没有解决上面的问题,后来在梳理整体流程的时候发现了一个原因。因为容器服务本身对 http 协议和 https 协议都是支持的,有一层 https 证书,在测试环境中没有问题,但是公网环境中所有服务访问的入口都要经过 Nginx 代理服务转发请求,而 Nginx 服务本身又设置了一层 https 证书,很可能是二层证书不一致导致了错误的发生。

如果真是这样的话,那解决这个问题就有两种方案,一是仅使用一层 https 证书;二是把两层证书统一,使用相同的数字签名证书。

总结思考

有时候,很多问题在自测的时候没有发现,是因为没有放到具体的生产环境中去,因此,开发过程中一定要考虑到未来部署后可能出现的问题,在编码时就尽量规避。