NGINX SSL握手错误 - sslv3警告证书过期:SSL警报号45

3

我正在使用NGINX作为DNS over TLS服务器。

然而,所有设备上的Android“私人DNS”突然停止工作。

使用kdig仍按预期工作。

kdig -d @my.dns.server +tls-ca +tls-host=my.dns.server example.org

然而,Android的请求失败了,我在NGINX日志中看到了以下错误

SSL_do_handshake() failed (SSL: error:14094415:SSL routines:ssl3_read_bytes:sslv3 alert certificate expired:SSL alert number 45) while SSL handshaking, client: **.**.**.**, server: 0.0.0.0:853

证书仍然有效,但我不确定为什么会出现此错误。
我的NGINX SSL配置为:
ssl_certificate /etc/letsencrypt/live/my.dns.server/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/my.dns.server/privkey.pem; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;

ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA";
ssl_handshake_timeout    10s;
ssl_session_cache        shared:SSL:20m;
ssl_session_timeout      4h;

请务必查看https://letsencrypt.org/2020/12/21/extending-android-compatibility.html,LE根证书今天已过期。 - Patrick Mevzek
@PatrickMevzek 有没有一种方法可以强制Certbot使用“ISRG Root X1”备用链? - Atrox1449
根据给定的链接,是可以实现的: “那么备用链呢?今天,如果用户已经配置了,一些ACME客户端可以请求备用链。我们目前提供获取以下链的选项:订阅者证书 < – R3 < – ISRG Root X1” - Patrick Mevzek
1
是的,我找到了。您可以将 --preferred-chain "ISRG Root X1" 添加到 certbot CLI 命令中。现在可以正常工作了。再次感谢 @PatrickMevzek - Atrox1449
1
你应该根据自己的发现编写答案,然后选择最佳答案。但是我不确定你的问题是否与编程有关,或许在[sf]上更合适。 - Patrick Mevzek
请查看 https://www.octopuce.fr/letsencrypt-certificate-expiration-consequences/。它似乎描述了类似的问题并提供了多种解决方案,包括您找到的解决方案。 - Patrick Mevzek
1个回答

1

问题:

DST Root CA X3证书已经过期,letsencrypt使用该证书。他们已经开始使用新的ISRG Root X1证书多年,但一些旧设备(例如android < 7.1.1)不知道这个新证书。这意味着这些设备不能使用新证书,也不应该再使用旧证书。

但是,letsencrypt注意到许多旧的ssl实现(包括android)不检查证书是否过期。因此,它们仍然可以为这些设备使用旧的DST Root CA X3证书。较新的ssl实现可以改用新的ISRG Root X1证书。

请参见:https://letsencrypt.org/2020/12/21/extending-android-compatibility.html

遗憾的是,一些较新的ssl实现(包括android点客户端)会注意到旧的过期证书并中止ssl连接,因为证书已过期。他们根本不检查新证书。由于这种实现相关行为,一些新程序无法工作,但其他程序仍能正常工作。

解决方案:

为了使所有较新的ssl实现都能正常工作,您需要仅使用新的ISRG Root X1证书。为此,您必须使用ISRG Root X1链。但这将破坏与尚未了解新ISRG Root X1证书的旧设备的兼容性。

如果您使用certbot,则可以使用以下标志--preferred-chain "ISRG Root X1"

如果您使用Caddy Web服务器,则可以在Caddyfile开头添加以下行:

{
    preferred_chains {
        root_common_name "ISRG Root X1"
    }
}

你的解释还有一个拼图缺失,才能完整地解决这个问题。TLS标准允许多个证书链同时存在并提供给客户端。然后客户端会迭代所有证书,直到找到它喜欢的信任锚点。理论上很好,但至少OpenSSL在实现中存在一个重大bug,会在第一个无效证书处停止。因此,如果您想同时提供旧和新的证书链,请确保先发送新的证书链。 - joerg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接