华为云函数根CA缺失排查
最近几年Serveless的云服务越来越火了,刚好这个周末准备试用一下,写点小工具。测试访问自己的网站时,一直失败,搞一下午最后发现是华为云的一个BUG,没有预置完整的根证书,这也太扯了,记录一下顺便提个单吧。
表现
使用华为云的函数工作流功能,编写python代码,在代码中使用 urlib3 或 requests 访问网站并打印内容,简单测试是正常的,例如访问百度的http和https站点。作为一个有自己博客的人,也经常会把自己的网站作为测试用例的一部分,结果发现,居然报 SSLError [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1123)
,真是瞎了我的狗眼。
poc:
1 | import urllib3 |
初步结论
无论使用 urllib3 还是 requests,表现都是一样的,说明问题出在网关那里。我测试的网站绝大部分都是正常的,唯独我自己的博客提示证书不可信,难道是访问冷门站点的https资源就自带劫持?也罢,今天就查个水落石出吧。
仔细排查
查看SSL证书
难度倒是不大,主要是云函数提供的环境比较简陋,不让自己pip安装依赖,允许os.system,path下有什么东西也全靠尝试,最终选择使用环境里的 openssl
CLI,网上抄来一段代码:
1 | echo | openssl s_client -showcerts -servername www.leadroyal.cn -connect www.leadroyal.cn:443 2>/dev/null | openssl x509 -inform pem -noout -text |
在本地执行后,在云函数中 os.system执行,对比结果发现证书一模一样,签发者一模一样。
奇怪了,世界未解之谜,超出了我的认知范围。
查看root CA、Intermediate CA
同样,这里主要难度在于如何使用残破的工具完成证书查看,最后使用了这个命令,成功打印出了证书链。
1 | echo | openssl s_client -showcerts -servername www.leadroyal.cn -connect www.leadroyal.cn:443 2>/dev/null |
观察网站SSL证书,一模一样;观察中间签发机构,一模一样;观察根证书签发机构,一模一样;只有最后几行输出的校验结果不一样:
1 | 本地: |
更奇怪了,完全没有被劫持的痕迹,确实是权威机构签发的,为什么被认为不受信任呢?
大胆猜测,小心求证
事到如今,只能认为是操作系统的问题了,我猜是操作系统内置的根证书不完整。
随便找几台机器看看,根据 https://serverfault.com/questions/62496/ssl-certificate-location-on-unix-linux 的提示,我尝试在 ubuntu 和 centos 里寻找根证书,我的根证书信息是:O=Comodo CA Limited,CN=AAA Certificate Services。
在 ubuntu-22.04 的 /etc/ssl/certs/Comodo_AAA_Services_root.pem
下成功找到。
1 | [root@dcbf508431fa /]# realpath /usr/share/ca-certificates/mozilla/Comodo_AAA_Services_root.crt |
在 centos8/7/6 的 /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem
下,centos5 的 /etc/pki/tls/cert.pem
下,成功找到。
1 | [root@55ad8e627d9f /]# grep Comodo /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem |
删除对应的文件后,即可复现云函数中的现象,无法访问我的博客,此时可以有很大的把握认为是环境的问题。
到环境上,执行命令,grep "#" /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem
,翻了所有的别名,确实没有。
好了,破案了,我使用的ssl证书的颁发者不在操作系统认可的名单里,被这种傻逼问题折腾了一下午,绝对属于现网严重问题了,大面积可用性问题,忍不住使用一些文明用语了。
谁是罪魁祸首?
通过 cat /proc/version
得知系统信息 Linux version 3.10.0-862.14.1.5.h520.eulerosv2r7.x86_64 (abuild@szxrtosci10000) (gcc version 4.8.5 20150623 (EulerOS 4.8.5-28) (GCC) ) #1 SMP Wed Nov 25 18:33:06 UTC 2020
,看起来是华为的euleros操作系统。
众所周知,华为将 openEuler 捐献到了开源基金会,而 euleros 是商业版,我并不能查明 euleros 为什么没有这个CA,于是去测试 openEuler。
使用同样的方式在 docker 里测试 openEuler 的 20.03、22.03版本,没有故障。
再仔细看版本信息,看起来像是很古老的版本了,古老到连centos5都有这张证书了,不知道exp能不能把这个老容器打穿了。
结论
euleros和华为云长点心吧。。。