B Seven B Seven - 10 months ago 63
Ruby Question

How to make a secure HTTP/2 connection to Ruby server with Chrome and Firefox?

The following server code makes an SSL connection with curl and Safari, but it does not work with Firefox or Chrome. Works on Safari after saving cert exception.

server = TCPServer.new( 8080 )

ctx = OpenSSL::SSL::SSLContext.new
ctx.cert = OpenSSL::X509::Certificate.new(File.open('lib/keys/server.crt'))
ctx.key = OpenSSL::PKey::RSA.new(File.open('lib/keys/server.key'))

ctx.ssl_version = :TLSv1_2
ctx.options = OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:options]
ctx.ciphers = OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:ciphers]

server = OpenSSL::SSL::SSLServer.new(server, ctx)

I tried adding the certificate to Firefox and the Keychain (OSX), but I still get

The webpage at https://localhost:8080/ might be temporarily down or it may have moved permanently to a new web address.


Googling suggests that there is an issue with the ciphers, but the following did not make a difference:

ctx.ciphers = 'AESGCM:HIGH:!aNULL:!MD5'
ctx.ciphers = 'TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5'

Commenting out
did not help either.

On Firefox, the connection hangs. Did not find a good way of getting the error.

Using Chrome 53, Firefox 46 and OpenSSL 1.0.2j.

What could cause this error?

Answer Source

It seems that Chrome insists on using ephemeral ECDH key exchange for HTTP/2, and to get that to work you need to set tmp_ecdh_callback:

ctx.tmp_ecdh_callback = lambda do |*args|
  OpenSSL::PKey::EC.new 'prime256v1'

I’ve based this on the example code from the Ruby http-2 gem, which I think is where you’ve got your code from too. Note that in that code it uses lambda do |_args|, (with the underscore but no *) and this causes problems because the number of args is wrong and lambda is strict about passing the right number, so you get errors. I’ve changed it back to the original *args here, it appears to have been changed to fix Rubocop warnings. As you seem to be active in that repo, you might want to change it to something like |*_args|.