Background
I've been stuggling to get a redirection working via iptables - a combination of restrictive capabilities of the s/w versions on DD-WRT and (more likely) my shoddy script.
We have a very limited bandwidth out to the internet on the network in question, and so I've deployed a number of measures to make utilisation more efficient e.g. ad blocking & replacement technology, traffic filtering, QoS prioritisation
I have the ISP-supplied router as the outer router, and an inner router running WiFi, LANs & VPN out to the internet.
Specific Problem
Among the list of enhancements is DNS caching on a dedicated server node, and redirection of all DNS requests to this server. Most of this is done via network settings in the dhcp servers, but some mobile & desktop apps are overriding this.
I use DNS upstream servers as targets from the LAN DNS server which I know are trustworthy. The inner router has a firewall script which is designed to apply a vpn killswitch and allow sticky IP's access outside of the VPN / straight out via our ISP (thanks a bunch Netflix).
However I'm struggling to get the DNS traffic redirection working on DD-WRT - I tested it on a combination of servers and desktops using dig
and tcpdump
, simulating a request being made to server A, redirected to server B, and the client getting a DNS response accordingly. That appeared to work as expected, but when I applied the same configuration to the inner router it has no effect. I can't see any traffic arriving at the DNS server when I fire a request out to a public resolver e.g. Cloudflare.
In fact the request is still blocked.
lanDns="dns server IP"
iptables -I FORWARD -s ! $lanDns -p tcp --dport 53 -j ACCEPT
iptables -I FORWARD -s ! $lanDns -p udp --dport 53 -j ACCEPT
iptables -t nat -A PREROUTING -s ! $lanDns -p tcp --dport 53 -j DNAT --to $lanDns:53
iptables -t nat -A PREROUTING -s ! $lanDns -p udp --dport 53 -j DNAT --to $lanDns:53
iptables -I FORWARD -s ! $lanDns -p tcp --dport 5353 -j ACCEPT
iptables -I FORWARD -s ! $lanDns -p udp --dport 5353 -j ACCEPT
iptables -t nat -A PREROUTING -s ! $lanDns -p tcp --dport 5353 -j DNAT --to $lanDns:53
iptables -t nat -A PREROUTING -s ! $lanDns -p udp --dport 5353 -j DNAT --to $lanDns:53
# secure DNS - TODO letsencrypt certificate for <servername>
iptables -t nat -A PREROUTING -s ! $lanDns -p tcp --dport 853 -j DNAT --to $lanDns:853
# allow direct DNS traffic from the LAN DNS server, don't need to drop as well as this will only interfere
iptables -A FORWARD -p tcp --dport 53 -s $lanDns -j ACCEPT
iptables -A FORWARD -p udp --dport 53 -s $lanDns -j ACCEPT
iptables output looks ok, but what am I missing? Is it as simple as ordering or just my poor iptables usage? :)
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DNAT udp -- 0.0.0.0/0 0.0.0.0/0 udp dpt:53 to:[DNS server ip]
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:53 to:[DNS server ip]
DNAT tcp -- ![DNS server ip] 0.0.0.0/0 tcp dpt:53 to:[DNS server ip]:53
DNAT udp -- ![DNS server ip] 0.0.0.0/0 udp dpt:53 to:[DNS server ip]:53
DNAT tcp -- ![DNS server ip] 0.0.0.0/0 tcp dpt:5353 to:[DNS server ip]:53
DNAT udp -- ![DNS server ip] 0.0.0.0/0 udp dpt:5353 to:[DNS server ip]:53
iptables version on DD-WRT (Kong Ac): 1.3.7
Update
Thanks to a comment by davidgo it appears that the requests are being redirected correctly, but the responses are getting as far as the router (but not being send back to the requestor). Will experiment with rule ordering a little more and update if progress - support welcome if that makes the problem easier to identify
Alternative Solutions Not Appropriate Here
I acknowledge that the following are good solutions, but are not appropriate in the context of this specific scenario:
- PiHole - other nodes are delivering similar capabilities
- Replacing router
- Replacing DD-WRT firmware with a.n. other firmware distro
- Non-Linux solutions
- Closed-source solutions
domain-name-servers
directive is not working i.e. they want to make direct DNS queries to whatever DNS server they have been built / configured to request from.