A DNS server in a taped together cardboard box

A few days ago I became the kind of person who runs their own DNS resolver in a taped together cardboard box. I'm still not sure how to feel about this.


Despite my profession, I strive to have as few computers as possible in my life. So why would I add a hand-maintained computer in the critical path to useful internet in my home?

A few reasons:

  1. remembering how to sysadmin again
  2. filtering ads on my entire network (not just on devices that run UBlock)
  3. depriving my ISP of surveillance data puts on tinfoil hat

An aside about DNS surveillance

DNS traffic is unencrypted by default so anyone can see which domains computers on your network are looking up. ISPs sell these traces which can then be used to link (and de-anonymize) other tracking data. The marketting euphemism for this process is building a "unified customer journey." Ew.

Using DNS over TLS avoids snooping by ISPs. Round-robining queries between upstream resolvers owned by multiple companies makes it more annoying (but not impossible) for them to reassemble a full activity log.

Build Process

I did this whole thing on a Raspberry Pi with an ethernet jack. There are a zillion guides for setting up Rasberry Pis, so I won't re-write all those details. I used a Raspbian Lite image and ran

touch <mysdcard>/ssh

from the computer that I used to image the SD card so I'd have SSH access when the Pi booted up.

Get a static IP

After plugging in the Pi, I found it on my home router's admin console and assigned it a static IP. I rebooted the Pi again, just to be sure it stuck

Change the default password.

This step is required or the security deities will smite you.

I ssh'd in to my lovely new server as pi with password raspberry and then immediately changed the password with passwd

Run PiHole

Next, I installed PiHole. They have lovely instructions so I won't bore you. On install you can set the upstream resolver to whatever they suggest, we'll be changing it later.

I set my router to use the static IP from earlier as a DNS server. Flip the wifi on and off on my computer to (hopefully) refresh this setting. Does the internet still work? Good work, go team.

I could have stopped here if I just wanted ad blocking and didn't want to play with my new toy even more.

Round Robin DNS over TLS (Unbound)

On to the fun part. I installed unbound

sudo apt-get install unbound

I then hacked together a configuration starting with Weaver's config and these pihole+unbound instructions.

The end result was this:

        interface: # listen on alternative port
        do-ip6: no

        access-control: refuse
        access-control: allow
        access-control: allow

        hide-identity: yes
        hide-version: yes

        rrset-roundrobin: yes
        prefetch: yes
        prefetch-key: yes

        # Uncomment to enable qname minimisation.
        # https://tools.ietf.org/html/draft-ietf-dnsop-qname-minimisation-08
        qname-minimisation: yes

        name: "."
        forward-ssl-upstream: yes
        forward-addr:    # cloudflare
        forward-addr:    # cloudflare secondary
        forward-addr:         # quad9.net
        forward-addr: # quad9.net secondary
        forward-addr:            # GOOG
        forward-addr:            # GOOG secondary

I made unbound reload it's configuration with sudo service unbound restart and then went to the pihole admin console and changed the upstream DNS server to localhost port 5353. For some reason, the pihole configuration represents this as (everyone else uses : to seperate ports, but I don't run this place).

Does the internet still work? Good work, go team.

Unexpected Oddities

After deploying this setup, I looked at the PiHole admin page and gleefully watched the numbers increase. One strange thing stood out: there is only one IP address being logged as a client, and it is the IP of my router. Some Googling later, and I learn that Amplifi (my router brand, they are great) has its own DNS cache, so it proxies all DNS to whatever you configure as the DNS Server.

There's an option to turn off the cache, but I decide I don't care. The alternative behavior is to hand out the DNS Server when a new device joins the network via DHCP. My network now has three DNS caches (PiHole via FTL, Unbound, Amplifi). I look forward to debugging all of them when something breaks.

I also notice that my Android device is still seeing ads and its DNS activity doesn't appear in the PiHole log. This is because of Android DNS Privacy. None of the DNS servers I just deployed are running TLS themselves, so Android automatically uses a TLS-capable server instead. I could disable this setting on the Android but then I'd lose DNS encryption when I'm on other networks.

I may fix this by running yet another DNS server using TLS on my Pi, but I mostly don't care.

Bonus Tweaks

My DNS server. Maybe it would prefer a Tiffany Box?

My DNS server. Maybe it would prefer a Tiffany Box?

I set up automatic updates so I don't need to keep the base debian install up-to-date by hand.

sudo apt-get install unattended-upgrades

and then adjusted the configuration file to include origin=Raspberry Pi Foundation in a bunch of places.

I set PiHole to keep less history by changing MAXDBDAYS. A year of DNS logs seems excessive and the whole point of this is avoiding DNS logging.

I built a case using the box some checks came in and gaff tape. I should probably cut more holes in it so it doesn't overheat.

Carla G