A DNS Server for the Home
Background
As part of my home infrastructure, I'm now starting to run a lot of software services, mostly as docker containers on my NAS server. I can run them in host mode or bridge mode. With host mode, they don't take up an IP address, but I have to map ports. In bridge mode, each one can get their own IP addreess. The benefit of running in host mode is I can limit the network interactions of the container. However, I now have to keep track of port numbers, which makes it harder to tell others in the family how to use those services.
While I can of course simply run bind and manage my own DNS server (I've done it before), I found a lot of people talking about Pi-hole. Pi-hole in addition to an easy to manage local DNS server, Pi-hole's raison dĂȘtre is filtering unwanted content such as ad-blocking / malware-blocking.
The internet is full of websites that span the gamut from annoying to potentially harmful. So having something like Pi-hole that can help protect all the devices on my network is doubly beneficial.
Goals
Here are my primary goals for me DNS server:
- Easy to manage local DNS entries
- Ability to monitor DNS queries (especially for IoT devices)
- Ability to filter potentially harmful websites
I personally am less concerned about tracking and ad-blocking. However quite often websites and apps can be so overloaded with these that blocking them helps to make them run faster. However, sometimes blocking too much can break functionality. So having the ability to choose the level of aggressiveness here would be ideal.
After reading up on and experimenting with Pi-hole a bit, I found that it meets my needs pretty well. And it has a vibrant community, which is always important for an open source project.
Hardware
Many people have run Pi-hole on dedicated hardware such as a Raspberry Pi. I had considered either a Nano PI R5C for $80 or Nano PI Neo for $35. But with any such embedded system, there's always potential snags in getting software working, especially if there isn't great support or a big community around it. So in the end, I decided to just use my existing QNAP NAS since it has a decent amount of power and memory, and running and upgrading containers is really easy.
Software
Docker Configuration
The docker-pi-hole github page details all the Environment values you might consider. I used:
Environment:
- TZ=America/Los_Angeles
- WEBPASSWORD=MySuperSecretPiHolePassword
For network settings, I chose a static IP address as well as a custom fixed MAC address. Be sure to pick a MAC in the range of reserved MAC address range, basically one of x2:xx:xx:xx:xx:xx, x6:xx:xx:xx:xx:xx, xA:xx:xx:xx:xx:xx, xE:xx:xx:xx:xx:xx. The primary reason for a fixed MAC address for me is because I'm planning on implementing MAC allow lists on my network. If you don't have a need for this, a dynamically assigned MAC address is probably fine.
I feel the docker-pi-hole example on the share folders are a bit incomplete. Mine are setup as follows:
- /ContainerData/pihole/etc/pihole:/etc/pihole
- /ContainerData/pihole/etc/dnsmasq.d:/etc/dnsmasq.d
- /ContainerData/pihole/log:/var/log/pihole
This ensures logs and configuration are not lost when you restart the container.
Configuration
Once you have the docker up and running, you'll want to load your web browser onto the admin page, which must be /admin
. If you go direclty to the IP address, you will get "403 Forbidden". In other words if you have Pi-hole configured on 192.168.5.5, then your admin page will be http://192.168.5.5/admin/.
Beyond that, Pi-hole itself is pretty straightforward to install and configure if you know anything about DNS.
One part that will definitely depend on your goals is the setting for upstream DNS server. You can pick from some of the major DNS services or provide your own. In my case, I have my upstream set to my UniFi gateway.
Ad Blocking
I was a little disappointed that the default installation did not include obviously unpleasant websites such as https.com (which can be a very easy mistake to type). So I discovered another community around block lists:
- Avoid The Hack: The Best Pi-Hole Blocklists (2023)
- The Blocklist Collection
- Reddit Malicious blocklist based on Emerging Threats github page
- OISD
I ended up choosing the OISD Big list primarily for it's claims of blocking: Phishing, Malvertising, Malware, Spyware, Ransomware, CryptoJacking, Scam, etc. It does also include Ad blocking and Telemetry.
Local Domains
Now the fun part, let's setup a local domain. How about .home
as a "fake TLD"? There's some evidence this may remain reserved, though it's not officially in RFC2606 or RFC6761.
Really anything you want to pick works well enough, though it's best to choose a TLD does not exist to avoid potential conflicts. However, I quickly learned of one problem with picking a fake TLD. Safari's URL/search bar will attempt to search the web rather than attempt to resolve the domain. While this sounds like a dumb bug, it may be an attempt to limit the effects of DNS hijacking practiced by many unpleasant ISPs.
One way to get around this is to simply include a "/" to the end of your search. Example: "pihole.home/" In the future, perhaps I'll take up the mantle and create a Safari extension.
UniFi gateway DHCP configuration
The next is to configure your DHCP server to include the DNS server for the clients. For my UniFi gateway, I have multiple VLANs setup. Unfortunately there does not appear to be a global configuration and so you must go to each Network that you wish to participate, switch DHCP to "Manual", and add the IP address of your Pi-hole server.
In my case, I used 3 IP addresses in the following order:
- My Pi-hole server
- My UniFi gateway
- 9.9.9.9 - Quad9's free DNS service that provides malware blocking
I chose to keep the UniFi gateway as the secondary backup for performance and so that I can still have some visibility and control if there are issues. Quad9's DNS server is the final resort and to still provide some protection against malicious websites if the first two servers have issues.
In addition, it would be useful to set the default subdomain list for your dhcp clients. It's not obvious to do this from the UniFi gateway. You'll need to go to Custom DHCP Options and add:
- Name: custom-search
- Code: 119
- Type: Text
- Text: local, home
The Text
field shoudl be a comma separated list of subdomains you wish clients to search for by default (in order of precedence). In my case, I thought .local
and .home
would be useful.
mDNS / multicast-DNS
By default Pi-hole will return NXDOMAIN (i.e. "non-existant domain") for any .local
domains.
According to the documentation and forums, in order for Pi-hole to respond to .local
domains, you'll need to enable "Conditional Forwarding" and point it to your DHCP/DNS server (in my case my UniFi gateway). However this never worked for me. But it has not been a problem as normal tools that perform name resolution seem to figure out to look at both the DNS server and the mDNS cache.
Note: when testing mdns names, tools like nslookup
and dig
will not work. You'll instead want to rely on ping
or your web browser.
Done
That's about it!