Skip to content

Instantly share code, notes, and snippets.

@Blaok
Last active September 7, 2015 02:37
Show Gist options
  • Save Blaok/63f2d3c35f717cbf7046 to your computer and use it in GitHub Desktop.
Save Blaok/63f2d3c35f717cbf7046 to your computer and use it in GitHub Desktop.
#!/bin/bash
# Dump network traffic continuously and see who use most quota
# Needs root
# Requires `tcpdump`, `python` and `mergecap`
# Also needs `mv`, `rm`, `clear`, `ps`, `ip`, `date`, `mktemp` and `lsof`
INTERFACE=eth0
INTERVAL=2 # Dump a pcap file every 2 sec by default, this will be the display refresh interval
LEN=50 # 26 ether + 20 ipv4 + 4 tcp/udp port by default
COUNT=30 # Display top 30 by default
MAC=`ip link show $INTERFACE |grep ther|awk -F ' ' '{print $2}'`
FILTER="net 0.0.0.0/0" # Filter IPv4 traffic only by default
FINAL=`pwd`/accumulate.pcap
###########################################################################
RESULT=`mktemp`
STAT=`mktemp`
TMP=`mktemp`
DUMP=`mktemp -d`
START=`date`
SCRIPT="
#!/usr/bin/python
import sys
import operator
def sizeof_fmt(num, suffix=\"B\"):
for unit in [\"\",\"Ki\",\"Mi\",\"Gi\",\"Ti\",\"Pi\",\"Ei\",\"Zi\"]:
if abs(num) < 1024.0:
return \"%3.1f%s%s\" % (num, unit, suffix)
num /= 1024.0
return \"%.1f%s%s\" % (num, \"Yi\", suffix)
stat = {}
total = 0
for line in sys.stdin:
line = line.split(\" \")
if line[0] in stat:
stat[line[0]] += int(line[1])
else:
stat[line[0]] = int(line[1])
total += int(line[1])
sys.stderr.write(\"Total: \"+sizeof_fmt(total)+\"\n\")
count = 0
for ip in sorted(stat.items(), key=operator.itemgetter(1),reverse=True):
sys.stdout.write(ip[0]+\" \"+str(ip[1])+\"\n\")
if count<$COUNT:
sys.stderr.write(ip[0]+\"\t\"+sizeof_fmt(ip[1])+\"\n\")
count += 1
"
touch $FINAL
mv $FINAL $RESULT
trap "rm -rf $TMP $STAT $LAST $CURRENT $DUMP;mv $RESULT $FINAL; exit" SIGHUP SIGINT SIGTERM
tcpdump -i $INTERFACE -qq -nn -e -s $LEN -f "(ether host $MAC)and($FILTER)" -G $INTERVAL -w "$DUMP/tcpdump_%s.pcap" &
PID=`ps --ppid $! -o pid=`
LAST=`lsof|grep "^tcpdump.*$PID.*tcpdump_[0-9]*.pcap"|awk -F ' ' '{print $9}'`
tcpdump -nnr $RESULT -e -q 2>/dev/null|grep -i \>\ $MAC|awk -F ' ' '{print $8" "$7}'|sed -e 's/://g'>>$STAT
tcpdump -nnr $RESULT -e -q 2>/dev/null|grep -i $MAC\ \>|awk -F ' ' '{print $10" "$7}'|sed -e 's/://g'>>$STAT
while true
do
CURRENT=`lsof|grep "^tcpdump.*$PID.*tcpdump_[0-9]*.pcap"|awk -F ' ' '{print $9}'`
if [[ "$CURRENT" != "$LAST" ]]
then
tcpdump -nnr $LAST -e -q 2>/dev/null|grep -i \>\ $MAC|awk -F ' ' '{print $8" "$7}'|sed -e 's/://g'>>$STAT
tcpdump -nnr $LAST -e -q 2>/dev/null|grep -i $MAC\ \>|awk -F ' ' '{print $10" "$7}'|sed -e 's/://g'>>$STAT
clear
echo From $START to `date`:
python -c "$SCRIPT" <$STAT >$TMP
mv $TMP $STAT
mergecap -T ether $LAST $RESULT -w $TMP
mv $TMP $RESULT
rm $LAST -f
LAST=$CURRENT
fi
sleep 0.1s
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment