I'm using this script that actually checks for the rate of incoming packets and it gets triggered if the rate hits 5mbps or more. The packets are then logged to a tcpdump file.
interface=eth0
dumpdir=/tmp/
while /bin/true; do
pkt_old=`grep $interface: /proc/net/dev | cut -d : -f2 | awk '{ print $2 }'`
sleep 1
pkt_new=`grep $interface: /proc/net/dev | cut -d : -f2 | awk '{ print $2 }'`
pkt=$(( $pkt_new - $pkt_old ))
echo -ne "\r$pkt packets/s\033[0K"
if [ $pkt -gt 5000 ]; then
echo -e "\n`date` Under attack, dumping packets."
tcpdump -n -s0 -c 2000 -w $dumpdir/dump.`date +"%Y%m%d-%H%M%S"`.cap
echo "`date` Packets dumped, sleeping now."
sleep 300
fi
done
The output is something like 2000 Packets captured. XXX packets recieved by Filter and XXX-(minus)2000 dropped by Kernel.
Now what I want to know here is that the output file wouldn't actually tell me the rate of the attack like if it was 300mbps or what? So is the XXX packets recieved by filter is per second? If not, how do I check that because my port sometimes gets saturated.
UPDATE:
I used a program to capture statistics from the captured file through the above script. Here is what I got:
root@$:/tmp/dumps# capinfos dump.20130621-174506.cap
File name: dump.20130621-174506.cap
File type: Wireshark/tcpdump/... - libpcap
File encapsulation: Linux cooked-mode capture
Number of packets: 2000
File size: 2065933 bytes
Data size: 2033909 bytes
Capture duration: 43 seconds
Start time: Fri Jun 21 17:45:06 2013
End time: Fri Jun 21 17:45:49 2013
Data byte rate: 46968.49 bytes/sec
Data bit rate: 375747.94 bits/sec
Average packet size: 1016.95 bytes
Average packet rate: 46.19 packets/sec
I believe the attack might only have lasted a good 15-20 seconds while the captured information was 43 seconds so the data-bit rate here might have been averaged over from this total time. What might help here is if someone could edit the original script above instead of capturing 2000 packets and dropping the rest, to capture all packets for a duration of lets say 5 seconds when the threshold hits.
UPDATE:
After changing the script as mentioned, it looked like the file was damaged as I read it in Wireshark which said "The capture file appears to have been cut short in the middle of a packet." Here is output from capinfos:
capinfos: An error occurred after reading 3085 packets from `"dump.20130710-215413.cap": Less data was read than was expected.
On a 2nd try, I was able to read that file only when I pressed Ctrl+C in console of the script:
capinfos dump.20130710-215413.cap
File name: dump.20130710-215413.cap
File type: Wireshark/tcpdump/... - libpcap
File encapsulation: Linux cooked-mode capture
Number of packets: 18136
File size: 2600821 bytes
Data size: 2310621 bytes
Capture duration: 591 seconds
Start time: Wed Jul 10 21:54:13 2013
End time: Wed Jul 10 22:04:04 2013
Data byte rate: 3909.73 bytes/sec
Data bit rate: 31277.83 bits/sec
Average packet size: 127.41 bytes
Average packet rate: 30.69 packets/sec
Notice capture duration 591 seconds. I believe the 'sleep 300' has something to do over here because as I see the console output. This output is with '-c 2000' option:
./Log.sh
10275 packets/s
Wed Jul 10 12:41:31 MSD 2013 Under attack, dumping packets.
tcpdump: listening on venet0, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes
2000 packets captured
100012 packets received by filter
98003 packets dropped by kernel
Wed Jul 10 12:42:34 MSD 2013 Packets dumped, sleeping now.
Now this is the output after you modified the script with 'sleep 5':
./Log.sh
24103 packets/s
Wed Jul 10 21:54:13 MSD 2013 Under attack, dumping packets.
tcpdump: listening on venet0, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes
Wed Jul 10 21:54:18 MSD 2013 Packets dumped, sleeping now.
1620 packets/sroot@nl:~# 18136 packets captured
1850288 packets received by filter
1832106 packets dropped by kernel
^C
Notice I pressed Ctrl+C to break the sleep function I guess which made reading of the file possible.
capinfos is what you are looking for:
Pay attention to the Data bit rate.
How about this:
How to measure the packet rate (frequency) using
tcpdump
and nano-second-resolution timestampsQuick Summary:
For both options shown below, update the
num_packets
values and thetcpdump
commands is all, in these "one-liner" command blobs:Option 1:
This always works and is pretty good:
Option 2 [best]:
This works with most, if not all,
tcpdump
commands which do not include the-t
flag, and is much better!:Option 1: manually time the whole process using nanosecond-resolution timestamps from
date
This works ok. I simply tell
tcpdump
to grab a certain number of packets, time the whole thing, and calculate the packet rate:It's a bash "one-liner". Copy and paste the whole chunk at once. Be sure to update the
num_packets
variable first to how many packets you want to capture, and update yourtcpdump
line to filter on just your packets of interest. In other words, modify these 2 lines for your needs:It will print out the packet rate at the end, like this (where the true packet rate is 10.00 Hz):
Note that due to some overhead of
tcpdump
as is starts up, the calculated frequency shown (9.698 Hz in this case) is skewed a bit low. I know its actual frequency is 10.00 Hz (yes, >2 zeros of precision), since I wrote the code which sends the packets and used precision timing to do so--see my answer here for the timing part of that code: How to run a high-resolution, high-precision periodic loop in Linux easily, at any frequency (ex: up to 10 KHz~100 KHz) using a soft real-time scheduler and nanosecond delaysSo, for Option 1, using larger packet counts (setting
num_packets
to a larger value, such as25
to50
or more) is better because it reduces the error introduced by the overhead of starting uptcpdump
, which we are including in our timing, but don't want to.Example full command and output on real data:
Option 2 [BEST--USE THIS WHEN POSSIBLE INSTEAD!]: extract the first and last packet timestamps from the
tcpdump
output and use those to determine the packet rateFor this technique, we need to do a few things:
-l
(dash lower-case L, NOT dash one) flag withtcpdump
here to make the stdout output line buffered so that you will see it periodically update while the script is running. If you don't use this flag, you'll only see the output once at the very end of thetcpdump
command if the output is short, or in huge periodic chunks each time the stdout buffer totally fills up if the output is long.tee
so that it A) saves it into a file you can extract the timestamps from afterwards and B) prints it to stdout so you can see it live.Here is the "one-liner". Note that the
time
part is optional. It just prints out a total time at the end, which I think is nice. Again, update thenum_packets
value and thetcpdump
command for your needs. The minimumnum_packets
value you can use is2
. This technique has such good accuracy that you do not need to use largenum_packets
values to make it work well. Collecting as few as2
packets produces good results, and10
packets produces excellent results.Again, modify these 2 lines (shown below) for your needs, keeping these things in mind:
tcpdump
line, be sure to keep-l
and| tee tcpdump.txt
, as described above.-t
withtcpdump
means "Don't print a timestamp on each dump line.", and if used, will cause this technique to not work since it relies on those timestamps. Option 1 above will still work just fine, however.tee
output into a file in a writable part of your file system, such as perhaps/var/log/tcpdump.txt
or/tmp/tcpdump.txt
instead of justtcpdump.txt
in your current directory.rw
) first, as shown below. Then, run thetcpdump
command above. When done, you can mount it back as read-only (ro
) as shown here:sudo
command, in which case you'll need to ssh or log into the board as root directly, and also remove thesudo
word from thetcpdump
command above.Example packet rate printed at the end (where the true packet rate is 10.00 Hz):
Example full command and output on real data. Note that when line-buffering the output with
-l
, thestderr
output, such as the lines which indicate how many packets were captured, received, and dropped, get accidentally intermingled with the rest of thestdout
output. That's ok. It's non-ideal, but there's nothing we can do about it. So, it's normal.Option 1 vs Option 2
If Option 2 above is so much better and produces so much better results, why would we ever use Option 1?
Well, if you ever use the
-t
flag withtcpdump
,man tcpdump
indicates that it means:So, Option 2 clearly doesn't work if you use that flag, since it relies on those timestamps. But, Option 1 would still work just fine there!
If any other scenarios or possible
tcpdump
commands come up which don't work well with Option 2, you can use Option 1, which always works. But, whenever possible, use Option 2, as it produces much more accurate and precise output!References
grep
: https://regex101.com/