Homelab, step two — who the DNS server trusts

Homelab, step two — who the DNS server trusts#

Part one ended with Pi-hole running and the observation that a service that runs and a service that gets used are two different things. Three points were left open. Two are now done, and the third deliberately is not.

The one catch in the router#

The filter had been running for days and filtering nothing, because nobody asked it. The UDM kept handing out its own address as the nameserver over DHCP, and every device in the house went along with that — a directory sitting on the shelf while everyone keeps consulting the old one.

What changes it is a single field: DHCP Name Server, from Auto to Manual, with 10.10.10.3 in it. Days of work came down to one click. How the field actually works, why no second public resolver belongs next to it, and when devices really pick it up is under Handing Out Pi-hole via DHCP.

The proof did not come from a config file but from the live log: where the server itself had been more or less the only entry, suddenly half the household’s addresses ran past. A TV that queries something every few seconds while idle is a small revelation of its own.

The librarian who looks things up elsewhere#

So the filter was in use — by everyone except one. The thin client itself kept asking the router and a public resolver, because its /etc/resolv.conf still held whatever the installer had written there four days earlier. The one machine in the house running the filter was the only one not using it.

In practice: package sources, blocklist updates, everything the server does on its own ran unfiltered and unlogged. And any test done on the box itself out of convenience tests something Pi-hole never answered.

The file was interesting for a second reason: it lies. Its header reads # Generated by dhcpcd — except there is no dhcpcd on this machine. The service does not exist, neither resolvconf nor openresolv is installed, and the file still carries the date of the installation. It is maintained by hand, and hand edits survive. My own note warned at this exact spot about a problem that does not exist here — which shows a pleasant side effect of writing things down: you only rediscover your unexamined assumptions when you go back and measure them.

One line sits there now, nameserver 127.0.0.1, and deliberately without a second entry: if Pi-hole fails, the server resolves nothing. That is inconvenient and correct — a fallback entry would put the hole in the filter on the filtering machine itself. The reasoning, down to the loopback detail, is under The DNS Server Asks Itself.

The recipient was Google all along#

That leaves the most uncomfortable point. Pi-hole does not know the addresses of the world; whatever is not on a blocklist it forwards — and the installer suggests Google for that. Confirming it builds a system that locks out advertising networks and then delivers every single query to Google. Neatly bundled behind one address.

So the filter changes how many queries leave the house, not whether somebody sees them. That is an awkward thing to notice when privacy was the reason for building it.

Quad9 sits there now. A Swiss foundation with no advertising business, storing no client addresses and additionally blocking known malicious domains — which complements Pi-hole rather than duplicating it: ads and tracking here, malware and phishing there. Honesty requires adding that this too is just a provider being trusted, and that a second filter you do not maintain yourself can be wrong. The trade-offs between providers are under Choosing an Upstream DNS.

And once, deliberately, nothing#

The third open point was DNSSEC — the cryptographic check of whether an answer was forged in transit. It sounded like the most self-evident of the three, and thinking it through turned it into a no.

Quad9 already validates. Doing it locally would win exactly one point: no longer depending on the upstream having checked honestly. Against that stands a real risk of outage, because expired signatures happen, to large operators too — and then a domain answers SERVFAIL rather than not at all. In the household that looks like a Pi-hole outage, and that is where people will start looking.

The point comes back as soon as the upstream is a recursive resolver of my own. Validation then becomes the actual purpose of the exercise, because the chain is recomputed to the root instead of taking a provider’s word for it. Until then it would be double bookkeeping with an extra way to fail. What DNSSEC does and does not do is written down regardless — a decision against something only counts as one if you can justify it.

Next: the network after all#

The setup is clean now: devices ask the filter, the filter asks a provider chosen on purpose, and the machine in between filters for itself as well.

Before a second machine joins, the network is next — five segments instead of one flat /16. The plan has been sitting there for a few days, including the order of operations for the evening of the rebuild and the pitfall that otherwise tips it over: with listeningMode = LOCAL Pi-hole only answers queries from its own subnet, and after the cut four fifths of the household are exactly that no longer. The plan is under Network Layout with VLANs.

Notes on that once it runs.