How can I capture the packet headers but not the data?

Blue Bar separator

I need to run tcpdump or wireshark (tshark/dumpcap) or <insert favorite packet capture utility> but the data is proprietary/personal/top secret. How can I capture the packet headers but not the data? This is a question I hear a lot.

Both tcpdump and tshark/dumpcap use the "-s" option to limit the amount of data captured (snap length).

$ man tcpdump | grep -B 1 -A 12 "snapshot-length"
       -s snaplen
       --snapshot-length=snaplen
              Snarf snaplen bytes of data from each  packet  rather  than  the
              default of 262144 bytes.  Packets truncated because of a limited
              snapshot are indicated in the output  with  ``[|proto]'',  where
              proto  is the name of the protocol level at which the truncation
              has occurred.  Note that taking larger snapshots both  increases
              the amount of time it takes to process packets and, effectively,
              decreases the amount of packet buffering.  This may cause  pack‐
              ets to be lost.  You should limit snaplen to the smallest number
              that will capture the protocol information you're interested in.
              Setting snaplen to 0 sets it to the default of 262144, for back‐
              wards compatibility with recent older versions of tcpdump.


$ man tshark | grep -B 2 -A 10 "snaplen bytes" 
       -s  
           Set the default snapshot length to use when capturing live data.
           No more than snaplen bytes of each network packet will be read into
           memory, or saved to disk.  A value of 0 specifies a snapshot length
           of 65535, so that the full packet is captured; this is the default.

           This option can occur multiple times.  If used before the first
           occurrence of the -i option, it sets the default snapshot length.
           If used after an -i option, it sets the snapshot length for the
           interface specified by the last -i option occurring before this
           option.  If the snapshot length is not set specifically, the
           default snapshot length is used if provided.

$ man dumpcap | grep -B 2 -A 10 "snaplen bytes" 
       -s  
           Set the default snapshot length to use when capturing live data.
           No more than snaplen bytes of each network packet will be read into
           memory, or saved to disk.  A value of 0 specifies a snapshot length
           of 65535, so that the full packet is captured; this is the default.

           This option can occur multiple times. If used before the first
           occurrence of the -i option, it sets the default snapshot length.
           If used after an -i option, it sets the snapshot length for the
           interface specified by the last -i option occurring before this
           option. If the snapshot length is not set specifically, the default
           snapshot length is used if provided.
Figure 1 - man page extracts for tcpdump, tshark and dumpcap

So the next question is what should the value of snaplen be?

The problem is that one size does not fit all. The Ethernet and IPv4 headers are usually fixed at 14 and 20 bytes, although there are exceptions. An Ethernet header with a vlan tag will be 18 bytes. If you have captured on a Linux system with the "-i any" argument you will have an SLL header instead of an Ethernet header and the fixed size will be 16 + 20 bytes. I am ignoring IPv4 options because they are so rarely used. The TCP header can be anywhere from 20 bytes to 60 bytes. The TCP timestamp option is very common and adds 12 bytes to the header and a typical set of TCP options in the first 2 segments of a connection will add 20 bytes. See table 1 for a list of headers and sizes.

If you want to be absolutely sure that not a single byte of data is captured then for an Ethernet frame with no vlan tag and no IPv4 options the snap length should be 54 bytes. This length will capture none of the TCP options, for example the window scale specified at the start of a connection. These options may be critical to understanding the TCP connection but if the alternative is no trace, then half a frame is better than no frame.

If you can live with a small amount of "possible" data leakage then a snap length of 74 bytes should be set. This should capture the typical set of TCP options specified at the start of a connection and also the TCP time stamp option in the data packets. If there are selective acknowledge (SACK) blocks in the header they may be truncated and if there aren't and there is also no TCP time stamp option you can have up to 20 bytes of data leakage in a frame.

The next size up would be 94 bytes. This will allow the capture of the maximum size TCP header. Of course there might be 40 bytes of data leakage in a frame.

If the TCP packet is carried over IPv6 instead of IPv4 the snap lengths would be 74, 94 or 114 bytes for capturing the minimum, typical and maximum headers. Assuming that there are no IPv6 extension headers.

If your are interested in UDP data, the UDP header is fixed at 8 bytes so you only need 42 bytes for UDP over IPv4 and 62 bytes for IPv6.

All this assumes that the data directly follows the transport header. If there is another header, like RPC/NFS following the transport header your top secret data is probably safe but if the problem is in one of these higher level protocols you will not see it in the trace.

Ethernet II14 bytes   
Ethernet 802.3 LLC17 bytes
Ethernet 802.3 SNAP22 bytes
Ethernet II + vlan18 bytes
Ethernet 802.3 LLC + vlan21 bytes
Ethernet 802.3 SNAP + vlan26 bytes
sll header16 bytes
IPv420 bytes
IPv4 with max options60 bytes
IPv6 with no extension headers40 bytes
TCP with no options20 bytes
TCP SYN packet with typical options   40 bytes
TCP + timestamp32 bytes
TCP + max options60 bytes
UDP8 bytes
Table 1 - Header sizes



What do you do if the packet trace has already been captured and you discover that the snaplen is too large and data is leaking?

You can edit the file to reduce the snap length. The Wireshark set of utilities comes with a tool called editcap that allows you to specify a new smaller snap length.

$ man editcap | grep -B 1 -A 12 "Sets the snapshot"
       -s  
           Sets the snapshot length to use when writing the data.  If the -s
           flag is used to specify a snapshot length, packets in the input
           file with more captured data than the specified snapshot length
           will have only the amount of data specified by the snapshot length
           written to the output file.

           This may be useful if the program that is to read the output file
           cannot handle packets larger than a certain size (for example, the
           versions of snoop in Solaris 2.5.1 and Solaris 2.6 appear to reject
           Ethernet packets larger than the standard Ethernet MTU, making them
           incapable of handling gigabit Ethernet captures if jumbo packets
           were used).
Figure 2 - man page extract for editcap

The following example shows the frame length, capture length and TCP options length from a small trace file and what happens to those lengths after running editcap with a length of 74. It also shows how capturing with a snap length of 74 would effect the TCP option lengths. Note that before running editcap the frame length and capture lengths are the same. Frames 10, 13, 15 and 17 have option lengths of 40, 40, 32 and 32 respectively. After the editcap command the maximum capture length is 74 and frames 10, 13, 15 and 17 have option lengths of only 20. So TCP option data has been lost.

$ (echo Number Frame-len Capture-len TCP-options-len; tshark -r test.pcap -T
fields -e frame.number -e frame.len -e frame.cap_len -e tcp.options | awk '{print $1 " "
$2 " " $3 " " (1+length($4))/3}') | column -t
Number  Frame-len  Capture-len  TCP-options-len
1       74         74           20
2       74         74           20
3       66         66           12
4       1514       1514         12
5       666        666          12
6       1514       1514         12
7       1514       1514         12
8       2962       2962         12
9       1514       1514         12
10      94         94           40
11      7306       7306         12
12      1514       1514         12
13      94         94           40
14      5858       5858         12
15      86         86           32
16      1514       1514         12
17      86         86           32


$ editcap -s 74 test.pcap test-editcap-74.pcap

$ (echo Number Frame-len Capture-len TCP-options-len; tshark -r test-editcap-74.pcap -T
fields -e frame.number -e frame.len -e frame.cap_len -e tcp.options | awk '{print $1 " " 
$2 " " $3 " " (1+length($4))/3}') | column -t
Number  Frame-len  Capture-len  TCP-options-len
1       74         74           20
2       74         74           20
3       66         66           12
4       1514       74           12
5       666        74           12
6       1514       74           12
7       1514       74           12
8       2962       74           12
9       1514       74           12
10      94         74           20
11      7306       74           12
12      1514       74           12
13      94         74           20
14      5858       74           12
15      86         74           20
16      1514       74           12
17      86         74           20
Example 1 - lengths before and after editcap is run

There is a tool called tracewrangler (https://www.tracewrangler.com/) which is smart enough to remove data above the TCP header but not damage the TCP header. It is a Microsoft Windows application but can be run on Linux under wine (https://www.winehq.org/), Tracewrangler has a GUI interface which is pretty simple. The following example shows starting tracewrangler under wine and the the output from the edited capture file. Note that the option lengths match the original file (from the previous example) and the capture lengths are smaller in many instances indicating that everything above the TCP header has been removed.

$ wine tracewrangler


$ (echo Number Frame-len Capture-len TCP-options-len; tshark -r test_anon.pcapng -T 
fields -e frame.number -e frame.len -e frame.cap_len -e tcp.options | awk '{print $1 " " 
$2 " " $3 " " (1+length($4))/3}') | column -t
Number  Frame-len  Capture-len  TCP-options-len
1       74         74           20
2       74         74           20
3       66         66           12
4       1514       66           12
5       666        66           12
6       1514       66           12
7       1514       66           12
8       2962       66           12
9       1514       66           12
10      94         94           40
11      7306       66           12
12      1514       66           12
13      94         94           40
14      5858       66           12
15      86         86           32
16      1514       66           12
17      86         86           32
Example 2 - lengths after tracewrangler is run

This of course leads to the conclusion that it is better to capture with at least "-s 94" for IPv4 or "-s 114" for IPv6 and then post process the trace file with tracewrangler to remove the data above TCP without damaging the TCP header then to capture with a smaller snaplen.

Blue Bar separator
This page was last modified on 17-12-10
mailbox Send comments and suggestions
to noah@noahdavids.org