Fixed bug in bridge_and_sniff

Sniff() optionally accepts an interface or a list of interfaces

Added "direction" attribute to pkt when received by L2ListenSocket

Patch PEP08'ified

Do not force to print interface

Updated usage.rst with multi-interfaces sniffing

Fixed missing pic in usage.rst

tethereal -> tshark
This commit is contained in:
Amedeo 2016-02-28 21:24:14 +01:00
parent 60ed0c8d46
commit 1d2ebbf111
3 changed files with 72 additions and 36 deletions

View File

@ -79,7 +79,7 @@ The ``/`` operator has been used as a composition operator between two layers. W
<IP frag=0 proto=55 |<TCP |>>
.. image:: graphics/fieldsmanagement.*
.. image:: graphics/fieldsmanagement.png
:scale: 90
Each packet can be build or dissected (note: in Python ``_`` (underscore) is the latest result)::
@ -520,7 +520,7 @@ Sniffing
.. index::
single: sniff()
We can easily capture some packets or even clone tcpdump or tethereal. If no interface is given, sniffing will happen on every interfaces::
We can easily capture some packets or even clone tcpdump or tshark. Either one interface or a list of interfaces to sniff on can be provided. If no interface is given, sniffing will happen on every interface::
>>> sniff(filter="icmp and host 66.35.250.151", count=2)
<Sniffed: UDP:0 TCP:0 ICMP:2 Other:0>
@ -607,6 +607,11 @@ We can easily capture some packets or even clone tcpdump or tethereal. If no int
load = 'B\xf7i\xa9\x00\x04\x149\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\x22#$%&\'()*+,-./01234567'
---[ Padding ]---
load = '\n_\x00\x0b'
>>> sniff(iface=["eth1","eth2"], prn=lambda x: x.sniffed_on+": "+x.summary())
eth3: Ether / IP / ICMP 192.168.5.21 > 66.35.250.151 echo-request 0 / Raw
eth3: Ether / IP / ICMP 66.35.250.151 > 192.168.5.21 echo-reply 0 / Raw
eth2: Ether / IP / ICMP 192.168.5.22 > 66.35.250.152 echo-request 0 / Raw
eth2: Ether / IP / ICMP 66.35.250.152 > 192.168.5.22 echo-reply 0 / Raw
For even more control over displayed information we can use the ``sprintf()`` function::

View File

@ -65,6 +65,17 @@ SOL_SOCKET = 1
RTF_UP = 0x0001 # Route usable
RTF_REJECT = 0x0200
# From if_packet.h
PACKET_HOST = 0 # To us
PACKET_BROADCAST = 1 # To all
PACKET_MULTICAST = 2 # To group
PACKET_OTHERHOST = 3 # To someone else
PACKET_OUTGOING = 4 # Outgoing of any type
PACKET_LOOPBACK = 5 # MC/BRD frame looped back
PACKET_USER = 6 # To user space
PACKET_KERNEL = 7 # To kernel space
PACKET_FASTROUTE = 6 # Fastrouted frame
# Unused, PACKET_FASTROUTE and PACKET_LOOPBACK are invisible to user space
LOOPBACK_NAME="lo"
@ -508,7 +519,9 @@ class L2ListenSocket(SuperSocket):
cls = conf.l3types[sa_ll[1]]
else:
cls = conf.default_l2
warning("Unable to guess type (interface=%s protocol=%#x family=%i). Using %s" % (sa_ll[0],sa_ll[1],sa_ll[3],cls.name))
warning("Unable to guess type (interface=%s protocol=%#x "
"family=%i). Using %s" % (sa_ll[0], sa_ll[1], sa_ll[3],
cls.name))
try:
pkt = cls(pkt)
@ -519,6 +532,7 @@ class L2ListenSocket(SuperSocket):
raise
pkt = conf.raw_layer(pkt)
pkt.time = get_last_packet_timestamp(self.ins)
pkt.direction = sa_ll[2]
return pkt
def send(self, x):

View File

@ -538,10 +538,12 @@ iface: listen answers only on the given interface"""
@conf.commands.register
def sniff(count=0, store=1, offline=None, prn = None, lfilter=None, L2socket=None, timeout=None,
opened_socket=None, stop_filter=None, *arg, **karg):
def sniff(count=0, store=1, offline=None, prn=None, lfilter=None,
L2socket=None, timeout=None, opened_socket=None,
stop_filter=None, iface=None, *arg, **karg):
"""Sniff packets
sniff([count=0,] [prn=None,] [store=1,] [offline=None,] [lfilter=None,] + L2ListenSocket args) -> list of packets
sniff([count=0,] [prn=None,] [store=1,] [offline=None,]
[lfilter=None,] + L2ListenSocket args) -> list of packets
count: number of packets to capture. 0 means infinity
store: wether to store sniffed packets or discard them
@ -558,47 +560,58 @@ opened_socket: provide an object ready to use .recv() on
stop_filter: python function applied to each packet to determine
if we have to stop the capture after this packet
ex: stop_filter = lambda x: x.haslayer(TCP)
iface: interface or list of interfaces (default: None for sniffing on all
interfaces)
"""
c = 0
label = {}
ls = []
if opened_socket is not None:
s = opened_socket
ls = [opened_socket]
else:
if offline is None:
if L2socket is None:
L2socket = conf.L2listen
s = L2socket(type=ETH_P_ALL, *arg, **karg)
if type(iface) is list:
for i in iface:
s = L2socket(type=ETH_P_ALL, iface=i, *arg, **karg)
label[s] = i
ls.append(s)
else:
ls = [L2socket(type=ETH_P_ALL, iface=iface, *arg, **karg)]
else:
s = PcapReader(offline)
ls = [PcapReader(offline)]
lst = []
if timeout is not None:
stoptime = time.time()+timeout
remain = None
try:
while 1:
stop_event = 0
while not stop_event:
if timeout is not None:
remain = stoptime-time.time()
if remain <= 0:
break
sel = select([s],[],[],remain)
if s in sel[0]:
p = s.recv(MTU)
if p is None:
continue
if lfilter and not lfilter(p):
continue
if store:
lst.append(p)
c += 1
if prn:
r = prn(p)
if r is not None:
print r
if stop_filter and stop_filter(p):
break
if count > 0 and c >= count:
break
sel = select(ls, [], [], remain)
for s in sel[0]:
p = s.recv()
if p is not None:
if lfilter and not lfilter(p):
continue
if s in label:
p.sniffed_on = label[s]
if store:
lst.append(p)
c += 1
if prn:
r = prn(p)
if r is not None:
print r
if stop_filter and stop_filter(p):
stop_event = 1
if count > 0 and c >= count:
stop_event = 1
except KeyboardInterrupt:
pass
if opened_socket is None:
@ -607,10 +620,12 @@ stop_filter: python function applied to each packet to determine
@conf.commands.register
def bridge_and_sniff(if1, if2, count=0, store=1, offline=None, prn = None, lfilter=None, L2socket=None, timeout=None,
def bridge_and_sniff(if1, if2, count=0, store=1, offline=None, prn=None,
lfilter=None, L2socket=None, timeout=None,
stop_filter=None, *args, **kargs):
"""Forward traffic between two interfaces and sniff packets exchanged
bridge_and_sniff([count=0,] [prn=None,] [store=1,] [offline=None,] [lfilter=None,] + L2Socket args) -> list of packets
bridge_and_sniff([count=0,] [prn=None,] [store=1,] [offline=None,]
[lfilter=None,] + L2Socket args) -> list of packets
count: number of packets to capture. 0 means infinity
store: wether to store sniffed packets or discard them
@ -639,12 +654,13 @@ stop_filter: python function applied to each packet to determine
stoptime = time.time()+timeout
remain = None
try:
while True:
stop_event = 0
while not stop_event:
if timeout is not None:
remain = stoptime-time.time()
if remain <= 0:
break
ins,outs,errs = select([s1,s2],[],[], remain)
ins, outs, errs = select([s1, s2], [], [], remain)
for s in ins:
p = s.recv()
if p is not None:
@ -658,11 +674,11 @@ stop_filter: python function applied to each packet to determine
if prn:
r = prn(p)
if r is not None:
print "%s: %s" % (label[s],r)
print r
if stop_filter and stop_filter(p):
break
stop_event = 1
if count > 0 and c >= count:
break
stop_event = 1
except KeyboardInterrupt:
pass
finally:
@ -674,3 +690,4 @@ def tshark(*args,**kargs):
"""Sniff packets and print them calling pkt.show(), a bit like text wireshark"""
sniff(prn=lambda x: x.display(),*args,**kargs)