解决方案更新(讨论后)

解决方案更新(讨论后)

我无法理解以下问题。使用 openssl 验证服务器的证书失败,证书链不完整。

免责声明:我不是管理员,并且尚未处理过太多证书工作。

使用 OpenSSL 验证

$ openssl verify -CAfile /etc/letsencrypt/live/co2-avatar.com/fullchain.pem  /etc/letsencrypt/live/co2-avatar.com/cert.pem

# /etc/letsencrypt/live/co2-avatar.com/cert.pem: C = US, O = Internet Security Research Group, CN = ISRG Root X1
# error 2 at 2 depth lookup:unable to get issuer certificate

检查证书中的某个域名

openssl s_client -connect co2avatar.org:443 -servername co2avatar.org
# CONNECTED(00000003)
# depth=0 CN = gitlab.sustainable-data-platform.org
# verify error:num=20:unable to get local issuer certificate
# verify return:1
# depth=0 CN = gitlab.sustainable-data-platform.org
# verify error:num=21:unable to verify the first certificate
# verify return:1
# ---
# Certificate chain
#  0 s:CN = gitlab.sustainable-data-platform.org
#    i:C = US, O = Let's Encrypt, CN = R3
# ---
# Server certificate
# -----BEGIN CERTIFICATE-----

或者运行

curl -v https://co2avatar.org
# *   Trying 85.214.38.88:443...
# * TCP_NODELAY set
# * Connected to co2avatar.org (85.214.38.88) port 443 (#0)
# * ALPN, offering h2
# * ALPN, offering http/1.1
# * successfully set certificate verify locations:
# *   CAfile: /etc/ssl/certs/ca-certificates.crt
#   CApath: /etc/ssl/certs
# * TLSv1.3 (OUT), TLS handshake, Client hello (1):
# * TLSv1.3 (IN), TLS handshake, Server hello (2):
# * TLSv1.2 (IN), TLS handshake, Certificate (11):
# * TLSv1.2 (OUT), TLS alert, unknown CA (560):
# * SSL certificate problem: unable to get local issuer certificate
# * Closing connection 0
# curl: (60) SSL certificate problem: unable to get local issuer certificate

可能我的 Apache VHost 中存在错误的域配置,也可能证书链本身存在问题。我该如何检查最后一个问题(我在 Google 上搜索了很多,但大多数搜索结果都是关于openssl verify不同-CAfile的证书颁发者)?

我需要检查根证书包那么具体怎么做呢?

有没有类似-addtrust旗帜为了certbot certonly

答案1

尝试 openssl s_client 并让您显示证书。命令是:

$ openssl s_client -connect co2avatar.org:443 -servername co2avatar.org -showcerts

您会发现您的服务器返回了一个证书CN = gitlab.sustainable-data-platform.org和一个包含您的域名的主题备用名称DNS:co2-avatar.com。因此证书本身没有问题。

如果您想将所有内容合并到一个命令管道中来查看证书的内容:

echo | openssl s_client -connect co2avatar.org:443 -servername co2avatar.org -showcerts 2>/dev/null |sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | openssl x509 -noout -text

缺少的是中间证书。这也应该由服务器发送,但第一个命令显示它不存在 - 只有证书由您的服务器发送。

因此失败的 openssl 是正确的,因为确实缺少中间证书。

因此,要解决这个问题,您需要调整 Apache 配置。您的配置可能如下所示:

文件名应类似于/etc/apache2/sites-enabled/co2-avatar.com-le-ssl.conf

<IfModule mod_ssl.c>
SSLStaplingCache shmcb:/var/run/apache2/stapling_cache(128000)
<VirtualHost *:443>
        ServerName co2-avatar.com
        ServerAlias www.co2-avatar.com
#... 
#... insert your other stuff here...
#...

SSLCertificateFile /etc/letsencrypt/live/co2-avatar.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/co2-avatar.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
SSLUseStapling on
</VirtualHost>
</IfModule>

根据您的描述,我猜测您的配置中有以下行是错误的: SSLCertificateFile /etc/letsencrypt/live/co2-avatar.com/cert.pem。应将其替换为SSLCertificateFile /etc/letsencrypt/live/co2-avatar.com/fullchain.pem,以便同时发送中间体。

解决方案更新(讨论后)

讨论发现,此 CentOS 服务器上使用的 openssl 和 Apache 版本较旧,因此某些功能不受支持。(Apache 2.4.6、OpenSSL 1.0.2k、中间配置、无 HSTS、无 OCSP)

根据Mozilla SSL 配置生成器在这种情况下可以使用以下通用配置:

<VirtualHost *:443>
    SSLEngine on
    SSLCertificateFile      /path/to/signed_certificate
    SSLCertificateChainFile /path/to/intermediate_certificate
    SSLCertificateKeyFile   /path/to/private_key
</VirtualHost>

翻译到这个特定的案例,最终的工作配置将如下所示:

<VirtualHost *:443>
    ServerName  sustainable-data-platform.org
    ServerAlias co2-avatar.com
    ServerAlias ... <include all other SAN names here>
    
    SSLEngine on
    SSLCertificateFile      /etc/letsencrypt/live/co2-avatar.com/cert.pem
    SSLCertificateChainFile /etc/letsencrypt/live/co2-avatar.com/fullchain.pem
    SSLCertificateKeyFile   /etc/letsencrypt/live/co2-avatar.com/privkey.pem

</VirtualHost>

对于这些旧装置

交叉签名的 Let's Encrypt R3 和 DST Root CA X3、中间证书和根证书将分别于 2021 年 9 月 29 日和 2021 年 9 月 30 日到期。因此,自 2021 年 5 月 4 日起,新颁发的证书使用更长的链,并以交叉签名的 ISRG Root X1 作为中间证书。

不幸的是,由于证书路径的构建和验证方式,并非所有 TLS 实现都能成功验证交叉签名。OpenSSL 1.0.2 就是这种情况。因此,在 RHEL/CentOS 7 上运行的使用 OpenSSL 的程序很可能无法验证新的证书链或建立 TLS 连接。在这样的平台上升级到较新的 Openssl 版本并不简单。

有几个选项:在客户端更新信任库(删除 DST Root CA X3 根证书 - 一旦删除,影响应该是最小的)(或者)在服务器端更改证书链。

对于 Nginx

对于 Nginx,只有一个参数可以指定证书文件。您应该使用fullchain.pemcertbot 提供的参数才能使其正常工作。

给定虚拟主机的服务器块中的正确配置如下:

server {
  ...
  ssl_certificate /etc/letsencrypt/live/co2-avatar.com/fullchain.pem;  -> replaced cert.pem for fullchain.pem
  ssl_certificate_key /etc/letsencrypt/live/co2-avatar.com/privkey.pem;
}

参考

相关内容