As the license on my Meraki Cloud gear gets closer to expiration I’ve been working more and more to get my home environment migrated to some new technologies. Some of these focus on simplification of my media set up - moving services like Plex back from the cloud and into an On Prem environment. Others focus on implementing some new tech to make managing my infrastructure more simple.
Once you start to get past a couple of services, running a DNS server starts to become quite attractive. It allows you to more easily manage your environment, and makes accessing servers and services much more straightforward - especially for mobile devices where typing an IP address can be a pain.
I’ve used PiHole running on Debian VM for a long time to block adverts at home, adding entries manually for local devices as I’ve needed them but I wanted something which allowed me to manage local entries more simply. I also wanted to implement DoH (DNS over HTTPS) given the fact that privacy is increasingly coming under attack. DoH encrypts DNS traffic between you and the Internet DNS Server, ensuring that eyes in the middle (such as ISPs) cannot store, datamine or sell this information. However, the provider at the far end still can, and there have been a lot of concerns about data retention and sale.
But where to begin? I’ve a little experience with PowerDNS, so decided it would be the best choice for the majority of my DNS efforts. I knew I would need two parts - an Authoritative DNS serer to create and manage my local zones, and a recursor to resolve internet hosts and insure that the local hosts were forwarded to the authoritative server. PowerDNS is modular, with the recursor and the Authoritative parts running separately. You can also chose the backend storage methodology from a wide range - I went for a local database as it is also supported by PDNS Manager - the web management interface I chose to manage the Authoritative server. It has a clean, easy to use interface and seemed straightforward to intall. For DoH, Cloudflare’s cloudflared was my choice, as Cloudflare currently conform to Mozilla’s strict policies on DNS DoH Providers.
There were a few order of operations issues I came across, but in the end, the following process was followed. Note that I already had PiHole installed on another server:
- Install PDNS Authoritative and Recursive servers
- Install MariaDB and PDNS MariaDB backend
- Install PDNS Manager and Web Server (I like
apache
) - Download and install
cloudflared
- Configure PDNS Manager + PDNS Authoritative Server
- Configure
cloudflared
- Configure PDNS Recursor
- Configure PiHole
This seems like a lot but it’s pretty straight forward - Get the packages:
stadmin@ns~# apt install pdns-server pdns-recursor pdns-backend-mysql mariadb-server apache2 php7.3 php7.3-json php7.3-mysql php7.3-readline php-apcu
Get and prepare PDNS Manager:
stadmin@ns~# wget https://dl.pdnsmanager.org/pdnsmanager-2.0.1.tar.gz
stadmin@ns~# tar -zxf pdnsmanager-2.0.1.tar.gz
stadmin@ns~# mv pdnsmanager-2.0.1/* /var/www/html
stadmin@ns~# chown -R www-data:www-data /var/www/html/frontend
And cloudflared
:
stadmin@ns~# wget https://bin.equinox.io/c/VdrWdbjqyF/cloudflared-stable-linux-amd64.deb
stadmin@ns~# dpkg -i cloudflared-stable-linux-amd64.deb
Let’s start configuration with MariaDB - secure the database by running the built in script:
stadmin@ns~# mysql_secure_installation
Then create a new empty database to use:
stadmin@ns~# mysql -u root -p
Enter password:
MariaDB [(none)]> CREATE DATABASE powerdns;
Query OK, 1 row affected (0.001 sec)
MariaDB [(none)]> exit
Bye
Next, configure Apache, PHP and PDNS Manager. I’m using the configuration available in the PDNS Manager Docs:
stadmin@ns~# a2ensite default-ssl
stadmin@ns~# a2enmod rewrite ssl php7.3
stadmin@ns~# phpenmod apcu json readline
stadmin@ns~# systemctl restart apache2.service
You should now be able to browse to https://<YOUR-SERVER>/setup
and set up your database connection and user credentials. You’ll get an invalid cert warning unless you’ve properly configured SSL.
With that done, we now configure pdns-server
with the same information. Note that I only configure it to listen locally and on port 5300. This is because pdns-recursor
and PDNS Manager will be the only services using it.
stadmin@ns~# vim /etc/powerdns/pdns.conf
#--------
#SETTINGS
#--------
allow-axfr-ips=127.0.0.1
allow-dnsupdate-from=127.0.0.1/8,::1
config-dir=/etc/powerdns
daemon=yes
disable-axfr=no
local-address=127.0.0.1
local-port=5300
#--------
#DATABASE
#--------
launch=gmysql
gmysql-host=127.0.0.1
gmysql-port=3306
gmysql-dbname=powerdns
gmysql-user=root
gmysql-password=<PASSOWRD>
stadmin@ns~# systemctl restart pdns.service
And finally enable it to run at boot:
stadmin@ns~# systemctl enable pdns.service
Now you can log into PDNS Manager and add your Zones and Records.
Next up, we configure cloudflared
. cloudflared
will use default settings, running on port 53 unless otherwise configured. This can be done with a short YAML file located in /etc/cloudflared/config.yml
:
proxy-dns: true
proxy-dns-port: 5053
proxy-dns-upstream:
- https://1.1.1.1/dns-query
- https://1.0.0.1/dns-query
Enable and start cloudflared:
stadmin@ns~# systemctl enable cloudflared.service
stadmin@ns~# systemctl start cloudflared.service
You can confirm it’s running with netstat
or by trying to resolve a domain:
stadmin@ns~# dig +short @localhost -p 5053 google.com
216.58.213.110
Almost there - onto the PDNS Recursor now!
stadmin@ns~# vim /etc/powerdns/recursor.conf
allow-from=127.0.0.0/8,<LOCAL-NETWORK>
forward-zones=<YOUR-ZONE>=127.0.0.1:5300
forward-zones-recurse=.=127.0.0.1:5053
local-address=0.0.0.0
stadmin@ns~# systemctl restart pdns-recursor.service
stadmin@ns~# systemctl enable pdns-recursor.service
Again confirm with netstat
and dig
(Note, no port needed this time):
stadmin@ns~# dig +short @localhost bbc.com
151.101.0.81
151.101.192.81
151.101.64.81
151.101.128.81
Our DNS server is now answering requests on port 53, and forwarding anything for the internet to cloudflared
using DoH. For local zones defined in the recursor.conf
file, it will forward them to the PDNS Authoritative Server:
stadmin@ns~# dig +short @localhost pihole.jewhurst.net
172.16.25.25
While this setup will work entirely on it’s own, I also wanted to enabled ad-blocking with PiHole - so the final step is adding our newly configured DoH DNS Server to PiHole as an upstream server. It should be the only server selected unless you create a second setup as above. Note that you’d need to enable MySQL replication for the Authoritative Server.
Ensure PiHole is your DHCP Server, or your Router hands out PiHoles IP as the DNS server of choice and the setup is complete. You can even go as far as blocking port 53 on your firewall.
So there you go - fully secured DNS over HTTPS with an internal authoritative name-server and added ad-blocking.