bear-metal / tunemygc

TuneMyGC - optimal MRI Ruby 2.1+ Garbage Collection
https://www.tunemygc.com
346 stars 25 forks source link

SSL handshake failures #22

Closed travisp closed 8 years ago

travisp commented 9 years ago

When attempting to use tunemygc, syncing snapshots with the server seems to result in:

Config reccommendation error (SSL_connect returned=1 errno=0 state=SSLv2/v3 read server hello A: sslv3 alert handshake failure)

Not sure if this is a result of a misconfiguration in the tunemygc gem or the servers.

kevinjbayer commented 9 years ago

I'm getting the exact same thing on Heroku.

Config reccommendation error (SSL_connect returned=1 errno=0 state=SSLv2/v3 read server hello A: sslv3 alert handshake failure)

knightq commented 9 years ago

We are getting a similar error too:

Config reccommendation error (SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed)

(ruby: 2.2.2)

mjtko commented 9 years ago

I've spent a little time trying to track this down, and believe I've got to the bottom of it. I have, at least, made a simple SSL connection reproduction stop failing though I haven't finished performing a full end-to-end test of tunemygc yet.

My repro was:

irb(main):001:0> require 'net/https'
=> true
irb(main):002:0> uri = URI("https://tunemygc.com")
=> #<URI::HTTPS https://tunemygc.com>
irb(main):003:0> client = Net::HTTP.new(uri.host, uri.port)
=> #<Net::HTTP tunemygc.com:443 open=false>
irb(main):004:0> client.use_ssl = true
=> true
irb(main):005:0> client.post('/ruby', 'test')
OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed
    from /app/vendor/ruby-2.2.2/lib/ruby/2.2.0/net/http.rb:923:in `connect'
    from /app/vendor/ruby-2.2.2/lib/ruby/2.2.0/net/http.rb:923:in `block in connect'
    from /app/vendor/ruby-2.2.2/lib/ruby/2.2.0/timeout.rb:74:in `timeout'
    from /app/vendor/ruby-2.2.2/lib/ruby/2.2.0/net/http.rb:923:in `connect'
    from /app/vendor/ruby-2.2.2/lib/ruby/2.2.0/net/http.rb:863:in `do_start'
    from /app/vendor/ruby-2.2.2/lib/ruby/2.2.0/net/http.rb:852:in `start'
    from /app/vendor/ruby-2.2.2/lib/ruby/2.2.0/net/http.rb:1375:in `request'
    from /app/vendor/ruby-2.2.2/lib/ruby/2.2.0/net/http.rb:1398:in `send_entity'
    from /app/vendor/ruby-2.2.2/lib/ruby/2.2.0/net/http.rb:1186:in `post'
    from (irb):6
    from /app/bin/irb:15:in `<main>'

It turns out that Heroku's cedar-10 stack ships with openssl 0.9.8k (OpenSSL 0.9.8k 25 Mar 2009). The certificate in use on https://tunemygc.com/ (from Cloudflare) is not compatible with openssl 0.9.8 -- see "Handshake simulation" from these SSL Labs test results:

https://www.ssllabs.com/ssltest/analyze.html?d=tunemygc.com&s=104.28.24.78&hideResults=on

So, if you're getting this error, try upgrading to a more modern OpenSSL -- in my Heroku case, migrating from the cedar-10 stack to the cedar-14 stack seems to do the trick as that ships with openssl 1.0.1f (OpenSSL 1.0.1f 6 Jan 2014).

With this in place, my previously failing repro case no longer fails:

irb(main):001:0> require 'net/https'
=> true
irb(main):002:0> uri = URI.parse('https://tunemygc.com')
=> #<URI::HTTPS https://tunemygc.com>
irb(main):003:0> client = Net::HTTP.new(uri.host, uri.port)
=> #<Net::HTTP tunemygc.com:443 open=false>
irb(main):004:0> client.use_ssl = true
=> true
irb(main):005:0> client.post('/ruby', 'test')
=> #<Net::HTTPOK 200 OK readbody=true>
irb(main):006:0>

HTH! I'll report back once I've completed an end-to-end run too.

mjtko commented 9 years ago

It lives! Now getting measurements through! :fireworks:

Ways of mitigating this problem that spring to mind:

Option 2 seems like a good one if option 1 isn't possible!

methodmissing commented 9 years ago

Awesome investigation :-) We'll work on options 1 and 2. Thanks so much!

mjtko commented 9 years ago

Just in case you didn't see my line note... See my above line note. :)