curl 和 openssl 查看不同的发行者
curl and openssl see different issuers
我对此感到很困惑,毫无疑问这是我的误解或类似的误解,但我试图让我的机器与上游代理对话,我正在使用 redsocks 透明地重定向到上游.
下面我们可以看到curl
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 工作,并给了我一个确定,但 curl 不知何故正在使用不同的路径
我实际上不确定如何调试 curl 到底发生了什么。我以为我会得到一个类似的发行人。我可能误解了 s_client 是如何工作的,有人知道发生了什么吗?
您的网络中有一个 SSL 拦截代理,curl 正在使用它,而 openssl 没有使用它,或者该代理没有拦截连接。从你的描述中不清楚具体是什么情况,但可能是
- 您使用的是不同的机器,其中一台的连接被拦截,而另一台则没有
- 拦截代理不会拦截没有服务器名称指示 (SNI) 的连接。 Curl 执行 SNI,而 openssl 不是您使用它的方式。使用
-servername
参数重试 SNI。
1) 您使用了 -k 选项来卷曲,这使得它忽略了 CA 验证 - 但至少它显示了问题所在,一个 MITM SSL 代理。
大概您无法绕过它,在这种情况下,更好的选择可能是检索 "CORPORATE PROXY" CA 本身,并使其成为您工作站上的受信任 CA。这通常不是一个好主意,因为它会破坏 CA 为验证证书主题所做的任何努力。另一方面,公司网络通常会为您做出这个决定。
2) openssl 抱怨只是因为它默认不检查 CA 链。看起来你们不在同一个网络上 and/or 使用与 curl 不同的代理集。如果您检查 http_proxy 或类似的环境,您可能会了解到这一点:
# printenv|egrep -i '(http|proxy)'
或者,如果所有其他方法都失败了,也许您正在使用的 curl 被硬连接为使用不同的 socks 代理,您可以使用 strace 检查 curl 和 openssl 连接到的 IP 地址。寻找连接系统调用使用:
# strace -f -e connect curl https://www.google.com:443
正如您所提到的,openssl 需要 -CApath CERTIFICATEDIR 选项来使用在 CERTIFICATEDIR 中专门命名的 CA 证书验证颁发者。除了 CERTIFICATEDIR 之外,它实际上也在检查系统证书目录以及由发行版提供的 - 因此作为快捷方式,通常可以使用简单的东西:
# openssl s_client -CApath 1 -connect bower.herokuapp.com:443
1会被检查为证书目录,但如果不存在,则会查询系统。您可以在 s_client
的手册中找到其他有用的选项
-servername SNI
将在初始 clienthello 数据包中发送主机名选项,以便服务器(和公司代理)可以更好地决定在主机上使用哪个证书。
-CAfile FILE
如果您知道连接只有一个可接受的 CA。
-showcerts
如果要记录分析所有PEM格式的证书。
-status
它要求服务器通过 OCSP stapling 提供自己证书的 OCSP 状态,openssl 将验证它是否有效。
在我的例子中,我有环境变量 https_proxy 定义代理,curl 正在获取和使用它,而 openssl 没有使用它。因此,公司代理为证书的不同颁发者提供服务。向 openssl 添加命令参数 -proxy 后,curl 和 openssl 都服务于相同的证书链。
我对此感到很困惑,毫无疑问这是我的误解或类似的误解,但我试图让我的机器与上游代理对话,我正在使用 redsocks 透明地重定向到上游.
下面我们可以看到curl
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 工作,并给了我一个确定,但 curl 不知何故正在使用不同的路径
我实际上不确定如何调试 curl 到底发生了什么。我以为我会得到一个类似的发行人。我可能误解了 s_client 是如何工作的,有人知道发生了什么吗?
您的网络中有一个 SSL 拦截代理,curl 正在使用它,而 openssl 没有使用它,或者该代理没有拦截连接。从你的描述中不清楚具体是什么情况,但可能是
- 您使用的是不同的机器,其中一台的连接被拦截,而另一台则没有
- 拦截代理不会拦截没有服务器名称指示 (SNI) 的连接。 Curl 执行 SNI,而 openssl 不是您使用它的方式。使用
-servername
参数重试 SNI。
1) 您使用了 -k 选项来卷曲,这使得它忽略了 CA 验证 - 但至少它显示了问题所在,一个 MITM SSL 代理。
大概您无法绕过它,在这种情况下,更好的选择可能是检索 "CORPORATE PROXY" CA 本身,并使其成为您工作站上的受信任 CA。这通常不是一个好主意,因为它会破坏 CA 为验证证书主题所做的任何努力。另一方面,公司网络通常会为您做出这个决定。
2) openssl 抱怨只是因为它默认不检查 CA 链。看起来你们不在同一个网络上 and/or 使用与 curl 不同的代理集。如果您检查 http_proxy 或类似的环境,您可能会了解到这一点:
# printenv|egrep -i '(http|proxy)'
或者,如果所有其他方法都失败了,也许您正在使用的 curl 被硬连接为使用不同的 socks 代理,您可以使用 strace 检查 curl 和 openssl 连接到的 IP 地址。寻找连接系统调用使用:
# strace -f -e connect curl https://www.google.com:443
正如您所提到的,openssl 需要 -CApath CERTIFICATEDIR 选项来使用在 CERTIFICATEDIR 中专门命名的 CA 证书验证颁发者。除了 CERTIFICATEDIR 之外,它实际上也在检查系统证书目录以及由发行版提供的 - 因此作为快捷方式,通常可以使用简单的东西:
# openssl s_client -CApath 1 -connect bower.herokuapp.com:443
1会被检查为证书目录,但如果不存在,则会查询系统。您可以在 s_client
的手册中找到其他有用的选项-servername SNI
将在初始 clienthello 数据包中发送主机名选项,以便服务器(和公司代理)可以更好地决定在主机上使用哪个证书。
-CAfile FILE
如果您知道连接只有一个可接受的 CA。
-showcerts
如果要记录分析所有PEM格式的证书。
-status
它要求服务器通过 OCSP stapling 提供自己证书的 OCSP 状态,openssl 将验证它是否有效。
在我的例子中,我有环境变量 https_proxy 定义代理,curl 正在获取和使用它,而 openssl 没有使用它。因此,公司代理为证书的不同颁发者提供服务。向 openssl 添加命令参数 -proxy 后,curl 和 openssl 都服务于相同的证书链。