0

I want to write a simple server in Ruby that returns a different TLS certificate depending on the hostname. Currently I do it so that I specify a TCPServer with SSLContext and give the SSLContext certificate and key. This certificate is then used for all connections regardless of the hostname.

context = OpenSSL::SSL::SSLContext.new

context.min_version = :TLS1_2
context.add_certificate cert, key

serv = TCPServer.new host, port
secure = OpenSSL::SSL::SSLServer.new(serv, context)

Thread.new(secure.accept) do |conn|
  # do stuff
end

Therefore a different certificate should be sent depending on the SNI. How to implement this?

Marek Küthe
  • 90
  • 1
  • 8

1 Answers1

0

You can use servername_cb:

context.servername_cb = lambda do |_, name|
  ctx = OpenSSL::SSL::SSLContext.new

  # load certificate for name

  ctx.add_certificate cert[0], cert[1]
        
  return ctx
end

Alternatively, you can use the already existing Context:

context.servername_cb = lambda do |socket, name|
  ctx = socket.context

  # load certificate for name

  ctx.add_certificate cert[0], cert[1]
        
  return ctx
end

The function which servername_cb is called during the TLS handshake. It is passed an SSLSocket and the name as argument. It is expected to return an SSLContext with corresponding certificates. https://ruby-doc.org/3.1.2/exts/openssl/OpenSSL/SSL/SSLContext.html#attribute-i-servername_cb

Marek Küthe
  • 90
  • 1
  • 8