我需要使用 向网站发出请求curl
,但网站没有在 tls 中提供中间证书。
我的意思是说:
当使用 TLS 连接到服务器时,它必须(rfc5246 F.1.1、rfc5246 7.4.2)向客户端提供足以验证服务器证书的所有证书。这意味着当连接到www.google.com时,它会为我提供主机证书 (*.google.com) 和中间证书 (GTS CA 1C3) 和根证书 (GTS Root R1)。当连接到问题站点时,它仅提供主机证书。
示例:openssl s_client -connect google.com:443 -showcerts 2>&1 < /dev/null
- 给您 3 个证书。
对于大多数浏览器来说这是可以的,但对于 CURL 来说就不行了。
所以我必须使用curl --insecure
或手动更新该网站的捆绑包。
我想让我的连接安全,但自动进行。
是否有某种工具可以从 url 构建完整的证书链,根据根 CA 捆绑包对其进行验证,并输出值以在curl --insecure --pinnedpubkey <value>
验证失败时使用或不使用?
这种情况下的curl 处理取决于构建。
curl 可以使用在编译时确定的多种 TLS 实现中的任何一种,并且curl 中 TLS 实现的行为依赖于curl 中的 TLS 实现也就不足为奇了。
带有 schannel 的curl 可以使用 AIA 获取丢失的链证书(不是由服务器发送,按照 RFC 的要求),并验证结果。此外,如果丢失的链证书位于 Windows 证书存储中(就像它始终根据 Windows 证书存储中的根进行验证一样),则带有 schannel 的curl 将填充缺失的链证书,虽然我无法轻松验证此类链何时出现证书放在Windows 商店中,我的(Win 10 Home)系统每天用于大量的网页浏览,偶尔用于curl和powershell iwr之类的东西,确实有大约十几个证书。当然,curl 和 schannel 只能在 Windows 上使用。由于您建议您使用--pinnedpubkey
schannel 不支持的功能,因此您可能没有使用 schannel。
OpenSSL 绝对不会为此使用 AIA,因此在许多(但不是全部)Linux 发行版上流行的 OpenSSL 卷曲也不会使用 AIA。正如 Frederic 发现的那样,OpenSSL将从提供的文件中填写链证书(以及根)--cacert
,因此,如果您知道或可以猜测您将需要什么链证书,并将它们(全部)下载到提前,这会起作用。
我很确定 NSS 本身可以执行 AIA(因为 Firefox 可以),但我不知道curl 是否以及如何访问或启用它,并且我可以轻松测试带有 NSS 的一个curl(不可否认,在 WSL 上的 Ubuntu 16.04 上)有点过时了)不这样做..
我不了解 GnuTLS,但在 CentOS 7 上使用 GnuTLS 进行curl 则无法做到这一点。
但是,对于您真正的问题,我没有任何工具可以手动执行此操作并保存结果。
https://www.ssllabs.com/ssltest/对 SSL/TLS 功能和兼容性进行了非常广泛的测试,其中包括以类似浏览器的方式填写和验证您的证书/链并显示结果;if 如果找到的话甚至会显示多个信任路径,而浏览器不会这样做。您也许能够抓取这些结果。https://whatsmychaincert.com/只进行链构建/校正,我似乎记得它产生了一个很好的 PEM,但我无法验证,因为我知道的唯一公开测试目前已被破坏(与 Frederic 引用的相同) ,incomplete-chain.badssl.com)。
Java(更准确地说,JSSE,使用“标准”加密提供程序时 Java 中的 SSL/TLS 实现)可以使用 AIA 进行获取作为验证的一部分(但不是默认情况下,您必须启用它),因此您可以编写一个简单的 Java 程序来连接到网站,在启用 AIA.caIssuers 的情况下验证证书,如果成功,则写出生成的证书和/或其密钥以进行固定;我预计这只是 20-30 行,如果没有提供更好的解决方案,并且稍后我有时间,我会尝试一下。(或者,这就是 Stack,任何其他人都可以这样做。)