How to block DNS over HTTPS using IPtables
I've recently started using iptables for the first time on my OpenWrt, Linux based router. Out of the box the OpenWrt firewall is very good, however, after wanting to do more advanced things with the firewall such as forced DNS, iptables looked like it was the only way to go.
So what I'm trying to do is force all DNS traffic through the router so that users connected to the network can't override the DNS servers by setting manual DNS settings on their devices. I have successfully done this for standard port 53 traffic using a redirection rule.
I tested this by setting a DNS on my OpenWrt router and using 'dnsleaktest.com' to see what DNSs have been picked up. As expected I was using the DNS set in OpenWrt. Next, on Windows I set a manual DNS, different to the openwrt one and did the test again on 'dnsleaktest.com' and started to see some of the overridden DNSs show up. Finally I applied the iptables redirect rule and did the test a third time, and indeed this time the manual DNS set on the client weren't showing and instead the router's DNSs were coming through.
Additionally I have also blocked DNS over TLS (DoT) by dropping port 853. However, the one I'm having difficulty with is DNS over HTTPS (DoH).
I have read in a few places the only way to stop DoH is to block the IP's at port 443 (SSL). With this in mind I have made an entire list of public DNS over HTTPS servers such as Google, Adguard and Cloudflare. I have put the IP's into an ipset and loaded them into iptables but it doesn't seem to be working.
For the testing of DoH I have been enabling the 'Enable DNS over HTTPS' checkbox under Mozilla Firefox's Network Settings and testing with 'dnsleaktest.com'.
/etc/Block_DoH.txt (ipset)
create Block_DoH hash:ip,port
add Block_DoH 8.8.4.4,443
add Block_DoH 8.8.8.8,443
add Block_DoH 149.112.112.112,443
add Block_DoH 9.9.9.9,443
add Block_DoH 149.112.112.9,443
add Block_DoH 9.9.9.10,443
add Block_DoH 149.112.112.10,443
add Block_DoH 9.9.9.11,443
add Block_DoH 149.112.112.11,443
add Block_DoH 104.28.1.106,443
add Block_DoH 104.28.0.106,443
add Block_DoH 45.90.28.0,443
add Block_DoH 45.90.30.0,443
add Block_DoH 176.103.130.131,443
add Block_DoH 176.103.130.130,443
add Block_DoH 176.103.130.132,443
add Block_DoH 176.103.130.134,443
add Block_DoH 96.113.151.147,443
add Block_DoH 185.228.168.9,443
add Block_DoH 185.228.169.9,443
add Block_DoH 185.228.168.168,443
add Block_DoH 185.228.169.168,443
add Block_DoH 185.228.168.10,443
add Block_DoH 185.228.169.11,443
add Block_DoH 1.1.1.1,443
add Block_DoH 1.0.0.1,443
# Force DNS to router's DNS
iptables -t nat -A PREROUTING -p udp --dport 53 -j REDIRECT
iptables -t nat -A PREROUTING -p tcp --dport 53 -j REDIRECT
# Block DNS over TLS
iptables -I INPUT -p tcp --sport 853 -j DROP
iptables -I INPUT -p udp --sport 853 -j DROP
iptables -I OUTPUT -p tcp --dport 853 -j DROP
iptables -I OUTPUT -p udp --dport 853 -j DROP
# Block DNS over HTTPS
iptables -I OUTPUT -m set --match-set Block_DoH src -j DROP
iptables -I INPUT -m set --match-set Block_DoH dst -j DROP
# Tried blocking Cloudflare with IPtables directly
iptables -I INPUT -s 1.1.1.1 -j DROP
iptables -I INPUT -s 1.0.0.1 -j DROP
iptables -I OUTPUT -d 1.1.1.1 -j DROP
iptables -I OUTPUT -d 1.0.0.1 -j DROP
# Tried to redirect to DNS running on router
iptables -t nat -I OUTPUT -p tcp -s 1.1.1.1 --sport 443 -d 192.168.1.1 --dport 53 -j REDIRECT
iptables -t nat -I OUTPUT -p udp -s 1.1.1.1 --sport 443 -d 192.168.1.1 --dport 53 -j REDIRECT
iptables -t nat -I OUTPUT -p tcp -s 1.0.0.1 --sport 443 -d 192.168.1.1 --dport 53 -j REDIRECT
iptables -t nat -I OUTPUT -p udp -s 1.0.0.1 --sport 443 -d 192.168.1.1 --dport 53 -j REDIRECT
Any ideas?
Many thanks in advance.
UPDATE 1
@hardillb The lines I'm focussing on is the #Block DNS over HTTPS
. I'm explicitly trying to block DoH so that the client will fallback to standard DNS.
It's hard or even impossible to block DoH protocol on a router. DoH cannot be easily blocked, because it uses TCP port 443, which happens to be the same port used for HTTPS. You could block such IPs:443, but some of those servers use it for both DoH and content. For example, the DoH server dns.cloudflare.com has the same IP(s) as cdnjs.cloudflare.com, the later is used to serve some scripts, used by several websites, such as linuxquestions.org
So you could block only some DoH servers.
As an option you could setup an own DoH server in lan using dnscrypt2 / H2O / Simple AdBlock etc. But an application may or may not want to use it.
Force redirecting traffic to own DoH server won't work, because of cryptography protection