一文解剖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 更新***的證書。