这让我忙了好几个小时。我读了很多其他文章和 Stackexchange 问题,并尝试了其他方法,但到目前为止还没有积极的结果。
运行 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/证书/和/usr/(本地/)共享/ca-证书/)并恢复这些文件夹中常见 CA 证书的备份,以及恢复备份/etc/ca-certificates.conf。然后跑了更新 ca 证书。另外:我将 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 = 根 CA、CN = GlobalSign 根 CA。
我确信这两个根证书位于我信任的 CA 存储中。这是建议的技巧的输出片段马龙在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 证书存储是完整的,我认为是这样。我在忽略什么?我应该看哪里,或者我应该做什么来解决这个问题?
答案1
解决了我自己的问题,并将在这里分享解决方案。受信任的 CA 存储中的证书确实没问题。我的问题是由卸载并重建 OpenSSL 引起的。
“新的”OpenSSL 安装目录除其他外还包含/证书和/私人的文件夹和 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/证书。简单来说,这就是为什么 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”文件夹,但它不在。添加了符号链接。解决了。