Pi-hole on Raspberry Pi OS with dnscrypt-proxy


Note: A condensed version of this guide is available from https://github.com/pi-hole/docs/pull/990.

Pi-hole is a software suite facilitating the installation and configuration of your own DNS resolver with filtering capabilities on your local network, preventing domains associated with unwanted content, such as malware and advertisements, from being resolved. Pi-hole can be installed in a Docker container as well as on several Linux distributions, including Raspberry Pi OS.

By default, Pi-hole uses its own forwarding DNS server named FTLDNS, which is based on the venerable dnsmasq. While FTLDNS is lightweight and stable, it lacks support for encrypted DNS protocols, such as as DNS-over-HTTPS (DoH), rendering DNS traffic between Pi-hole and upstream DNS servers susceptible to eavesdropping and modification by attackers in a man-in-the-middle position. To this end, the Pi-hole project provides instructions for installing a forwarding DNS server that supports DoH called cloudflared. While cloudflared can be configured with upstream DNS services beyond Cloudflare, Raspberry Pi OS lacks a package for it, requiring efforts to keep cloudflared updated.

Fortunately, Raspberry Pi OS maintains a package for the flexible and stable dnscrypt-proxy that supports DoH among other DNS protocols with encryption. The steps below illustrate how dnscrypt-proxy can be installed and configured to work with Pi-hole on Raspberry Pi OS. Note that while dnscrypt-proxy takes care of encrypting DNS traffic between Pi-hole and upstream DNS services on the internet, traffic between client devices and Pi-hole remains unencrypted and is susceptible to man-in-the-middle attacks.

  1. Install Raspberry Pi OS per the official instructions.
  2. Install Pi-hole on Raspberry Pi OS per the official instructions.
  3. Log into your Raspberry Pi locally or remotely using SSH.
  4. Run sudo apt update && sudo apt install dnscrypt-proxy to install dnscrypt-proxy.
  5. By default, FTLDNS listens on the standard DNS port 53. To avoid conflicts, edit /usr/lib/systemd/system/dnscrypt-proxy.socket to ensure dnscrypt-proxy listens on a port that is not in use by other services, such as port 5335. Specifically, the following settings, let dnscrypt-proxy listen on localhost on port 5335:
  6. Edit /etc/dnscrypt-proxy/dnscrypt-proxy.toml, setting listen_addresses = [] to use the systemd socket activation.
  7. Edit /etc/dnscrypt-proxy/dnscrypt-proxy.toml, setting server_names to the desired upstream DNS services. A list of servers with supported protocols is available from https://dnscrypt.info/public-servers/. For example, the setting server_names = ['cloudflare-security'] configures Cloudflare DNS with malware blocking as the DNS resolver with DoH.
  8. Run sudo systemctl restart dnscrypt-proxy.socket to restart the dnscrypt-proxy systemd socket process.
  9. Run sudo systemctl restart dnscrypt-proxy.service to restart dnscrypt-proxy.
  10. Run sudo systemctl restart pihole-FTL.service to restart FTLDNS.
  11. Log into the Pi-hole admin web interface.
  12. Navigate to Settings and from there to the DNS tab.
  13. Under "Upstream DNS Servers" on the left, uncheck all boxes for public DNS servers. Under "Upstream DNS Servers" on the right, check only the box for "Custom 1 (IPv4)" and fill the box with the IP address and port dnscrypt-proxy listens on, such as See this screenshot for an example. Click "Save" at the bottom.
  14. Configure other settings, such as Adlists. Since FTL v5.22, Pi-hole supports the Adblock Plus (ABP) syntax for domain filter lists. Several filter lists, including several of the lists used by uBlock Origin (uBO) are available in ABP syntax.
  15. If possible, reboot Pi-hole and ensure all services work as expected after a full system restart.
  16. Configure your router (and devices if necessary) to use Pi-hole for DNS per the official instructions.