Saturday, October 25, 2008

TShark - High performance packet capture

Wireshark users may not realize that there is a command line version of Wireshark, namely TShark, which provides superior packet capture performance. The challenge with Wireshark is that it has to update all of the window elements while at the same time capturing data, and it's defaults do not favor performance.

When you are in a situation of very high traffic flow (like a DoS attack perhaps), you really need to capture as much of the data as possible to a file for later "post analysis". I always use a combination of setting up the TShark capture with Berkeley Packet Filter (BPF), and then plugging the RJ-45 Ethernet cable in after the capture is set to run.

To run TShark within MS-Windows, you need to start a command window first.

Start -> Run -> CMD.EXE

Find the directory that TShark is installed within. For a default Wireshark installation, it is probably as follows:

CD \Program Files\Wireshark

Then, find out the HELP syntax from TShark:

tshark -h

The first thing you must do is find out which network interface number you must use for the data capture.

tshark -D shows all of the interfaces with an integer number in front of them. Windows understands all network interfaces by the long hexadecimal object identifier but you really don't want to have to remember that!

Now, select the right interface, capture some data and write it directly to a file. For example:

tshark-i 2 -s 200 -w example.pcap -f "tcp[13] = 0x14"

The particular example shown above captures data with the 13th offset of the TCP header equal to hexadecimal of 0x14. This happens to be packets that have the TCP flags of RST and ACK set. The -i flag is used to select the capture interface.

TShark will count the packets captured, and then you simply use the CTRL-C keyboard sequence to stop the capture when finished. After that, open your example.pcap file within Wireshark for full analysis. The (.pcap) file extension ensures you could simply double click the file itself.

With regard to the -s (snap length) flag, be aware that TShark will default to a packet capture length of 65,535 bytes, which given a standard 1514 MTU Ethernet frame size, will always capture the entire packet. Using a snaplen of 68 bytes makes the behavior of TShark identical to tcpdump default behavior.

Early versions of TShark did not allow a snaplen that is less than 68 bytes, however I believe there is a source patch that has fixed this now for those who like capturing headers only! Some quick calculations:

Ethernet header = 14 bytes

IPv4 header (without options) = 20 bytes

TCP header (without options) = 20 bytes

Typical TCP header options for Windows Vista = 12 bytes

UDP header = 8 bytes

If we examine a TCP SYN packet of a modern operating system, there are almost always TCP options attached. Windows Vista by default will use Max Segment Size (0x02), Window Scaling (0x03), and Selective Acknowledgement (0x04), as well as three No Operation (NOP = 0x01) options, giving a total of 12 bytes on a TCP SYN packet. The NOP option is used to pad the options data to even byte boundaries so that 32-bit processor code is happy!

To capture a Windows Vista TCP SYN packet header under IPv4 with all options, we would need a minimal snap length as follows:

If you want to throw in some payload data, then add more to the snap length from there. I find that a snap length of about 200 gives good performance and captures a reasonable amount of data.

Keep your goals in mind! If you were capturing traffic that is a Samba CIFS file read for example, you can be pretty sure that the server to client TCP packets will have 1514 bytes of data, so use the default snaplen!

With regard to the Berkeley Packet Filters (libpcap / BPF), the standard language syntax applies. So, if ever in need of help, you can always get on a UN*X host somewhere and do 'man tcpdump' and learn all about the BPF syntax used within libpcap.

This last example shows some interesting ways to use the BPF syntax in combination with binary masking for very specific filter matches. In the below example, we are taking the 13th byte of the TCP header, shifting it left by a nibble (4 bits), then masking it with 0x40 which is binary 0010 0000, and finally testing it not equal to zero. In short, this will show any packet with the TCP RST flag set, but not exclusively that flag. (ie: would could see purely the RST flag, or perhaps even packets with RST+ACK, or some other illegal combination)

-f "(tcp[13] << 4 & 0x40) != 0"

BPF syntax allows us to either use macros for matching (like: src port), or header field matches with integer offsets for the more sophisticated.

Next time you need to capture traffic that is saturating some network link, give TShark some consideration for ensure a high degree of performance and better accuracy.

Finally, for maximum network and security analyst safety, please always ensure you have the latest version of Wireshark and WinPCAP. There have been published exploits against these open source products and you don't want to be a victim!