DNS Leak Prevention and Firewall Configuration
It is important to block all outbound DNS traffic on the host except traffic destined to your Pi-hole and Unbound services (whether on host or Docker network). This prevents DNS queries from bypassing your private DNS, avoiding leaks to ISP or external resolvers.
Red Hat-based Distros (RHEL, CentOS, Fedora, Rocky Linux, AlmaLinux, etc.) Using firewalld
firewalld
# Block all outbound DNS TCP/UDP traffic by default
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="0.0.0.0/0" port port="53" protocol="tcp" reject'
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="0.0.0.0/0" port port="53" protocol="udp" reject'
# Allow DNS traffic to local Docker bridge subnet (example here: 172.28.0.0/16)
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="172.28.0.0/16" port port="53" protocol="tcp" accept'
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="172.28.0.0/16" port port="53" protocol="udp" accept'
# Reload firewall to apply rules
sudo firewall-cmd --reload
Debian/Ubuntu Using ufw
ufw
# Deny all outgoing DNS traffic by default
sudo ufw deny out 53/tcp
sudo ufw deny out 53/udp
# Allow DNS queries only to Docker network IP range (example: 172.28.0.0/16)
sudo ufw allow out to 172.28.0.0/16 port 53 proto tcp
sudo ufw allow out to 172.28.0.0/16 port 53 proto udp
# Reload ufw to apply changes
sudo ufw reload
Arch Linux or Other Distros Using iptables
iptables
# Drop all outbound DNS TCP and UDP traffic
sudo iptables -A OUTPUT -p tcp --dport 53 -j DROP
sudo iptables -A OUTPUT -p udp --dport 53 -j DROP
# Insert rule to ACCEPT DNS traffic to Docker bridge subnet before drop rules
sudo iptables -I OUTPUT -p tcp -d 172.28.0.0/16 --dport 53 -j ACCEPT
sudo iptables -I OUTPUT -p udp -d 172.28.0.0/16 --dport 53 -j ACCEPT
For Arch Linux or Other Distros Using nftables
nftables
nft add table inet filter
nft add chain inet filter output { type filter hook output priority 0 \; }
# Drop all outbound DNS traffic
nft add rule inet filter output udp dport 53 drop
nft add rule inet filter output tcp dport 53 drop
# Accept DNS traffic to Docker subnet (replace subnet accordingly)
nft add rule inet filter output ip daddr 172.28.0.0/16 udp dport 53 accept
nft add rule inet filter output ip daddr 172.28.0.0/16 tcp dport 53 accept
Firewall Configuration Notes
Replace
172.28.0.0/16
with the actual subnet of your Docker bridge network or host DNS servers as applicable.Ensure all client devices and the host itself use only Pi-hole IP(s) as their DNS servers.
Test your DNS leak protection with online tools like dnsleaktest.com.
Adjust firewall rules for IPv6 if your network utilizes it.
For less common firewalls, consult the distro or firewall documentation for equivalent rules permitting and restricting DNS traffic.
PreviousPrivate and Secure DNS with Pi-hole and UnboundNextConfiguring DoT with Unbound and Pi-hole on OPNsense
Last updated