Client side DNS

How a client turns a name into an address: the order nsswitch.conf sets, the servers and timeouts in resolv.conf, and why dig and an application can disagree about the same name.

Lesson 4 of 4 in objective 109. Networking fundamentals, part of LPIC-1 Exam 102-500.

Two different routes to an address, which is why they can disagree. getent, and applications — How it asks: getaddrinfo, through NSS; Reads /etc/hosts: Yes; Obeys nsswitch.conf: Yes; Use it to: See what the program sees. dig, host, nslookup — How it asks: A DNS query to a server; Reads /etc/hosts: No; Obeys nsswitch.conf: No; Use it to: Ask a name server directly getent, and applications dig, host, nslookup How it asks getaddrinfo, through NSS A DNS query to a server Reads /etc/hosts Yes No Obeys nsswitch.conf Yes No Use it to See what the program sees Ask a name server directly
Two different routes to an address, which is why they can disagree.

Which source answers, and in what order

/etc/nsswitch.conf lists, for each database, the sources to consult and the order to consult them in. The line that matters here is the hosts one, whose usual sources are files — meaning /etc/hosts — and dns, with resolve appearing as well on a machine running systemd-resolved. The list is scanned left to right and the FIRST source that returns a match ends the scan. That is the whole mechanism, and it is the answer to the commonest complaint on this objective: with hosts: dns files, a name that exists in public DNS is answered before /etc/hosts is ever opened, so the local override does nothing. Reversing it to hosts: files dns is what makes local overrides work. /etc/host.conf is the older ordering file for programs that do not use the switch, and it holds no host entries of its own.

/etc/hosts itself is a flat table: an address, then the canonical host name, then any number of aliases, separated by whitespace, one entry per line. The address may be of either family, so a standard file carries both 127.0.0.1 localhost and ::1 localhost ip6-localhost. A comment runs from a # to the end of the line — the semicolon convention belongs to DNS zone files and not to this one. The file is read on demand during a lookup, so an edit applies to the next resolution with nothing to restart; a caching layer such as nscd or systemd-resolved may still be holding an older answer, but the file needs no reload for its own sake.

One line of /etc/hosts: the address first, the canonical name second. 10.0.0.9 build.example.com build # staging — part 1, 10.0.0.9: the address, IPv4 or IPv6; part 2, build.example.com: the canonical name; part 3, build: aliases, any number of them; part 4, # staging: a comment, from # to end of line. 1 10.0.0.9 2 build.example.com 3 build 4 # staging 1 the address, IPv4 or IPv6 2 the canonical name 3 aliases, any number of them 4 a comment, from # to end of line
One line of /etc/hosts: the address first, the canonical name second.

The servers, and how long the resolver waits for them

/etc/resolv.conf is where the DNS half is configured. Each nameserver line names one server by address, and they are tried in the order listed. The ceiling is worth knowing exactly: the glibc resolver compiles in a limit of three, so a fourth and fifth line are parsed and then silently disregarded. Listing five servers for redundancy does not give redundancy, and genuine failover belongs in a local caching resolver rather than in this file. The search line gives a list of domains used to complete UNQUALIFIED names, and domain is the older single-entry form of the same idea; neither has any bearing on which server is asked.

An options line tunes the waiting. options timeout:1 sets how many seconds the resolver waits on ONE server before giving up on that try, and the default of five is why a single dead first entry stalls every lookup for five seconds. options attempts:2 sets how many passes are made over the whole server list, which is a different number: lowering it reduces how OFTEN the wait is paid rather than how long each one is. Both are capped internally, timeout at thirty and attempts at five. options rotate round-robins over the servers between queries to spread load, which still starts some queries on the dead one, and options ndots:1 decides how many dots a name must contain before it is tried as absolute instead of being run through the search list. None of them is the real fix for an unreachable server, which is to take it out of the file.

The clients, and which layer each one proves

dig, host and nslookup are DNS clients: each builds a DNS query and sends it to a name server, reading /etc/resolv.conf only to find out which server to ask. None of them consults /etc/nsswitch.conf or /etc/hosts. An argument beginning with @ overrides even that — dig @192.0.2.53 db01.example.com sends the query to that one server, which is exactly what is wanted when testing a server the client is not yet configured to use. Keep it apart from the options that change what is ASKED rather than who is asked: -x makes it a reverse lookup, +trace walks the delegation down from the root servers, +nssearch finds the zone's authoritative servers, and +short merely trims the output.

The record type is given differently by each tool, and both spellings are examinable. dig takes it as a bare trailing argument, as in dig example.com MX. host takes it as an option: host -t MX example.com asks for that type alone, where host with no -t asks for A, AAAA and MX records and prints whatever comes back. Type names are matched without regard to case. dig -x 192.0.2.25 builds the reverse name for you — 25.2.0.192.in-addr.arpa — and sets the type to PTR; an IPv6 address would need nibble-reversed labels under ip6.arpa instead. A missing PTR is a server-side omission rather than a client fault, because forward and reverse zones are separate and one does not imply the other.

getent is the one that answers the other question. It takes a database name and a key and resolves the key through the switch, exactly as an application's library call does, so getent hosts licence.example.com shows the answer /etc/hosts or any other configured source supplies. That is the command for a name that works for every program on the machine while dig returns NXDOMAIN: more debug output from a DNS client cannot reveal a non-DNS source, and getent can. The database chosen also decides the address family. hosts returns one family, the IPv6 answer where there is one; ahostsv4 pins IPv4 and ahostsv6 pins IPv6; getent ahosts www.example.com leaves the family unspecified, so both come back with the socket type for each, which is the view to take before switching a service to dual-stack.

dig licence.example.com;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 41822DNS has never heard of itgetent hosts licence.example.com10.0.0.9        licence.example.comso the answer is coming from /etc/hostshost -t MX example.comexample.com mail is handled by 10 mx1.example.com.
Two clients, two answers, and what the disagreement proves.

systemd-resolved, and the stub on 127.0.0.53

On a host running systemd-resolved, /etc/resolv.conf is a symbolic link into /run — to /run/systemd/resolve/stub-resolv.conf — and contains one entry, nameserver 127.0.0.53. That address is a stub listener the daemon runs on the loopback interface, so every application on the machine sends its queries to the local stub and resolved does the real work. Hand-edited nameserver lines vanish because the file is GENERATED: resolved rewrites it, and there was never anything there to keep.

The upstream servers are set in DNS= in /etc/systemd/resolved.conf, or in a drop-in under /etc/systemd/resolved.conf.d/, with FallbackDNS= behind it, and the daemon is restarted to read them; per-link servers arriving from DHCP through networkd or NetworkManager are added to those. resolvectl dns eth0 192.0.2.1 does set the servers for one link, but only in the RUNNING daemon — it writes nothing to disk, so the setting is gone at the next restart, which is the distinction a question here is built on. resolvectl status prints which servers are actually in force, per link, and is the quickest way to see what the stub is really asking.

On a resolved host, every query goes to a stub on the loopback first. In order: The application (reads /etc/resolv.conf like any other program), then nameserver 127.0.0.53 (the stub listener, in a generated file), then systemd-resolved (DNS= in resolved.conf, plus per-link servers), then The upstream name servers. The application reads /etc/resolv.conf like any other program nameserver 127.0.0.53 the stub listener, in a generated file systemd-resolved DNS= in resolved.conf, plus per-link servers The upstream name servers
On a resolved host, every query goes to a stub on the loopback first.

Worth carrying in

/etc/nsswitch.conf
The hosts line names the sources and their order — files dns, plus resolve under systemd-resolved.
/etc/hosts
Address, canonical name, aliases. # starts a comment; either address family is allowed.
/etc/resolv.conf
nameserver lines, at most three of them, plus search and options.
options timeout:1 attempts:2
Seconds waited per server, and passes over the whole list. The defaults are 5 and 2.
dig @192.0.2.53 name
Query that one server. The record type is a bare trailing argument.
dig -x 192.0.2.25
Reverse lookup: builds the in-addr.arpa name and asks for PTR.
host -t MX example.com
One record type. Without -t, host asks for A, AAAA and MX.
getent hosts name
Resolve the way an application does. ahosts returns both families at once.
/etc/systemd/resolved.conf
DNS= and FallbackDNS=. Drop-ins go under resolved.conf.d/.
resolvectl status
Which servers resolved is really using, per link. resolvectl dns sets one at runtime only.

What the exam does with this

Objective
109. Networking fundamentals
Share of the exam
23.33% (the whole objective)
Questions in this lesson
10
Signed for by a person
0

Partly checked. None of the 10 questions here has been read against the cited source by a person. 10 questions have been checked against their cited clause by an automated pass — which is not the same thing, and is not a signature.

Only questions a person has signed for are used in mock exams here. That is the whole difference between the two kinds of checking above.

How these questions are written — where each question comes from, what the verification ledger records, and what happens when one is found wrong.

Drill this lesson

A lesson is one sitting: the trainer draws a short run from these questions alone and spaces the ones you get wrong.

Practise Client side DNS

Questions in this lesson

Practise Client side DNS

The rest of objective 109