I've sweat so much over this so I thought I would share how I did it. Maybe there is already a guide somewhere or something.... I asked here but we didn't find a solution and on the DDWRT website I spent a week reading and trying before posting.
I wanted to force the PiHole to be the only accessible DNS server. Using DDWRT, I tried forcing it, but since the clients would detect that the wrong server answered the query, it didn't work.
nslookup google.com
;; reply from unexpected source: 192.168.1.2#53, expected 1.1.1.1#53
;; reply from unexpected source: 192.168.1.2#53, expected 1.1.1.1#53
;; connection timed out; no servers could be reached
My firewall rules (I don't think it changed much)
iptables -t nat -I PREROUTING -i br0 -p tcp -s ! 192.168.1.2 --dport 53 -j DNAT --to 192.168.1.2:53
iptables -t nat -I PREROUTING -i br0 -p udp -s ! 192.168.1.2 --dport 53 -j DNAT --to 192.168.1.2:53
I also tried with many iptables commands but nothing would work properly.
It would work with masquerade, but all requests looked like they were coming from the router.
iptables -t nat -A POSTROUTING -j MASQUERADE
Since I want to know which client made the request, this wasn't an option.
I stumbled upon this reply in a post on reddit which suggested that the requests received had to go back to the router "allowing it to remove the DNAT on the reply packet".
I was out of options so...
Note that my main network is 192.168.1.1 (br0).
I also have a public wireless network set on 192.168.10.1 (br1).
My PiHole is connected on Port 3 behind my router.
In Setup > Basic, I set Static DNS 1 to 192.168.2.2. I did not check "Use DNSMasq for DNS"
In Setup > VLANs, I assigned Post 3 to VLAN 3 (which wasn't used).
In Setup > Networking I set the Port Setup VLAN 3 with the following:
Bridge Assignment: Unbridged
Masquerade/NAT: Enable
IP: 192.168.2.1
Mask: 255.255.255.0
I don't know if it does anything and I spent too much this on this issue that I won't test without it for now but in Services:
Additional Dnsmasq Options:
interface=br0,br1
domain=local
local=/local/
listen-address=192.168.2.2
Administration > Commands:
# Private network
iptables -t nat -I PREROUTING -i br0 -p tcp -s ! 192.168.2.2 --dport 53 -j DNAT --to 192.168.2.2:53
iptables -t nat -I PREROUTING -i br0 -p udp -s ! 192.168.2.2 --dport 53 -j DNAT --to 192.168.2.2:53
# Public network, you don't probably need this depending...
iptables -t nat -I PREROUTING -i br1 -p tcp -s ! 192.168.2.2 --dport 53 -j DNAT --to 192.168.2.2:53
iptables -t nat -I PREROUTING -i br1 -p udp -s ! 192.168.2.2 --dport 53 -j DNAT --to 192.168.2.2:53
Click Save Firewall.
Since I'm using DNS over HTTPS, a DNS leak test would reveal multiple servers if this wasn't working.
I tested by setting my Static DNS server on my computer to 1.1.1.1.
$ nslookup duckduckgo.com
Server: 1.1.1.1
Address: 1.1.1.1#53
Non-authoritative answer:
Name: duckduckgo.com
Address: 107.20.240.232
Name: duckduckgo.com
Address: 184.72.104.138
Name: duckduckgo.com
Address: 23.21.193.169
the PiHole catched the request for duckduckgo.com
DSN Leak result:
The PiHole catched everything.
I have no idea if this would be possible with wireless. I think you would need a virtual access point just for it. I also think it would draw more power or something and put more stress on the router.
Since I want my DNS server to be fast and reliable, it was already connected with a cable. It was on Port 6 though and DDWRT GUI don't show those, So I switched.
I'm no pro, I don't know if someone already posted this... but I couldn't find anything in the last month regarding this issue that worked for me. Also, it's possible there is an easier solution, but I'm a noob so idk
Hope it helps someone.
EDIT: I should've use 'caught' instead of 'catched' maybe? oopsie