请帮助我理解为什么我无法通过https:
成功卷曲此网址我使用的是Ubuntu 12.04.5,卷曲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
然后返回Verify return code: 0 (ok)
我还运行sudo update-ca-certificates --fresh
只是为了确定,但没有运气。
所以在我看来,证书有效(未过期,主机名与CN匹配),但我永远无法使用curl获得成功的响应(除非我当然使用-k
或--insecure
选项)。有人可以解释一下吗?
答案 0 :(得分:3)
您遇到了一个长期存在的问题,即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 error和http://kriscience.blogspot.de/2013/03/supporting-trusted-but-untrusted.html以及the OpenSSL bug report。
您可以做什么:从https://certs.godaddy.com/repository/valicert_class2_root.crt获取遗失的证书,并在--cacert
参数中使用它。
答案 1 :(得分:1)
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