Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Server Name Indication support in Net::HTTP?

I'm trying to get Ruby's Net::HTTP implementation to work with SNI.

Both mail.google.com and gmail.com live on the same IP address, so when connecting via SSL, the Google server needs to know which certificate to use. By default, it returns the mail.google.com certificate, which is a problem if you're trying to implement WebFinger.

WebFinger requires you to retrieve https://gmail.com/.well-known/host-meta to get the LRDD information, however, for security reasons, it's critical to verify the SSL certificate information.

Since Google serves up the default mail.google.com certificate in this case, the SSL post_connection_check fails. The correct solution here would be to enable Server Name Indication for Net::HTTP, but it's not clear to me how to get that working with the Ruby bindings for OpenSSL. Anyone else have an idea?

You should be able to see the problem by running:

require 'open-uri'
open('https://gmail.com/.well-known/host-meta') { |f| f.read }

I've also created a gist that exhibits the problem using an earlier version of curl and OpenSSL:

https://gist.github.com/7936ef38787092a22897

like image 976
Bob Aman Avatar asked Jan 13 '11 21:01

Bob Aman


2 Answers

For SNI support, you need a newer OpenSSL release (0.9.8f with --enable-tlsext or 0.9.8j or later) and call OpenSSL::SSL::SSLSocket#hostname = 'hostname' before SSLSocket#connect. Net::HTTPS does not support SNI yet, and open-uri doesn't.

Checking out httpclient development repository should support SNI.

  • https://github.com/nahi/httpclient

Let me know if you need released gem real soon now...

like image 61
NaHi Avatar answered Oct 27 '22 01:10

NaHi


Ruby 2.0 will address the TLS SNI (Server Name Indication) issue:

from net/http..

#        ...
#           s.session = @ssl_session if @ssl_session
#           # Server Name Indication (SNI) RFC 3546
#           s.hostname = @address if s.respond_to? :hostname=
#           Timeout.timeout(@open_timeout, Net::OpenTimeout) { s.connect }
#           if @ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE
#             s.post_connection_check(@address)
#           end
#           ...

To make this work in 1.9.2 (or higher ) apply similar patch to net/http

#         ...
# BEGIN:  SNI PATCH http://bugs.ruby-lang.org/issues/4351
#          s.hostname = @address if s.respond_to? :hostname=
# END:   SNI PATCH http://bugs.ruby-lang.org/issues/4351
#          timeout(@open_timeout) { s.connect }
#          if @ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE
#            s.post_connection_check(@address)
#          end
#        ...

see also: http://bugs.ruby-lang.org/issues/4351 http://en.wikipedia.org/wiki/Server_Name_Indication

like image 30
michael bisignani Avatar answered Oct 27 '22 01:10

michael bisignani