class PacketThief::Handlers::SSLTransparentProxy

Provides a transparent proxy for any TCP connection.

Attributes

buffer[RW]

An internal buffer of packet data received from the client. It will grow until the destination connection connects.

client[RW]

This holds a reference to the connection to the client. It is actually self.

client_host[R]
client_port[R]
closed[RW]

Boolean that represents whether this handler has started to close/unbind. Used to ensure there is no unbind-loop between the two connections that make up the proxy.

dest[RW]

This holds a reference to the connection to the destination. If it is null, it hasn’t been created yet.

dest_ctx[RW]

The SSLContext that will be used on the connection to the destination. Initially, its verify_mode is set to OpenSSL::SSL::VERIFY_NONE.

dest_host[RW]

Override these before connecting to dest to change the dest connection.

dest_hostname[RW]

If a client specifies a TLS hostname extension (SNI) as the hostname, then we can forward that fact on to the real server. We can also use it to choose a certificate to present.

dest_port[RW]

Override these before connecting to dest to change the dest connection.

Public Class Methods

new(tcpsocket, logger=nil) click to toggle source
# File lib/packetthief/handlers/ssl_transparent_proxy.rb, line 86
def initialize(tcpsocket, logger=nil)
  super
  @closed = false

  @client = self
  @dest = nil

  @buffer = []
  @@activeconns ||= {}

  @client_port, @client_host = Socket.unpack_sockaddr_in(get_peername)
  @dest_port, @dest_host = PacketThief.original_dest(self)

  if @@activeconns.has_key? "#{client_host}:#{client_port}"
    logwarn "loop detected! Stopping the loop."
    close_connection
    return
  end

  @dest_ctx = OpenSSL::SSL::SSLContext.new
  @dest_ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE

end

Public Instance Methods

_send_buffer() click to toggle source
# File lib/packetthief/handlers/ssl_transparent_proxy.rb, line 138
def _send_buffer
  @buffer.each do |pkt|
    @dest.send_data pkt
  end
  @buffer = []
end
client_closed() click to toggle source

Called when the client connection closes. At present, it only provides informational utility.

# File lib/packetthief/handlers/ssl_transparent_proxy.rb, line 196
def client_closed
end
client_connected() click to toggle source

This method is called when a client connects, and the TLS handhsake has completed. The default behavior is to begin initating the connection to the original destination. Override this method to change its behavior.

# File lib/packetthief/handlers/ssl_transparent_proxy.rb, line 177
def client_connected
  connect_to_dest
end
client_handshake_failed() click to toggle source

This method is called when the TLS handshake between the client and the proxy fails. It does nothing by default.

# File lib/packetthief/handlers/ssl_transparent_proxy.rb, line 183
def client_handshake_failed
end
client_recv(data) click to toggle source

This method is called when the proxy receives data from the client connection. The default behavior is to call #send_to_dest(data) in order to foward the data on to the original destination. Override this method to analyze the data, or modify it before sending it on.

# File lib/packetthief/handlers/ssl_transparent_proxy.rb, line 190
def client_recv(data)
  send_to_dest data
end
connect_to_dest() click to toggle source

Initiate the connection to @#dest_host:@dest_port.

# File lib/packetthief/handlers/ssl_transparent_proxy.rb, line 130
def connect_to_dest
  return if @dest
  @dest = SSLProxyConnection.connect(@dest_host, @dest_port, self, @dest_ctx)
  newport, newhost = Socket::unpack_sockaddr_in(@dest.get_sockname)
  # Add the new connection to the list to prevent loops.
  @@activeconns["#{newhost}:#{newport}"] = "#{dest_host}:#{dest_port}"
end
dest_cert_chain() click to toggle source

Returns the certificate chain for the destination, or nil if the destination connection does not exist yet.

# File lib/packetthief/handlers/ssl_transparent_proxy.rb, line 160
def dest_cert_chain
  return @dest.sslsocket.peer_cert_chain if @dest
  nil
end
dest_closed() click to toggle source

Called when the original destination connection closes. At present, it only provides informational utility.

# File lib/packetthief/handlers/ssl_transparent_proxy.rb, line 219
def dest_closed
end
dest_connected() click to toggle source

Called when the connection to and the TLS handshake between the proxy and the destination succeeds. The default behavior does nothing.

# File lib/packetthief/handlers/ssl_transparent_proxy.rb, line 201
def dest_connected
end
dest_handshake_failed(e) click to toggle source

Called when the TLS handshake between the proxy and the destination fails.

# File lib/packetthief/handlers/ssl_transparent_proxy.rb, line 206
def dest_handshake_failed(e)
end
dest_recv(data) click to toggle source

Called when the proxy receives data from the destination connection. The default behavior calls dest_recv() to send the data to the client.

Override it to analyze or modify the data.

# File lib/packetthief/handlers/ssl_transparent_proxy.rb, line 213
def dest_recv(data)
  send_to_client data
end
receive_data(data) click to toggle source
# File lib/packetthief/handlers/ssl_transparent_proxy.rb, line 115
def receive_data(data)
  client_recv data
end
send_to_client(data) click to toggle source

Sends data back to the client

# File lib/packetthief/handlers/ssl_transparent_proxy.rb, line 154
def send_to_client(data)
  send_data data
end
send_to_dest(data) click to toggle source

Queues up data to send to the remote host, only sending it if the connection to the remote host exists.

# File lib/packetthief/handlers/ssl_transparent_proxy.rb, line 148
def send_to_dest(data)
  @buffer << data
  _send_buffer if @dest
end
servername_cb(sslsock, hostname) click to toggle source

Set #dest_hostname in addition to the default behavior.

# File lib/packetthief/handlers/ssl_transparent_proxy.rb, line 168
def servername_cb(sslsock, hostname)
  @dest_hostname = hostname

  super(sslsock, hostname)
end
tls_successful_handshake() click to toggle source

Just calls #client_connected to keep things straightforward.

# File lib/packetthief/handlers/ssl_transparent_proxy.rb, line 111
def tls_successful_handshake
  client_connected
end
unbind() click to toggle source

Start the closing process and close the other connection if it is not already closing.

# File lib/packetthief/handlers/ssl_transparent_proxy.rb, line 121
      def unbind
        client_closed
        @@activeconns.delete "#{client_host}:#{client_port}"
        self.closed = true
#        @dest.client = nil if @dest
        @dest.close_connection_after_writing if @dest and not @dest.closed
      end