【问题标题】:curl SSL certificate error: verifcation failedcurl SSL证书错误:验证失败
【发布时间】:2015-06-05 15:25:27
【问题描述】:

请帮助我理解为什么我无法通过 https 成功 curl 这个网址:

我正在使用带有 curl 7.22.0、libcurl 7.22.0 和 OpenSSL 1.0.1-4ubuntu5.25 的 Ubuntu 12.04.5

$ curl -v https://www.onevanilla.com/
* About to connect() to www.onevanilla.com port 443 (#0)
*   Trying 199.83.128.4... connected
* successfully set certificate verify locations:
*   CAfile: none
  CApath: /etc/ssl/certs
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS alert, Server hello (2):
* SSL certificate problem, verify that the CA cert is OK. Details:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
* Closing connection #0
curl: (60) SSL certificate problem, verify that the CA cert is OK. Details:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

所以我尝试手动获取证书:

$ openssl s_client -connect www.onevanilla.com:443 </dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > /tmp/www.onevanilla.com.pem

然后:

$ curl -v --cacert /tmp/www.onevanilla.com.pem https://www.onevanilla.com

但我得到相同的结果:

* About to connect() to www.onevanilla.com port 443 (#0)
*   Trying 199.83.128.4... connected
* successfully set certificate verify locations:
*   CAfile: /tmp/www.onevanilla.com.pem
  CApath: /etc/ssl/certs
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS alert, Server hello (2):
* SSL certificate problem, verify that the CA cert is OK. Details:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
* Closing connection #0
curl: (60) SSL certificate problem, verify that the CA cert is OK. Details:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

我可以用 openssl 验证证书:

$ openssl s_client -host www.onevanilla.com -port 443 -CApath /etc/ssl/certs

这会返回Verify return code: 0 (ok)

为了确定,我还运行了sudo update-ca-certificates --fresh,但没有运气。

所以在我看来,证书是有效的(未过期,主机名与 CN 匹配),但我永远无法使用 curl 获得成功的响应(当然,除非我使用 -k--insecure 选项)。谁能解释一下?

【问题讨论】:

标签: ssl curl https ssl-certificate


【解决方案1】:

您遇到了一个长期存在的问题,即 OpenSSL 无法正确处理具有多个信任路径的情况。如果您查看report from SSLLabs,您会看到,服务器提供了以下链:

[0] /O=www.onevanilla.com/OU=Domain Control Validated/CN=www.onevanilla.com SAN=DNS:www.onevanilla.com,DNS:onevanilla.com
[1] /C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certificates.godaddy.com/repository/CN=Go Daddy Secure Certification Authority/serialNumber=07969287
[2] /C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
[3] /L=ValiCert Validation Network/O=ValiCert, Inc./OU=ValiCert Class 2 Policy Validation Authority/CN=http://www.valicert.com//emailAddress=info@valicert.com

浏览器已包含Go Daddy Class 2 Certification Authority 的根证书,因此可以使用 [0]、[1] 和根证书构建信任路径,因此它们将忽略证书 [2] 和 [3]。相反,OpenSSL 将仅忽略证书 [3],因为它是自签名的,因此根本不应该包含在链中。然后它将尝试验证链 [0],[1],[2] 并且将失败,因为它没有找到根证书签名 [2]。它不会尝试验证较短的链 [0],[1]。

有关此问题的更多详细信息,请参阅 Python Urllib2 SSL errorhttp://kriscience.blogspot.de/2013/03/supporting-trusted-but-untrusted.htmlthe OpenSSL bug report

您可以做什么:从https://certs.godaddy.com/repository/valicert_class2_root.crt 获取丢失的证书并在--cacert 参数中使用它。

【讨论】:

    【解决方案2】:

    curl --cacert &lt;cert&gt; 选项用于指定一个证书颁发机构,用于验证服务器证书。您从s_client 输出复制的证书是服务器证书,将其用作--cacert 参数会失败,因为服务器证书不是自签名的,而是由不同的证书颁发机构签名的(在你的情况下,Go Daddy)。

    使用 --capath 选项调用 curl 以指定受信任的根 CA。这类似于 s_client -CApath &lt;dir&gt; 选项。

    $ curl -v --capath /etc/ssl/certs https://www.onevanilla.com
    

    【讨论】:

      猜你喜欢
      • 2014-10-14
      • 2019-09-08
      • 2015-11-19
      • 1970-01-01
      • 2018-06-07
      • 1970-01-01
      • 2018-03-16
      • 1970-01-01
      相关资源
      最近更新 更多