DNS // RFC 1035
The Domain Name System turns names into records. Every query and response shares one header, four counted sections and a variable-length name encoding with compression pointers. DNS normally rides UDP/53, falls back to TCP for truncation and zone transfers, and is increasingly carried inside QUIC, TLS and HTTPS.
01Message layout
twelve bytes · four counted sectionsA DNS message begins with a fixed 12-byte header. ID matches a response to its query; the flags word carries direction, opcode, truncation and response code; the four counts say how many entries follow in the question, answer, authority and additional sections. Everything after the header is a sequence of names, fixed fields and length-delimited RDATA.
| Section | Count field | Contents | Notes |
|---|---|---|---|
| Question | QDCOUNT | QNAME, QTYPE, QCLASS | Normally exactly one question. The name is not repeated with a type/class header. |
| Answer | ANCOUNT | Resource records | Direct answers, CNAME chains and DNSSEC signatures. |
| Authority | NSCOUNT | Resource records | Delegation NS records or the SOA that proves a negative answer. |
| Additional | ARCOUNT | Resource records | Glue addresses, OPT (EDNS), TSIG and other supporting records. |
A parser must stop when the bytes run out even if the counts promise more records. Truncated messages, compression loops and bad RDLENGTH values are common in captures. The decoder below reports the first inconsistency instead of guessing.
02Flags & response codes
one 16-bit word · direction, policy and statusThe flags word is dense: one direction bit, a four-bit opcode, five single-bit flags (AA, TC, RD, RA and the reserved Z), the two DNSSEC bits AD and CD, and a four-bit response code. Extended response codes live in the EDNS OPT record, so the effective RCODE can be larger than 15.
| Flags-word bit | Name | Meaning | Set by |
|---|---|---|---|
0 | QR | 0 = query, 1 = response | Responder |
1–4 | Opcode | QUERY (0), IQUERY (1), STATUS (2), NOTIFY (4), UPDATE (5), DSO (6) | Sender |
5 | AA | Authoritative Answer: this server owns the zone | Authoritative server |
6 | TC | TrunCation: the message did not fit and should be retried over TCP | Responder |
7 | RD | Recursion Desired: ask the resolver to chase the answer | Client |
8 | RA | Recursion Available: the server is willing to recurse | Responder |
9 | Z | Reserved; must be zero | — |
10 | AD | Authentic Data: the resolver validated DNSSEC for this answer | Validating resolver |
11 | CD | Checking Disabled: do not validate DNSSEC on this path | Client |
12–15 | RCODE | Response code: NOERROR (0), FORMERR (1), SERVFAIL (2), NXDOMAIN (3), NOTIMP (4), REFUSED (5) | Responder |
| RCODE | Name | Meaning |
|---|---|---|
0 | NOERROR | The query completed. The answer section may still be empty (NODATA). |
1 | FORMERR | The server could not parse the query. |
2 | SERVFAIL | The server failed for an internal or upstream reason. |
3 | NXDOMAIN | The queried name does not exist. |
4 | NOTIMP | The opcode or query type is not implemented. |
5 | REFUSED | Policy refused to answer, often because recursion is disabled. |
9 | NOTAUTH | The server is not authoritative for the zone in the query. |
16 | BADVERS | EDNS version not supported. Carried in the OPT record. |
NXDOMAIN means the name does not exist. NOERROR with an empty answer and an SOA in the authority section means the name exists but has no record of that type. Tools that collapse both into “not found” hide useful DNS behaviour.
03Names & compression
length-prefixed labels · 14-bit pointersA domain name is a sequence of labels. Each label starts with a length byte (1–63), followed by that many bytes; a zero byte terminates the name. The root is a single zero byte. Total encoded length is at most 255 bytes, and a presentation-format name is at most 253 characters.
DNS compresses repeated suffixes. A length byte with its top two bits set is a pointer: the remaining 14 bits are an offset from the start of the message. A pointer terminates the current name, so a parser must jump, continue reading, and remember where it should resume after the pointer. Pointers may not point forward in practice, must stay inside the message, and must not loop.
The pointer target is an absolute offset from the first byte of the DNS message. A
name at offset 0x0024 that points to 0xC00C means “continue at
byte 12” — normally the question name. When a decoder reports a name, it should also
report how many pointers it followed.
| Encoding | First byte | Meaning | Example |
|---|---|---|---|
| Label | 0x01–0x3F | Length 1–63, followed by label bytes | 07 example |
| Terminator | 0x00 | End of name (root label) | 00 |
| Pointer | 0xC0–0xFF | 14-bit offset from message start | C0 0C → offset 12 |
| Reserved | 0x40, 0x80 | Unsupported label types; reject | — |
04Resource records
name · type · class · TTL · RDLENGTH · RDATAEvery answer, authority and additional entry uses the same resource-record envelope. The type decides how to interpret RDATA; RDLENGTH lets a parser skip a record even when it does not understand the type. That length-delimited design is what makes DNS extensible.
| Type | Code | RDATA | Typical use |
|---|---|---|---|
| A | 1 | 4-byte IPv4 address | Name to IPv4 address. |
| NS | 2 | Domain name | Delegation to an authoritative name server. |
| CNAME | 5 | Domain name | Alias. A CNAME owner cannot have other data at the same name. |
| SOA | 6 | MNAME, RNAME, serial, refresh, retry, expire, minimum | Zone apex metadata and negative-answer authority. |
| PTR | 12 | Domain name | Reverse lookup under in-addr.arpa or ip6.arpa. |
| MX | 15 | 16-bit preference + exchange name | Mail routing; lower preference wins. |
| TXT | 16 | One or more length-prefixed strings | SPF, DKIM, site verification, policy text. |
| AAAA | 28 | 16-byte IPv6 address | Name to IPv6 address. |
| SRV | 33 | Priority, weight, port + target name | Service discovery; target must not use compression. |
| OPT | 41 | EDNS option TLVs | Pseudo-record: UDP size, extended RCODE, DO bit, options. |
| DS | 43 | Key tag, algorithm, digest type, digest | Delegation signer for DNSSEC. |
| RRSIG | 46 | Signature metadata + signature | DNSSEC signature over an RRset. |
| DNSKEY | 48 | Flags, protocol, algorithm, public key | Zone signing key or key-signing key. |
| HTTPS / SVCB | 65 / 64 | Priority + target + service parameters | HTTPS hints: ALPN, port, IPv4/IPv6 hints, ECH. |
| CAA | 257 | Flags, tag, value | Which certificate authorities may issue for a name. |
RFC 2181 restricts TTL to 31 bits; a value with the high bit set is treated as zero by many implementations. TTL is a cache lifetime in seconds, not a timestamp. Resolvers decrement it as records sit in cache.
05Transport & EDNS(0)
UDP/53 · TCP/53 · 512 B and beyond
DNS is transport-independent. Classic DNS uses a single UDP datagram per message and
retries over TCP when the response sets TC. TCP carries a two-byte length
prefix before each message because a TCP stream has no message boundaries. Zone
transfers (AXFR, IXFR) always use TCP.
| Transport | Framing | Default limit | Used for |
|---|---|---|---|
| UDP/53 | One message per datagram | 512 B without EDNS(0) | Ordinary queries and responses. |
| TCP/53 | 2-byte length prefix per message | 65,535 B per message | Truncated responses, AXFR/IXFR, large DNSSEC answers. |
| DoT | TLS record layer over TCP/853 | Same as TCP DNS | Encrypted DNS to a recursive resolver. |
| DoH | HTTP/2 or HTTP/3 POST/GET | HTTP message limits | DNS inside HTTPS, often to port 443. |
| DoQ | One DNS message per QUIC stream | QUIC stream limits | Encrypted DNS over QUIC, port 853. |
EDNS(0)
EDNS(0) adds one OPT pseudo-record in the additional section. It advertises a larger UDP payload size, carries an extended RCODE and the DNSSEC OK bit, and transports options. OPT is never cached and never appears in a zone file.
| OPT field | Width | Meaning |
|---|---|---|
| NAME | 1 B | Root (0x00); the owner name must be empty. |
| TYPE | 2 B | 41 (OPT). |
| CLASS | 2 B | Requestor's UDP payload size in bytes, not a DNS class. |
| TTL | 4 B | Extended RCODE (8 bits), EDNS version (8 bits), flags (16 bits; DO is 0x8000). |
| RDLENGTH | 2 B | Length of the option area. |
| RDATA | var | Sequence of option code, length and data. |
| Option | Code | Purpose |
|---|---|---|
| ECS | 8 | EDNS Client Subnet: partial client address for authoritative geolocation. |
| COOKIE | 10 | Client/server cookies for off-path spoofing resistance. |
| Padding | 12 | Pads messages to a size that resists traffic analysis. |
| EDE | 15 | Extended DNS Errors: a 16-bit info code plus UTF-8 text. |
| NSID | 3 | Name Server Identifier, useful when debugging anycast. |
| TCP Keepalive | 11 | Idle timeout for long-lived TCP DNS connections. |
Large UDP responses can be fragmented at the IP layer, which is lossy and sometimes filtered. Modern guidance is to advertise an EDNS payload of about 1232 bytes over IPv6 and to prefer TCP when the answer is larger. A 4096-byte advertisement is a maximum, not a promise that the path will carry it.
06Encoder
query or response · raw DNS or UDP datagram
Build a DNS message from a question and zero or more resource records. Record lines use
name [ttl] TYPE data. Names may be written with or without a trailing dot;
the encoder adds root termination and compresses repeated suffixes.
DNS parameters
RFC 1035Record syntax: name [ttl] TYPE data. Examples: example.com. 300 A 192.0.2.10, example.com. 300 MX 10 mail.example.com., example.com. 300 TXT "hello world", _sip._tcp 300 SRV 10 60 5060 sip.example.com.. Output counts are derived from the parsed records.
wire output
waitingno bytes built yet
The encoder reuses earlier suffixes by writing a pointer to their offset. A DNS message is therefore not self-contained per record: RDATA names can point into the question section. Re-ordering sections without rebuilding pointers breaks it.
07Decoder
raw DNS · UDP · TCP · IPv4 · IPv6 · EthernetPaste a DNS message, a UDP datagram, a TCP DNS payload with its two-byte length prefix, a complete IP packet, or an Ethernet frame. The decoder follows compression pointers, validates RDLENGTH, expands the sections and reports the transport context when it is visible.
parse bytes
RFC 1035 · pointers · EDNS08Wire notes
small messages, large operational surfaceName comparisons ignore ASCII case, yet resolvers may randomise the case of query labels (DNS 0x20 encoding) and check that the response echoes it. A canonicalising decoder should preserve the original bytes even when it compares names case-insensitively.
- ID is not authentication. A 16-bit transaction ID plus source-port randomisation raises the cost of off-path spoofing, but DNS cookies and DNSSEC are the actual defences.
- Compression pointers must not loop. A pointer may jump backwards but must terminate. Parsers need a jump limit and a bound check on every target offset.
- RDLENGTH is authoritative for skipping. A parser that does not understand a type can still walk the message because RDATA is length-delimited. Never parse past RDLENGTH.
- TC means retry over TCP. A truncated UDP response is not a complete answer. The client should repeat the query over TCP rather than guess at the missing records.
- UDP payload size is advertised, not guaranteed. EDNS CLASS is the requestor's receive buffer. Path MTU, fragmentation and middleboxes still decide what arrives.
- CNAME chains end at the queried type. A response may contain a CNAME and then records for the canonical target. The owner name in each record is absolute after compression resolution.
- DNSSEC does not encrypt. RRSIG and DNSKEY prove integrity and origin for signed zones. Names and addresses remain visible unless the transport is encrypted (DoT, DoH, DoQ).
- mDNS and LLMNR are different protocols. They use DNS message format on multicast addresses and local ports; they are not part of the global DNS hierarchy.
References
- RFC 1035DNS implementation and specification
- RFC 2181DNS clarifications · TTL and CNAME rules
- RFC 2308Negative caching · NXDOMAIN vs NODATA
- RFC 3596AAAA and IPv6 reverse mapping
- RFC 6891EDNS(0)
- RFC 7873DNS cookies
- RFC 8914Extended DNS Errors
- RFC 8484DNS over HTTPS
- RFC 9250DNS over QUIC
- IANA registryDNS parameters, types, opcodes and rcodes