Adding SSL to the connection

How do you protect a socket with SSL in Ruby when you need to communicate with clear text first?

I cannot use OpenSSL::SSL::SSLServer , as the client must first request an SSL connection

In short, I am trying to implement RFC3207 where the client sends the keyword "STARTTLS" and then an SSL connection is created.

My question is: "How to create an SSL connection after the server sends" 220 OK "?

I know that I can use OpenSSL::SSL::SSLSocket on the client side, but I have no idea what to do on the server side

If you know how to do this in a language other than Ruby, just submit the code and I will translate it, I have been working on it for about 8 hours and I need everything I can get

I asked in # ruby-lang, but to no avail, and I tried wrapping Socket objects in SSLSockets on the server and client at the same time, but this does not work either

In short, I'm very stuck, I need all the help I can get

+6
source share
3 answers

I created this gist to illustrate how to configure a minimal TLS server. You can leave lines 62-67 to show the new function on the trunk.

But besides this, it is a fully working TLS server, you can use it to add additional features.

You can also change the CN server certificate from "localhost" to the real domain if you want to use it seriously :)

You may notice that most of the work actually sets up PKI aspects correctly. The main part of the server is as follows:

 ctx = OpenSSL::SSL::SSLContext.new ctx.cert = ... # the server certificate ctx.key = ... # the key associated with this certificate ctx.ssl_version = :SSLv23 tcps = TCPServer.new('127.0.0.1', 8443) ssls = OpenSSL::SSL::SSLServer.new(tcps, ctx) ssls.start_immediately = true begin loop do ssl = ssls.accept puts "Connected" begin while line = ssl.gets puts "Client says: #{line}" ssl.write(line) # simple echo, do something more useful here end ensure ssl.close end end ensure tcps.close if tcps end 
+3
source

You must set the SS_Server start_immediately field to false in order to start the SSL server in plain text mode. At any time (i.e. when you receive the STARTTLS command from the client), you can call the SSLSocket receive method to initiate the SSL / TLS handshake. Of course, the client must agree to the protocol :)

Here is an example server that I wrote to test this:

 #!/usr/bin/ruby require 'socket'; require 'openssl'; certfile = 'mycert.pem'; port = 9002; server = TCPServer.new( port ); # Establish an SSL context sslContext = OpenSSL::SSL::SSLContext.new sslContext.cert = OpenSSL::X509::Certificate.new( File.open( certfile ) ); sslContext.key = OpenSSL::PKey::RSA.new( File.open( certfile ) ); # Create SSL server sslServer = OpenSSL::SSL::SSLServer.new( server, sslContext ); # Don't expect an immidate SSL handshake upon connection. sslServer.start_immediately = false; sslSocket = sslServer.accept; sslSocket.puts( "Toast.." ); # Server loop while line = sslSocket.gets line.chomp!; if "STARTTLS" == line # Starting TLS sslSocket.accept; end sslSocket.puts( "Got '#{line}'" ); end sslSocket.close; 

I'm sure the original poster knows how to test STARTTLS, but the rest of us may need this reminder. Usually I usually use the utils from the GNUTLS package (gnutls-bin in debian / ubuntu) to test starttls because it allows me to start shaking hands when I want:

 $ gnutls-cli --starttls --port 9002 --insecure localhost 

This connection is in plain text TCP socket mode. Enter a few lines and get their echo. This traffic is not encrypted. If you send STARTTLS , sslSocket.accept is sslSocket.accept and the server is waiting for SSL confirmation. Press ctrl-d (EOF) to start handshaking from the gnutls client and see how to establish an encrypted SSL connection. Subsequent lines will also echo, but traffic is now encrypted.

+3
source

I made some progress on this, saved for future use:

  • Yes, you should use OpenSSL :: SSL :: SSLSocket at both ends
  • On the server side, you must create an OpenSSL :: SSL :: SSLContext object , passing the character with the protocol you want to use, and "_server" is added to the end, see OpenSSL :: SSL :: SSLContext :: METHODS I mean, in short, โ€œTLSv1_serverโ€ for RFC3207 does not even need to do this, on the server side create a context with certificates, and then call #accept on the socket to wait for the client to transfer
  • Passing SSL certificates to a ctx object

Edit as you wish

0
source

Source: https://habr.com/ru/post/913812/


All Articles