使用 OpenSSL 客户端连接到 URL 可以工作,但curl 失败

Dav*_*gan 5 ssl centos openssl curl

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

openssl s_client -connect <server>:443 -CAfile /path/to/GeoTrustCA.pem
Run Code Online (Sandbox Code Playgroud)

工作正常,但是

curl --cacert /path/to/GeoTrustCA.pem https://<server>/
Run Code Online (Sandbox Code Playgroud)

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

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

$ 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
Run Code Online (Sandbox Code Playgroud)

$ openssl version
OpenSSL 0.9.8e-fips-rhel5 01 Jul 2008
Run Code Online (Sandbox Code Playgroud)

我很困惑。我连接的服务器多年来一直工作没有明显问题:我从未听说过任何人或任何系统无法像这样连接到它。

Mik*_*e B 6

我对此很好奇,所以我做了一些测试。据我所知,在使用根 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.
Run Code Online (Sandbox Code Playgroud)

现在,我尝试了相同的测试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)
---
Run Code Online (Sandbox Code Playgroud)

您会注意到初始链描述中没有错误,并且它显示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)
---
Run Code Online (Sandbox Code Playgroud)

这次,我们收到验证错误。

Soooooo,综上所述,我倾向于怀疑以下内容:

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

至于openssl为什么要这样做呢?不知道。该开关的文档没有提及此工作流程/行为:

-CAfile 文件

A file containing trusted certificates to use during server authentication and to use when attempting to build the client certificate chain.
Run Code Online (Sandbox Code Playgroud)

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