module PacketThief

Framework for intercepting packets, redirecting them to a handler, and doing something with the “stolen” connection.

Description

PacketThief is a little Ruby framework for programatically intercepting network traffic. It provides an abstraction around configuring various OS firewalls and for gathering information about the original connection, and it offers several sample handler classes (for use with EventMachine) for intercepting and forwarding traffic. If you want a full fledged security tool for intercepting and analyzing network traffic, check out Mallory instead.

PacketThief is currently intended to be run on a computer that should be configured as the gateway for whatever network traffic you wish to intercept. You then use PacketThief to configure your OS firewall and network routing to send specified network traffic to a socket. The socket handling code can then read the data, modify it, send it on to the original destination (although the new connection will originate from the gateway), etc.

Currently, PacketThief supports basic redirection using Ipfw (Mac OS X, BSD) and Netfilter (Linux). It also more than likely requires your PacketThief-based script to be run as root in order to modify your system’s firewall.

Usage

First, you must configure the system that will run PacketThief to be able to intercept network traffic. If that host system has two network interfaces (such as a laptop with ethernet and wifi), then you can turn the system into a router by configure one interface to be an external interface that can communicate with your main network and the Internet, and the other interface can be configured as the gateway for one or more devices/client systems that you would like to test.

NATing multiple network interfaces can be easily done in Mac OS X by enabling Internet Sharing in the Sharing System Preference pane, which will also let you configure your wifi to be a wireless access point. For Linux, take a look at the examples/setup_iptables.sh script, or search the Internet for tutorials on various ways to set up Mallory.

Basic use:

require 'packetthief'
# redirect tcp traffic destined for port 443 to localhost port 65432:
PacketThief.redirect(:to_ports => 65432).where(:protocol => :tcp, :dest_port => 443).run
at_exit { PacketThief.revert } # Remove our firewall rules when we exit

This will set up Firewall/routing rules to redirect packets matching the .where clause to the localhost port specified by the redirect() clause. The Kernel#at_exit handler calls the .revert method which will remove the firewall rules added by PacketThief.

You can then capture network traffic in your script by opening a listening socket your :to_ports destination. When you create the socket, set the hostname to a blank string to have it listen on all interfaces – this winds up being more compatible with different firewalls.

Using a TCPServer:

TCPServer.new('', 65432)

or (untested):

TCPServer.new(65432)

Using EventMachine:

EM.run {
    start_server '', 65432, MyHandler
}

In your listener code you can recover the original destination by passing in an accepted socket or an EventMachine::Connection-based handler.

PacketThief.original_dest(socket_or_em_connection)

PacketThief also provides several EventMachine handlers to help build interceptors. For example, PacketThief::Handlers::TransparentProxy provides a class that allows you to view or mangle arbitrary TCP traffic before passing it on to the original destination. The package also includes several handlers for dealing with SSL-based traffic. Unlike EventMachine's built-in SSL support (start_tls), PacketThief::Handlers::SSLClient and PacketThief::Handlers::SSLServer give you direct access to the OpenSSL::SSL::SSLContext to configure certificates and callbacks, and PacketThief::Handlers::SSLSmartProxy will connect to the original destination in order to acquire its host certificate, which it then modifies for use with a configured CA. See the documentation and the example directory for more information.

Mac OS X Setup example

Note that connections initiated both on the Mac and on any device from the network will hit your socket. In the future, you will be able to narrow down what traffic is caught.

Public Class Methods

guess_implementation() click to toggle source
# File lib/packetthief.rb, line 139
def self.guess_implementation
  case RUBY_PLATFORM
  when %rlinux/
    Impl::Netfilter
  when %rdarwin(10|[0-9]($|[^0]))/ # Mac OS X 10.6 and earlier.
    Impl::Ipfw
  when %rdarwin(11)/ # Mac OS X 10.7
    Impl::PFRdr
  else
    raise "Platform #{RUBY_PLATFORM} not yet supported! If you know your network implementation, call it directly."
  end
end
implementation() click to toggle source
# File lib/packetthief.rb, line 120
def self.implementation; @implementation ; end
implementation=(newimpl) click to toggle source
# File lib/packetthief.rb, line 122
def self.implementation=(newimpl)
  logdebug "Set implementation to: #{newimpl}"
  if newimpl == nil
    @implementation = nil
  elsif newimpl.kind_of? Module
    @implementation = newimpl
  else
    PacketThief::Impl.constants.each do |c|
      if c.downcase.to_sym == newimpl.downcase.to_sym
        @implementation = PacketThief::Impl.const_get c
        return @implementation
      end
    end
    raise AttributeError, "Unknown implementation"
  end
end
method_missing(m, *args, &block) click to toggle source

Pass the call on to @implementation, or an OS-specific default, if one is known.

# File lib/packetthief.rb, line 153
def self.method_missing(m, *args, &block)
  logdebug "method_missing: #{m}", :args => args, :block => block
  if self.implementation == nil
    self.implementation = guess_implementation
  end
  implementation.logger = @logger if implementation.respond_to? :logger=
  self.implementation.send(m, *args, &block)
end
revert() click to toggle source

Quietly ignore .revert calls if implementation is nil.

# File lib/packetthief.rb, line 163
def self.revert
  implementation.revert if implementation
end