Reading a DNS response header, what do the ID field and the QR, AA, RD and RA flags tell you about who answered and how?
answer
- twelve octets before any record
- pairing a reply with its query
- authority for the question name
- asked for versus offered
- availability, not use
basics
~20 sThe 16-bit ID pairs the reply with its query; QR=1 marks a response; AA=1 means the server is authoritative for the queried name; RD echoes whether recursion was requested; RA says whether the server offers recursion at all.
solid answer
~50 sThe DNS header is the first 12 octets of every message (RFC 1035 section 4.1.1). The `ID` is a 16-bit value chosen by the querier and copied into the reply, so the client can match the reply to its outstanding query. `QR` is 0 in a query and 1 in a response. `AA` is valid in responses and says the responding server is an authority for the name in the question section, so an answer relayed by a recursive resolver normally has `AA=0` even when correct, while an authoritative server's own answer has `AA=1`. `RD` is set by the client to ask for recursion and copied back. `RA` is set by the server and, as RFC 1034 puts it, signals availability rather than use: an authoritative-only server answers with `RA=0` even when `RD=1` was asked.
go deeper
Recall that every DNS message starts with a 12-byte header holding an ID, the query or response bit, a few flags, the rcode and four section counts.
Explain each flag's owner: the querier sets RD and the ID, the responder sets AA, RA and TC, and RD, ID and Opcode are copied back. Say what AA=0 from a recursive resolver means.
Show you can diagnose from the header alone: RD=1 but RA=0 means the wrong kind of server, AA tells you whether you reached the zone itself, and TC means the answer must be re-asked over TCP.
Use the header to reason about where answers come from across your estate: which clients reach authoritative servers directly, which go through resolvers, and whether any server offers recursion it should not.
## The 12-octet header Every DNS message, query or response, starts with a fixed **header of 12 octets** (RFC 1035 §4.1.1; RFC 9499 §4). It is six 16-bit words: ``` ID (16 bits) QR | Opcode | AA | TC | RD | RA | Z | RCODE QDCOUNT (16 bits) ANCOUNT (16 bits) NSCOUNT (16 bits) ARCOUNT (16 bits) ``` The second word packs the flags: `QR` (1 bit), `Opcode` (4 bits), `AA`, `TC`, `RD`, `RA` (1 bit each), `Z` (3 bits, reserved in RFC 1035) and `RCODE` (4 bits). Reading these bits is the fastest way to learn **what kind of server answered and what it did**, before looking at a single record. ## Field by field | Field | Set by | Meaning | |---|---|---| | `ID` | querier; copied into the reply | 16-bit identifier used to match a reply to its outstanding query | | `QR` | sender | 0 = query, 1 = response | | `Opcode` | querier; copied into the reply | kind of query; 0 is a standard `QUERY` | | `AA` | responder | **Authoritative Answer**: the responder is an authority for the name in the question section | | `TC` | responder | the message was truncated to fit the transport | | `RD` | querier; copied into the reply | **Recursion Desired**: please resolve this fully for me | | `RA` | responder | **Recursion Available**: this server offers recursive service | | `RCODE` | responder | the response code | | four counts | sender | number of entries in the question, answer, authority and additional sections | Details worth being precise about: - **`ID` matching.** RFC 1035 says the identifier is copied into the reply so the requester can match replies to queries. It is one input to that match; a resolver also checks the addresses, ports and question it sent. How much protection those give against forged replies is a resolver-security topic. - **`AA` names one name.** RFC 1035 ties `AA` to the name that matches the query name, or the first owner name in the answer section. With an alias chain, RFC 1034 notes that `AA` vouches for the data matching the query name and not necessarily for every later record. - **`RD` versus `RA`.** `RD` is a request; `RA` is an offer. RFC 1034 says `RA` is set or cleared in all responses and "signals availability rather than use": a server sets it if it is willing to recurse for this client, whether or not the client asked. - **Opcodes beyond QUERY.** Later RFCs added opcodes such as `NOTIFY` (RFC 1996) and `UPDATE` (RFC 2136); the inverse query `IQUERY` was declared obsolete by RFC 3425. ## Reading typical responses | Who answered | `AA` | `RD` (echoed) | `RA` | Answer section | |---|---|---|---|---| | Recursive resolver, answering from cache or after resolving | 0 (normally) | 1 | 1 | records | | Authoritative server, name in its zone | 1 | as sent | 0 if authoritative-only | records, or empty for NODATA | | Authoritative server for a parent zone, giving a referral | 0 | as sent | usually 0 | empty; `NS` records in authority | | Server that will not recurse, asked with `RD=1` about a name outside its zones | 0 | 1 | 0 | empty or an error rcode | A practical sequence for reading a response header: 1. Confirm `QR=1` and that the `ID` matches the query you sent. 2. Check `TC`; if set, the reply is incomplete and must be re-asked over TCP. 3. Read the `RCODE`: success, a name error or a server failure. 4. Read `AA` to know whether this is the zone's own voice or a relayed copy. 5. Compare `RD` and `RA`: if you asked for recursion and `RA=0`, this server will not resolve on your behalf, and you are talking to the wrong kind of server. 6. Use the counts: `ANCOUNT=0` with `NOERROR` means NODATA or a referral, and `ARCOUNT` includes the EDNS0 `OPT` pseudo-record when one is present. ## What the header does not tell you - **`AA=0` is not "wrong".** A recursive resolver's answer is normally non-authoritative because it is relaying data it fetched or cached. Correctness and authority are different questions. - **`AA=1` is not "fresh from the zone" for every record.** It speaks for the question name. - **`RA=1` does not mean recursion happened.** It says the service is available. - **The `Z` bits are not all spare.** Two of them were later assigned as the DNSSEC `AD` and `CD` flags, which belong to validation, not to this header reading. ## Common misconceptions - Treating `RD` as something the server sets to show it recursed. - Reading `AA=0` from a recursive resolver as a sign of a stale or bad answer. - Believing the `ID` alone authenticates a reply.
- A recursive DNS resolver returns a correct answer with AA=0. Is something misconfigured?No. `AA` says the responding server is an authority for the queried name. A recursive resolver normally is not; it relays data fetched from the authoritative servers or held in its cache, so `AA=0` is expected. You would see `AA=1` by querying an authoritative server for the zone directly, or when the resolver is itself authoritative for that zone.
- What can a DNS server return to a query sent with RD=0?Only what it holds locally. RFC 9499 describes a non-recursive query as one a server answers from local information: an error, the answer from a zone it serves or its cache, or a referral to servers closer to the answer. It does not go and ask other servers. Recursive resolvers typically send their own queries to authoritative servers this way.
- What do the four DNS header counts tell you before any record is parsed?`QDCOUNT`, `ANCOUNT`, `NSCOUNT` and `ARCOUNT` give the number of entries in the question, answer, authority and additional sections. `ANCOUNT=0` with `NOERROR` means NODATA or a referral, and the authority section tells them apart. `ARCOUNT` also counts the EDNS0 `OPT` pseudo-record when present, so it can be non-zero with no real additional data.
saying these in an interview costs you the question
- The server sets RD in its response to show that it performed recursion.
- An answer with AA=0 from a recursive resolver is stale or unreliable.
- RA=1 in a response means the server recursed for this query.
- The 16-bit ID alone proves a DNS reply is genuine.
- The DNS header's size varies with the number of flags that are set.
- AA=1 vouches for every record in the answer section, aliases included.