curl SSL证书错误:验证失败

4

请帮我理解为什么我无法通过https成功地使用curl访问此URL:

我正在使用Ubuntu 12.04.5,curl 7.22.0,libcurl 7.22.0和OpenSSL 1.0.1-4ubuntu5.25。

$ 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

并且这会返回 验证返回代码:0(ok)

我也运行了sudo update-ca-certificates --fresh以确保,但没有成功。

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


2个回答

4
你遇到了一个由长期存在的问题引起的错误,即OpenSSL在处理多个信任路径的情况时存在问题。如果你查看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.html以及OpenSSL bug report

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

4
curl 的 --cacert <cert> 选项用于指定 证书授权机构 以验证服务器证书。您从 s_client 输出中复制的证书是 服务器证书,而将其作为 --cacert 参数使用会失败,因为服务器证书不是自签名的,而是由另一个证书授权机构签署的(在您的情况下是 Go Daddy)。
使用--capath 选项调用 curl,以指定信任的根 CA。 这类似于 s_client-CApath <dir> 选项。
$ curl -v --capath /etc/ssl/certs https://www.onevanilla.com

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