Ruby SSL error - sslv3 alert unexpected message

匆匆过客 提交于 2019-11-28 11:30:06

Just to answer my own question.

The problem seems to be with how Ruby negotiates SSL connections. There's an error in Xpiron's TLS mechanism, and it throws an error instead of retrying to other SSL versions.

If you force the SSL version to 3.0, it works:

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

I also created an issue on Ruby's bug tracker.

I think it's because of the https URL. There's a mean, completely insecure hack for bypassing this, but please google for it at your own risk. I will rather show you the secure way of doing it, using 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

You may obtain the certificate files by entering your URL in the browser (e.g. Firefox), and then clicking on the icon left of the URL/More Information/View Certificate/Details -> there click on each certificate in the chain and export it as a PEM file under the names I used above. Put these files in the same directory as the script referencing them. That should do the magic. But I noticed that a cookie is required to login to that page, so it might require a bit more effort of modifying your request appropriately.

After a full day of hacking, this one finally worked for me:

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

Note that rest-client gem does not have a means to set this as of this writing. There is an outstanding pull request but the gem does not appear to be maintained, unfortunately.

It can be

require 'openssl'
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!