Bug #10533
closedHTTP reconnection with SNI does not send correct hostname
Description
When reconnecting after connection timeout on an SNI connection the server name is not sent during reconnect which results in a failed reconnection:
$ cat test.rb
require 'net/http'
uri = URI 'https://david.shanske.com'
Net::HTTP.start uri.hostname, uri.port, use_ssl: true do |http|
req = Net::HTTP::Get.new uri
response = http.request req
p response.code
sleep 310
req = Net::HTTP::Get.new uri
response = http.request req
p response.code
end
$ ruby -v test.rb
ruby 2.1.5p273 (2014-11-13 revision 48405) [x86_64-darwin14.0]
"200"
/usr/local/lib/ruby/2.1.0/openssl/ssl.rb:178:in `post_connection_check': hostname "david.shanske.com" does not match the server certificate (OpenSSL::SSL::SSLError)
from /usr/local/lib/ruby/2.1.0/net/http.rb:922:in `connect'
from /usr/local/lib/ruby/2.1.0/net/http.rb:1447:in `begin_transport'
from /usr/local/lib/ruby/2.1.0/net/http.rb:1404:in `transport_request'
from /usr/local/lib/ruby/2.1.0/net/http.rb:1378:in `request'
from test.rb:10:in `block in <main>'
from /usr/local/lib/ruby/2.1.0/net/http.rb:853:in `start'
from /usr/local/lib/ruby/2.1.0/net/http.rb:583:in `start'
from test.rb:4:in `<main>'
Files
Updated by drbrain (Eric Hodel) almost 10 years ago
- File net.http.bug10533.patch net.http.bug10533.patch added
- Backport changed from 2.0.0: UNKNOWN, 2.1: UNKNOWN to 2.0.0: REQUIRED, 2.1: REQUIRED
If session resumption is requested with an expired SSL session on an SNI server then the handshake goes wrong and the connection fails as above.
The attached patch only attempts session resumption if the session is still valid.
Updated by drbrain (Eric Hodel) almost 10 years ago
- Status changed from Open to Assigned
- Assignee set to naruse (Yui NARUSE)
Updated by drbrain (Eric Hodel) almost 10 years ago
Ultimately I think this may be an OpenSSL bug.
Looking at the ClientHello message for the second connection (which uses session resumption) no ServerNameIndication extension is present. Without this the server won't be able to respond with the correct certificate.
Updated by drbrain (Eric Hodel) almost 10 years ago
- Assignee changed from naruse (Yui NARUSE) to drbrain (Eric Hodel)
Via #ruby-core IRC:
22:53 nurse: ok > 10533
So I will commit it.
Updated by drbrain (Eric Hodel) almost 10 years ago
- Status changed from Assigned to Closed
- % Done changed from 0 to 100
Applied in changeset r48563.
- lib/net/http.rb: Do not attempt SSL session resumption when the
session is expired. [Bug #10533]
Updated by usa (Usaku NAKAMURA) almost 10 years ago
- Backport changed from 2.0.0: REQUIRED, 2.1: REQUIRED to 2.0.0: DONE, 2.1: REQUIRED
Backported into ruby_2_0_0
at r48636.
Updated by nagachika (Tomoyuki Chikanaga) almost 10 years ago
- Backport changed from 2.0.0: DONE, 2.1: REQUIRED to 2.0.0: DONE, 2.1: DONE
r48563 and test for it (r46261,r48581) were backported into ruby_2_1
branch at r49631.
Updated by mkarnebeek (Michiel Karnebeek) over 9 years ago
The patch does not seem to solve the reported issue.
Reconnecting HTTP connections still do not send an SNI.
I'm running ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-darwin14] and checked using Wireshark.
Updated by mkarnebeek (Michiel Karnebeek) over 9 years ago
Following up on my comment a few days ago:
I ran a test in python using https://github.com/nabla-c0d3/sslyze (with OpenSSL 1.0.2a, same version as in Ruby) and introduced a sleep longer than the ssl session TTL at https://github.com/nabla-c0d3/sslyze/blob/master/plugins/PluginSessionResumption.py#L248 to see if this did supply the SNI
According to Wireshark, this correctly put both the SNI and session ticket in the Client Hello packet.
I think this is evidence that the OpenSSL used is capable of doing this, and that either Net::Http or the c-bindings for ruby to OpenSSL are doing something wrong.
Updated by mkarnebeek (Michiel Karnebeek) over 9 years ago
It looks like i've solved it: Moving s.hostname = @address
before s.session = @ssl_session
has solved it on my end.
See the attached patch
Updated by mkarnebeek (Michiel Karnebeek) over 9 years ago
Updated by mkarnebeek (Michiel Karnebeek) over 9 years ago
Root cause seems to be in ossl_ssl.c:
Net::Http calls s.session=
(C-method ossl_ssl_set_session
), which calls C-method ossl_ssl_setup
, which only sets up the ssl client (ssl
) once due to "if(!ssl){
". The problem is that the hostname setting (the call to SSL_set_tlsext_host_name
) is done within that "if(!ssl){
" block.
When later Net::Http calls s.connect
(C-method ossl_ssl_connect
), ossl_ssl_setup
is called a second time, but it does not set up the hostname.
Updated by a.holstvoogd (Arthur Holstvoogd) over 9 years ago
Related i.e same issue: #10398
Updated by naruse (Yui NARUSE) over 9 years ago
- Related to Bug #10398: Server Name Indication support broken when reusing a (dead) session added