Tcpdump is a very powerful packet capture tool. This artical 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
Table of Contents
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.|
Capture packets with A particular TCP Flag
Here are the numbers which match with the corresponding TCP flags.
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 == 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 TCP/IP protocol, the 13th byte of the TCP header contains a set of control flags. This is also known as the “TCP Flags” field. Each bit in this field represents a specific flag, and the value of that bit indicates whether the flag is set or not.
For example, the second bit from the left in the TCP Flags field represents the “SYN” flag, which is used for the initial synchronization of a connection between two hosts.
|Flag||Bit Value||Binary Value|
Let’s have a closer look at octet no. 13:
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.
|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 == 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 == 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
|FIN, ACK||17 (1 + 16)|
|SYN, ACK||18 (2 + 16)|
|PSH, ACK||24 (8 + 16)|
|FIN, PSH||9 (1 + 8)|
|FIN, PSH, ACK||25 (1 + 8 + 16)|
We can use the following way to capture syn-ack packets. This is 10010 in binary and 18 in decimal.
tcpdump -i utun1 'tcp == 18'
For psh-ack packets, we can use this way. This is 11000 in binary and 24 in decimal.
tcpdump -i utun1 'tcp == 24'
If we need to capture syn and syn-ack packets, we can do this in the following ways.
- tcpdump -i utun1 ‘tcp == 18 or tcp == 2’
- tcpdump -i utun1 ‘tcp == 18 or tcp[tcpflags] == ‘tcp-syn”
- tcpdump -i utun1 ‘tcp & 2 == 2’
Let’s see what happens to octet 13 when a TCP datagram with SYN-ACK set arrives:
|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 == 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 & 2 == 2′
Some offsets and field values may be expressed as names rather than as numeric values. For example tcp 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.
Tcpdump provides several options that enhance or modify its output. The following are the commonly used options for tcpdump command.
|-i||Listen on the specified interface.|
|-n||Don’t resolve hostnames. You can use -nn to don’t resolve hostnames or port names.|
|-t||Print human-readable timestamp on each dump line, -tttt: Give maximally human-readable timestamp output.|
|-X||Show the packet’s contents in both hex and ascii.|
|-v, -vv, -vvv||enables verbose logging/details (which among other things will give us a running total on how many packets are captured|
|-c N||Only get N number of packets and then stop.|
|-s||Define the snaplength (size) of the capture in bytes. Use -s0 to get everything, unless you are intentionally capturing less.|
|-S||Print absolute sequence numbers.|
|-q||Show less protocol information.|
|-w||Write the raw packets to file|
|-C file_size(M)||tells tcpdump to store up to x MB of packet data per file.|
|-G rotate_seconds||Create a new file every time the specified number of seconds has elapsed.|