中間 CA 的 Debian 問題
語境
由於某些原因,我需要生成:
- 根 CA
- 中間 CA(由根 CA 簽名)
- 證書(由中間 CA 簽名)
- 連鎖,鏈條
我在一個 Dockerized 環境中,有 3 個容器:
- 容器 A:Nginx 反向代理,解碼 SSL(使用鏈 + 密鑰)並將請求轉發到容器 B
- 容器 B:Nginx(這裡沒什麼特別的,響應的應用程序)
- 容器 C :需要捲曲 A 的應用程序(沒有不安全標誌)。我需要在這個上安裝中間 CA
這看起來像一個簡單的問題,但是當 Container C 基於 Debian 時,我被困住了。例如,它在 Ubuntu 容器上就像一個魅力。它也適用於 Ubuntu 桌面虛擬機。我的中間 CA 也可以在我的 Mac 上使用 OSX 鑰匙串儲存。
這看起來像是 Debian 特定的問題。
我是如何測試的
我遵循了幾個步驟: - 生成 ca/certs/chain - 在我的 mac 上安裝中間 CA - curl -XGET https://service.local在終端內:好的
然後,使用 Docker,在 ubuntu 上掛載中間 CA,然後呼叫 update-ca-certificates,並使用 curl 進行測試:OK
然後,使用 Docker,在 Debian 上掛載中間 CA,然後呼叫 update-ca-certificates,並使用 curl 進行測試:KO
腳本部分
我已經編寫了整個 certs/ca/chain 生成的腳本,這裡沒問題,除非你需要它們,否則我不會詳細介紹。
容器 C 的 Docker-compose
我正在嘗試使用不同的作業系統,這就是為什麼有幾個服務,它表明我在 ubuntu 和幾個版本的 Debian 之間做同樣的事情。
我通過不呼叫 update-ca-certificates 採取了一些捷徑;相反,我將文件直接安裝在 /etc/ssl/certs 中,因為它實際上並沒有做更多的事情……對於那些想知道的人:我還嘗試將文件安裝在其他地方,然後呼叫 update-ca-certificates,然後 curl,使用另一個版本的入口點,但最終結果相同,它適用於 Ubuntu 而不是 Debian。
version: '2' services: ubuntu: image : "ubuntu:16.04" volumes : - './local_ca/LOCAL_CA.crt:/etc/ssl/certs/local_ca.pem:ro' - './entrypoint.sh:/entrypoint.sh' command : 'bash -c "/entrypoint.sh"' debian7: image : "debian:wheezy" volumes : - './local_ca/LOCAL_CA.crt:/etc/ssl/certs/local_ca.pem:ro' - './entrypoint.sh:/entrypoint.sh' command : 'bash -c "/entrypoint.sh"' debian8: image : "debian:jessie" volumes : - './local_ca/LOCAL_CA.crt:/etc/ssl/certs/local_ca.pem:ro' - './entrypoint.sh:/entrypoint.sh' command : 'bash -c "/entrypoint.sh"' debian9: image : "debian:stretch" volumes : - './local_ca/LOCAL_CA.crt:/etc/ssl/certs/local_ca.pem:ro' - './entrypoint.sh:/entrypoint.sh' command : 'bash -c "/entrypoint.sh"'
entrypoint.sh
為了範例的目的,假設 IP 是已知的並在以下模板中替換:
#!/bin/bash apt-get update apt-get install -y curl echo '{{ip_of_reverse_proxy}} service.local' >> /etc/hosts curl -XGET https://service.local
正如我之前所說,我也做了一個版本,我呼叫 update-ca-certificates 而不是直接掛載,但它沒有任何區別,它適用於 Ubuntu 而不是 Debian
碼頭工人撰寫日誌
這是輸出日誌,被截斷以便我們只得到有趣的部分。如您所見,ubuntu 上的 curl 使用 JSON 回答,而 debian 拒絕證書驗證,因為 root ca 不受信任。
ubuntu_1 | {"_links":{"self":{"href":"\/"}}} debian7_1 | curl performs SSL certificate verification by default, using a "bundle" [...] (see debian9_1 logs) debian8_1 | curl performs SSL certificate verification by default, using a "bundle" [...] (see debian9_1 logs) debian9_1 | curl: (60) SSL certificate problem: self signed certificate in certificate chain debian9_1 | More details here: https://curl.haxx.se/docs/sslcerts.html debian9_1 | debian9_1 | curl performs SSL certificate verification by default, using a "bundle" debian9_1 | of Certificate Authority (CA) public keys (CA certs). If the default debian9_1 | bundle file isn't adequate, you can specify an alternate file debian9_1 | using the --cacert option. debian9_1 | If this HTTPS server uses a certificate signed by a CA represented in debian9_1 | the bundle, the certificate verification probably failed due to a debian9_1 | problem with the certificate (it might be expired, or the name might debian9_1 | not match the domain name in the URL). debian9_1 | If you'd like to turn off curl's verification of the certificate, use debian9_1 | the -k (or --insecure) option.
問題
問題 1:當我注入完全相同的文件並遵循完全相同的過程時,為什麼它可以在 ubuntu 而不是 debian 上執行?他們不是共享同一個基地嗎?
問題 2:Debian 的正確解決方案是什麼?我真的需要注入和安裝根 CA 嗎?(當我這樣做時它會起作用,但對我來說它看起來很奇怪,因為中間 CA 應該就足夠了)
經過進一步調查,ubuntu 和 debian 最大的區別在於使用的 SSL 庫:
- 在 Debian 上,curl 是使用 OpenSSL 預編譯的
- 在 Ubuntu 上,curl 是使用 GnuTLS 預編譯的
我在 Debian 上用 GnuTLS 重新編譯了 curl,它只使用中間 CA 就可以正常工作。
我在 Ubuntu 上使用 OpenSSL 重新編譯了 curl,如果我希望我的請求通過,現在必須信任根 CA。
您不需要在依賴方(容器 C)中安裝任何從屬 CA 證書。
RFC 5246 7.4.2規定伺服器必須以鏈的形式提供任何和所有從屬 CA 證書。也就是說,您在容器 A 中的 Ngnix 伺服器必須配置為在連接時向客戶端發送證書(根 CA 證書除外)。
只有根 CA 證書必須安裝在客戶端(容器 C)上,才能信任伺服器提供的鏈。