TCPDump – Understanding TCP Header Offset 13

tcptcpdump

I am trying to understand how tcpdump works and trying to read TCP header control flags SYN,ACK etc.

After researching online I came to know that the control flags are available at offset 13 and I need to use tcp[13] however I am not able to understand how this value 13 is been calculated.

Can anyone help?

Best Answer

TCP[13] is an array of bits (flags). When they're set to a 1 they're enabled, when they're a 0 they're disabled.

These tcpdump commands show how you can take the collection of TCP[13] bits and do bit-wise ands to test if the bits are enabled:

Show all URG packets:
# tcpdump 'tcp[13] & 32 != 0'

Show all ACK packets:
# tcpdump 'tcp[13] & 16 != 0'

Show all PSH packets:
# tcpdump 'tcp[13] & 8 != 0'

Show all RST packets:
# tcpdump 'tcp[13] & 4 != 0'

Show all SYN packets:
# tcpdump 'tcp[13] & 2 != 0'

Show all FIN packets:
# tcpdump 'tcp[13] & 1 != 0'

Show all SYN-ACK packets:
# tcpdump 'tcp[13] = 18

The referenced URL (below) had this bullet which explains it as well:

Keep in mind the reasons these filters work. The filters above find these various packets because tcp[13] looks at offset 13 in the TCP header, the number represents the location within the byte, and the !=0 means that the flag in question is set to 1, i.e. it’s on.

TCP Header

If you take a look at the RFC 793 3.1 as well as this article on tcpdump advanced filters it becomes more obvious.

TCP header
----------

    0                   1                   2                   3   
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |          Source Port          |       Destination Port        |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                        Sequence Number                        |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                    Acknowledgment Number                      |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |  Data |       |C|E|U|A|P|R|S|F|                               |
    | Offset|  Res. |W|C|R|C|S|S|Y|I|            Window             | 
    |       |       |R|E|G|K|H|T|N|N|                               |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |           Checksum            |         Urgent Pointer        |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                    Options                    |    Padding    |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                             data                              |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

- Matching any TCP traffic with a source port > 1024
# tcpdump -i eth1 'tcp[0:2] > 1024'

- Matching TCP traffic with particular flag combinations

The flags are defined in the 14th byte of the TCP header.

    +-+-+-+-+-+-+-+-+
    |C|E|U|A|P|R|S|F|
    |W|C|R|C|S|S|Y|I|
    |R|E|G|K|H|T|N|N|
    +-+-+-+-+-+-+-+-+

NOTE: These are the flags we're interested.

Calculating flag's position

You count the bytes (8 bits) from the top, numbering them at 0:

  • So "Source Port" & "Destination Port" would make up bytes 0, 1, 2, & 3.
  • The next row, "Sequence Number", would be 4-7.
  • "Acknowledge Number" would be bytes 8-11.
  • "Data Offset" & "Res." would be byte 12.
  • That takes you to byte 13, the bits in this byte are the flags.

Bit order

I'll also mention that the number stored in byte 13 is ordered such that:

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

References