tcpdump – how to grep or save output in real time

Tcpdump is a handy tool for capturing network packets. It will keep on capturing packets until it receives a SIGINT or SIGTERM signal, or the specified number of packets have been processed. If you have tried to pipe the output of tcpdump to a file or tried to grep it, you will notice a significant delay before you even see an output. The reason behind that is, tcpdump buffers output in 4k byte chunks and it doesn’t flush it until 4k of data is captured.

To get around the buffering, you can use ‘-l’ option to see the packets captured in real time in order to ‘grep’ or ‘tee’ output to a file. From the man page –

-l     Make stdout line buffered.  Useful if you want to see the data while capturing it.  
     E.g. "tcpdump  -l  |  tee dat" or "tcpdump  -l   > dat  &  tail  -f  dat"

Send output to a file while watching the captured packets in real time –

root@linubuvma:~# tcpdump -l -i any -qn port 53 | tee -a /tmp/dnslogs
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes
09:02:48.772892 IP > UDP, length 33
09:02:48.773196 IP > UDP, length 33
09:02:48.775062 IP > UDP, length 78
09:02:48.775085 IP > UDP, length 117
09:02:50.274318 IP > UDP, length 33
09:02:50.274695 IP > UDP, length 33
09:02:50.275531 IP > UDP, length 78
09:02:50.276384 IP > UDP, length 117

Grep text pattern in real time –

root@linubuvma:~# tcpdump -l -i any -vv |grep --color -i google
tcpdump: listening on any, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes > [bad udp cksum 0x96c1  0x4797!] 34365+ A? (28) > [bad udp cksum 0x96c1  0x9bf1!] 12744+ AAAA? (28) > [udp sum ok] 12744 q: AAAA? 1/0/0 AAAA 2607:f8b0:4002:c07::66 (56) > [udp sum ok] 34365 q: A? 6/0/0 A, A, A, A, A, A (124)
173 packets captured
240 packets received by filter
0 packets dropped by kernel

A handy cheat sheet for tcpdump –

References –