Nginx

無法獲取本地頒發者證書(但我信任的 CA 證書商店似乎還可以)

  • July 30, 2021

這讓我忙了好幾個小時。我已經閱讀了很多其他文章和 Stackexchange-questions,並嘗試了其他東西,但到目前為止還沒有積極的結果。

執行 Ubuntu20/Nginx/Openssl v1.1.1。

在普通 Web 資源上使用 wget、openssl s_client 或 curl,我收到消息:“驗證返回程式碼:20(無法獲取本地頒發者證書)”或等效資訊。

$ openssl s_client -connect google.com:443
CONNECTED(00000003)
depth=2 C = US, O = Google Trust Services LLC, CN = GTS Root R1
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=1 C = US, O = Google Trust Services LLC, CN = GTS CA 1C3
verify return:1
depth=0 CN = *.google.com
verify return:1
---
Certificate chain
0 s:CN = *.google.com
  i:C = US, O = Google Trust Services LLC, CN = GTS CA 1C3
1 s:C = US, O = Google Trust Services LLC, CN = GTS CA 1C3
  i:C = US, O = Google Trust Services LLC, CN = GTS Root R1
2 s:C = US, O = Google Trust Services LLC, CN = GTS Root R1
  i:C = BE, O = GlobalSign nv-sa, OU = Root CA, CN = GlobalSign Root CA
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIN...

一點背景。SSL 握手用於這些常見的 Web 資源。但是我有一個應用程序需要將自簽名證書添加到受信任的 CA 證書儲存中。為此工作了二十個小時,嘗試了很多事情。最後決定“重新開始”並刪除我整個受信任的證書儲存,方法是刪除*/etc/ssl/certs//usr/(local/)share/ca-certificates/中的所有內容並恢復常見 CA 的備份-這些文件夾中的證書,以及/etc/ca-certificates.conf的還原備份。然後執行update-ca-certificates*。另外:我將 OpenSSL 從 v1.1.1 降級到 1.0.2,然後再次將其從 1.0.2 升級到 1.1.1。

下面的輸出表明它看起來沒問題。

$ update-ca-certificates -f
Clearing symlinks in /etc/ssl/certs...
done.
Updating certificates in /etc/ssl/certs...
129 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.

據我所知,我受信任的證書儲存似乎很好:它包含鏈中請求的根證書。注意上面的例子有兩個根證書:(1) C = US, O = Google Trust Services LLC, CN = GTS Root R1 , (2) C = BE, O = GlobalSign nv-sa, OU = Root CA, CN = GlobalSign 根CA。

我確信這兩個根證書在我信任的 CA 儲存中。這是Marlon在NginX 客戶端證書身份驗證中建議的技巧的輸出片段,失敗並顯示“無法獲取頒發者證書”

$ awk -v cmd='openssl x509 -noout -subject' ' /BEGIN/{close(cmd)};{print | cmd}' < /etc/ssl/certs/ca-certificates.crt
...
subject=OU = GlobalSign ECC Root CA - R4, O = GlobalSign, CN = GlobalSign
subject=OU = GlobalSign ECC Root CA - R5, O = GlobalSign, CN = GlobalSign
subject=C = BE, O = GlobalSign nv-sa, OU = Root CA, CN = GlobalSign Root CA
subject=OU = GlobalSign Root CA - R2, O = GlobalSign, CN = GlobalSign
subject=OU = GlobalSign Root CA - R3, O = GlobalSign, CN = GlobalSign
subject=OU = GlobalSign Root CA - R6, O = GlobalSign, CN = GlobalSign
...
subject=C = US, O = Google Trust Services LLC, CN = GTS Root R1
subject=C = US, O = Google Trust Services LLC, CN = GTS Root R2
subject=C = US, O = Google Trust Services LLC, CN = GTS Root R3
subject=C = US, O = Google Trust Services LLC, CN = GTS Root R4

因此,我的範例 (google.com) 中的主機使用的根證書在我受信任的 CA 儲存中。為什麼我仍然收到“驗證錯誤:無法獲取本地頒發者證書”?

此外,當我明確定義可信 CA 證書儲存的路徑時,我將添加輸出。SSL 握手成功!我在看什麼?

$ openssl s_client -CApath /etc/ssl/certs -connect google.com:443
CONNECTED(00000003)
depth=2 C = US, O = Google Trust Services LLC, CN = GTS Root R1
verify return:1
depth=1 C = US, O = Google Trust Services LLC, CN = GTS CA 1C3
verify return:1
depth=0 CN = *.google.com
verify return:1
---
Certificate chain
0 s:CN = *.google.com
  i:C = US, O = Google Trust Services LLC, CN = GTS CA 1C3
1 s:C = US, O = Google Trust Services LLC, CN = GTS CA 1C3
  i:C = US, O = Google Trust Services LLC, CN = GTS Root R1
2 s:C = US, O = Google Trust Services LLC, CN = GTS Root R1
  i:C = BE, O = GlobalSign nv-sa, OU = Root CA, CN = GlobalSign Root CA
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIN...
...
-----END CERTIFICATE-----
subject=CN = *.google.com

issuer=C = US, O = Google Trust Services LLC, CN = GTS CA 1C3

---
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: ECDSA
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 6523 bytes and written 392 bytes
Verification: OK
---
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Server public key is 256 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---

總結:我可能忽略了某些東西,一些設置或參數可能已經被重置,或者在我修補系統的時間裡設置錯誤。但是,我只是看不到它,到目前為止我已經閱讀和嘗試過的資料大多提到確保我受信任的 CA-cert 儲存是完整的,我認為它是完整的。我在看什麼?我應該在哪裡看,或者我應該怎麼做才能解決這個問題?

解決了我自己的問題,並將在這里分享解決方案。受信任的 CA 儲存中的證書確實很好。我的問題是由解除安裝和重建 OpenSSL 引起的。

‘新鮮的’ OpenSSL 安裝目錄包含一個*/certs/private*文件夾以及一個 openssl.cnf 文件。

$ ll
total 68
drwxr-xr-x  9 root root  4096 Jul 28 12:10 ./
drwxr-xr-x 11 root root  4096 Jul 26 21:58 ../
drwxr-xr-x  2 root root  4096 Jul 26 21:59 bin/
drwxr-xr-x  2 root root  4096 Jul 26 21:59 certs/
-rw-r--r--  1 root root   412 Jul 28 12:10 ct_log_list.cnf
-rw-r--r--  1 root root   412 Jul 28 12:10 ct_log_list.cnf.dist
drwxr-xr-x  3 root root  4096 Jul 26 21:59 include/
drwxr-xr-x  4 root root  4096 Jul 26 21:59 lib/
drwxr-xr-x  6 root root  4096 Jul 26 21:58 man/
drwxr-xr-x  2 root root  4096 Jul 28 12:10 misc/
-rw-r--r--  1 root root 10835 Jul 26 21:59 openssl.cnf
-rw-r--r--  1 root root 10909 Jul 28 12:10 openssl.cnf.dist
drwxr-xr-x  2 root root  4096 Jul 26 21:59 private/

但是這個伺服器(由第三方提供,而不是“新鮮的、預設的 Ubuntu20”)將其受信任的 CA 儲存儲存在*/etc/ssl/certs*中。這就是為什麼,簡單來說,OpenSSL 沒有“找到”我的 CA 儲存與所有通用證書。解決方案是刪除這個原始文件夾,並將符號連結添加到我實際受信任的 CA 儲存中:

$ rmdir certs    
$ ln -s /etc/ssl/certs ./certs

還補充說:

$ rm openssl.cnf
$ rmdir private
$ ln -s /etc/ssl/openssl.cnf ./openssl.cnf
$ ln -s /etc/ssl/private ./private

現在它看起來像:

$ ll
total 48
drwxr-xr-x  7 root root  4096 Jul 30 17:02 ./
drwxr-xr-x 11 root root  4096 Jul 26 21:58 ../
drwxr-xr-x  2 root root  4096 Jul 26 21:59 bin/
lrwxrwxrwx  1 root root    14 Jul 30 16:57 certs -> /etc/ssl/certs/
-rw-r--r--  1 root root   412 Jul 28 12:10 ct_log_list.cnf
-rw-r--r--  1 root root   412 Jul 28 12:10 ct_log_list.cnf.dist
drwxr-xr-x  3 root root  4096 Jul 26 21:59 include/
drwxr-xr-x  4 root root  4096 Jul 26 21:59 lib/
drwxr-xr-x  6 root root  4096 Jul 26 21:58 man/
drwxr-xr-x  2 root root  4096 Jul 28 12:10 misc/
lrwxrwxrwx  1 root root    20 Jul 30 17:02 openssl.cnf -> /etc/ssl/openssl.cnf
-rw-r--r--  1 root root 10909 Jul 28 12:10 openssl.cnf.dist
lrwxrwxrwx  1 root root    16 Jul 30 17:02 private -> /etc/ssl/private/

通過登錄以相同方式配置的另一台伺服器並查找 OPENSSLDIR(OpenSSL 安裝目錄)找到了解決方案。

openssl version -d

這兩個伺服器之間存在差異。去看看這個文件夾裡面。在它正在工作的伺服器上的文件夾中找到符號連結。在伺服器上找到了一個空的“certs”文件夾,但它不是。添加了符號連結。解決了。

引用自:https://unix.stackexchange.com/questions/660361