-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2844 from haukepetersen/ng_sniffer
dist: added ng_sniffer script
- Loading branch information
Showing
2 changed files
with
201 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
# RIOT Sniffer Application | ||
|
||
|
||
## About | ||
|
||
This sniffer script can be used to sniff network traffic using RIOT based | ||
nodes. It is primarily designed for sniffing wireless data traffic, but can also | ||
well be used for wired network traffic, as long as the used network devices | ||
support promiscuous mode and output of raw data. | ||
|
||
The sniffer is based on a RIOT node running the [ng_sniffer application](https://github.com/RIOT-OS/applications/tree/master/ng_sniffer) application located in [RIOTs application repository](https://github.com/RIOT-OS/applications). | ||
This node outputs received network traffic via a serial port in the Wireshark | ||
pcap format. This output is then parsed by the `ng_sniffer.py` script included | ||
in this folder run on a host computer. | ||
|
||
The `ng_sniffer.py` script is a modified version of [malvira's script](https://github.com/malvira/libmc1322x/blob/master/tools/rftestrx2pcap.py) for the Redbee Ecotag | ||
(https://github.com/malvira/libmc1322x/wiki/wireshark). | ||
|
||
|
||
## Dependencies | ||
|
||
The `ng_sniffer.py` script needs [pyserial](https://pypi.python.org/pypi/pyserial). | ||
|
||
Installing the dependencies: | ||
|
||
#### Debuntu | ||
apt-get install python-serial | ||
|
||
#### PIP | ||
pip install pyserial | ||
|
||
|
||
## Usage | ||
|
||
General usage: | ||
|
||
1. Flash an applicable RIOT node with the sniffer application from | ||
(https://github.com/RIOT-OS/applications/tree/master/ng_sniffer) | ||
|
||
2. Run the `ng_sniffer.py` script | ||
``` | ||
$ ./ng_sniffer.py <tty> <baudrate> <channel> [outfile] | ||
``` | ||
The script has the following parameters: | ||
|
||
- **tty:** The serial port the RIOT board is connected to. Under Linux, this is | ||
typically something like /dev/ttyUSB0 or /dev/ttyACM0. Under Windows, | ||
this is typically something like COM0 or COM1 | ||
- **baudrate:** The baudrate the serial port is configured to. The default in | ||
RIOT is 115200, though this is defined per board and some boards | ||
have some other value defined per default. NOTE: when sniffing | ||
networks where the on-air bitrate is > baudrate, it makes sense | ||
to increase the baudrate so no data is skipped when sniffing. | ||
- **channel:** The radio channel to use when sniffing. Possible values vary and | ||
depend on the link-layer that is sniffed. This parameter is | ||
ignored when sniffing wired networks. | ||
- **[outfile]:** When this parameter is specified, the sniffer output is saved | ||
into this file. See the examples below for alternatives to | ||
specifying this parameter. (optional) | ||
|
||
|
||
### Examples | ||
|
||
The following examples are made when using the sniffer application together with | ||
an `iot-lab_M3` node that is connected to /dev/ttyUSB1 (or COM1) and runs per | ||
default with a baudrate of 500000. | ||
|
||
#### Linux | ||
|
||
Dump packets to a file: | ||
``` | ||
$ ./ng_sniffer.py /dev/ttyUSB1 500000 17 > foo.pcap | ||
``` | ||
|
||
This .pcap can then be opened in wireshark. | ||
|
||
Alternatively for live captures, you can pipe directly into wireshark with: | ||
``` | ||
$ ./ng_sniffer.py /dev/ttyUSB1 500000 17 | wireshark -k -i - | ||
``` | ||
|
||
#### Windows | ||
|
||
For windows you can use the optional third argument to output to a | ||
.pcap: | ||
|
||
``` | ||
$ ./ng_sniffer.py COM1 500000 17 foo.pcap | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
#!/usr/bin/env python2 | ||
''' | ||
(C) 2012, Mariano Alvira <mar@devl.org> | ||
(C) 2014, Oliver Hahm <oliver.hahm@inria.fr> | ||
(C) 2015, Hauke Petersen <hauke.petersen@fu-berlin.de> | ||
Redistribution and use in source and binary forms, with or without | ||
modification, are permitted provided that the following conditions | ||
are met: | ||
1. Redistributions of source code must retain the above copyright | ||
notice, this list of conditions and the following disclaimer. | ||
2. Redistributions in binary form must reproduce the above copyright | ||
notice, this list of conditions and the following disclaimer in the | ||
documentation and/or other materials provided with the distribution. | ||
3. Neither the name of the Institute nor the names of its contributors | ||
may be used to endorse or promote products derived from this software | ||
without specific prior written permission. | ||
THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND | ||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE | ||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
SUCH DAMAGE. | ||
''' | ||
|
||
import sys,os,time | ||
from struct import pack | ||
import re | ||
import serial | ||
|
||
if len(sys.argv) < 4: | ||
sys.stderr.write( "Usage: %s tty baudrate channel [outfile]\n" %(sys.argv[0])) | ||
sys.stderr.write( " channel = 11-26\n") | ||
sys.exit(2) | ||
|
||
# change the channel | ||
|
||
try: | ||
#serport = serial.Serial(sys.argv[1], baudrate=115200, dsrdtr=0, rtscts=0, timeout=1) | ||
serport = serial.Serial(sys.argv[1], sys.argv[2], dsrdtr=0, rtscts=0, timeout=1) | ||
serport.setDTR(0) | ||
serport.setRTS(0) | ||
except IOError: | ||
print "error opening port" | ||
sys.exit(2) | ||
|
||
time.sleep(1) | ||
|
||
sys.stderr.write('ifconfig 4 set chan %s\n' % sys.argv[3]) | ||
sys.stderr.write('ifconfig 4 raw\n') | ||
sys.stderr.write('ifconfig 4 promisc\n') | ||
serport.write('ifconfig 4 set chan %s\n' % sys.argv[3]) | ||
serport.write('ifconfig 4 raw\n') | ||
serport.write('ifconfig 4 promisc\n') | ||
|
||
time.sleep(1) | ||
|
||
# figure out where to write | ||
try: | ||
sys.stderr.write('trying to open file %s\n' % sys.argv[4]) | ||
outfile = open(sys.argv[4], 'w+b') | ||
except IndexError: | ||
outfile = sys.stdout | ||
|
||
# PCAP setup | ||
MAGIC = 0xa1b2c3d4 | ||
MAJOR = 2 | ||
MINOR = 4 | ||
ZONE = 0 | ||
SIG = 0 | ||
SNAPLEN = 0xffff | ||
NETWORK = 230 # 802.15.4 no FCS | ||
|
||
# output overall PCAP header | ||
outfile.write(pack('<LHHLLLL', MAGIC, MAJOR, MINOR, ZONE, SIG, SNAPLEN, NETWORK)) | ||
|
||
# count incoming packets | ||
count = 0 | ||
sys.stderr.write("RX: %i\r" % count) | ||
|
||
try: | ||
while 1: | ||
line = serport.readline().rstrip() | ||
|
||
pkt_header = re.match(r">? *rftest-rx --- len 0x(\w\w).*", line) | ||
if pkt_header: | ||
t = time.time() | ||
sec = int(t) | ||
usec = (t - sec) * 100000 | ||
length = int(pkt_header.group(1), 16) | ||
outfile.write(pack('<LLLL', sec, usec, length, length)) | ||
outfile.flush() | ||
count += 1 | ||
sys.stderr.write("RX: %i\r" % count) | ||
continue | ||
|
||
pkt_data = re.match(r"(0x\w\w )+", line) | ||
if pkt_data: | ||
for part in line.split(' '): | ||
byte = re.match(r"0x(\w\w)", part) | ||
if byte: | ||
outfile.write(pack('<B', int(byte.group(1), 16))) | ||
outfile.flush() | ||
|
||
except KeyboardInterrupt: | ||
sys.exit(2) |