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 |
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 II | 14 bytes    |
Ethernet 802.3 LLC | 17 bytes |
Ethernet 802.3 SNAP | 22 bytes |
Ethernet II + vlan | 18 bytes |
Ethernet 802.3 LLC + vlan | 21 bytes |
Ethernet 802.3 SNAP + vlan | 26 bytes |
sll header | 16 bytes |
IPv4 | 20 bytes |
IPv4 with max options | 60 bytes |
IPv6 with no extension headers | 40 bytes |
TCP with no options | 20 bytes |
TCP SYN packet with typical options    | 40 bytes |
TCP + timestamp | 32 bytes |
TCP + max options | 60 bytes |
UDP | 8 bytes |
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 |
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 |
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 |
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.