Packet Capture, part 2 - Page 9
In this segment from the O'Reilly book, Network Troubleshooting Tools, you will learn all abut how to use the tcpdump in relation to packet capturing.
18.104.22.168.3. Packet characteristics.
Filters can also be designed based on packet characteristics such as packet length or the contents of a particular field. These filters must include a relational operator. To use length, the keyword less or greater is used. Here is an example:
bsd1# tcpdump greater 200
This command collects packets longer than 200 bytes.
Looking inside packets is a little more complicated in that you must understand the structure of the packet's header. But despite the complexity, or perhaps because of it, this technique gives you the greatest control over what is captured. (If you are charged with creating a firewall using a product that requires specifying offsets into headers, practicing with tcpdump could prove invaluable.)
The general syntax is proto [ expr : size ]. The field proto indicates which header to look into -- ip for the IP header, tcp for the TCP header, and so forth. The expr field gives an offset into the header indexed from 0. That is, the first byte in a header is number 0, the second byte is number 1, and so forth. Alternately, you can think of expr as the number of bytes in the header to skip over. The size field is optional. It specifies the number of bytes to use and can be 1, 2, or 4.
bsd1# tcpdump "ip = 6"
looks into the IP header at the tenth byte, the protocol field, for a value of 6. Notice that this must be quoted. Either an apostrophe or double quotes should work, but a backquote will not work.
bsd1# tcpdump tcp
is an equivalent command since 6 is the protocol number for TCP.
This technique is frequently used with a mask to select specific bits. Values should be in hex. Comparisons are specified using the syntax & followed by a bit mask. The next example extracts the first byte from the Ethernet header (i.e., the first byte of the destination address), extracts the low-order bit, and makes sure the bit is not 0:
The astute reader will notice that this test could be more concisely written as =1 rather than !=0. While it doesn't matter for this example, using the second form simplifies testing in some cases and is a common idiom. In the next command, the syntax is simpler since you are testing to see if multiple bits are set.
bsd1# tcpdump 'ether & 1 != 0'
With both of these examples, there are better ways of matching the packets. For a more realistic example, consider the command:
bsd1# tcpdump "tcp & 0x03 != 0"
This filter skips the first 13 bytes in the TCP header, extracting the flag byte. The mask 0x03 selects the first and second bits, which are the FIN and SYN bits. A packet is captured if either bit is set. This will capture setup or teardown packets for a TCP connection.
It is tempting to try to mix in relational operators with these logical operators. Unfortunately, expressions like tcp src port > 23 don't work. The best way of thinking about it is that the expression tcp src port returns a value of true or false, not a numerical value, so it can't be compared to a number. If you want to look for all TCP traffic with a source port with a value greater than 23, you must extract the port field from the header using syntax such as "tcp[0:2] & 0xffff > 0x0017".