DNS Protocol Technical Guide (RFC 1035)
This document is a detailed technical guide to RFC 1035, including message formats, resource record types, practical examples, and tool usage instructions. For official RFC chapter translations, please refer to the individual chapter documents.
Document Information
- RFC Number: 1035
- Title: Domain Names - Implementation and Specification
- Published Date: November 1987
- Author: P. Mockapetris (USC/Information Sciences Institute)
- Status: INTERNET STANDARD (STD 13)
Abstract
This RFC defines the implementation details of DNS (Domain Name System), including message formats, resource record formats, and behavioral specifications for name servers and resolvers. This document is a companion to RFC 1034 (DNS Concepts and Facilities), where RFC 1034 defines concepts, and this document defines specific implementations.
Core Concept: RFC 1035 is the implementation specification for DNS, defining message formats, record types, and implementation details.
Relationship with RFC 1034
RFC 1034 (Concepts) RFC 1035 (Implementation)
───────────────── ─────────────────
✓ What is DNS → ✓ Message format
✓ Domain name structure → ✓ Resource record format
✓ Name server architecture → ✓ Resolution algorithm
✓ Caching strategy → ✓ Compression mechanism
✓ Query types → ✓ Protocol details
Recommendation:
Read RFC 1034 first to understand concepts
Then read RFC 1035 to learn implementation
DNS Message Format
Message Structure
All DNS messages use the same format:
+---------------------+
| Header | 12 bytes, fixed
+---------------------+
| Question | Query section (variable length)
+---------------------+
| Answer | Answer section (variable length)
+---------------------+
| Authority | Authority section (variable length)
+---------------------+
| Additional | Additional section (variable length)
+---------------------+
Header Format
1 1 1 1 1 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ID |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|QR| Opcode |AA|TC|RD|RA| Z | RCODE |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| QDCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ANCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| NSCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ARCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Total length: 12 bytes
Field Details
ID (16 bits)
Purpose: Match queries and responses
Range: 0-65535
Usage: Client randomly generates, server returns unchanged
Example:
Query: ID = 12345
Response: ID = 12345 (same)
QR (1 bit) - Query/Response
0 = Query
1 = Response
Example:
Client sends: QR=0
Server replies: QR=1
Opcode (4 bits) - Operation Code
0 = QUERY (standard query)
1 = IQUERY (inverse query, obsolete)
2 = STATUS (server status query)
3-15 = Reserved
Common: Opcode=0 (standard query)
AA (1 bit) - Authoritative Answer
Authoritative answer flag
0 = Non-authoritative answer (from cache)
1 = Authoritative answer (from authoritative server)
Example:
Query example.com A record
→ NS for example.com returns: AA=1
→ Caching server returns: AA=0
TC (1 bit) - Truncation
Truncation flag
0 = Not truncated
1 = Truncated (message exceeds 512 bytes, UDP)
Handling:
if TC=1:
Retry query using TCP
RD (1 bit) - Recursion Desired
Recursion desired
0 = Don't recurse (query local only)
1 = Please recurse
Client setting:
Usually set to 1, requesting DNS server to recurse
RA (1 bit) - Recursion Available
Recursion available
0 = Recursion not supported
1 = Recursion supported
Server response:
if server supports recursion: RA=1
else: RA=0
Z (3 bits) - Reserved
Reserved field, must be 0
Note:
Modern extensions use part of Z bits
DNSSEC uses one bit (AD, CD)
RCODE (4 bits) - Response Code
Response code
| RCODE | Meaning | Description |
|-------|---------|------------|
| 0 | NOERROR | Success |
| 1 | FORMERR | Format error |
| 2 | SERVFAIL | Server failure |
| 3 | NXDOMAIN | Name does not exist |
| 4 | NOTIMP | Not implemented |
| 5 | REFUSED | Query refused |
Common errors:
NXDOMAIN (3) = Domain name does not exist
SERVFAIL (2) = Server temporary failure
QDCOUNT (16 bits)
Number of entries in Question section
Usually 1
ANCOUNT (16 bits)
Number of resource records in Answer section
NSCOUNT (16 bits)
Number of resource records in Authority section
ARCOUNT (16 bits)
Number of resource records in Additional section
Question Section Format
1 1 1 1 1 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| |
/ QNAME /
/ /
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| QTYPE |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| QCLASS |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
QNAME: Domain name to query (variable length)
QTYPE: Query type (16 bits)
QCLASS: Query class (16 bits, usually 1=IN)
QNAME Encoding
Domain names are encoded as a sequence of labels:
Domain name: www.example.com
Encoding:
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|03| w w w |07| e x a m p l e |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|02| c o m |00|
+--+--+--+--+--+
Format:
- Each label preceded by length (1 byte)
- Label content (ASCII characters)
- Terminated with 0
Example:
"www.example.com" =
3 "www" 7 "example" 3 "com" 0
Root domain: 0 (single 0 byte)
QTYPE (Query Type)
Common types:
| Value | Type | Description |
|-------|------|-------------|
| 1 | A | IPv4 address |
| 2 | NS | Name server |
| 5 | CNAME | Canonical name (alias) |
| 6 | SOA | Start of authority |
| 12 | PTR | Pointer (reverse lookup) |
| 15 | MX | Mail exchange |
| 16 | TXT | Text record |
| 28 | AAAA | IPv6 address |
| 255 | ANY | All records (deprecated) |
Example:
Query IPv4 address for example.com:
QTYPE = 1 (A record)
QCLASS (Query Class)
| Value | Class | Description |
|-------|-------|-------------|
| 1 | IN | Internet |
| 2 | CS | CSNET (obsolete) |
| 3 | CH | CHAOS |
| 4 | HS | Hesiod |
| 255 | ANY | Any class |
Usually used: QCLASS = 1 (IN)
Answer/Authority/Additional Format
Resource Record (RR) format:
1 1 1 1 1 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| |
/ NAME /
/ /
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| TYPE |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| CLASS |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| TTL |
| |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| RDLENGTH |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
/ RDATA /
/ /
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
NAME: Domain name
TYPE: Record type
CLASS: Record class (usually 1=IN)
TTL: Time to live (seconds)
RDLENGTH: RDATA length
RDATA: Record data (format depends on TYPE)
Resource Record Types Explained
A Record - IPv4 Address
TYPE = 1
RDLENGTH = 4 (bytes)
RDATA = 32-bit IPv4 address
Example:
NAME: example.com
TYPE: A (1)
CLASS: IN (1)
TTL: 3600
RDLENGTH: 4
RDATA: 93.184.216.34
Encoding (RDATA):
93.184.216.34 → 0x5DB8D822
NS Record - Name Server
TYPE = 2
RDATA = Domain name of name server
Example:
NAME: example.com
TYPE: NS (2)
TTL: 86400
RDATA: ns1.example.com
Meaning: The authoritative server for example.com is ns1.example.com
CNAME Record - Alias
TYPE = 5
RDATA = Canonical name
Example:
NAME: www.example.com
TYPE: CNAME (5)
TTL: 3600
RDATA: example.com
Meaning: www.example.com is an alias for example.com
Query flow:
Query www.example.com A
→ Returns CNAME example.com
→ Continue query example.com A
→ Returns 93.184.216.34
SOA Record - Start of Authority
TYPE = 6
RDATA format:
MNAME: Primary name server
RNAME: Responsible person's mailbox
SERIAL: Serial number
REFRESH: Refresh interval
RETRY: Retry interval
EXPIRE: Expire time
MINIMUM: Minimum TTL
Example:
NAME: example.com
TYPE: SOA (6)
TTL: 86400
RDATA:
MNAME: ns1.example.com
RNAME: admin.example.com ([email protected])
SERIAL: 2024010101
REFRESH: 3600
RETRY: 600
EXPIRE: 604800
MINIMUM: 86400
Usage:
- Identify zone authoritative information
- Control zone transfers
- Set caching policy
MX Record - Mail Exchange
TYPE = 15
RDATA format:
PREFERENCE: Priority (16 bits)
EXCHANGE: Mail server domain name
Example:
NAME: example.com
TYPE: MX (15)
TTL: 3600
RDATA:
PREFERENCE: 10
EXCHANGE: mail1.example.com
Multiple MX records:
example.com MX 10 mail1.example.com
example.com MX 20 mail2.example.com
example.com MX 30 mail3.example.com
Processing:
- Prefer lower values
- Random selection for same priority
- Try next on failure
TXT Record - Text
TYPE = 16
RDATA = Arbitrary text string
Example:
NAME: example.com
TYPE: TXT (16)
TTL: 3600
RDATA: "v=spf1 include:_spf.google.com ~all"
Usage:
- SPF (Sender Policy Framework)
- DKIM (DomainKeys Identified Mail)
- Domain verification
- Arbitrary metadata
Multiple strings:
RDATA can contain multiple <length><string> pairs
AAAA Record - IPv6 Address
TYPE = 28
RDLENGTH = 16 (bytes)
RDATA = 128-bit IPv6 address
Example:
NAME: example.com
TYPE: AAAA (28)
TTL: 3600
RDLENGTH: 16
RDATA: 2606:2800:220:1:248:1893:25c8:1946
Encoding:
IPv6 addresses stored as 16 bytes in network byte order
PTR Record - Reverse Lookup
TYPE = 12
RDATA = Domain name
Usage: Reverse IP address to domain name lookup
Example:
Query: Domain name for 93.184.216.34
NAME: 34.216.184.93.in-addr.arpa
TYPE: PTR (12)
RDATA: example.com
IPv6 reverse:
2606:2800:220:1::1
→ 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.0.0.0.2.2.0.0.0.8.2.6.0.6.2.ip6.arpa
DNS Message Compression
To reduce message size, DNS uses pointer compression to eliminate duplicate domain names:
Compression format:
Domain name label length:
- 00-3F: Normal label length (0-63)
- C0-FF: Pointer (11xxxxxx xxxxxxxx)
Pointer format:
11 <14-bit offset>
Example:
Original message:
Offset 12: 3 "www" 7 "example" 3 "com" 0
Offset 30: 7 "example" 3 "com" 0
Compressed:
Offset 12: 3 "www" 7 "example" 3 "com" 0
Offset 30: C0 0x11 (points to offset 12+4="example")
Savings:
30: "example.com" (12 bytes)
Compressed to: C0 0x11 (2 bytes)
Saved: 10 bytes
Compression Example:
Query: www.example.com, A record for example.com
Uncompressed:
Question:
12: 3"www"7"example"3"com"0 (17 bytes)
Answer:
29: 3"www"7"example"3"com"0 (17 bytes)
46: 7"example"3"com"0 (13 bytes)
Compressed:
Question:
12: 3"www"7"example"3"com"0 (17 bytes)
Answer:
29: C0 0C (2 bytes, points to offset 12)
31: C0 10 (2 bytes, points to offset 16="example.com")
Total saved: (17-2) + (13-2) = 26 bytes
DNS Query Examples
Complete DNS Query/Response
# Python DNS query example
import socket
import struct
def build_dns_query(domain, qtype=1):
"""Build DNS query message"""
# Header
transaction_id = 0x1234
flags = 0x0100 # Standard query, recursion desired
qdcount = 1
ancount = 0
nscount = 0
arcount = 0
header = struct.pack('!HHHHHH',
transaction_id,
flags,
qdcount, ancount, nscount, arcount)
# Question
qname = b''
for part in domain.split('.'):
qname += struct.pack('B', len(part)) + part.encode()
qname += b'\x00' # End marker
question = qname + struct.pack('!HH', qtype, 1) # TYPE, CLASS
return header + question
def parse_dns_response(data):
"""Parse DNS response"""
# Parse Header
transaction_id, flags, qdcount, ancount, nscount, arcount = \
struct.unpack('!HHHHHH', data[:12])
print(f'Transaction ID: 0x{transaction_id:04x}')
print(f'Flags: 0x{flags:04x}')
print(f'Questions: {qdcount}')
print(f'Answers: {ancount}')
# Skip Question section
offset = 12
# (Simplified, actual parsing of QNAME needed)
while data[offset] != 0:
length = data[offset]
offset += length + 1
offset += 5 # End marker + QTYPE + QCLASS
# Parse Answer
for _ in range(ancount):
# NAME (may be pointer)
if (data[offset] & 0xC0) == 0xC0:
# Pointer
offset += 2
else:
# Full domain name
while data[offset] != 0:
length = data[offset]
offset += length + 1
offset += 1
# TYPE, CLASS, TTL, RDLENGTH
rtype, rclass, ttl, rdlength = struct.unpack('!HHIH',
data[offset:offset+10])
offset += 10
print(f'\nAnswer:')
print(f' Type: {rtype}')
print(f' TTL: {ttl}')
# RDATA
if rtype == 1: # A record
ip = '.'.join(str(b) for b in data[offset:offset+4])
print(f' IP: {ip}')
offset += rdlength
def dns_query(domain, dns_server='8.8.8.8', port=53):
"""Execute DNS query"""
# Build query
query = build_dns_query(domain)
# Send query (UDP)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.settimeout(5.0)
try:
sock.sendto(query, (dns_server, port))
response, _ = sock.recvfrom(512)
print(f'Query {domain}:')
parse_dns_response(response)
finally:
sock.close()
# Usage
dns_query('example.com')
Output Example:
Query example.com:
Transaction ID: 0x1234
Flags: 0x8180
Questions: 1
Answers: 1
Answer:
Type: 1
TTL: 3600
IP: 93.184.216.34
Practical Tools
dig Command Details
# Basic query
dig example.com
# Specify record type
dig example.com A # IPv4
dig example.com AAAA # IPv6
dig example.com MX # Mail server
dig example.com NS # Name server
dig example.com TXT # Text record
# Specify DNS server
dig @8.8.8.8 example.com
# Trace query path
dig +trace example.com
# Short format output
dig +short example.com
# Reverse lookup
dig -x 93.184.216.34
# TCP query
dig +tcp example.com
# View complete response
dig +noall +answer +additional example.com
nslookup Usage
# Interactive mode
nslookup
> example.com
> set type=MX
> example.com
> exit
# Command line mode
nslookup example.com
nslookup -type=MX example.com
nslookup -type=NS example.com
host Command
# Simple query
host example.com
# Verbose output
host -v example.com
# Specify record type
host -t MX example.com
host -t NS example.com
References
Core RFCs:
- [RFC 1034] Domain Names - Concepts and Facilities
- [RFC 1035] Domain Names - Implementation and Specification ← This document
Extensions and Updates:
- [RFC 2181] Clarifications to the DNS Specification
- [RFC 2308] Negative Caching of DNS Queries (DNS NCACHE)
- [RFC 4033] DNS Security Introduction and Requirements
- [RFC 4034] Resource Records for the DNS Security Extensions
- [RFC 4035] Protocol Modifications for the DNS Security Extensions
- [RFC 6891] Extension Mechanisms for DNS (EDNS(0))
Related Protocols:
- [RFC 8484] DNS Queries over HTTPS (DoH)
- [RFC 7858] Specification for DNS over Transport Layer Security (TLS)
Summary: RFC 1035 defines the implementation details of DNS and is a key document for understanding how the DNS protocol works. From message formats to resource records, from query flows to compression mechanisms, this RFC provides detailed specifications for all DNS implementations. Together with RFC 1034, you will have a comprehensive understanding of the DNS system!