​A little while ago I blogged about how to setup Pi-Hole on a Raspberry Pi 4 B with DNSCrypt. However, not all devices on your network may play nice with your DHCP server and respect the DNS servers that it provides. Google is infamous for hard coding DNS in products, such as Chromecast. Or maybe it's another IoT device that is dumb, and you want it to use Pi-Hole. This how-to will show you how to use your Ubiquiti EdgeRouter to capture the rogue DNS requests and send them to your Pi-Hole.
​After some research for quality border routers that could play well with my Eero mesh wifi and capture DNS requests, I decided to buy the Ubiquiti EdgeRouter 12 for my network. It has a hardware ethernet switch built in (some smaller EdgeRouter versions switch in software), so I could connect both of my Raspberry Pi 4s, NAS, and other devices locally to the router. There are cheaper/smaller Ubiquiti EdgeRouter models that would work for captive DNS, so you don't have to buy the larger "12" model. Other routers maybe provide similar advanced NAT rule or captive DNS features, but I didn't research beyond Ubiquity.
​Network Configuration
In this example my internal network address space is: 10.13.2.0/24. I've configured the EdgeRouter 12 for WAN+2LAN2 mode. And my two Pi-Hole servers are at 10.13.2.200 and 10.13.2.201. Adjust your configuration accordingly for your address space and Pi-Hole IPs.
​Masquerade for DNS
​First we need to setup a NAT masquerade rule. Go into EdgeOS, Firewall/NAT, Add Source NAT rule. Use the template below as your guide. Save your new NAT rule. If you only have one Pi-Hole, just use a single destination address.
​Destination NAT Rule
​Next, add a Destination NAT rule. Use the template below. Notice the last two Pi-Hole addresses are prefixed with a !. If you have a single Pi-Hole, just use that single IP in place of the range I have below.
​Captive DNS Results
​After you get the rules saved and your 'rogue' devices try to do DNS queries, the Count should start to increase. You should also perform a few tests to ensure that both Pi-Hole and this new captive DNS rule are working as advertised.
​Testing Pi-Hole and your Captive DNS
​Next we should run a few tests to make sure everything is working. First, I SSH'd into my Raspberry Pi and did a nslookup on a domain I know Pi-Hole is blocking. As expect I got back all zeros. This didn't touch our NAT rules.
​Next, let's make sure that our Raspberry Pi, where Pi-Hole is running, can perform public DNS queries. This will make sure our NAT rule is allowing an exception for our RPIs. I did an nslookup on www.aol.com, and yes, got back the expected results.
​Next, let's simulate a rogue device on my network, like an evil Chromecast. To do that I'll use my MacBook Pro, open a shell, and use the dig command. Let's dig xp.apple.com, which should come back blocked and a result of all zeros. Windows doesn't have 'dig' natively, so you can follow the tedious instructions here to install BIND and use DIG.
​And viola, our Edgerouter 12 intercepted the DNS query to 8.8.8.8, redirected it to Pi-Hole, and Pi-Hole blocked it. Everything is working!
Note: If you run the DIG command from your RaspberryPi, it will NOT be intercepted and will return public information so don't be alarmed.
​Summary
​As you can see, configuring a Ubiquity EdgeRouter to intecept DNS queries is not at all difficult. After you setup two NAT rules you can then run some nslookup and DIG tests to ensure everything is working. All DNS queries from your network are now being funneled through to your Pi-Hole.
As normal Derek, your articles are excellent and I like the pdf output etc
If you get bored this winter, do fancy doing another PKI series based on Windows 2016/2019 and vSphere 6.7, Nutanix ?
Great work Derek
Derek thanks for the detailed overview. Wondering if you can fix the link to the original article that you referenced for setting up the Pi-Hole?
Thanks Derek for this fantastic guide, this setup works perfectly. It does leave me with one (naive) question, though: is there any way to provide an optional exception to these rules? From time to time during development, it might be necessary to use dig (or a similar DNS utility) from a host served by this captive DNS setup. Is the only option to either temporarily disable your captive DNS nat rules, or create a host ip whitelist for devices you want to exclude from captive DNS (although this exclusion would be permanent, and I’m not sure that’s ideal either)?
Awesome guide, worked perfectly for me. Thanks for putting this together!
One comment I wanted to add in case anyone stumbles across this later like I did: the xp.apple.com hostname doesn’t seem to be in Pi-Hole’s blacklist at this point, or at least it wasn’t in my basic install.
I used doubleclick.net instead to verify that DNS traffic is going through my Pi-Hole and is blocked accordingly:
Very helpful guide! Thank you for posting. I was blocking port 53 from all outgoing traffic on my iOT VLAN but this is a much better solution. Why is the source NAT masquerade needed (i.e., what is it doing)? My configuration is different from yours and it seems to work using only the destination NAT. I am blocking hard coded DNS from my iOT VLAN and my Pihole is on a different VLAN with a firewall rule to allow iOT devices to reach the PiHole.
How I understand it is the Source NAT completes the redirect back from the PiHole DNS.
Example, a mobile game with ads, will just fail to progress because even though the DNS request was forwarded to the PiHole (and then blocked), the response won’t make it back to the original client. The client will time out (where the game freezes).
To test this, run a nslookup to a domain, and point to a separate DNS, like 8.8.8.8. It will time out if you disable the Source NAT because the response isn’t translated back to the original client.
I try to answer this very late, the SNAT rule is for “disguising” the answer coming from its requested source. Many OSes would otherwise trash any reponses not coming back from their requested source, i.e. being your router.
This is a really helpful article Derek, but what would make it even better is if it also covered the Edgerouter 4 which doesn’t have an inbuilt switch and therefore no Switch0 interface. I obviously don’t understand it well enough to work it out for myself, but I surely can’t be alone?
Can you do the same whit IPv6?
This settings do not seem to work when IPv6 is enabled on the EdgeMax router. Are there a similar set of settings that could be used for IPv6?
Thanks.
You could just disable access to port 53 in your ipv6 rules for any client, and while your at it, also for port 853 for DoT.
Also my figure is, this technique of blocking DNS will come to a senseless state, as clients will more and more adopt to DoH. And you will not want to block port 443….