Chapter 10 · Part III · At internet scale

Names on the network you're sitting on

Most of this site is about the global DNS: one tree, run by thousands of organizations, the same answers for everyone. But the first decisions about a name are made on your own machine and your own network, long before any root server hears of it. How a home router hands out a resolver is covered in networks · DHCP & DNS and networks · Your home network; how a VPN carries your traffic to the office is networks · VPNs, tunnels & overlays. This chapter is about what happens to a name on that local network: the search list that quietly rewrites what you type, the .local names that never touch a DNS server, the printer that announces itself, the company name that works at your desk and vanishes on the VPN, and the old fallback protocols that will answer for a stranger.

5353the UDP port Multicast DNS uses for .local names, the same message format as ordinary DNS on port 53 (RFC 6762)
224.0.0.251 · ff02::fbthe IPv4 and IPv6 link-local multicast groups every mDNS query is sent to; routers never forward them off the link
home.arpathe name reserved for home networks by RFC 8375 in May 2018, replacing the earlier .home

Common mix-up: .local is not a private top-level domain you can use for your company's internal DNS. It is reserved for Multicast DNS: a name ending in .local is supposed to be shouted to the local link, not sent to a DNS server. Networks that named their internal zone corp.local years ago now fight every Mac, phone and Linux laptop that joins them. RFC 6762 recommends against it outright. Use a subdomain of a domain you own, such as corp.example.com, or home.arpa at home.

Before any packet leaves

Where a name goes first

A program that wants an address calls a library function, usually getaddrinfo. That function, the stub resolver and its helpers in the operating system, makes several decisions before a single DNS packet is sent. Get any of them wrong and you see behavior that looks like DNS is lying, when DNS was never asked.

  1. The hosts file. /etc/hosts on Unix-like systems and macOS, C:\Windows\System32\drivers\etc\hosts on Windows. A line in it wins over everything else, which is why a forgotten test entry can pin a name to an old address for years.
  2. Special names. localhost is answered locally. A name ending in .local is handed to the Multicast DNS responder (mDNSResponder on Apple systems, Avahi with nss-mdns on most Linux desktops; recent Windows versions also speak mDNS).
  3. The search list. If the name is short, the stub may try it with one or more suffixes appended before trying it as typed. The rules are set by the search list and a threshold called ndots, the subject of the next section.
  4. Unicast DNS. Each candidate name is sent, usually as an A and an AAAA question, to the resolver the network handed out (or one you configured), and from there into everything the rest of this site describes.
  5. Fallbacks. On Windows, if DNS fails, the system may still try Link-Local Multicast Name Resolution (LLMNR) and NetBIOS name service, asking every machine on the link whether it has that name. The last section of this chapter explains why that is dangerous.

On Linux the order is written down in one line of /etc/nsswitch.conf. A typical desktop has hosts: files mdns4_minimal [NOTFOUND=return] dns: hosts file, then mDNS for .local names (and stop there if mDNS has no answer, so .local never leaks to a DNS server), then DNS. macOS and Windows keep the equivalent logic inside their resolver services, which is why dig and nslookup, which talk to a DNS server directly, can disagree with what your browser sees. A browser goes through the system resolver; dig skips the hosts file, the search list (unless you ask with +search) and mDNS entirely.

Instrument 1

The search-list expander

Set a search list and an ndots value, then type a name. The expander follows the same rules as the Linux stub resolver and lists, in order, every question it would send and where each one goes, until one gets an answer. It flags internal names that leak to the public DNS and short names that resolve somewhere you did not intend. The network is simulated: internal zones corp.example, lab.corp.example, cluster.test and home.arpa live on the company resolver; everything else is "the internet," with a handful of made-up public records.

Candidates tried–
Packets on the wire–
Leaked to public DNS–
Answered by–

    Go deeper: the exact rules, and where they differ

    The algorithm the expander uses is the one in the GNU C library's res_search. Count the dots in the name. If the count is at least ndots, try the name as an absolute name first, then with each search suffix. If it is lower, try each suffix first and the bare name last. A trailing dot turns all of this off. The resolv.conf manual caps ndots at 15; since glibc 2.26 the search list itself is unlimited (it used to be six domains).

    Implementations differ at the edges. musl, the C library in many small container images, handles the search list in its own way. Windows has separate settings for the primary suffix, connection-specific suffixes and "devolution," a feature that walks up the computer's own domain name one label at a time, the pattern RFC 1535 warned about, so check how far it is allowed to go. systemd-resolved applies the search list itself and can route each suffix to a different server (see split DNS below). When a lookup surprises you, look at the queries actually sent with a packet capture rather than reasoning from the config file.

    Two settings help. Make names in configuration files fully qualified, with a trailing dot where the software allows it. And raise ndots only as far as your shortest internal names need: ndots:2 stops git.lab leaking, without making every external name pay the search-list tax.

    No server at all

    Multicast DNS: .local

    A home network has no one to run a DNS zone. Nobody types the printer's address into a server. Yet your phone finds printer.local. That is Multicast DNS (mDNS), published as RFC 6762 in 2013 after more than a decade of use in Apple's Bonjour. The idea is plain: instead of asking a server, ask everyone on the link at once, and let the device that owns the name answer for itself.

    The messages are ordinary DNS messages, the same header and sections described in Chapter 2. What changes is where they go. A query for any name ending in .local. is sent to UDP port 5353 at the multicast group 224.0.0.251 (or ff02::fb over IPv6). Every mDNS responder on the link receives it. The one that holds the name answers, normally by multicast too, so every other device can update its own cache from the same packet. Those groups are link-local: routers do not forward them, which is why printer.local on the guest Wi-Fi is invisible from the main network.

    ; simulated mDNS exchange on one link (documentation addresses)
    ; 192.0.2.10 → 224.0.0.251:5353   query
    ;printer.local.             IN  A
    ; 192.0.2.40 → 224.0.0.251:5353   response, sent by the printer itself
    printer.local.    120  IN  A   192.0.2.40     ; class has the cache-flush bit set

    Claiming a name: probing and announcing

    With no registry, two devices can want the same name. RFC 6762 settles that with a short ritual every responder performs when it starts or joins a network. First it probes: after a random wait of up to 250 ms, it sends a query for the name it wants, three times, 250 ms apart, asking whether anyone already holds it. A device that does answers, and the newcomer must pick another name, for example by adding a number (printer-2.local, or "Office Printer (2)" for a service), then probe again. The RFC notes the window is deliberately short: an existing holder has just 750 ms to defend its name. If no one objects, the device announces: at least two unsolicited responses, one second apart, so every cache on the link learns the name at once.

    Records whose name or data is a host name, such as A, AAAA and SRV, get a TTL of 120 seconds; others get 75 minutes. A device leaving the network politely sends its records again with a TTL of 0, a "goodbye," so caches drop them at once rather than waiting.

    Go deeper: the two bits mDNS borrows, and how it stays quiet

    mDNS reuses the top bit of the 16-bit class field. In a question it is the unicast-response bit ("QU"): please answer me directly rather than to the group, used for the first query after a device wakes up. In an answer it is the cache-flush bit: this record set is complete, so throw away any older records for the same name and type. That is how a device that changed address corrects everyone's cache in one packet.

    Because every query reaches every device, mDNS works hard to send fewer packets. A querier lists the answers it already has, with enough TTL left, in the answer section of its question (known-answer suppression), and responders that see their record listed stay silent. Repeated queries back off, the gap at least doubling from one second. Responders delay their replies by 20 to 120 ms when an answer is shared by many devices, so a question about a common service doesn't produce a burst of simultaneous replies. Even so, mDNS was designed for one link, and it grows noisy on large Wi-Fi networks; that is the motivation for the unicast alternatives at the end of the next section.

    Finding things, not just names

    DNS-based service discovery

    Knowing that printer.local is at 192.0.2.40 is only useful if you already knew to ask for printer.local. The real question a laptop has is "which printers are there?" DNS-Based Service Discovery (DNS-SD, RFC 6763) answers it with nothing but ordinary record types arranged in a chain. It works over mDNS on a home network and over unicast DNS in a managed one.

    1. PTR: browse. Ask for PTR records at the service type, _ipp._tcp.local for printers that speak the Internet Printing Protocol. Each answer names one service instance: Office Printer._ipp._tcp.local. The instance name is a human-readable label and may contain spaces and capitals.
    2. SRV: where. Ask for the SRV record of the instance you picked. It gives the host and the port: printer.local, port 631.
    3. TXT: details. The TXT record at the same name holds key=value pairs describing the service: the queue path, the model, the formats it accepts.
    4. A / AAAA: address. Finally resolve the host from the SRV record, as with any name.
    ; simulated DNS-SD chain for one printer
    _ipp._tcp.local.                 4500 IN PTR  Office\032Printer._ipp._tcp.local.
    Office\032Printer._ipp._tcp.local. 120 IN SRV  0 0 631 printer.local.
    Office\032Printer._ipp._tcp.local. 4500 IN TXT "txtvers=1" "rp=ipp/print" "ty=Example Laser 400"
    printer.local.                    120 IN A    192.0.2.40
    ; \032 is a space written as a decimal escape: the instance name is "Office Printer"

    Responders usually put the SRV, TXT and address records in the additional section of the PTR reply, so one round trip does the whole chain. A special query for PTR records at _services._dns-sd._udp.local lists every service type present on the link, which is how network browsers build their menus.

    Go deeper: DNS-SD beyond one link

    Because DNS-SD is only record types, a network operator can publish the same PTR, SRV and TXT records in a normal unicast zone, say _ipp._tcp.corp.example, and laptops that know to browse corp.example will find printers across a whole campus without any multicast. Two newer standards automate that. The Discovery Proxy (RFC 8766) sits on a link, listens to mDNS, and answers unicast DNS-SD questions about what it hears. The Service Registration Protocol (RFC 9665, 2025) lets devices register their services with a server using DNS UPDATE, protected by a public key each device keeps, so wireless and low-power networks don't have to carry multicast at all.

    Instrument 2

    The mDNS browser

    A simulated home link with four devices. Browse a service type to see the PTR answers arrive from the devices themselves, then pick an instance to follow the SRV, TXT and address records. Plug in a second printer that also wants the name printer.local and watch it probe, lose, rename itself and announce. Packets are drawn four times slower than real time so you can follow them. All names and addresses are simulated.

    Browse a service type to see instances.

    Names that are never delegated

    home.arpa and the other special-use names

    Some names are carved out of the public tree on purpose. RFC 6761 (2013) set the rules for these special-use domain names and IANA keeps the registry. Each entry says how applications, stub resolvers, recursive resolvers and authoritative servers should treat the name. For local networks, these are the ones that matter:

    NameReserved byWhat it is forWhat a resolver does with it
    home.arpaRFC 8375 (2018)Names inside a home network, such as nas.home.arpa. Not unique: every home has its own.Answers from local data; MUST NOT forward the query to the internet (RFC 6303 rules)
    localRFC 6762 (2013)Multicast DNS names on one linkSends to 224.0.0.251 / ff02::fb port 5353, not to a DNS server
    localhostRFC 6761 (2013)This machine, always the loopback addressAnswers locally; never asks a server
    test, example, invalidRFC 6761 (2013, from RFC 2606)Testing, documentation, names that must never resolveinvalid always NXDOMAIN; the others may be used in private test setups
    altRFC 9476 (2023)Namespaces that are not DNS at all (for example peer-to-peer naming systems)Never sent into the DNS
    ipv4only.arpaRFC 7050, RFC 8880 (2020)Lets a host discover the NAT64 prefix (see DNS64 below)Has fixed well-known answers
    10.in-addr.arpa etc.RFC 6761, RFC 6303Reverse names for private address rangesAnswered locally; no reason to ask the public reverse tree (Chapter 7)

    home.arpa has a short, telling history. The home-networking working group first used .home, a name that was never delegated but that home routers had used for years, and which an enormous number of misconfigured devices were already leaking to the root servers. RFC 8375 moved it under .arpa, the infrastructure domain the IETF controls, where a reservation could actually be made and enforced: the public arpa zone holds an insecure delegation for home.arpa, so DNSSEC validators accept local answers for it instead of rejecting them.

    The practical advice follows. At home, use home.arpa (or just .local names via mDNS). In an organization, use a subdomain of a domain you have registered: corp.example.com or internal.example.com. You can then get certificates for it, delegate it, and never collide with a future top-level domain. RFC 6762's Appendix G lists made-up suffixes people have used, .corp, .lan, .internal, .home among them, and says plainly that it does not recommend unregistered top-level domains at all.

    Same question, different answer

    Split horizon, and why the VPN breaks it

    Global DNS gives everyone the same answer. Organizations often want the opposite. The company website www.example.com should resolve, from the internet, to the public address on the firewall; from a desk in the office, it should resolve straight to the server's inside address, without going out to the internet and back. The wiki wiki.corp.example should not exist on the internet at all. Running different answers for the same name depending on who asks is called split horizon or split DNS. Servers implement it with views: the server checks where a query came from and answers it from one of two (or more) copies of the zone.

    ; the same question to the same server name, from two places (simulated)
    ; from a desk in the office: the inside view
    www.example.com.    300  IN  A   198.51.100.10
    ; from a café: the outside view
    www.example.com.    300  IN  A   203.0.113.10
    ; and wiki.corp.example from the café
    ;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN

    Why not just give everyone the public address? Because from inside, the public address points at your own firewall, and reaching your own public address from inside your own network needs hairpin NAT (the firewall turning the packet around), which many routers don't do. Split horizon avoids the question by never handing an inside client the outside answer.

    The trouble is that a view is chosen by which resolver you ask, and that depends on where you are and what your machine has been told. It works perfectly in the office. It goes wrong when people take laptops home:

    • The VPN routes traffic but not DNS. The tunnel is up and the wiki's inside address would be reachable, but the laptop still asks the home router's resolver, which has the outside view: NXDOMAIN. The classic "works in the office, fails on VPN."
    • Split tunnel, full DNS. Only office addresses go through the tunnel, but every name is resolved by the office. Usually fine, but every lookup now crosses the tunnel, and the office learns every site the person visits.
    • Full tunnel with the outside view. All traffic leaves through the office, so connecting to the public address of the office's own server needs hairpin NAT again.
    • Encrypted DNS in the browser. A browser configured to send its lookups over HTTPS to a public resolver bypasses whatever the VPN pushed. The public resolver has the outside view, so internal names vanish in the browser while still working in the terminal. Browsers look for signals that a network or managed device wants its own resolver used; Chapter 12 covers that negotiation.

    The robust fix is split DNS on the client: the VPN tells the operating system which suffixes belong to the office (corp.example, and example.com if it is split), and the system sends only those names to the office resolver and everything else to the normal one. macOS does this with per-domain resolver entries, systemd-resolved with per-link routing domains, Windows with its Name Resolution Policy Table.

    Instrument 3

    The split-horizon simulator

    Put the laptop in the office, at home, or at home on the VPN; choose how the VPN handles routes and DNS; and switch on the browser's own encrypted DNS. For each of four names the simulator works out which resolver is asked, which view answers, whether the address that comes back is reachable along the route you chose, and so whether the name works. Pick a name to draw its path. The company's inside addresses are shown in 198.51.100.0/24 and its public face in 203.0.113.0/24; everything is simulated.

    NameAskedAnswerRoute to itResult

    Names that write themselves

    Dynamic updates from DHCP

    In a managed network, you can type a colleague's machine name and reach it, even though nobody edited a zone file when that laptop joined. The DHCP server, or the laptop itself, registered the name with DNS UPDATE, defined in RFC 2136 (1997). An UPDATE message uses the DNS format with a different opcode (5) and renames the four sections: Zone (which zone to change), Prerequisite (conditions that must hold), Update (records to add or delete) and Additional.

    The prerequisites are what make it safe for many writers to share one zone. "This name must not exist yet," "this exact record set must be present": the server checks them atomically and refuses the whole update if any fails. A typical DHCP flow is: the client sends its preferred host name (the Client FQDN option, number 81 in DHCPv4 per RFC 4702, 39 in DHCPv6 per RFC 4704), the DHCP server hands out an address, then sends an update that adds the A record and the matching PTR record in the reverse zone.

    ; a DNS UPDATE as a person would write it with nsupdate (simulated, harmless)
    zone corp.example.
    prereq nxdomain laptop-17.corp.example.          ; only if nobody has the name
    update add laptop-17.corp.example. 3600 A 198.51.100.117
    send
    ; server reply: status NOERROR, the zone's SOA serial goes up by one

    An open UPDATE port is an open door: anyone who can reach it can rewrite your names. So updates must be authenticated. RFC 3007 defines secure dynamic update; in practice that means TSIG, a shared secret key between the DHCP server and the DNS server that signs every message (RFC 8945, and Chapter 6 on how TSIG also protects zone transfers), or GSS-TSIG with Kerberos in Windows domains. Restrict which keys may change which names, and keep dynamic names in their own subzone so that a compromised key cannot rewrite www.

    DNS64, in one paragraph

    Some networks, mobile carriers especially, give devices only IPv6. To reach a site that has only an IPv4 address, they pair a NAT64 gateway with a DNS64 resolver (RFC 6147). When a name has an A record but no AAAA, DNS64 synthesizes an AAAA record by embedding the IPv4 address in an IPv6 prefix that routes to the gateway, usually the well-known 64:ff9b::/96 from RFC 6052. Ask for the AAAA of a site at 192.0.2.33 and you get 64:ff9b::c000:221; your packets go to the gateway, which translates them to IPv4. Hosts discover the prefix by asking for ipv4only.arpa, which has only well-known IPv4 addresses. Because the answer is invented by the resolver, DNS64 and DNSSEC validation on the device do not mix: a validating client will see that the synthesized record carries no valid signature.

    Defense

    When DNS fails, a stranger answers

    Windows inherited two older ways to find a name on the local link: NetBIOS name service (NBT-NS, UDP 137, broadcast) and Link-Local Multicast Name Resolution (LLMNR, RFC 4795, UDP 5355 to 224.0.0.252 or ff02::1:3). Both are used as fallbacks when DNS has no answer. Both ask everyone on the link, and both believe whoever answers first. Neither has any way to check that the answer comes from the real owner of the name.

    That is the weakness MITRE ATT&CK catalogs as T1557.001, LLMNR/NBT-NS Poisoning and SMB Relay. Someone mistypes a file-share name, DNS says NXDOMAIN, the machine falls back to asking the room, and any device on the same network can reply "that's me." If the name was a file share, the machine then tries to sign in to the impostor, which receives a challenge-response derived from the user's password that it can try to crack offline or relay to another server. Nothing about this needs a flaw in DNS; it needs only a typo and a fallback. MITRE's entry notes the same spoofing applies to mDNS traffic, which is one more reason to keep mDNS to networks that need it.

    The fixes are well established and boring, which is what you want:

    • Turn off LLMNR and NetBIOS name service where they aren't needed, by group policy or the network adapter settings. On a network with working DNS, they add nothing but risk.
    • Require SMB signing, which stops a captured authentication from being relayed to another server.
    • Keep internal DNS complete, so lookups don't fail and fall back: register machines with secure dynamic update, and use fully qualified names in configuration.
    • Watch for it. MITRE's detection guidance is to look for traffic on UDP 5355 and UDP 137 where it shouldn't be, and for changes that re-enable multicast name resolution.
    Go deeper: why mDNS is safer, but not safe

    mDNS has the same basic trust model as LLMNR: anyone on the link can answer. The differences are in how it is used. Browsers and operating systems consult mDNS only for .local names, never as a fallback for a failed company name, so a typo in a share name doesn't wander onto the link. And it is designed for networks where everyone on the link is trusted to about the same degree: a home, not a hotel lobby. On guest and public networks, isolating clients from each other at the access point removes the audience for both mDNS and LLMNR. The Service Registration Protocol mentioned above goes further, binding each registered name to a key so a later impostor cannot take it over.

    Cheat sheet

    Terms from this chapter

    Stub resolver
    The resolver code on your own machine. It applies the hosts file, the search list and special names, then forwards questions to a recursive resolver.
    Search list
    Suffixes the stub resolver appends to short names before (or after) trying them as typed, such as corp.example.
    ndots
    The number of dots a name needs before the stub tries it as an absolute name first. Default 1 on Linux; Kubernetes pods use 5.
    Fully qualified name
    A name ending in a dot, such as wiki.corp.example.. The search list is never applied to it.
    Multicast DNS (mDNS)
    DNS messages sent to everyone on the local link (224.0.0.251 / ff02::fb, UDP 5353) for names ending in .local, answered by the device that owns the name (RFC 6762).
    Probing
    The three quick queries, 250 ms apart, an mDNS device sends to check nobody else holds a name before claiming it.
    DNS-SD
    DNS-Based Service Discovery: finding services by browsing PTR records for a service type, then reading the instance's SRV, TXT and address records (RFC 6763).
    Special-use domain name
    A name reserved outside the normal delegation rules, such as home.arpa, local or invalid, listed in IANA's registry (RFC 6761).
    Split horizon
    Giving different answers to the same question depending on where it comes from, usually an inside view and an outside view of one zone.
    DNS UPDATE
    A DNS message (opcode 5) that adds or removes records, with prerequisites checked atomically; how DHCP servers register host names (RFC 2136).
    DNS64
    A resolver that synthesizes AAAA records for IPv4-only names so IPv6-only clients can reach them through a NAT64 gateway (RFC 6147).
    LLMNR
    Link-Local Multicast Name Resolution: a Windows fallback that asks the local link for a name DNS could not resolve; easily spoofed, best disabled (RFC 4795).
    Where this comes from

    Sources