Tcpdump: Filter Packets with Tcp Flags

Updated: Jun 14

Tcpdump is a very powerful packet capture tool. This tutorial will show you how to filter tcp Flags packets with tcpdump and why.

  • What are Tcp Flags?

  • Capture packets with A particular TCP Flag

  • Capture packets with a Combination of TCP Flags



What are Tcp Flags?

Tcpflags are some combination of S (SYN), F (FIN), P (PUSH), R (RST), U (URG), W (ECN CWR), E (ECN-Echo) or `.' (ACK), or `none' if no flags are set.


The following are the commonly used TCP flags.

  • SYN - The synchronization flag is used as a first step in establishing a three-way handshake between two hosts. Only the first packet from both the sender and receiver should have this flag set.

  • ACK - The acknowledgment flag is used to acknowledge the successful receipt of a packet.

  • FIN - The finished flag means there is no more data from the sender. Therefore, it is used in the last packet sent from the sender.



  • URG - The urgent flag is used to notify the receiver to process the urgent packets before processing all other packets. The receiver will be notified when all known urgent data has been received.

  • PSH - The push flag is somewhat similar to the URG flag and tells the receiver to process these packets as they are received instead of buffering them.

  • RST - The reset flag gets sent from the receiver to the sender when a packet is sent to a particular host that was not expecting it.

  • ECE - This flag is responsible for indicating if the TCP peer is ECN capable. See RFC 3168 for more details.

  • CWR - The congestion window reduced flag is used by the sending host to indicate it received a packet with the ECE flag set. See RFC 3168 for more details.

  • NS (experimental) - The nonce sum flag is still an experimental flag used to help protect against accidental malicious concealment of packets from the sender. See RFC 3540 for more details.



Capturing packets with A particular TCP Flag

Here are the numbers which match with the corresponding TCP flags.


URG     ACK     PSH     RST     SYN     FIN
32      16      8       4       2       1

We can use the following ways to capture packets with syn TCP flag. Syn flag is 00000010 in tcp header. That is 2 in decimal.


tcpdump -i utun1 tcp[tcpflags] == 'tcp-syn'
tcpdump -i utun1 tcp[13] == 2

The following TCP flag field values are also available: tcp-fin, tcp-syn, tcp-rst, tcp-push, tcp-act, tcp-urg.





If we need to capture PSH packet, can we use the following way to capture it?

tcpdump -i utun1 tcp[tcpflags] == 'tcp-push'

No. All the packets have an ack flag in them except the syn packets. In this case, we need to filter push ack packets for this. We will discuss this in the next part.


This is an example of how to capture packets with syn TCP flag and why in tcpdump.


TCP Header

0 15 31

-----------------------------------------------------------------

| source port | destination port |

-----------------------------------------------------------------

| sequence number |

-----------------------------------------------------------------

| acknowledgment number |

-----------------------------------------------------------------

| HL | rsvd |C|E|U|A|P|R|S|F| window size |

-----------------------------------------------------------------

| TCP checksum | urgent pointer |

-----------------------------------------------------------------



Starting to count with 0, the relevant TCP control bits are contained in octet 13:

0 7| 15| 23| 31

----------------|---------------|---------------|----------------

| HL | rsvd |C|E|U|A|P|R|S|F| window size |

----------------|---------------|---------------|----------------

| | 13th octet | | |


Let's have a closer look at octet no. 13:


| |

|-------------------|

|C|E|U|A|P|R|S|F|

|7-------<---------0|


These are the TCP control bits we are interested in. We have numbered the bits in this octet from 0 to 7, right to left, so the PSH bit is bit number 3, while the URG bit is number 5.




Recall that we want to capture packets with only SYN set. Let's see what happens to octet 13 if a TCP datagram arrives with the SYN bit set in its header. |C|E|U|A|P|R|S|F|

|---------------|

|0 0 0 0 0 0 1 0|

|---------------|

|7 6 5 4 3 2 1 0|


Looking at the control bits section we see that only bit number 1 (SYN) is set.


Assuming that octet number 13 is an 8-bit unsigned integer in network byte order, the binary value of this octet is 00000010 and its decimal representation is

7 6 5 4 3 2 1 0

0*2 + 0*2 + 0*2 + 0*2 + 0*2 + 0*2 + 1*2 + 0*2 = 2




We're almost done, because now we know that if only SYN is set, the value of the 13th octet in the TCP header, when interpreted as a 8-bit unsigned integer in network byte order, must be exactly 2.


This relationship can be expressed as tcp[13] == 2.

We can use this expression as the filter for tcpdump in order to watch packets which have only SYN set: tcpdump -i xl0 tcp[13] == 2


The expression says "let the 13th octet of a TCP datagram have the decimal value 2", which is exactly what we want.




Capture packets with a Combination of Tcp Flags


URG     ACK     PSH     RST     SYN     FIN
32      16      8       4       2       1

We can use the following way to capture syn-ack packets. This is 10010 in binary and 18 in decimal.

tcpdump -i utun1 'tcp[13]  == 18'

For psh-ack packets, we can use this way. This is 11000 in binary and 24 in decimal.

tcpdump -i utun1 'tcp[13]  == 24'

If we need to capture syn and syn-ack packets, we can do this in the following ways.

tcpdump -i utun1 'tcp[13]  == 18 or tcp[13] == 2'
tcpdump -i utun1 'tcp[13]  == 18 or tcp[tcpflags] == 'tcp-syn''
tcpdump -i utun1 'tcp[13] & 2 == 2'



Let's see what happens to octet 13 when a TCP datagram with SYN-ACK set arrives:


|C|E|U|A|P|R|S|F|

|-------------------|

|0 0 0 1 0 0 1 0|

|------------------|

|7 6 5 4 3 2 1 0|


Now bits 1 and 4 are set in the 13th octet. The binary value of octet 13 is

00010010

which translates to decimal

7 6 5 4 3 2 1 0

0*2 + 0*2 + 0*2 + 1*2 + 0*2 + 0*2 + 1*2 + 0*2 = 18


Now we can't just use 'tcp[13] == 18' in the tcpdump filter expression, because that would select only those packets that have SYN-ACK set, but not those with only SYN set. Remember that we don't care if ACK or any other control bit is set as long as SYN is set.




In order to achieve our goal, we need to logically AND the binary value of octet 13 with some other value to preserve the SYN bit. We know that we want SYN to be set in any case, so we'll logically AND the value in the 13th octet with the binary value of a SYN.


00010010 SYN-ACK 00000010 SYN AND 00000010 (we want SYN) AND 00000010 (we want SYN) -------- -------- = 00000010 = 00000010

We see that this AND operation delivers the same result regardless whether ACK or another TCP control bit is set. The decimal representation of the AND value as well as the result of this operation is 2 (binary 00000010), so we know that for packets with SYN set the following relation must hold true:


( ( value of octet 13 ) AND ( 2 ) ) == ( 2 )




This points us to the tcpdump filter expression tcpdump -i xl0 'tcp[13] & 2 == 2'


Some offsets and field values may be expressed as names rather than as numeric values. For example tcp[13] may be replaced with tcp[tcpflags]. The following TCP flag field values are also available: tcp-fin, tcp-syn, tcp-rst, tcp-push, tcp-act, tcp-urg.


This can be demonstrated as:

tcpdump -i xl0 'tcp[tcpflags] & tcp-push != 0'


Note that you should use single quotes or a backslash in the expression to hide the AND ('&') special character from the shell.


Related Post:

20 Advanced Tcpdump Examples On Linux

10 Useful tcpdump command examples



1,428 views
udemylinux.png

Join our newsletter! Get a free cloud server!  Never miss a post!

Thanks for submitting!