一文解剖Ubuntu,Curl,Openssl更新根证书的细节

但有一个关键主题一直没说,那就是 Curl 请求 HTTPS 网站的时候,需要使用本地的 CA 根 证书来校验网站的身份,那根证书由谁提供?证书在哪儿?有些同学说,这不废话吗?肯定由 OpenSSL 或 NSS 提供。实际上不同平台、不同密码学库、不同的应用软件,使用的 CA 根证书是有一定区别的。

顺藤摸瓜找到 ca-certificates

在 Ubuntu 下,安装 Curl 包的时候会额外安装一个包 ca-certificates,这个包和证书有关,实际上这个包由 OpenSSL 安装的,如下:

$ apt-cache depends openssl   openssl   依赖: libc6   依赖: libssl1.0.0   建议: ca-certificates   冲突: openssl:i386 

因为 Curl 是通过 OpenSSL 实现客户端 HTTPS 协议的,也就是说在 Curl/OpenSSL 平台下,Curl 使用的根证书库都是由 ca-certificates 包处理。

在介绍 ca-certificates 包之前,让我们了解在 Ubuntu/Curl(包括 openssl s_client 工具)在发送 HTTPS 请求的时候,其引用的根证书地址,见下图:

根证书库 CAfile: /etc/ssl/certs/ca-certificates.crt,让我们记住这一个文件,该文件是由 ca-certificates 包更新的。

深究 ca-certificates

运行如下命令了解 ca-certificates 包的详细信息:

$ apt-cache show ca-certificates 

This package includes PEM files of CA certificates to allow SSL-based applications to check for the authenticity of SSL connections.

It includes, among others, certificate authorities used by the Debian infrastructure and those shipped with Mozilla’s browsers.

也就是说这个包含了 PEM 格式的 CA 根证书,这些证书可以供基于 SSL 协议的引用程序使用,所有的 CA 根证书实际上是由 Mozilla 维护的。

接下去运行下列命令,了解下 ca-certificates 包含的文件:

$ dpkg  -L ca-certificates 

主要包含二种类型的文件:

1:/usr/share/ca-certificates/mozilla/

包含很多具体的 CA 根证书文件,每个 CA 机构的根证书对应一个文件。

2:/usr/sbin/update-ca-certificates

这是一个命令行工具,作用是什么?运行如下命令了解官方说明:

$ man update-ca-certificates 

update-ca-certificates - update /etc/ssl/certs and certificates.crt

直白的说,运行这个工具,它最终会更新 /etc/ssl/certs/ca-certificates.crt 文件。这下你应该明白了,有了这个文件,不管是 Curl 还是 openssl 在发送 HTTPS 请求的时候,都可以校验 HTTPS 网站的真实身份了。

具体执行步骤如下:

读取 /etc/ca-certificates.conf 文件,包含的内容就是所有 /usr/share/ca-certificates/mozilla/ 目录下的证书文件名。 将 /etc/ca-certificates.conf 文件对应的所有证书合并到 /etc/ssl/certs/ca-certificates.crt 文件中。

如何及时更新 CA 根证书

ca-certificates 包使用的 CA 根证书来自于 Mozilla,但对于一个发行版来说,升级和更新包的频率并不高。

思考一个情况,Mozilla 新引入了一个 CA,或者不信任一个 CA,也就是说对于 Mozilla 来说,其 CA 根证书列表发生了更新。其他使用 Mozilla CA 根证书的应用程序(包括 ca-certificates)可能无法做到及时更新,有没有办法及时更新本地的 CA 根证书呢?

可以使用 mk-ca-bundle.pl 工具,它是 Curl 工程发布的,Mozilla 将自己所信任的 CA 根证书全部存入 https://hg.mozilla.org/projects/nss/raw-file/default/lib/ckfw/builtins/certdata.txt 文件中(很少有应用程序直接使用 NSS cert9.db 文件)。

而 mk-ca-bundle.pl 要做的就是将 certdata.txt 转换为 PEM 格式,然后供 Curl(或者其他应用程序)使用。

$ wget https://raw.githubusercontent.com/curl/curl/master/lib/mk-ca-bundle.pl   $ chmod 0777 mk-ca-bundle.pl $ ./mk-ca-bundle.pl $cp ca-bundle.crt /etc/ssl/certs/ca-certificates.crt -fr 

运行结束后,/etc/ssl/certs/ca-certificates.crt 就更新了,Curl 就能使用***的根 CA 证书了。

细心的同学可能会发现,mk-ca-bundle.pl 工具没有自动在 /usr/share/ca-certificates/mozilla/ 目录下更新证书,自然 update-ca-certificates 工具也不能更新了。

后续我打算写一个工具解决该问题:

基于 mk-ca-bundle.pl,将证书同步到 /usr/share/ca-certificates/mozilla/ 目录。 然后使用 update-ca-certificates 更新***的证书。