Ruby client unable to connect via TLS

I can’t get a Ruby TCP client to connect to the HTTPS endpoint of a Fly application. curl works, and open-uri works, so that’s close!

But this simple script

require 'socket'
require 'openssl'

host = 'fly.io' # or any *.fly.dev
port = 443

socket = TCPSocket.new(host, port)
ssl_context = OpenSSL::SSL::SSLContext.new
ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE # just to prove it's not this

ssl_socket = OpenSSL::SSL::SSLSocket.new(socket, ssl_context)
ssl_socket.sync_close = true

ssl_socket.connect

blows up with

SSL_connect SYSCALL returned=5 errno=0 state=SSLv3/TLS write client hello (OpenSSL::SSL::SSLError)

I checked ssl_context.ciphers and there is overlap with Fly’s supported ciphers.

I tried it on a couple versions of Ruby and OpenSSL, the newest being Ruby 3.2.2 and OpenSSL 3.1.0.

The original reason for diving into this was trying to get Faye::WebSocket::Client to connect, but it was being closed immediately without an error. I think this is the root cause, but I’m at my wit’s end. Thanks in advance for any suggestions or debugging tips.

Try:

require 'net/https'

host = 'fly.io'
port = 443

http = Net::HTTP.new(host, port) 
http.use_ssl = true
request = Net::HTTP::Get.new('/')
response = http.request(request)
puts response.body

There is a character encoding issue in the response, but yeah that works fine. Which lines up with open-uri working, too.

Unfortunately I still need the raw TCP connection to work to get a WebSocket client connected.

I have additionally tried allocating a static IPv4 address per the advice of @Andy_Glassman, but that didn’t help.

So I did find the fix for this particular problem. The solution was setting

ssl_socket.hostname = host

before connecting. This sets the “SNI hostname” extension, which I am guessing is required for Fly to figure out which certificate to serve up on a given IP endpoint.

Unfortunately, I dug into the source for faye-websocket and eventmachine, and the SNI hostname is correctly populated by these libraries. So I am back to square one, trying to figure out why the WebSocket client won’t connect. That’s a separate issue from my original question, so I may open a new thread for that.

It turns out the faye-websocket gem needed to be upgraded to v0.11.3 to pull in changes that set the SNI hostname correctly. After the upgrade, the WebSocket client connects up to Fly just fine.

2 Likes

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.