某一天,我在使用 docker 的时候遇到个奇怪的问题,在容器里面发起 https 请求报了个错。
经过测试发现在容器里面发起的所有 https 请求都报错,即使是 curl 发起 https 请求也报错。
而 http 请求却能正常发起请求。
curl测试结果如下
1 | curl https://www.qq.com |
从测试结果大致可以看出是证书的问题。
经过一系列 google 查询、chatgpt咨询、线下咨询运维大佬等都没能找到问题的正确原因。
只知道是证书问题,因此尝试过很多办法。
比如在 docker 打包的时候找一个正确的根证书(网上下载)打包进去
比如在打包的时候在基础镜像中执行安装根证书包的命令等等。
然而,都没有解决
。
神奇的自愈与whistle代理
由于折腾了各种办法都解决不了,于是就暂时放弃下班了。
只是思来想去还是不甘心,于是第二天早上一大早到公司之后又进入容器里面去折腾了下。
此时,神奇的事情发生了,当我在容器里面习惯性 curl https://www.qq.com
的时候发现竟然通了。
仔仔细细回想了下,没做啥特殊操作,也没改代码,当时就给我震惊了。
然后,和前一天一样,又查了很久,同样的也没找到它恢复的原因。
直到下午,开发另一个需求的时候为了方便调试,我执行了 w2 proxy
,对接口请求做了代理。
由于那个 https 请求的奇怪问题一直困扰着,于是在做需求的间隙又习惯性回来测试,竟然发现容器里面又不能发起 https 请求了。
因为以前因为设置代理遇到过类似的相关网络问题,于是,大胆怀疑,就是这个代理导致的。
后经过一番代理的打开和关闭测试与验证。石锤了就是因为开了 whistle 代理才导致在容器内部发起不了 https 的
。
那么 whistle 是如何影响到容器的 https 请求的呢?
验证过程,curl 输出请求的证书链
1 | curl -v -s -o /dev/null https://www.qq.com |
curl -vvvv 是 curl 命令的一个选项,用于启用最高级别的详细输出。
每个 v 代表一个级别的详细程度,因此 -vvvv 表示启用四个级别的详细输出。
curl -vvvv 会输出包括请求和响应的各种详细信息,如请求头、响应头、TLS 握手信息等。
上图圈选部分的信息就是关键错误信息。
将其交给 chatgpt 分析一下:
从上面的回答只能看出是证书的问题,但是具体怎么解决却没有办法。
也无法知晓 whistle 代理具体是如何导致错误的。
验证过程,输出详细的证书链信息
根据现象找原因还是有很多办法的,openssl 命令可以很方便的查到证书链信息。
1 | openssl s_client -connect www.qq.com:443 |
openssl s_client -connect 是一个 OpenSSL 命令。
该命令用于建立与指定主机和端口的 SSL/TLS 连接,并提供与链接相关的详细信息。
可以用来验证服务器端证书链的完整性、确认所使用的协议和加密套件、检查证书的有效期等。
该命令执行以下操作:
1 | 建立 SSL/TLS 连接:通过指定主机和端口,openssl s_client 命令会尝试与该主机建立 SSL/TLS 连接。 |
从上图可以很清楚的看到 whistle 的证书成为了 https 请求证书链的一个环节。
而由于他的证书并不是正规的官方系统信任的证书,因此出现上面的问题也就不奇怪了。