在使用apisix网关部署证书后,发现部分客户端报证书验证失败的情况,ios,mac端却没有这种情况,android端出现了这种情况,同样的证书,在nginx下却没有问题。
wireshark抓包显示三次握手成功后,建立TLS连接,客户端发了client hello,服务端回复server hello已经向客户端传输了证书后,客户端直接回复并关闭了tcp连接。
出现问题的是android客户端,使用的是flutter dio库,目前还没排查出问题的根本原因,网上有说是客户端没法SNI信息,但是我这边不是,我这边抓包是带了这个信息的。这种问题多半是apisix和客户端协商出了问题,但是究竟在哪里出错的还需要进一步排查,当然,这种问题解决也不是不能解决,客户端直接信任即可,但强迫症受不了,最好是在apisix端修改。
客户端报 Handshake error unable to get local issues
已找到原因:
引起这次问题的原因是flutter网络请求库验证证书的时候缺少证书链中的CA证书,问题的根本可能是flutter android端请求库验证证书的时候,并未获取到android手机中的完整证书信息,亦或者是根本就没有去获取完整证书信息,总之是flutter网络请求库在android端的证书校验存在处理失当问题,因为手机浏览器证书校验没问题,说明系统必然有内置根证书可以校验我们的网站证书。
此问题在github也有人提出:https://github.com/flutter/flutter/issues/50699
解决方案就是apisix上传公钥别只上传网站的公钥,而是将CA证书打包进网站公钥证书,形成完整的fullchain.cer作为公钥证书提交,私钥不需要变化。
由于我使用的是let's encrypt申请的,使用acme.sh申请的时候它已经下发了fullchain.cer了,所以我就不需要制作,只要将网站的xxx.cer换成这个已经包含了ca.cer的fullchain.cer即可。
总结:若没有https相关知识作指引,这种问题根本没办法看清本质。