使用 OpenSSL 客户端连接到 URL 有效,但 curl 失败

使用 OpenSSL 客户端连接到 URL 有效,但 curl 失败

我有一台 CentOS 5.9 服务器,我需要从该服务器与另一台服务器建立 SSL 连接。远程服务器有一个由 GeoTrust Global CA 最终签名的证书。在撰写本文时,此证书是GeoTrust 的下载页面。我得到的结果不一致,取决于我使用 OpenSSL 还是 curl 来建立连接:

openssl s_client -connect <server>:443 -CAfile /path/to/GeoTrustCA.pem

工作正常,但是

curl --cacert /path/to/GeoTrustCA.pem https://<server>/

失败,出现标准“无法验证证书”错误。

以下是我使用的工具的详细信息:

$ curl --version 
curl 7.15.5 (i386-redhat-linux-gnu) libcurl/7.15.5
OpenSSL/0.9.8b zlib/1.2.3 libidn/0.6.5 Protocols: tftp ftp telnet dict
ldap http file https ftps  Features: GSS-Negotiate IDN IPv6 Largefile
NTLM SSL libz

$ openssl version
OpenSSL 0.9.8e-fips-rhel5 01 Jul 2008

我被难住了。我连接的服务器多年来一直运行良好,没有出现任何明显问题:我从未听说过任何人或任何系统无法像这样连接到它。

答案1

我对此感到很好奇,因此做了一些测试。据我所知,在使用根 CA 交换机时(分别为和)考虑的因素openssl似乎存在根本差异。curl-CAfile--cacert

--cacert在 中使用开关时curl,它似乎仅在验证期间使用管理员指定的根。例如,我下载了您之前提到的 GeoTrust PEM 文件,并尝试使用它从 yahoo 获取页面:

[foo@foobox tmp]# curl --cacert /tmp/geotest.pem https://info.yahoo.com/
curl: (60) SSL certificate problem, verify that the CA cert is OK. Details:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
More details here: http://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). The default
 bundle is named curl-ca-bundle.crt; you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.

现在,我尝试使用以下方法进行相同的测试openssl

[foo@foobox tmp]# openssl s_client -connect info.yahoo.com:443 -CAfile /tmp/geotest.pem
CONNECTED(00000003)
depth=3 /C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority
verify return:1
depth=2 /C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 2006 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G5
verify return:1
depth=1 /C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)10/CN=VeriSign Class 3 Secure Server CA - G3
verify return:1
depth=0 /C=US/ST=California/L=Sunnyvale/O=Yahoo Inc./CN=www.yahoo.com
verify return:1
---
Certificate chain
 0 s:/C=US/ST=California/L=Sunnyvale/O=Yahoo Inc./CN=www.yahoo.com
   i:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)10/CN=VeriSign Class 3 Secure Server CA - G3
 1 s:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)10/CN=VeriSign Class 3 Secure Server CA - G3
   i:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 2006 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G5
 2 s:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 2006 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G5
   i:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority
---
...
...
...
...
...
...
SSL handshake has read 5342 bytes and written 435 bytes
---
New, TLSv1/SSLv3, Cipher is RC4-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : RC4-SHA
    Session-ID: 6CAE87314ED66784B25C0FB36197D822CC73032FBFF30AD9E37CFF3D1678EBCC
    Session-ID-ctx:
    Master-Key: 6B9135F16512A251AB6DBEF62C6B261EC31DB90A0076C33DD67B27EAAB83A0333D50B1B7F10727DE47AB051A9C3A0499
    Key-Arg   : None
    Krb5 Principal: None
    Start Time: 1415842989
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---

您会注意到初始链描述中没有错误,并且显示Verify return code: 0 (ok)在底部。

因此,即使证书链中根本没有提及 GeoTrust,OpenSSL 也能够以某种方式验证/确认根。

嗯……

这让我开始思考 OpenSSL 的默认信任库在哪里……出于某种原因,我很难在网上找到有关它的信息(我确信它有很好的文档记录,只是我瞎了眼)。在我的系统上四处搜索后,我偶然发现了/etc/pki/tls/certs/ca-bundle.crt

我在 ca-bundle.crt 中搜索并删除了 yahoo 使用的根目录(/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority)并运行了相同的精确的再次命令:

[foo@foobox tmp]# openssl s_client -connect info.yahoo.com:443 -CAfile /tmp/geotest.pem
CONNECTED(00000003)
depth=2 /C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 2006 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G5
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
 0 s:/C=US/ST=California/L=Sunnyvale/O=Yahoo Inc./CN=www.yahoo.com
   i:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)10/CN=VeriSign Class 3 Secure Server CA - G3
 1 s:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)10/CN=VeriSign Class 3 Secure Server CA - G3
   i:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 2006 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G5
 2 s:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 2006 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G5
   i:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority
---
...
...
...
...
...
...
...
...
---
SSL handshake has read 5342 bytes and written 435 bytes
---
New, TLSv1/SSLv3, Cipher is RC4-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : RC4-SHA
    Session-ID: 09D998B153574D5C785BFF191B99CAB8BFCEF4DAC482F75A601886E668BF9CE6
    Session-ID-ctx:
    Master-Key: 1F98289FEB5926B8814D5E3B163FB40CC03BBC5C2D8A0045C0DFF0532458F18F722D5FD53155327B0A78627E3FE909E5
    Key-Arg   : None
    Krb5 Principal: None
    Start Time: 1415843859
    Timeout   : 300 (sec)
    Verify return code: 20 (unable to get local issuer certificate)
---

这次,我们遇到了验证错误。

因此,综合上述所有情况,我倾向于怀疑以下情况:

  • 您使用的根证书可能实际上与您需要使用的根证书不匹配。
  • curl仅使用您告诉它使用的根。
  • openssl使用您指向的根 ANNNND 以及其默认信任库中的任何根。

至于为什么 openssl 会这样做?不知道。文档因为该开关没有提到这个工作流程/行为:

-CAfile 文件

A file containing trusted certificates to use during server authentication and to use when attempting to build the client certificate chain.

也许其他人可以检查 openssl 的代码并进一步详细说明。

相关内容