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.

RFC 1035 · DNS RFC 6891 · EDNS(0) RFC 3596 · AAAA RFC 2181 · clarifications 12 B header name compression UDP · TCP · DoH · DoQ
layer application header 12 B fixed transport UDP/53 · TCP/53 sections question · answer · authority · additional

01Message layout

twelve bytes · four counted sections

A 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.

SectionCount fieldContentsNotes
QuestionQDCOUNTQNAME, QTYPE, QCLASSNormally exactly one question. The name is not repeated with a type/class header.
AnswerANCOUNTResource recordsDirect answers, CNAME chains and DNSSEC signatures.
AuthorityNSCOUNTResource recordsDelegation NS records or the SOA that proves a negative answer.
AdditionalARCOUNTResource recordsGlue addresses, OPT (EDNS), TSIG and other supporting records.
counts are declarations, not limits

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 status

The 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 bitNameMeaningSet by
0QR0 = query, 1 = responseResponder
1–4OpcodeQUERY (0), IQUERY (1), STATUS (2), NOTIFY (4), UPDATE (5), DSO (6)Sender
5AAAuthoritative Answer: this server owns the zoneAuthoritative server
6TCTrunCation: the message did not fit and should be retried over TCPResponder
7RDRecursion Desired: ask the resolver to chase the answerClient
8RARecursion Available: the server is willing to recurseResponder
9ZReserved; must be zero—
10ADAuthentic Data: the resolver validated DNSSEC for this answerValidating resolver
11CDChecking Disabled: do not validate DNSSEC on this pathClient
12–15RCODEResponse code: NOERROR (0), FORMERR (1), SERVFAIL (2), NXDOMAIN (3), NOTIMP (4), REFUSED (5)Responder
RCODENameMeaning
0NOERRORThe query completed. The answer section may still be empty (NODATA).
1FORMERRThe server could not parse the query.
2SERVFAILThe server failed for an internal or upstream reason.
3NXDOMAINThe queried name does not exist.
4NOTIMPThe opcode or query type is not implemented.
5REFUSEDPolicy refused to answer, often because recursion is disabled.
9NOTAUTHThe server is not authoritative for the zone in the query.
16BADVERSEDNS version not supported. Carried in the OPT record.
NXDOMAIN is not NODATA

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 pointers

A 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.

compression is per message, not per record

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.

EncodingFirst byteMeaningExample
Label0x01–0x3FLength 1–63, followed by label bytes07 example
Terminator0x00End of name (root label)00
Pointer0xC0–0xFF14-bit offset from message startC0 0C → offset 12
Reserved0x40, 0x80Unsupported label types; reject—

04Resource records

name · type · class · TTL · RDLENGTH · RDATA

Every 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.

TypeCodeRDATATypical use
A14-byte IPv4 addressName to IPv4 address.
NS2Domain nameDelegation to an authoritative name server.
CNAME5Domain nameAlias. A CNAME owner cannot have other data at the same name.
SOA6MNAME, RNAME, serial, refresh, retry, expire, minimumZone apex metadata and negative-answer authority.
PTR12Domain nameReverse lookup under in-addr.arpa or ip6.arpa.
MX1516-bit preference + exchange nameMail routing; lower preference wins.
TXT16One or more length-prefixed stringsSPF, DKIM, site verification, policy text.
AAAA2816-byte IPv6 addressName to IPv6 address.
SRV33Priority, weight, port + target nameService discovery; target must not use compression.
OPT41EDNS option TLVsPseudo-record: UDP size, extended RCODE, DO bit, options.
DS43Key tag, algorithm, digest type, digestDelegation signer for DNSSEC.
RRSIG46Signature metadata + signatureDNSSEC signature over an RRset.
DNSKEY48Flags, protocol, algorithm, public keyZone signing key or key-signing key.
HTTPS / SVCB65 / 64Priority + target + service parametersHTTPS hints: ALPN, port, IPv4/IPv6 hints, ECH.
CAA257Flags, tag, valueWhich certificate authorities may issue for a name.
TTL is a 31-bit value

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.

TransportFramingDefault limitUsed for
UDP/53One message per datagram512 B without EDNS(0)Ordinary queries and responses.
TCP/532-byte length prefix per message65,535 B per messageTruncated responses, AXFR/IXFR, large DNSSEC answers.
DoTTLS record layer over TCP/853Same as TCP DNSEncrypted DNS to a recursive resolver.
DoHHTTP/2 or HTTP/3 POST/GETHTTP message limitsDNS inside HTTPS, often to port 443.
DoQOne DNS message per QUIC streamQUIC stream limitsEncrypted 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 fieldWidthMeaning
NAME1 BRoot (0x00); the owner name must be empty.
TYPE2 B41 (OPT).
CLASS2 BRequestor's UDP payload size in bytes, not a DNS class.
TTL4 BExtended RCODE (8 bits), EDNS version (8 bits), flags (16 bits; DO is 0x8000).
RDLENGTH2 BLength of the option area.
RDATAvarSequence of option code, length and data.
OptionCodePurpose
ECS8EDNS Client Subnet: partial client address for authoritative geolocation.
COOKIE10Client/server cookies for off-path spoofing resistance.
Padding12Pads messages to a size that resists traffic analysis.
EDE15Extended DNS Errors: a 16-bit info code plus UTF-8 text.
NSID3Name Server Identifier, useful when debugging anycast.
TCP Keepalive11Idle timeout for long-lived TCP DNS connections.
fragmentation is not free

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 1035
header flagsQR · AA · TC · RD · RA · AD · CD

Record 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

waiting
Set the fields and press Build DNS.
DNS message hex
no bytes built yet
message — questions — answers —
compression pointers are relative

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 · Ethernet

Paste 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 · EDNS
No DNS message decoded yet.

08Wire notes

small messages, large operational surface
DNS is case-insensitive on the wire, but case is preserved

Name 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