DNS Messages and Protocol Complete Guide
Understand DNS messaging including queries and responses, TCP vs UDP transport protocols, DNS transactions, header structure with all flags, and response codes (RCODES) for effective troubleshooting.
DNS Messages
We know that the core function of name resolution is carried out by two different messages:
- Query: Sent by the client requesting domain name resolution
- Response: Sent by the server providing the answer to the query
DNS Transactions and Transaction ID
Each exchange of these messages is referred to as a transaction, and it is assigned a transaction ID by DNS.
- Thanks to the Transaction ID, if a client sends three different name requests to three different servers, we can easily find out which query initiated which response
- This is an extremely useful feature that can be used when troubleshooting DNS issues or when conducting forensic network analysis
- Transaction IDs enable proper matching of responses to their corresponding queries
Transport Protocol: TCP vs UDP
As a layer seven application, DNS must rely on a transport protocol at layer four to transfer DNS messages from client to server and vice versa. Most network protocols residing at the application layer usually rely on either TCP or UDP. But DNS is interestingly one of the few protocols that use both depending on the operation taking place.
UDP for DNS - Default Protocol
- For name resolution, where speed is of the essence, UDP is used as a transport protocol
- Carries both DNS requests and responses
- No connection setup overhead - faster than TCP
- Since UDP does not offer a reliable method of delivering messages, it is up to the client to keep track of requests sent
- If a response is not received at a specific time interval, the corresponding request can be retransmitted
- In the interest of preventing excessive DNS traffic on the network, retransmissions are usually sent at an interval ranging from 2 to 5 seconds
TCP for DNS - Reliable Delivery
- Used when data must be delivered reliably
- Zone Transfers: Replicating DNS data from primary to secondary servers
- Large Responses: When a DNS response requires more than 512 bytes of space
- Provides reliable, connection-oriented delivery
- Handles retransmissions automatically
DNS Message Size Limitations
- All UDP DNS messages are limited to a payload of 512 bytes
- If a response message is larger than 512 bytes:
- The message is truncated
- A special flag (TC bit) in the header is set to indicate this outcome
- The client is expected to retry the query over TCP instead
- TCP doesn't have the same 512-byte size limitation as UDP
- Transactions taking place over TCP remain a very small fraction of overall DNS traffic, regardless of which transport protocol is used
DNS Port Numbers
| Component | Port Number | Description |
|---|---|---|
| DNS Server | 53 |
Standard port that servers listen on by default (both TCP and UDP) |
| DNS Client | Ephemeral Port | Random high-numbered port (typically 49152-65535) |
Other DNS Message Types
Other types of DNS messages outside the area of name resolution are:
- Notify: Allows master server to inform slave servers when the zone has changed
- Carried over UDP
- Enables efficient zone synchronization
- Update: Used to add or delete resource records or resource record sets from a specified zone
- Can be carried over either UDP or TCP depending on the size of the request
- Supports dynamic DNS updates
DNS Response Codes (RCODES)
In an ideal world, we would like to see every single query that we make result in a successful translation. Sometimes, however, we're not lucky, and DNS requests can fail to resolve for several reasons. Whenever that happens, we want to get a first hint behind the failure encountered so that we can troubleshoot the problem effectively, identify the root cause of the issue, and eventually fix it.
That's where RCODES come in.
RCODES (Response Codes) indicate whether an error condition exists in the response. Each code corresponds to a numeric value and provides information about the status of the DNS query.
Most Common RCODES
| Code | Name | Description |
|---|---|---|
| 0 | NoError | No Error - The query completed successfully |
| 1 | FormErr | Format Error - The name server was unable to interpret the query (malformed query) |
| 2 | ServFail | Server Failure - The name server was unable to process this query due to a problem with the name server |
| 3 | NXDomain | Non-Existent Domain - The domain name referenced in the query does not exist |
| 4 | NotImp | Not Implemented - The name server does not support the requested kind of query |
| 5 | Refused | Query Refused - The query was refused since the nameserver refused to perform the specified operation for policy reasons |
The full list of RCODES can be found on the IANA page:
https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6
DNS Header
The DNS header consists of a series of fields, and we are going to inspect each one in turn.
DNS Header Fields
1. Transaction ID (16 bits)
- The first field in the DNS header
- Purpose: Associate DNS queries with their corresponding responses
- Enables proper matching when multiple queries are in flight
- Critical for troubleshooting and network analysis
2. Flags (16 bits total)
| Flag | Bits | Description |
|---|---|---|
| QR | 1 bit | Query/Response: Indicates whether the header is for a query (0) or a response (1) |
| OPCODE | 4 bits | Operation Code: Specifies the query type (standard query, inverse query, status request, etc.) |
| AA | 1 bit | Authoritative Answer: Valid in responses. Specifies that the responding nameserver is an authority for the domain name being requested |
| TC | 1 bit | Truncation: Set when a message is truncated due to its length being greater than the maximum size (512 bytes for UDP) |
| RD | 1 bit | Recursion Desired: Set in the query when the client is sending a recursive request to the DNS resolver |
| RA | 1 bit | Recursion Available: Denotes whether the name server that is responding supports recursive queries |
| Z | 1 bit | Reserved: Reserved for future use. Must be zero in all queries and responses |
| AD | 1 bit | Authentic Data: Relevant to DNSSEC - indicates authenticated data |
| CD | 1 bit | Checking Disabled: Relevant to DNSSEC - disables security checking |
| RCODE | 4 bits | Response Code: Indicates whether an error condition exists in the response (0-15) |
3. Count Fields (Unsigned Integers - 16 bits each)
| Field | Name | Description |
|---|---|---|
| QDCOUNT | Query Count | Represents the number of questions in the query section |
| ANCOUNT | Answer Count | Represents the number of resource records in the answer section |
| NSCOUNT | Authority Count | Represents the number of authoritative resource records in the authority section |
| ARCOUNT | Additional Count | Represents the number of resource records in the additional records section |
The DNS header is fixed at 12 bytes and contains:
- Transaction ID - 16 bits
- Flags - 16 bits (QR, OPCODE, AA, TC, RD, RA, Z, AD, CD, RCODE)
- Question Count - 16 bits
- Answer Count - 16 bits
- Authority Count - 16 bits
- Additional Count - 16 bits
These fields appear in every DNS message whether query or response.
- DNS Messages: Queries (client) and Responses (server) with Transaction IDs for matching
- UDP for Speed: Default protocol for DNS queries/responses, 512-byte limit, port 53
- TCP for Reliability: Used for zone transfers and large responses (>512 bytes)
- UDP retransmissions occur at 2-5 second intervals to prevent network congestion
- When UDP message exceeds 512 bytes, TC flag is set and client retries over TCP
- Transaction ID: Critical for matching responses to queries in troubleshooting
- RCODES: Response codes indicate query status (NoError, FormErr, ServFail, NXDomain, NotImp, Refused)
- DNS Header: Fixed 12 bytes with Transaction ID, Flags, and 4 count fields
- Key Flags: QR (query/response), RD (recursion desired), RA (recursion available), AA (authoritative)
- TC Flag: Indicates truncation when response exceeds 512 bytes
- AD/CD Flags: Related to DNSSEC authentication
- Notify Messages: Master informs slaves of zone changes (UDP)
- Update Messages: Dynamic DNS updates (UDP or TCP based on size)
- DNS server port:
53| Client port: ephemeral (high-numbered)
📚 Practice Exercises
- Capture DNS traffic using Wireshark and identify the Transaction ID in a query/response pair
- Perform a DNS query and note whether UDP or TCP was used - explain why
- Trigger a large DNS response and observe the TC flag being set and TCP fallback
- Use nslookup or dig to query a non-existent domain and identify the RCODE returned (NXDomain)
- Examine DNS header flags in a recursive query - which flags are set (RD)?
- Compare the DNS header of a query vs response - what differences do you observe?
- Calculate the total size of a DNS header (in bytes)
- Query a domain's SOA record and check if the AA (Authoritative Answer) flag is set
- Explain when ServFail (RCODE 2) vs NXDomain (RCODE 3) would be returned
- Describe a scenario where DNS would switch from UDP to TCP during resolution
- NXDomain errors: Check for typos in domain name or verify domain exists
- ServFail errors: Name server issues - check server logs and configuration
- FormErr errors: Malformed query - check client DNS software version
- Refused errors: Policy restrictions - verify ACLs and firewall rules
- TC flag set: Response truncated - client should automatically retry over TCP
- No RA flag: Server doesn't support recursion - may need to query different server

No comments:
Post a Comment