Loading episodes…
0:00 0:00

DNS Deep Dive: Tracing a Full Recursive Lookup

00:00
BACK TO HOME

DNS Deep Dive: Tracing a Full Recursive Lookup

10xTeam January 15, 2026 8 min read

Welcome back.

In this DNS series, we’re covering all things DNS. From the first query from a client all the way through the backend. We’ll explore how DNS is secured, the roles of TCP and UDP, and everything in between.

In this article, we’ll look at what happens when a request goes to a recursive server. What happens next on the back end? How does that recursive server fully look up a domain name?

This is important because DNS is hierarchical. There’s not a single server anywhere in the world that owns all domain names or knows every name-to-IP mapping. We can’t just go to one server to get the answer.

Instead, a recursive server queries several different machines to fully resolve the name we’re looking for.

The DNS Lookup Flow

Let’s trace the journey of a DNS request. It starts with a client and its recursive name server.

graph TD
    A[Client] -- 1. example.com? --> B(Recursive Server);
    B -- 2. Who knows .com? --> C(Root Server);
    C -- 3. Ask the TLD server --> B;
    B -- 4. Who knows example.com? --> D(TLD Server for .com);
    D -- 5. Ask the Authoritative Server --> B;
    B -- 6. What is example.com's IP? --> E(Authoritative Server for example.com);
    E -- 7. IP is 93.184.216.34 --> B;
    B -- 8. Here is the IP --> A;

For most of us at home, the recursive server might be our local gateway or a simple lab system. That box doesn’t have every lookup known to man. It has to do the backend query work for us.

We send our request, say for example.com. We ask, “If you don’t have this in your cache, look it up for me.” “If you do have it, send back the IP address.” “But if you don’t, do your thing.”

The first thing that server does is consult a built-in list of root servers. Let’s assume the recursive name server has an empty cache. It just woke up from a nap and has to look up this whole chain.

Step 1: Querying the Root Server

We send example.com out to a root name server. There are only 13 root server names that it knows to query. This doesn’t mean 13 individual servers; there are hundreds, but they are reached through those 13 named entry points.

The root server responds: “I don’t know about example.com.” “I’ve never heard of that domain.” “But I do know who the top-level domain (TLD) servers are for the .com domain.” “Go talk to them, and they’ll steer you further.”

Step 2: Querying the TLD Server

The recursive server says, “Great, wonderful.” It then sends the same request to the .com TLD server. “What about example.com?”

The TLD server’s job isn’t to know every domain either. It replies: “I’m the top-level domain, but I’m not the authoritative name server for the domain you’re looking for.” “Here is the authoritative name server. Go talk to it.” “It will have the A record you’re looking for.”

Step 3: Querying the Authoritative Name Server

Finally, the authoritative name server kicks back the IP address. That IP address is then forwarded on to the client.

This entire process often happens without our field of view. Most of us are down here at the client level. We only see what happens between us and the recursive name server.

That’s why in Wireshark, you often just see a request go to your recursor and an address come back. Just two packets.

You don’t see what’s going on behind the scenes with all these conversations. Your local recursive server might even be a simple forwarder, sending the request to your ISP’s name server, which does the real backend work.

Unless you’re in the world of DNS, you might never see these conversations. But it’s really important to understand how it works.

Into the Packets

Alright, let’s dive into the packets. The capture file for this is named DNS-full-recursion.pcap.

There’s a ton to unpack here. This first packet is our end client requesting from its local recursive server.

We are looking for b2b.infoblocks.com. The query type is A, for a host address (IPv4).

In the additional records, we see a UDP payload size. This tells the server, “Don’t send me anything bigger than this.” If the response is larger, we have to switch to TCP.

The next packet goes out from the server. It uses IPv6 for its next hop. If you look at packet 1 in Wireshark, you’ll see it pairs up with the response in packet 31. All the stuff in between is the backend work.

Let’s make this easier to read in Wireshark. I’ll enable name resolution to see the server names instead of just IPs. I’ll also give my resolver a friendly name, “resolver.”

The Switch to TCP

The resolver sends its query for infoblocks.com to a root server. The UDP payload size is set to 512 bytes.

While it’s at it, the resolver also does a quick check. “Hey, root server, do I have your latest info? Is g.root-servers.net still correct?” It’s just validating its own cached information about the root servers.

The first response from the root server comes back in packet 4. And what do we find? The Truncated flag is set.

[!WARNING] The root server is saying, “Sorry, the response I have for you is way more than UDP can handle. I have to kick this over to TCP.”

The resolver gets the hint. Packet 6 is where we kick off a TCP SYN to the DNS resolver. A standard TCP handshake begins.

After the handshake, we see the response in packet 15. It’s no longer truncated. The response contains the names of all the root servers: A, B, C, D, and so on.

These names are historically short for a reason. Keeping them as single letters ensures the list of all 13 fits within the old 512-byte UDP limit. If the names were longer, we’d break the datagram size.

The response updates the resolver with the latest IPv4 and IPv6 addresses for all root servers.

Finding the TLD

Now, let’s get back to our main query. We send a request over our new TCP connection. “Hey, give me infoblocks.com.”

The server comes back, not truncated. The root server says: “Great, you’re asking for a .com domain.” “I don’t care about the b2b.infoblocks part. I just see .com.” “To find out more, you need to talk to these top-level domain (TLD) servers.”

It provides a list of TLD servers for .com:

  • e.gtld-servers.net
  • l.gtld-servers.net
  • k.gtld-servers.net
  • And so on…

It also provides the IP addresses for these servers in the “Additional records” section. Our resolver is using IPv6, so it will pick one of the quad-A records. At the beginning, it just picks one at random.

In packet 19, the root server tells us the address for g.gtld-servers.net. Our resolver says, “Cool, let me go talk to that one.”

Finding the Authoritative Server

In packet 21, the resolver moves to the next step. It sends a UDP request to the TLD server (g.gtld-servers.net). “Hey, give me infoblocks.com, A record.”

The TLD server responds 7 milliseconds later. “I see your infoblocks.com request.” “I know about .com, but I don’t know about infoblocks specifically.” “I’m going to send you to the authoritative name server that keeps things fresh.”

It then provides records for the next step:

  • ns5.infoblocks.com
  • ns6.infoblocks.com
  • ns7.infoblocks.com
  • ns1.infoblocks.com

The additional records contain the IP addresses for these authoritative servers. The resolver chooses ns5.

The Final Answer

Packet 24 is the final step. Our resolver reaches out to the authoritative name server, ns5.infoblocks.com. “Hey, I was told to talk to you.”

Packet 30 comes back. This is where we get our actual answer. We’re no longer looking for the server that knows the answer; we’ve finally found it.

The query was for infoblocks.com. The answers section contains the IP: 8.39.143.138.

Finally, the resolver turns around and sends this response back to the original client. “Here’s the A record you asked for: 8.39.143.138.” “Now have at it. Go issue that TCP connection, do that ping, whatever you wanted to do.”

Conclusion

That’s a lot of steps on the back end, isn’t it? DNS is super interesting.

We go to the root, then the top-level domain, then an authoritative name server. This process is often blind to the end user.

This is another reason why we don’t want to block TCP in DNS environments. If a record is larger than the UDP payload allows, the resolver has to use TCP. Blocking TCP is not a good practice. DNS is not just over UDP.

So there’s your full recursive lookup.

Where do we go from here? Next up is security. Not just securing the data, but securing the protocol itself. What are the ramifications of DNSSEC, DNS over TLS, and DNS over HTTPS?

That’s for our next article. Thanks for stopping by.


Join the 10xdev Community

Subscribe and get 8+ free PDFs that contain detailed roadmaps with recommended learning periods for each programming language or field, along with links to free resources such as books, YouTube tutorials, and courses with certificates.

Audio Interrupted

We lost the audio stream. Retry with shorter sentences?