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.
Why?
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:
- remembering how to sysadmin again
- filtering ads on my entire network (not just on devices that run UBlock)
- 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 marketing 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:
server:
interface: 0.0.0.0@5353 # listen on alternative port
do-ip6: no
access-control: 0.0.0.0/0 refuse
access-control: 127.0.0.0/8 allow
access-control: 192.168.0.0/16 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
forward-zone:
name: "."
forward-ssl-upstream: yes
tls-cert-bundle: /etc/ssl/certs/ca-certificates.crt
forward-addr: 1.1.1.1@853#cloudflare-dns.com # cloudflare
forward-addr: 1.0.0.1@853#cloudflare-dns.com # cloudflare secondary
forward-addr: 9.9.9.9@853#dns.quad9.net # quad9.net
forward-addr: 149.112.112.112@853#dns.quad9.net # quad9.net secondary
forward-addr: 8.8.8.8@853#dns.google # GOOG
forward-addr: 8.8.4.4@853#dns.google # 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 127.0.0.1#5353
(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.
Update 2020-04-25 Android now seems to respect my local DNS settings, even with DNS privacy turned on.
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.
Update 2021-12-19 I made the mistake of running apt-get upgrade
and picked up a new version of unbound
which promptly spat out errors like this:
Dec 19 21:10:04 raspberrypi unbound[20014]: [20014:0] error: ssl handshake failed crypto error:1416F086:SSL routines:tls_process_server_ce
Dec 19 21:10:04 raspberrypi unbound[20014]: [20014:0] notice: ssl handshake failed 1.0.0.1 port 853
Some thinking, and reading of man unbound.conf
(because of course my internet is now broken) later I made a guess and added a tls-cert-bundle: /etc/ssl/certs/ca-certificates.crt
to my configuration and all was saved. Computers were a mistake.
Bonus Tweaks
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.