【问题标题】:Ruby SSL error - sslv3 alert unexpected messageRuby SSL 错误 - sslv3 警报意外消息
【发布时间】:2011-10-12 20:36:08
【问题描述】:

我正在尝试在 ruby​​ 脚本中连接到服务器 https://www.xpiron.com/schedule。但是,当我尝试连接时:

require 'open-uri'
doc = open('https://www.xpiron.com/schedule')

我收到以下错误消息:

OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=SSLv2/v3 read server hello A:  sslv3 alert unexpected message         
    from /usr/local/lib/ruby/1.9.1/net/http.rb:678:in `connect'
    from /usr/local/lib/ruby/1.9.1/net/http.rb:678:in `block in connect'
    from /usr/local/lib/ruby/1.9.1/timeout.rb:44:in `timeout'
    from /usr/local/lib/ruby/1.9.1/timeout.rb:87:in `timeout'
    from /usr/local/lib/ruby/1.9.1/net/http.rb:678:in `connect'
    from /usr/local/lib/ruby/1.9.1/net/http.rb:637:in `do_start'
    from /usr/local/lib/ruby/1.9.1/net/http.rb:626:in `start'
    from /usr/local/lib/ruby/1.9.1/net/http.rb:1168:in `request'
    from /usr/local/lib/ruby/1.9.1/net/http.rb:888:in `get'
    from (irb):32
    from /usr/local/bin/irb:12:in `<main>'

我正在运行 Ruby 1.9.2p180。它似乎在其他一些机器上工作,所以它可能是 OpenSSL 或 Ruby 的配置问题。我尝试重新安装所有 SSL 库,并从头开始重建 Ruby,但似乎没有任何效果。有人遇到过这个问题吗?

更新

在非工作机器上,openssl版本为0.9.8o 01 Jun 2010

在工作机器上,它是0.9.8k 25 Mar 2009

所以最近的一个似乎正在打破。

此外,如果我使用不同的 HTTP 客户端(Patron,基于 libcurl),它可以工作:

require 'patron'

sess = Patron::Session.new
sess.timeout = 5
url = 'https://www.xpiron.com/schedule'
resp = sess.get(url)
puts "#{resp.body}"

所以这似乎是 Ruby 的 OpenSSL 绑定的问题。

【问题讨论】:

  • ruby -ropenssl -e 'puts OpenSSL::OPENSSL_VERSION' 在它不工作的机器上说什么,在它工作的机器上说什么?
  • 工作:OpenSSL 0.9.8k 25 Mar 2009 不工作:OpenSSL 0.9.8o 01 Jun 2010 似乎最新版本有所不同。

标签: ruby openssl mechanize


【解决方案1】:

只是为了回答我自己的问题。

问题似乎在于 Ruby 如何协商 SSL 连接。 Xpiron 的 TLS 机制存在错误,它会抛出错误而不是重试其他 SSL 版本。

如果你强制 SSL 版本为 3.0,它可以工作:

require 'net/http'
url = URI.parse('https://www.xpiron.com/schedule')
req = Net::HTTP::Get.new(url.path)
sock = Net::HTTP.new(url.host, 443)
sock.use_ssl = true
sock.ssl_version="SSLv3"
sock.start do |http|
    response = http.request(req)
end

我还在 Ruby 的 bug tracker 上创建了一个问题。

【讨论】:

  • 如果您使用的是 RoR,请告诉我们您在哪个文件中进行了这些修改
【解决方案2】:

我认为这是因为 https URL。绕过这个有一个平均的,完全不安全的黑客,但请自行承担风险谷歌搜索。我宁愿向您展示使用 Net::HTTP 的安全方式:

require 'net/http'

url = URI.parse('https://www.xpiron.com/schedule')
req = Net::HTTP::Get.new(url.path)
sock = Net::HTTP.new(url.host, 443)
sock.use_ssl = true
store = OpenSSL::X509::Store.new
store.add_cert OpenSSL::X509::Certificate.new(File.new('addtrust_ca.pem'))
store.add_cert OpenSSL::X509::Certificate.new(File.new('utn.pem'))
store.add_cert OpenSSL::X509::Certificate.new(File.new('user_first_ca.pem'))
store.add_cert OpenSSL::X509::Certificate.new(File.new('xpiron.pem'))
sock.cert_store = store
sock.start do |http|
  response = http.request(req)
end

您可以通过在浏览器(例如 Firefox)中输入您的 URL 来获取证书文件,然后单击 URL 左侧的图标/更多信息/查看证书/详细信息 -> 单击链中的每个证书并以我上面使用的名称将其导出为 PEM 文件。将这些文件与引用它们的脚本放在同一目录中。那应该会变魔术。但我注意到登录该页面需要 cookie,因此可能需要更多的努力来适当地修改您的请求。

【讨论】:

  • 非常感谢您的回复。我尝试了所有这些,但错误仍然存​​在。我认为问题是 xpiron SSL 服务器配置错误。 Chrome 警告 The connection had to be retried using SSL 3.0. This typically means that the server is using very old software and may have other security issues.
【解决方案3】:

经过一整天的黑客攻击,这个终于为我工作了:

url = URI.parse("https://full-url?test=1&foo=bar")
response = Net::HTTP.start(url.host, use_ssl: true, ssl_version: 'SSLv3', verify_mode: OpenSSL::SSL::VERIFY_NONE) do |http|
  http.get url.request_uri
end

【讨论】:

    【解决方案4】:

    请注意,rest-client gem 在撰写本文时无法设置它。有an outstanding pull request,但不幸的是,gem 似乎没有得到维护。

    【讨论】:

    【解决方案5】:

    可以

    require 'openssl'
    OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
    

    【讨论】:

      猜你喜欢
      • 2012-04-20
      • 1970-01-01
      • 1970-01-01
      • 2022-09-29
      • 1970-01-01
      • 2019-05-10
      • 2016-05-09
      • 2020-08-15
      • 1970-01-01
      相关资源
      最近更新 更多