top of page

Top 5 Wireshark Filters for DNS

Domain Name System or DNS is one of the most important protocols in your network and out on the Internet. Why is that? Because you can't route a packet through a network using a word. It's just like when you are driving, and your GPS tells you to turn right, or go straight based on your current position. It uses your latitude and longitude, not the name of your current street. In the same way, routers use the numerical address to check their routing tables for the best path to send packets onto their destination. Computers are simply faster when using numbers instead of words.

DNS is the protocol that converts the easy-to-remember words we want to use, into the numbers that routers and hosts need. It's the connection between the names and the actual addresses where the services reside.

When you're troubleshooting DNS you need to have filters ready to go. There's no time to create them once you're on that bridge call. You know the one, "It's SLOW!". DNS is the beginning of most conversations, so best practice is to check DNS first. There is even a haiku for this philosophy written by SSBroski.

It's not DNS
There's no way it's DNS
It was DNS

Here are 5 Wireshark filters to make your DNS troubleshooting faster and easier. Add them to your profiles and spend that extra time on something fun.

1. Slow Responses

Usually this is what we are looking for. IMHO DNS servers should respond within a few milliseconds if they have the data in cache. Capture closest to the server to check server response time - no network roundtrip time to subtract. DNS errors will usually take longer to send, so they are excluded from the filter. We'll look at errors later in this post. Why greater than 100 milliseconds? Back in 2009, Amazon found that 100 milliseconds cost them 1% in sales revenue. I have always used it as the point where a user notices "it is slow".

dns.flags.rcode eq 0 and dns.time gt .1

2. Transaction ID

When the world is perfect, there is one DNS request and one reply. However in real life, things don't always work out that way. Filtering for a transaction ID lets you focus on a single transaction, no matter how many packets or servers are involved. If the client times out without an answer they will either:

  1. Retransmit the query with the same transaction ID to their primary server

  2. Retransmit the query with the same transaction ID to their secondary (or ternary) server

If they have to retransmit the query to either their secondary or ternary servers, the UDP stream number will change. However, the transaction ID will not.

Your goal is to filter for the transaction id - here is the important part - for the packet you already have selected. This syntax of fieldname eq ${fieldname} works for any field. It's pretty powerful. eq ${}

3. UDP or TCP Stream

When you are looking at a pcap and notice something interesting, you often want to filter for that conversation. Maybe the server is an unexpected IP address, or a zone transfer is refused. The key with context sensitive filters is to save them as a button on your toolbar for easy access. eq ${} eq ${}

A word of warning, if you try to create the UDP filter and you are on a TCP packet, or vice versa, the syntax check will be red. If you are creating this filter, be sure to select the packet of interest first.

4. Zone Transfers

Secondary servers should request all records (type 252) when they are first set up. After that, the primary should send a Notify (op code 4) after any changes. Then the secondaries send an incremental records (type 251) request to get the new records. If something goes awry, this filter will get you the whole picture.

dns.qry.type in {251 252} or dns.flags.opcode eq 4

5. DNS Errors

Finally, you'll need a filter for DNS errors. Anytime a server responds with anything besides yes, it's a bad thing. In DNS, a positive reply still isn't necessarily a positive reply. This happens with queries for an IPv6 address. Instead of sending a "no such name" error, the server replies with no error code and no IPv6 address! Seems a bit passive aggressive to me, but the clients understand the response and move to the next step. Yet there is still no IPv6 address.

dns.flags.rcode != 0 or (dns.flags.response eq 1 and dns.qry.type eq 28 and !dns.aaaa)

Be aware, this filter will turn the syntax check yellow due to the not equal, !=. But it's ok, the yellow is just a reminder that not equal only works as expected if the field is a single direction field. For example, ip.addr is bi-directional and http.response.code is single.

Are these all the filters you need for DNS? Of course not, but these should get you started. If you want my entire DNS profile, reach out to me on Twitter with the hashtag #ProfilesArePower. My handle is @PacketDetective.


Betty DuBois is the Chief Detective for Packet Detectives, an application and network performance consulting and training firm based in Atlanta, GA. She has been solving mysteries since 1997.

Experienced with a range of hardware and software packet capture solutions, she captures the right data, in the right place, and at the right time to find the real culprit.

Betty presents each year at SharkFest, the Wireshark Developer and User Conference, and is active in the Wireshark community.

Using packets to solve crimes against the network and applications is her passion. Teaching others to do the same is her calling.

Do you have a Packet mystery that you'd like Betty to solve? How about a team who needs training on how to catch the culprit themselves? Contact her at information. Your mystery will be solved in no time.


bottom of page