curl和openssl看到不同的发行人

时间:2015-12-14 06:49:38

标签: ssl curl openssl

我对此非常困惑,毫无疑问这是我的误解或其他一些问题,但我试图让我的机器与上游代理交谈,我使用redsocks来透明地重定向到上游。

下面我们可以看到卷曲

root@Amachine:/# curl -v -k https://bower.herokuapp.com
* Rebuilt URL to: https://bower.herokuapp.com/
* Hostname was NOT found in DNS cache
*   Trying 54.235.187.231...
* Connected to bower.herokuapp.com (54.235.187.231) port 443 (#0)
* 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 handshake, Server key exchange (12):
* SSLv3, TLS handshake, Server finished (14):
* SSLv3, TLS handshake, Client key exchange (16):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-SHA
* Server certificate:
*        subject: C=US; ST=California; L=San Francisco; O=Heroku, Inc.; CN=*.herokuapp.com
*        start date: 2014-01-21 00:00:00 GMT
*        expire date: 2017-05-19 12:00:00 GMT
*        issuer: CORPORATE PROXY

发行人似乎是公司代理人。打破所有ssl通讯。

root@machine:/# openssl s_client -connect bower.herokuapp.com:443
CONNECTED(00000003)
depth=1 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert SHA2 High Assurance Server CA
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
 0 s:/C=US/ST=California/L=San Francisco/O=Heroku, Inc./CN=*.herokuapp.com
   i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 High Assurance Server CA
 1 s:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 High Assurance Server CA
   i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA

令我困惑的是,他们有不同的发行人。 Granted curl似乎隐藏了大部分正在发生的事情。我可以指定根ca路径和openssl工作,并给我一个确定,但卷曲不知何故使用不同的路径

我实际上不确定如何调试卷曲中发生的事情。我以为我会得到一个类似的发行人。我可能误解了s_client的工作方式,有人知道发生了什么吗?

3 个答案:

答案 0 :(得分:5)

您的网络中有一个SSL拦截代理,而curl正在使用它,而openssl不使用它,或者代理不拦截连接。从您的描述中不清楚案件究竟是什么,但可能是

  • 你正在使用不同的机器,并且从一个连接被截获而另一个不是
  • 拦截代理不会在没有服务器名称指示(SNI)的情况下拦截连接。 Curl执行SNI而openssl不是您使用它的方式。使用-servername参数重试SNI。

答案 1 :(得分:1)

1) You used the -k option to curl, which makes it ignore the CA verification - but at least it's showing what would the problem be, an MITM SSL proxy.

Presumably you can't bypass it, in this case a better option might be to retrieve the "CORPORATE PROXY" CA itself, and make it a trusted CA on your workstation. This is generally not a good idea, as it's destroying any effort that the CA's made to verify the certificate subject. On the other hand corporate networks generally make this decision for you anyway.

2) openssl is complaining only because it does not check the CA chain by default. It also seems you're not on the same network and/or use a different set of proxies than with curl. You may learn this if you check the environment for http_proxy or similar:

# printenv|egrep -i '(http|proxy)'

Or, if all else fails, perhaps the curl you're using is hardwired to use a different socks proxy, you can check with strace, what IP address curl and openssl is connecting to. Look for the connect syscall use with:

# strace -f -e connect curl https://www.google.com:443

As you mentioned, openssl needs the -CApath CERTIFICATEDIR option to verify the issuers with the CA certificates specially named in the CERTIFICATEDIR. Apart from CERTIFICATEDIR, it's actually checking the system certificate directory as well which was provided by the distribution - so as a shortcut, something as simple can usually work:

# openssl s_client -CApath 1 -connect bower.herokuapp.com:443

1 will be checked as a directory for certificates, but if it does not exist, the system will be consulted. Other useful options you can find in the manual for s_client

-servername SNI

Will send a hostname option in the initial clienthello packet so that the server (and the corporate proxy) can better decide which certificate to use on the host.

-CAfile FILE

If you know there's only a single acceptable CA for the connection.

-showcerts

If you want to record and analyse all the certificates in PEM format.

-status

It asks the server to provide the OCSP status of its own certificate via OCSP stapling and openssl will verify if it is valid.

答案 2 :(得分:0)

就我而言,我有环境变量 https_proxy 定义了代理,curl正在获取和使用,而openssl未使用它。因此,公司代理为证书的不同发行人提供服务。将命令参数-proxy添加到openssl之后,curl和openssl都使用相同的证书链。