Display Filters are a large topic and a major part of Wireshark’s popularity. If you are unfamiliar with filtering for traffic, Hak5’s video on Display Filters in Wireshark is a good introduction.
Display filters allow you to use Wireshark’s powerful multi-pass packet processing capabilities.
To use a display filter with tshark, use the
-Y 'display filter'. Single quotes are recommended here for the display filter to avoid
bash expansions and
problems with spaces.
If you create a filter and want to see how it is evaluated, dftest is bundled with Wireshark.
For any major protocol, there is query for each direction and either.
eth.src == 00:11:22:33:44:55: Source MAC address is 00:11:22:33:44:55
ip.addr == 10.0.0.1: Find all traffic that has IP of 10.0.0.1
tcp.dstport != 80: Destination tcp port is NOT 80
For the table below, create a filter by joining the relevant header and word below it with a
For example, source MAC address becomes
Care must be taken when using
!= with a filter that specifies either direction like
If you are wondering why, dftest can be used to investigate.
Protocols you might run into are
http. These are provided as examples as the list of available protocols is extremely long.
bash$ tshark -Y 'icmp' Capturing on 'Wi-Fi: en0' 1 0.000000 192.168.1.246 → dns.google ICMP 98 Echo (ping) request id=0x1d5b, seq=48153/6588, ttl=63 2 0.025354 18.104.22.168 → mbp.attlocal.net ICMP 98 Echo (ping) reply id=0x1d5b, seq=48153/6588, ttl=53 (request in 1) 13 1.001761 192.168.1.246 → dns.google ICMP 98 Echo (ping) request id=0x1d5b, seq=48154/6844, ttl=63 14 1.026759 22.214.171.124 → mbp.attlocal.net ICMP 98 Echo (ping) reply id=0x1d5b, seq=48154/6844, ttl=53 (request in 13) 31 2.004378 192.168.1.246 → dns.google ICMP 98 Echo (ping) request id=0x1d5b, seq=48155/7100, ttl=63 35 2.029677 126.96.36.199 → mbp.attlocal.net ICMP 98 Echo (ping) reply id=0x1d5b, seq=48155/7100, ttl=53 (request in 31)
! are used to combine statements. For example, to get all traffic going to google’s dns servers that is not a ping or dns lookup, use
ip.addr == 188.8.131.52 and !(icmp or dns)
If you like C-style syntax, you can also use
&& instead of
|| instead of
Sometimes you know the protocol you’re looking for, just not the relevant fields you need to filter with.
tshark -G will print all protocols, so you can use it in conjunction with grep to find fields of interest.
If we already know what the field name is, we can get the full display filter by searching for it.
bash$ tshark -G | grep -E "sec_websocket_version" F Sec-WebSocket-Version http.sec_websocket_version FT_STRING http 0x0
In this example, use
http.response, and escape the periods.
bash$ tshark -G | grep -E "http\.response\." F Response line http.response.line FT_STRING http 0x0 F Response Version http.response.version FT_STRING http 0x0 HTTP Response HTTP-Version F Status Code http.response.code FT_UINT16 http BASE_DEC 0x0 HTTP Response Status Code F Status Code Description http.response.code.desc FT_STRING http 0x0 HTTP Response Status Code Description F Response Phrase http.response.phrase FT_STRING http 0x0 HTTP Response Reason Phrase
If you would like to optimize display filtering over 2
passes, you can specify the first and second with
-R <filter> -2 -Y <2nd filter>.
There are few circumstances where this relevant, but I can make a contrived example: Let’s say that you want the 5th arp frame in a capture. You could do this with two passes or by calling tshark twice. Using two passes is faster:
bash-5.0$ time tshark -r large.pcapng -R "arp" -2 -Y "frame.number == 5" 5 5.872787 18:68:cb:ad:97:60 → Broadcast ARP 60 Who has 192.168.1.64? Tell 192.168.1.141 real 0m2.945s user 0m2.702s sys 0m0.447s bash-5.0$ time tshark -r large.pcapng -Y "arp" -w - | tshark -r - -Y "frame.number == 5" 5 5.836911 18:68:cb:ad:97:60 → Broadcast ARP 60 Who has 192.168.1.64? Tell 192.168.1.141 real 0m4.660s user 0m4.633s sys 0m0.781s
One of the biggest differences between tshark and Wireshark is that you can change the Termshark is the way to analyze a capture in the terminal. You can change filters just like Wireshark’s GUI to see what’s happening.
Sometimes you want to search packet data and a display filter won’t cut it.
matches will search with a regex while
contains searches for exact byte sequences.
You cannot use matches and contains with fields that have a number type like
You’re looking for an HTTP GET that contains a request for a URL that
starts with ‘http’ or ‘https’, has the Russian ‘.ru’ domain, and contains the word ‘worm’ in the query string.
Luckily, Wireshark gives you
matches which uses PCRE regex syntax.
A simple one that satisfies this is
https?.*?\.ru.*?worm. If this seems like greek, you can explore it on regex101.
Given that this is GET, it’s better to just search the ‘http’ protocol:
http matches "https?.*?\.ru.*?worm"
Note that the regex is double quoted. With tshark,
-Y "display filter" also needs to be double-quoted.
In order to use this display filter, escape the inner quotes:
tshark -r $file -Y "frame matches \"https?.*?\.ru.*?worm\""
You cannot use the null character,
\x00 when using
matches because Wireshark uses null-terminated C-strings.
contains searches the text representation of a field.
If you’re looking for any frames that match an OUI ‘00:16:e3’,
there are a couple ways of doing this.
# These are all equivalent tshark -r $file -Y "eth.addr contains 00:16:e3" tshark -r $file -Y "eth.addr[0:3] == 00:16:e3" tshark -r $file -Y "eth.addr matches \"^[^\x01-\xff]\x16\xe3\""
This will be a long list as this is the meat of what Wireshark does.
matchhas a superset of functionality. Limited to pcaps and parses vastly fewer protocols.