Download Fedora Server ARM edition and write it to an SD card for the Raspberry Pi 3.
sudo fedora-arm-image-installer --resizefs --image=Fedora-Server-armhfp-30-1.2-sda.raw.xz --target=rpi3 --media=/dev/mmcblk0
Make sure your Raspberry Pi can already resolve DNS queries from some other source, such as your router or internet provider.
Log into the Fedora Server Cockpit web interface for the server (port 9090) and enable automatic updates from the Software tab. Else you can do updates manually.
sudo dnf -y update &amp;&amp; sudo reboot
Install Stubby to forward DNS requests over TLS.
sudo dnf install getdns-stubby bind-utils
Edit the Stubby config file.
sudo vim /etc/stubby/stubby.yml
Set listen_addresses to localhost 127.0.0.1 on port 53000 (also set your preferred upstream DNS providers, if you want to change the defaults, e.g. CloudFlare).
Start and enable Stubby, checking that it’s listening on port 53000.
sudo systemctl restart stubby sudo ss -lunp |grep 53000 sudo systemctl enable stubby
Stubby should now be listening on port 53000, which we can test with dig. The following command should return an IP address for google.com.
dig @localhost -p 53000 google.com
Next we’ll use Pi-hole as a caching DNS service to forward requests to Stubby (and provide advertisement blocking).
Sadly, Pi-hole doesn’t support SELinux at the moment so set it to permissive mode (or write your own rules).
sudo setenforce 0 sudo sed -i s/^SELINUX=.*/SELINUX=permissive/g /etc/selinux/config
Install Pi-hole from their Git repository.
sudo dnf install git git clone --depth 1 https://github.com/pi-hole/pi-hole.git Pi-hole cd "Pi-hole/automated install/" sudo ./basic-install.sh
The installer will run, install deps and prompt for configuration. When asked what DNS to use, select Custom from the bottom of the list.
Set the server to 127.0.0.1 (note that we cannot set the port here, we’ll do that later)
In the rest of the installer, also enable the web interface and server if you like and allow it to modify the firewall else this won’t work at all! 🙂 Make sure you take note of your admin password from the last screen, too.
Finally, add the port to our upstream (localhost) DNS server so that Pi-hole can forward requests to Stubby.
sudo sed -i '/^server=/ s/$/#53000/' /etc/dnsmasq.d/01-pihole.conf sudo sed -i '/^PIHOLE_DNS_[1-9]=/ s/$/#53000/' /etc/pihole/setupVars.conf sudo systemctl restart pihole-FTL
If you don’t want to muck around with localhost and ports you could probably add an IP alias and bind your Stubby to that on port 53 instead.
On a machine on your network, set /etc/resolv.conf to point to the IP address of your Pi-hole server to use it for DNS.
On the Pi-hole, check incoming DNS requests to ensure they are listening and forwarding on the right ports using tcpdump.
sudo tcpdump -Xnn -i any port 53 or port 53000 or port 853
Back on your client machine, ping google.com and with any luck it will resolve.
For a new query, tcpdump on your Pi-hole box should show an incoming request from the client machine to your pi-hole on port 53, a follow-up localhost request to 53000 and then outward request from your Pi-hole to 853, then finally the returned result back to your client machine.
You should also notice that the payload for the internal DNS queries are plain text, but the remote ones are encrypted.
Start browsing around and see if you notice any difference where you’d normally see ads. Then jump onto the web interface on your Pi-hole box and take a look around.
If that all worked, you could get your DHCP server to point clients to your shiny new Pi-hole box (i.e. use DHCP options 6,<ip_address>).
If you’re feeling extra brave, you could redirect all unencrypted DNS traffic on port 53 back to your internal DNS before it leaves your network, but that might be another blog post…