I use tcpdump a lot , we all do , but if someone tells you to explain how it works what would you say?

Well we know that tcpdump applies a number of rules (if told) to filter traffic before the kernel(iptables or similar) drops it , that’s why if you do something like

tcpdump -i any dst port 21

and you start some connections against port 21 you will see traffic even tho you might not have port 21 bound by any process (some ftp server or what not).

Well that’s a fair assumption , i want to divide this article in two/three parts , the first part is about how tcpdump filters ports , and shows you exactly what you want.

Let’s say I want to see all the packets going to port 21 with the SYN flag lit up?

tcpdump -i any dst port 21 and tcp[13] == 2

You can go check the osi layer offsets and see why this makes sense , but the question is how is this passed to the socket (potentially RAW) so it can filter , also it’s got to be something simple and fast so the overhead is not huge

Turns out that there’ss these bytecode language called bpf (http://www.tcpdump.org/papers/bpf-usenix93.pdf) , that generates an expression that you can attach the socket using a setsockopt().

Look at this for example , if you want to see the expression you can pass -d to tcpdump:


Neat , and if you wanna how is this passed to the socket you could strace, for example: image The key is SO_ATTACH_FILTER , which attaches that filter that was previously shown, plus some sizeofs etc.

Apparently there’s some iptables modules that let you attach complex bfp expressions in one single rule , meaning that your number of rules can go very deep and all in a single line , this will have tremendous impacts in the speed that rules are parsed (from an iptables perspective).

Let’s leave it here for now as I need to go to work , but i want to take a look to the iptables module and what happens after tcpdump accept() ‘s a package , how does it hand it over to the kernel or userland process etc.