Ramblings of an aging IT geek
← Ramblings of an aging IT geek
networking

i stopped trusting someone else's dns and ran my own

Why and how I replaced my upstream DNS with a self-hosted recursive resolver at home, and what it actually bought me.

Network cables and switches in a rack

For years my home network did what most do: hand DNS to whatever my router's DHCP advertised, which was my ISP's resolvers, and not think about it. Then I spent an evening actually watching the queries, and decided I'd rather not have a third party with a complete, timestamped log of every domain anyone in the house looks up. So I now run my own recursive resolver. Here's the reasoning and the setup, because the gap between "I should do this" and "this is running" is mostly just not knowing which knobs to turn.

forwarding versus resolving

First, a distinction that took me embarrassingly long to internalise. Most "run your own DNS" guides set up a forwarder: your box receives queries and hands them straight to 1.1.1.1 or 8.8.8.8 to do the actual work. That's better than nothing for caching and local records, but the upstream still sees every query. You've moved the logging, not removed it.

A recursive resolver does the work itself. It starts at the root servers, walks down through the TLD servers, and finally asks the authoritative server for the domain, caching results along the way. No single upstream sees your whole browsing pattern, because there isn't one. That's the version I wanted.

A rack of networking equipment in a small datacentre

unbound, which turned out to be the easy part

I went with unbound. It's small, it does recursion well, and the default configuration is sensible enough that the file you actually write is short. The core of it:

server:
    interface: 0.0.0.0
    access-control: 192.168.0.0/16 allow
    access-control: 0.0.0.0/0 refuse

    # privacy and hygiene
    hide-identity: yes
    hide-version: yes
    qname-minimisation: yes

    # validate DNSSEC
    auto-trust-anchor-file: "/var/lib/unbound/root.key"

    # cache aggressively, it's a home network
    msg-cache-size: 64m
    rrset-cache-size: 128m
    prefetch: yes

Two of those lines earn their place. qname-minimisation means unbound only tells each server in the chain the part of the name it actually needs to answer, rather than leaking the full hostname to the root and TLD servers at every step. And the auto-trust-anchor-file turns on DNSSEC validation, so if an answer's signatures don't check out, unbound returns SERVFAIL rather than handing me a forged record. That second one is the bit that makes running your own resolver a security win and not just a privacy one.

prefetch: yes is a nice quality-of-life touch: when a popular record is close to expiring and gets queried, unbound refreshes it in the background before it goes stale, so the cache stays warm for the names you actually use.

the bit nobody mentions: it's slower at first

Here's the honest tradeoff. A recursive resolver on a cold cache is slower than a giant shared forwarder, because the big public resolvers have basically everything cached already and you don't. The first lookup of a domain you've never visited walks the whole chain and that takes longer than asking a resolver that answered the same query a millisecond ago for someone else.

In practice this matters far less than the benchmark implies. Within a day my cache held everything the household visits regularly, and those answers are now served from local RAM faster than any network round-trip could manage. The slow ones are the genuinely novel domains, which are rare and not the ones you notice waiting for. I measured it for a week and the median lookup got faster, not slower, once the cache warmed.

Server racks with cabling

pointing the network at it

The last step is making everything use it. I set the resolver's address as the DNS server in my router's DHCP options so every device picks it up automatically, and I added a firewall rule that redirects any outbound port 53 traffic back to my box. That second rule matters more than it looks: plenty of devices, phones especially, ship hardcoded DNS servers and will quietly ignore what DHCP told them. The redirect means they get my resolver whether they like it or not.

The combination, my own recursion with DNSSEC validation and a forced redirect, means I now have a single, honest answer to "what resolves DNS on this network". It's the box in the cupboard, it logs nothing it doesn't need to, it validates what it returns, and no upstream provider gets a transcript of our browsing. That was the whole goal, and unbound made the doing of it far less work than the deciding to.