#

Blog

Subscribe
Blog September 16, 2026·13 min read

How DNS Queries Work — and How to Run One Yourself

Every time a device turns a name like example.com into an IP address, it sends a small, tightly structured message called a DNS query and waits for an equally structured answer. Most explanations of DNS either describe this process in the abstract or hand you a command to type without explaining what comes back. This guide does both at once: it walks through what a query actually contains and how it gets answered, then shows you how to generate and read that same process yourself from a terminal or PowerShell prompt, using dig, nslookup, and Resolve-DnsName.

1. What a DNS query actually is

A DNS query is a request for one specific piece of information: a record of a given type, for a given name. The client doesn’t ask “tell me everything about example.com” by default — it asks something closer to “do you have an A record for example.com?” The server’s reply follows the same rigid five-part structure, whether it arrives from a resolver you queried directly or one your operating system consulted on your behalf:

  • Header — identifies the message, states whether it’s a query or a reply, carries a response code (more on that in Section 6), and counts how many entries appear in each of the sections below.
  • Question — the name, record type, and class being asked about. This is the only section present in the original query message itself.
  • Answer — the actual record(s) that satisfy the question, present only in a reply.
  • Authority — name server records identifying which servers are authoritative for the relevant zone. This section is often empty in a straightforward, cached answer and becomes populated in referrals or negative responses.
  • Additional — supporting records that save a follow-up query, such as the IP address of a name server named in the Authority section.

When you run a command-line query, this structure is exactly what you’re looking at — it isn’t a simplification for teaching purposes. Section 5 shows this anatomy mapped directly onto real tool output.

2. Three ways a query gets answered

Before a query even leaves your device, it passes through a piece of software commonly called a stub resolver (Windows documentation calls the equivalent component the “DNS Client service”; the term traces back to the foundational DNS specifications, RFC 1034 and RFC 1123). A stub resolver doesn’t do the heavy lifting of resolution itself — it hands the question to a recursive resolver and waits for a complete answer. That division of labor is what makes the “recursive vs. iterative” distinction meaningful:

  • Recursive query — the querying party asks a server to fully resolve the name and return a final answer, doing whatever additional work is required on its own. This is what your stub resolver asks of your recursive resolver (your ISP’s server, or a public resolver like 1.1.1.1 or 8.8.8.8), and it’s the default behavior most people experience.
  • Iterative query — the querying party asks a server for the best answer it can give right now, without that server doing further work on the client’s behalf. If the server doesn’t have the answer, it replies with a referral — pointers to other servers that are more likely to know. The querying party (typically a recursive resolver, not your device directly) then follows that referral itself. This is exactly what you’ll see demonstrated with the +trace-style output in Section 5.
  • Non-recursive query — a query a server can answer immediately from its own authoritative data or its cache, with no recursion or referral needed at all.

In short: your device almost always makes a recursive request and expects a finished answer; the recursive resolver it’s talking to is the party that actually does the iterative work of walking the DNS hierarchy, described next.

3. From your device to the answer: a walkthrough

Assume a recursive resolver has never seen a query for www.example.com and holds nothing about it in cache. Here’s the sequence it follows:

  1. The resolver consults its root hints — a preconfigured list of the internet’s root name servers — and asks one of them about www.example.com.
  2. The root server doesn’t know the answer, but it knows who manages the .com top-level domain, so it returns a referral: the names and addresses of the .com top-level-domain (TLD) servers.
  3. The resolver asks a .com TLD server the same question. That server doesn’t have the final answer either, but it knows which name servers are authoritative for example.com, so it returns another referral.
  4. The resolver asks an example.com authoritative server directly. This server actually holds the zone data, so it replies authoritatively with the A record — the resolver’s chain of iterative, referral-following queries is complete.
  5. The resolver returns that answer to your device’s stub resolver, which passes it to the application that asked for it in the first place.

This entire multi-step process typically completes in well under a second, largely because of caching. Once the resolver has that answer, it stores it for a period set by the record’s TTL (Time To Live) — a value, in seconds, chosen by the domain’s administrator. Any client asking the same question again before the TTL expires gets the cached answer immediately, with no repeat of the root-to-authoritative walk. Lowering a record’s TTL before a planned change is a common way to shorten how long resolvers hold onto the old value once you switch it — but a resolver that already cached the old record under its previous, longer TTL keeps using it until that cached copy naturally expires, regardless of what the new TTL says.

4. Common DNS record types

A query always specifies a record type, because a name can have multiple kinds of records attached to it. These are the ones you’ll query most often:

Common DNS record types and when to query them
Type Holds Query it when…
A An IPv4 address You need the IPv4 address a hostname resolves to.
AAAA An IPv6 address You’re verifying IPv6 reachability for a domain.
CNAME An alias pointing to another name You’re tracing why a hostname doesn’t have its own A/AAAA records — it may be an alias for something that does.
MX Mail server hostnames and priorities You’re diagnosing email delivery or checking where mail for a domain is routed.
TXT Arbitrary text data You’re checking domain-ownership verification, SPF, or similar policy records.
NS Authoritative name servers for a zone You need to know which servers are authoritative for a domain, e.g. before querying them directly.
SOA Zone administration data, including the serial number You’re checking whether name servers have picked up a recent zone edit — the serial changes when the zone does.
SRV Host and port for a specific service You’re locating a service like XMPP or SIP that publishes its location in DNS instead of a fixed address.
CAA Certificate authorities allowed to issue for the domain A certificate request is being refused and you need to check which CAs are authorized.
PTR A hostname for a given IP address You’re doing a reverse lookup — going from IP to name rather than name to IP.

5. Querying DNS yourself: dig, nslookup, and Resolve-DnsName

Three tools cover almost every platform: dig (Linux and macOS, part of the BIND utilities), nslookup (ships with essentially every OS, including Windows, though it’s the oldest of the three and considered legacy on Linux), and Resolve-DnsName (a PowerShell cmdlet on Windows that returns structured objects rather than plain text). All three send the same kind of query described in Sections 1–3; they just present the result differently.

A plain lookup with dig — no options beyond a name — returns the full message anatomy from Section 1, laid out with each section labeled. The example below is a representative, illustrative capture rather than a live result, since no lookup was actually run for this article:

$ dig example.com

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 41230
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; QUESTION SECTION:
;example.com.            IN   A

;; ANSWER SECTION:
example.com.      86400  IN   A    93.184.216.34

;; Query time: 22 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)

Match this against Section 1: status: NOERROR is the header’s response code confirming no protocol error occurred (it does not, by itself, guarantee the Answer section is non-empty); the Question section repeats what was asked; the Answer section holds the actual record and its remaining TTL; and Authority/Additional are empty here because a direct, cached answer needed neither. Equivalent lookups with the other tools:

# nslookup (interactive or one-shot)
nslookup example.com

# PowerShell
Resolve-DnsName example.com

nslookup‘s default output is shorter and less structured than dig’s; Resolve-DnsName returns a table of properties (Name, Type, TTL, IPAddress) that scripts can filter directly, without text parsing.

The concepts from Section 2 aren’t just theoretical — a trace-style query demonstrates iteration directly. Running dig with a trace option instructs the tool to perform the same root→TLD→authoritative walk described in Section 3 itself, printing each referral as it’s followed, rather than delegating that work to a resolver and only seeing the final answer:

$ dig example.com +trace

.                  IN NS   a.root-servers.net.
;; Received referral from root servers

com.               IN NS   a.gtld-servers.net.
;; Received referral from .com TLD servers

example.com.       IN NS   ns1.example.com.
;; Received referral to authoritative servers

example.com.  86400 IN A   93.184.216.34
;; Answer received from an authoritative server

Each block above corresponds to one step in Section 3’s walkthrough: this is what “iteration” and “referral” actually look like when your own machine — rather than a recursive resolver on your behalf — follows the chain.

5a. Querying a specific record type or server

Append the record type after the name to query something other than the default A record, and prefix a server address with @ to bypass your configured resolver and ask a specific one directly:

dig example.com MX
dig example.com TXT @1.1.1.1
nslookup -type=MX example.com
Resolve-DnsName -Name example.com -Type MX -Server 1.1.1.1

Querying a specific server directly is one of the most useful troubleshooting habits: comparing what 8.8.8.8, 1.1.1.1, and a domain’s own authoritative servers each report for the same name tells you exactly where a discrepancy originates, a technique used directly in Section 6.

5b. Reverse DNS lookups

Reverse lookups go from IP address to hostname using PTR records, and they use a distinct option rather than a record-type flag:

dig -x 93.184.216.34
nslookup 93.184.216.34
Resolve-DnsName -Name 93.184.216.34 -Type PTR

PTR records are published by whoever controls the IP address block, not by the domain owner, so a great many legitimate addresses simply have no PTR record at all — an empty reverse-lookup result is common and not, by itself, evidence of a problem.

6. Diagnosing DNS problems

Most DNS failures surface as one of a small number of response codes, visible in the same header described in Section 1:

Common DNS response codes and what to check
Code Meaning Likely cause and next check
NXDOMAIN The exact queried name doesn’t exist Check for a typo in the full hostname first — the parent domain can be perfectly valid while a specific subdomain simply was never created.
SERVFAIL The server couldn’t complete the query Often a DNSSEC validation failure or an unreachable authoritative server. Compare a normal query against one that asks the resolver to skip DNSSEC validation; if skipping validation succeeds, the domain’s DNSSEC signing is likely misconfigured.
REFUSED The server declined to answer Confirm you’re querying the intended server and that it permits recursive queries or requests from your address — an authoritative-only server commonly refuses recursive requests by design.
Timeout / no response No reply arrived at all Compare a plain UDP query against one forced over TCP; if TCP succeeds where UDP doesn’t, outbound UDP port 53 is likely blocked somewhere on the path.

One of the most common points of confusion isn’t a response code at all: two different resolvers returning two different — but both valid — answers for the same name. It’s tempting to call this “DNS propagation,” but propagation delay is only one possible explanation, and often isn’t the right one. Several DNS mechanisms are specifically designed to give different resolvers different answers on purpose:

  • GeoDNS / load balancing — the authoritative server deliberately returns different IP addresses to different resolvers based on the resolver’s location or current load, to route users to a nearby or less-loaded server.
  • Split-horizon DNS — the same domain name intentionally resolves differently depending on whether the query comes from inside or outside an organization’s network.
  • EDNS Client Subnet (ECS) — an extension that lets a recursive resolver forward a portion of the querying client’s IP subnet to the authoritative server, so the authoritative server can tailor its GeoDNS answer more precisely — again, by design.

Before assuming a change simply hasn’t “propagated” yet, query the domain’s authoritative name servers directly (using the technique from Section 5a) and compare that against what public resolvers return. If the authoritative servers already agree with each other but a public resolver still returns the old value, that resolver’s cache genuinely hasn’t expired yet — check the TTL from Section 3. If different public resolvers return different, simultaneously valid answers, that’s more likely GeoDNS, split-horizon configuration, or ECS at work than a delay.

7. DNS security in brief

Plain DNS queries travel over UDP port 53 with no built-in authentication, which creates two distinct risk categories worth knowing about.

Answer integrity — DNSSEC. DNS Security Extensions add cryptographic signatures to records, letting a validating resolver confirm that an answer genuinely came from the zone’s authoritative servers and wasn’t altered in transit. You can request these signature records directly and check whether a resolver is validating them:

dig example.com +dnssec
dig example.com +dnssec | grep flags

An ad (Authenticated Data) flag in the response header indicates that resolver reports the answer as DNSSEC-validated — meaningful only to the extent you trust that resolver and the path to it, since dig itself does not perform independent validation of the signatures it displays.

Query confidentiality — DoT and DoH. A plain query is also readable by anyone on the network path. DNS over TLS (DoT, typically port 853) and DNS over HTTPS (DoH, typically port 443) encrypt the query itself:

dig example.com @1.1.1.1 +tls
dig example.com @1.1.1.1 +https

Broader threats. Because plain DNS has no way to verify a response’s authenticity, several related attacks exploit that gap: DNS spoofing (returning a forged answer), cache poisoning (a specific technique for planting a forged answer in a resolver’s cache so it’s served to many subsequent clients), and DNS hijacking (redirecting a user to attacker-controlled infrastructure, sometimes via a compromised registrar or router rather than the DNS protocol itself). DNS infrastructure is also a target for denial-of-service attacks aimed at making resolution fail entirely. DNSSEC addresses the authenticity gap that spoofing and poisoning exploit; DoT/DoH address the separate problem of query privacy; neither alone is a complete defense against every technique above.

8. FAQ

dig vs. nslookup vs. Resolve-DnsName — which should I use? On Linux or macOS, dig gives the most complete, scriptable output and is the standard troubleshooting tool. nslookup is available nearly everywhere, including Windows, and its interactive mode suits quick manual checks, though it’s considered legacy on Linux. On Windows, Resolve-DnsName is the more modern choice when you need structured output for a script rather than parsing text.

Why do different resolvers give me different answers? See Section 6 — GeoDNS, split-horizon configuration, and EDNS Client Subnet can all produce legitimately different answers with no propagation delay involved at all.

Does an empty ANY-query response mean something is broken? No. Per RFC 8482, servers are permitted to return a minimal or synthesized response to a query that asks for all records at once (an “ANY” query) rather than the full record set, specifically to discourage that query type. Query each record type you actually need individually instead.

NoScript Team

Leave a comment

Your email address will not be published. Required fields are marked *