Class: PacketThief::Handlers::SSLServer

Inherits:
AbstractSSLHandler show all
Defined in:
lib/packetthief/handlers/ssl_server.rb

Overview

Basic SSL/TLS Server built on Ruby’s OpenSSL objects instead of on EventMachine’s start_tls. This allows you to manipulate the SSLContext and other details of the connection that EM normally doesn’t let you touch.

Subclass it and override any of the methods in the following example to use the the functionality.

You can #send_data to send encrypted data to the other side, and #receive_data will be called when there is data for the handler.

EM.run {
  # Leave the hostname blank for Linux's netfilter.
  SSLServer.start '', 54321 do |p|

    # Note: this code block is actually too late to set up a new
    # #post_init since it runs just after post_init. Instead, you would
    # use post_init in a subclass.
    def p.post_init
      # modify p.ctx to configure your certificates, key, etc.
    end

    # In this example, the following would work in this initialization
    # block:
    h.ctx.cert = cert
    h.ctx.extra_chain_cert = chain
    h.ctx.key = key

    def servername_cb(sock, hostname)
      # implement your own SNI handling callback. The default will
      # return the originally configured context.
    end

    def p.tls_successful_handshake
      # the handshake succeeded
    end

    def p.tls_failed_handshake(e)
      # the ssl handshake failed, probably due to the client rejecting
      # your certificate. =)
    end

    def p.unbind
      # unbind handler, called regardless of handshake success
    end

    def p.receive_data(data)
      # do something with the unencrypted stream
      p.send_data("some message") # data to be encrypted then sent to the client
    end

  end
}

Note: During #initialize and #post_init, this class does not have access to its socket yet. Instead, use #tls_pre_start or the code block you pass to .start to initialize the SSLContext, and use #tls_post_accept to do anything once the SSL handshake has completed. You can also override #servername_cb to perform the SNI callback.

Direct Known Subclasses

SSLTransparentProxy

Defined Under Namespace

Modules: InitialServer

Instance Attribute Summary collapse

Attributes inherited from AbstractSSLHandler

#ctx, #sni_hostname, #sslsocket, #tcpsocket

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from AbstractSSLHandler

#close_connection, #close_connection_after_writing, #notify_readable, #notify_writable, #post_init, #receive_data, #send_data, #tls_begin, #tls_failed_handshake, #tls_successful_handshake, #unbind, #write_buffer, #write_buffer=

Methods included from Logging

log

Constructor Details

#initialize(tcpsocket) ⇒ SSLServer

Returns a new instance of SSLServer.



147
148
149
150
# File 'lib/packetthief/handlers/ssl_server.rb', line 147

def initialize(tcpsocket)
  super(tcpsocket)
  @ctx.servername_cb = proc {|sslsocket, hostname| self.servername_cb(sslsocket, hostname) }
end

Instance Attribute Details

#server_handlerObject

reference to the InitialServer that created the current handler. exists so you can call #stop_server or do something else to it directly.



67
68
69
# File 'lib/packetthief/handlers/ssl_server.rb', line 67

def server_handler
  @server_handler
end

Class Method Details

.start(host, port, *args, &block) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/packetthief/handlers/ssl_server.rb', line 69

def self.start(host, port, *args, &block)
  ssl_class = self

  serv = TCPServer.new host, port

  # We use InitialServer to listen for incoming connections. It will then
  # create the actual SSLServer.
  initialserver = ::EM.watch serv, InitialServer, serv, ssl_class, args, block do |h|
    h.notify_readable = true
  end

  initialserver
end

Instance Method Details

#servername_cb(sslsock, hostname) ⇒ Object

Called when the client sends a hostname using the SNI TLS extension.

This method should return an OpenSSL::SSL::SSLContext. It gives you an opportunity to pick or generate a different server certificate or certificate chain based on the hostname requested by the client.

The default implementation does nothing by just returning the original SSLContext.



161
162
163
# File 'lib/packetthief/handlers/ssl_server.rb', line 161

def servername_cb(sslsock, hostname)
  sslsock.context
end

#stop_serverObject

Stops the InitialListener sever handler that spawned this handler. Due to our use of EM.watch, we can’t rely on EM to close the socket.



167
168
169
# File 'lib/packetthief/handlers/ssl_server.rb', line 167

def stop_server
  @server_handler.stop_server
end