4

这篇文章几乎重复了许多其他文章,包括Rails 4 和 Ruby 2 Net/HTTP SSL Request: OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=SSLv2/v3 read server hello A: unknown protocol and SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed,但有一个关键区别:“证书验证失败”错误仅在通过 SSL 代理 ( Charles ) 代理时发生,并且仅在最新版本中发生红宝石。

具体来说,这个(非代理)代码有效:

  uri = URI.parse('https://www.ibm.com')
  http = Net::HTTP.new(uri.host, uri.port, nil)
  http.use_ssl = true
  http.start { |agent| agent.get(uri.path) }

并且此(代理)代码因“证书验证失败”错误而失败:

  uri = URI.parse('https://www.ibm.com')
  http = Net::HTTP.new(uri.host, uri.port, "localhost", 8888)
  http.use_ssl = true
  http.start { |agent| agent.get(uri.path) }

谜题

该错误仅在通过当前版本的 Ruby/OpenSSL 中的代理时出现。尤其是:

  • 不通过代理时没有错误,这让我认为本地证书是有效的。
  • 使用 Firefox 或 通过代理时没有错误curl -v https://www.ibm.com/,这让我认为 Charles 证书是有效的。
  • 在早期版本的 Ruby / OpenSSL 上通过代理没有错误(请参阅下面的两个环境)。

所有这一切让我怀疑是一个真正的 Ruby 错误,而不是我的证书有问题,但我很乐意看到其他情况。

当前环境

我正在观察这个环境的错误:

$ system_profiler SPSoftwareDataType | grep "System Version"
    System Version: OS X 10.8.5 (12F45)
$ ruby --version ; openssl version ; gem list | grep http
ruby 2.0.0p247 (2013-06-27) [x86_64-darwin12.4.0]
OpenSSL 1.0.1e 11 Feb 2013
http-cookie (1.0.2)
http_router (0.10.2)
net-http-digest_auth (1.4)
net-http-persistent (2.9)
ntlm-http (0.1.1)

之前的环境

稍旧版本的 ruby​​/OpenSSL 不会出现该错误:

$ ruby --version ; openssl version ; gem list | grep http
ruby 2.0.0p0 (2013-02-24 revision 39474) [x86_64-darwin10.8.0]
OpenSSL 0.9.8y 5 Feb 2013
http_router (0.11.0, 0.10.2)
httpauth (0.2.0)
net-http-digest_auth (1.2.1)
net-http-persistent (2.8)
ntlm-http (0.1.1)
4

2 回答 2

2

这里发生的情况是,Charles 无法为您提供“ https://www.ibm.com ”的有效证书,因为无论您为 Charles 设置什么证书(或者如果 Charles 创建自己的证书),它都不能用于“www.ibm.com”名称并由受信任的证书颁发机构认证。这就是为什么如果客户端验证证书连接失败,如果你跳过验证

http.verify_mode = OpenSSL::SSL::VERIFY_NONE

它可能适用于旧版本的 ruby​​,因为最近才调整“net/https”以默认验证证书。

于 2014-01-05T22:11:49.930 回答
0

我似乎记得需要在 ENV var 中指向该证书。如果您并不真正关心验证,则更容易:

http.verify_mode = OpenSSL::SSL::VERIFY_NONE
于 2013-10-20T02:02:45.130 回答