Class: PacketFu::Capture

Inherits:
Object
  • Object
show all
Defined in:
lib/packetfu/capture.rb

Overview

The Capture class is used to construct PcapRub objects in order to collect packets from an interface.

This class requires PcapRub. In addition, you will need root (or root-like) privileges in order to capture from the interface.

Note, on some wireless cards, setting :promisc => true will disable capturing.

Example

# Typical use
cap = PacketFu::Capture.new(:iface => 'eth0', :promisc => true)
cap.start
sleep 10
cap.save
first_packet = cap.array[0]

# Tcpdump-like use
cap = PacketFu::Capture.new(:start => true)
cap.show_live(:save => true, :filter => 'tcp and not port 22')

See Also

Read, Write

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(args = {}) ⇒ Capture



31
32
33
34
35
36
37
38
39
40
# File 'lib/packetfu/capture.rb', line 31

def initialize(args={})
  @array = [] # Where the packet array goes.
  @stream = [] # Where the stream goes.
  @iface = (args[:iface] || ENV['IFACE'] || Pcap.lookupdev || "lo").to_s
  @snaplen = args[:snaplen] || 0xffff
  @promisc = args[:promisc] || false # Sensible for some Intel wifi cards
  @timeout = args[:timeout] || 1

  setup_params(args)
end

Instance Attribute Details

#arrayObject

Leave these public and open.



28
29
30
# File 'lib/packetfu/capture.rb', line 28

def array
  @array
end

#ifaceObject (readonly)

Cant change after the init.



29
30
31
# File 'lib/packetfu/capture.rb', line 29

def iface
  @iface
end

#promiscObject (readonly)

Cant change after the init.



29
30
31
# File 'lib/packetfu/capture.rb', line 29

def promisc
  @promisc
end

#snaplenObject (readonly)

Cant change after the init.



29
30
31
# File 'lib/packetfu/capture.rb', line 29

def snaplen
  @snaplen
end

#streamObject

Leave these public and open.



28
29
30
# File 'lib/packetfu/capture.rb', line 28

def stream
  @stream
end

#timeoutObject (readonly)

Cant change after the init.



29
30
31
# File 'lib/packetfu/capture.rb', line 29

def timeout
  @timeout
end

Instance Method Details

#bpf(args = {}) ⇒ Object

bpf() sets a bpf filter on a capture session. Valid arugments are:

:filter
  Provide a bpf filter to enable for the capture. For example, 'ip and not tcp'


100
101
102
103
104
# File 'lib/packetfu/capture.rb', line 100

def bpf(args={})
  filter = args[:filter]
  capture if @stream.class == Array
  @stream.setfilter(filter)
end

#capture(args = {}) ⇒ Object

capture() initializes the @stream varaible. Valid arguments are:

:filter
  Provide a bpf filter to enable for the capture. For example, 'ip and not tcp'
:start
  When true, start capturing packets to the @stream variable. Defaults to true


56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/packetfu/capture.rb', line 56

def capture(args={})
  if Process.euid.zero?
    filter = args[:filter]
    start = args[:start] || true
    if start
      begin
        @stream = Pcap.open_live(@iface,@snaplen,@promisc,@timeout)
      rescue RuntimeError
        $stderr.print "Are you sure you're root? Error: "
        raise
      end
      bpf(:filter=>filter) if filter
    else
      @stream = []
    end
    @stream
  else
    raise RuntimeError,"Not root, so can't capture packets. Error: "
  end
end

#clear(args = {}) ⇒ Object

clear() clears the @stream and @array variables, essentially starting the capture session over. Valid arguments are:

:array 
  If true, the @array is cleared.
:stream
  If true, the @stream is cleared.


89
90
91
92
93
94
# File 'lib/packetfu/capture.rb', line 89

def clear(args={})
  array = args[:array] || true
  stream = args[:stream] || true
  @array = [] if array
  @stream = [] if stream
end

#nextObject

next() exposes the Stream object’s next method to the outside world.



124
125
126
# File 'lib/packetfu/capture.rb', line 124

def next
  return @stream.next
end

#save(args = {}) ⇒ Object

save() is a equivalent to wire_to_array()



134
135
136
# File 'lib/packetfu/capture.rb', line 134

def save(args={})
  wire_to_array(args)
end

#setup_params(args = {}) ⇒ Object

Used by new().



43
44
45
46
47
48
# File 'lib/packetfu/capture.rb', line 43

def setup_params(args={})
  filter = args[:filter] # Not global; filter criteria can change.
  start = args[:start] || false
  capture if start
  bpf(:filter=>filter) if filter
end

#show_live(args = {}) ⇒ Object

show_live() is a method to capture packets and display peek() data to stdout. Valid arguments are:

:filter
  Provide a bpf filter to captured packets.
:save
  Save the capture in @array
:verbose
  TODO: Not implemented yet; do more than just peek() at the packets.
:quiet
  TODO: Not implemented yet; do less than peek() at the packets.


148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/packetfu/capture.rb', line 148

def show_live(args={})
  filter = args[:filter]
  save = args[:save]
  verbose = args[:verbose] || args[:v] || false
  quiet = args[:quiet] || args[:q] || false # Setting q and v doesn't make a lot of sense but hey.

  # Ensure the capture's started.
  if @stream.class == Array
    capture
  end

  @stream.setfilter(filter) if filter
  while true
    @stream.each do |pkt|
      puts Packet.parse(pkt).peek
      @array << pkt if args[:save]
    end
  end
end

#start(args = {}) ⇒ Object

start() is equivalent to capture().



78
79
80
# File 'lib/packetfu/capture.rb', line 78

def start(args={})
  capture(args)
end

#w2a(args = {}) ⇒ Object

w2a() is a equivalent to wire_to_array()



129
130
131
# File 'lib/packetfu/capture.rb', line 129

def w2a(args={})
  wire_to_array(args)
end

#wire_to_array(args = {}) ⇒ Object

wire_to_array() saves a packet stream as an array of binary strings. From here, packets may accessed by other functions. Note that the wire_to_array empties the stream, so multiple calls will append new packets to @array. Valid arguments are:

:filter
  Provide a bpf filter to apply to packets moving from @stream to @array.


113
114
115
116
117
118
119
120
121
# File 'lib/packetfu/capture.rb', line 113

def wire_to_array(args={})
  filter = args[:filter] 
  bpf(:filter=>filter) if filter

  while this_pkt = @stream.next
    @array << this_pkt
  end
  @array.size
end