Block and Redirect DNS to PiHole

I'm trying to stop client DNS from resolving and redirect DNS to my pihole for add blocking. So I installed adblock and saw what it was doing with port forwarding rules. I applied those rules but it doesn't look like it works. The reason I say this is my Android phone will keep 8.8.8.8 as its primary DNS even though DHCP says use another IP (thanks Google!! :\ ) I know I could hard set DNS on the phone to my pihole but I'm more wondering why what I've implemented isn't working.

1 Like

See the solution by @vgaetera in Post #2. You'll have to SSH into your router. You'll also only have one MAC address instead of the two – replace the line with the contents "MAC_ADDR1 MAC_ADDR2" with your single Raspberry Pi's MAC address.

This will not redirect your DNS queries per se, but instead it blocks standard DoT and normal DNS queries over port 853 and 53 respectively. It will end up forcing your device to use your LAN's declared DNS server. Further details, including limitations are in that thread.

2 Likes

Another solution to actually hijack the requests and redirect them to OpenWrt's dnsmasq. From there the query is forwarded as usual to the piholes.
https://openwrt.org/docs/guide-user/services/dns/intercept
It has the disadvantage that all requests are seen as coming from OpenWrt, so statistics are useless.

My solution is using DNAT on the not allowed packets and sending them to pihole.

#
# DNS HIJACK
#
iptables -t nat -N dnshijack
# log packet - troubleshooting, remove "#"
#iptables -t nat -I dnshijack -j LOG --log-prefix "dnshijack4"
# send to pihole
iptables -t nat -A dnshijack -j DNAT --to-destination 10.0.2.2
# allow the PiHoles
iptables -t nat -A prerouting_lan_rule -m mac --mac-source aa:bb:cc:dd:ee:ff -p udp --dport 53 -j ACCEPT
iptables -t nat -A prerouting_lan_rule -m mac --mac-source aa:bb:cc:dd:ee:ff -p tcp --dport 53 -j ACCEPT
iptables -t nat -A prerouting_lan_rule -m mac --mac-source aa:bb:cc:dd:ee:00 -p udp --dport 53 -j ACCEPT
iptables -t nat -A prerouting_lan_rule -m mac --mac-source aa:bb:cc:dd:ee:00 -p tcp --dport 53 -j ACCEPT
# allow queries for local addresses
iptables -t nat -A prerouting_lan_rule -p tcp --dport 53 -d 10.0.2.1 -j ACCEPT
iptables -t nat -A prerouting_lan_rule -p udp --dport 53 -d 10.0.2.1 -j ACCEPT
# send the rest to PiHole
iptables -t nat -A prerouting_lan_rule -p udp --dport 53 -j dnshijack
iptables -t nat -A prerouting_lan_rule -p tcp --dport 53 -j dnshijack

2.1 is the OpenWrt router and 2.2 a pihole DNS.
You can disable the LOG line in the hijack chain to decrease logs, but it can be useful for testing and troubleshooting.

3 Likes

If you Pi-hole is in the same LAN subnet and your OpenWrt dnsmasq is pointing to your ISP's DNS servers this will need some tweaking.

My network:

subnet 192.168.1.0/24
openwrt 192.168.1.1
pi-hole 1291.68.1.153

Firewall rules:

-A zone_lan_prerouting ! -s 192.168.1.153 -p tcp -m tcp --dport 53 -m comment --comment "!fw3: DNS Pi-hole, port 53" -j DNAT --to-destination 192.168.1.153:53
-A zone_lan_prerouting ! -s 192.168.1.153 -p udp -m udp --dport 53 -m comment --comment "!fw3: DNS Pi-hole, port 53" -j DNAT --to-destination 192.168.1.153:53
-A zone_lan_postrouting -s 192.168.1.0/24 -d 192.168.1.153 -p tcp -m tcp --dport 53 -m comment --comment "!fw3: DNS Pi-hole MASQUERADE" -j MASQUERADE
-A zone_lan_postrouting -s 192.168.1.0/24 -d pi-hole.lan -p udp -m udp --dport 53 -m comment --comment "!fw3: DNS Pi-hole MASQUERADE" -j MASQUERADE
-A zone_wan_postrouting -m comment --comment "!fw3" -j MASQUERADE

Please, note the MASQUERADE rules, they tend to be forgotten in this scenario. And, my backend configuration in /etc/config/firewall looks like:

config redirect
	option dest_port '53'
	option src 'lan'
	option dest 'lan'
	option name 'DNS Pi-hole, port 53'
	option src_ip '!192.168.1.153'
	option target 'DNAT'
	option dest_ip '192.168.1.153'
	option src_dport '53'
	list proto 'tcp'
	list proto 'udp'

config nat
	option dest_port '53'
	option src 'lan'
	option name 'DNS Pi-hole MASQUERADE'
	option target 'MASQUERADE'
	option dest_ip '192.168.1.153'
	list proto 'tcp'
	list proto 'udp'
	option src_ip '192.168.1.0/24'

One thing I did not see anywhere in this forum yet, are IPv6 rules including masquerading, I know, NAT6 should be forbidden but I think NAT6 is a good approach to hijack IPv6 DNS traffic and redirect it to your Pi-hole.

In this case I had to add the rules into a /etc/firewall.nat6 as per wiki tutorial, and I had to use ipset as I was not able to force pihole-FTL to bind only to one local interface IPv6 address, so our local or public address could be used to send DNS requests. Here it goes:

# Create missing zone chains from IPv4 NAT tables
iptables-save -t nat | sed -e "/\s[DS]NAT\s/d;/\sMASQUERADE$/d" | ip6tables-restore -T nat
iptables-save -t raw | ip6tables-restore -T raw

# Prepare ipset with all Pi-hole IPv6 addresses
ipset destroy ipset-lan-pihole
ipset create ipset-lan-pihole hash:ip family inet6
ipset add ipset-lan-pihole fd57:11da:b11c::153
ipset add ipset-lan-pihole 2403:5800:3101:f000::153

# Accept port forwards and redirections to mimic IPv4 rules
ip6tables -t filter -I zone_lan_forward 2 -m conntrack --ctstate DNAT -m comment --comment "!fw3: Accept port forwards" -j ACCEPT
ip6tables -t filter -I zone_lan_input 2 -m conntrack --ctstate DNAT -m comment --comment "!fw3: Accept port redirections" -j ACCEPT
ip6tables -t filter -I zone_wan_forward 11 -m conntrack --ctstate DNAT -m comment --comment "!fw3: Accept port forwards" -j ACCEPT
ip6tables -t filter -I zone_wan_input 18 -m conntrack --ctstate DNAT -m comment --comment "!fw3: Accept port redirections" -j ACCEPT

# Redirect all DNS Queries to Router (IPv6) 
ip6tables -t nat -A zone_lan_prerouting -p udp -m set ! --match-set ipset-lan-pihole src -m multiport --dports 53,853,5353 -j DNAT --to-destination [fd57:11da:b11c::153]:53 -m comment --comment "DNS, ports 53, 853, 5353"
ip6tables -t nat -A zone_lan_prerouting -p tcp -m set ! --match-set ipset-lan-pihole src -m multiport --dports 53,853,5353 -j DNAT --to-destination [fd57:11da:b11c::153]:53 -m comment --comment "DNS, ports 53, 853, 5353"

# MASQUERADE rules
ip6tables -t nat -A POSTROUTING -o br-lan -m comment --comment "MASQUERADE" -j MASQUERADE

One thing to note is that I tried to add a proper MASQUERADE rule and it did not work, does anybody know why?:
ip6tables -t nat -A zone_wan_postrouting -s fd57:11da:b11c::/64 -m comment --comment "MASQUERADE" -j MASQUERADE

Backend in /etc/config/firewall for firewall.nat6 looks like this:

config include 'nat6'
	option path '/etc/firewall.nat6'
	option reload '1'

And, finally do not forget to activate in Pi-hole Conditional Forwarding and point it to your DHCP in OpenWrt:


I hope this helps all of you out there that faced this very same scenario.

Kind regards.

4 Likes

My Piholes are in the same LAN subnet. The OpenWrt dnsmasq is pointing to the Piholes. I don't see the reason to have anything pointing to upstream DNS except the Piholes.

Here you are:

#
# DNSHIJACKv6
#
ip6tables -t nat -N dnshijack
ip6tables -t nat -I dnshijack -j LOG --log-prefix "dnshijack6 "
ip6tables -t nat -A dnshijack -j DNAT --to-destination fd00:bbbb::2
ip6tables -t nat -A PREROUTING -p tcp --dport 53 -d fd00:bbbb::1 -j ACCEPT
ip6tables -t nat -A PREROUTING -p udp --dport 53 -d fd00:bbbb::1 -j ACCEPT
ip6tables -t nat -A PREROUTING -m mac --mac-source aa:bb:cc:dd:ee:ff -p udp --dport 53 -j ACCEPT
ip6tables -t nat -A PREROUTING -m mac --mac-source aa:bb:cc:dd:ee:ff -p tcp --dport 53 -j ACCEPT
ip6tables -t nat -A PREROUTING -p udp --dport 53 -j dnshijack
ip6tables -t nat -A PREROUTING -p tcp --dport 53 -j dnshijack

You'll need the nat6 kmod.

Hi, @trendy,

What I mean with my comment about NAT6 rules is that I had to come up with them, as nobody was posting them, thanks for yours.

So here comes my question, how do you avoid a possible loop between OpenWrt and Pi-hole? I think I am missing something here. I do not see you utilising a MASQUERADE rule. And, most relevant to me, when your DNS server replies like below, how do you solve it?

**➜** **~** dig @2001:4860:4860::8844 www.google.com.au  
;; reply from unexpected source: fd57:11da:b11c::153#53, expected 2001:4860:4860::8844#53
;; reply from unexpected source: fd57:11da:b11c::153#53, expected 2001:4860:4860::8844#53
;; reply from unexpected source: fd57:11da:b11c::153#53, expected 2001:4860:4860::8844#53
; <<>> DiG 9.10.6 <<>> @2001:4860:4860::8844 www.google.com.au
; (1 server found)
;; global options: +cmd
;; connection timed out; no servers could be reached

Kind regards.

I thought of them myself too, glad I found someone else interested in the same so we can look it together.

The NS for my LAN are the PIholes. They are advertised in dhcp option 6 for the hosts, and they are directly configured in OpenWrt in the lan interface. So every device, including OpenWrt, is instructed to query Piholes. Piholes will query dnsmasq in OpenWrt only for local addresses.

I don't see how that would help. Your masq rule is just changing the source IP to packets going out to br-lan to the router IPv6.

I have not worked that out. For now I leave it to the client to decide if to accept the response or ask the next NS in the list.

This MASQUERADE rule works on packets going to an external DNS that are being DNAT'd to an internal one, so when the packet comes back it looks like the external DNS is answering avoiding reply from unexpected source. It works fine on my side.

And here comes the MASQUERADE rule, give it a try.

You are right! I tried the masquerade rules (initially I thought you were saying about the wan postrouting masquerade) and now replies back to clients seem to come from the legitimate nameserver.

Regarding IPv6 why are you trying to masquerade on the wan? Any host contacting some other host on the internet should use the GUA, not the LUA.
I also fixed the reply from unexpected source for ipv6 just with this: ip6tables -t nat -A POSTROUTING -d fd00:bbbb::2 -p udp -m udp --dport 53 -m comment --comment "!fw3: DNS Pi-hole MASQUERADE" -j MASQUERADE

My current config for reference:

#
# DNSHIJACKv4
# Log and hijack to Pihole
iptables -t nat -N dnshijack
iptables -t nat -I dnshijack -j LOG --log-prefix "dnshijack4 "
iptables -t nat -A dnshijack -j DNAT --to-destination 10.0.2.2
# allow Pihole to query internet
iptables -t nat -A prerouting_lan_rule -m mac --mac-source 00:11:22:33:44:55 -p udp --dport 53 -j ACCEPT
iptables -t nat -A prerouting_lan_rule -m mac --mac-source 00:11:22:33:44:55 -p tcp --dport 53 -j ACCEPT
# allow queries to OpenWrt
iptables -t nat -A prerouting_lan_rule -p tcp --dport 53 -d 10.0.2.1 -j ACCEPT
iptables -t nat -A prerouting_lan_rule -p udp --dport 53 -d 10.0.2.1 -j ACCEPT
# anything else is hijacked
iptables -t nat -A prerouting_lan_rule -p udp --dport 53 -j dnshijack
iptables -t nat -A prerouting_lan_rule -p tcp --dport 53 -j dnshijack
# other zones
iptables -t nat -A prerouting_guest_rule -p tcp --dport 53 -d 10.0.2.2 -j ACCEPT
iptables -t nat -A prerouting_guest_rule -p udp --dport 53 -d 10.0.2.2 -j ACCEPT
iptables -t nat -A prerouting_guest_rule -p udp --dport 53 -j dnshijack
iptables -t nat -A prerouting_guest_rule -p tcp --dport 53 -j dnshijack
iptables -t nat -A prerouting_iot_rule -p tcp --dport 53 -d 10.0.2.2 -j ACCEPT
iptables -t nat -A prerouting_iot_rule -p udp --dport 53 -d 10.0.2.2 -j ACCEPT
iptables -t nat -A prerouting_iot_rule -p udp --dport 53 -j dnshijack
iptables -t nat -A prerouting_iot_rule -p tcp --dport 53 -j dnshijack
# fix "reply from unexpected source"
iptables -t nat -A postrouting_lan_rule -d 10.0.2.2 -p tcp -m tcp --dport 53 -m comment --comment "!fw3: DNS Pi-hole MASQUERADE" -j MASQUERADE
iptables -t nat -A postrouting_lan_rule -d 10.0.2.2 -p udp -m udp --dport 53 -m comment --comment "!fw3: DNS Pi-hole MASQUERADE" -j MASQUERADE



#
# DNSHIJACKv6
# Log and send to Pihole
ip6tables -t nat -N dnshijack
ip6tables -t nat -I dnshijack -j LOG --log-prefix "dnshijack6 "
ip6tables -t nat -A dnshijack -j DNAT --to-destination fd00:bbbb::2
# allow to ask OpenWrt
ip6tables -t nat -A prerouting_lan_rule -p tcp --dport 53 -d fd00:bbbb::1 -j ACCEPT
ip6tables -t nat -A prerouting_lan_rule -p udp --dport 53 -d fd00:bbbb::1 -j ACCEPT
# allow Pihole to query internet
ip6tables -t nat -A prerouting_lan_rule -m mac --mac-source 00:11:22:33:44:55 -p udp --dport 53 -j ACCEPT
ip6tables -t nat -A prerouting_lan_rule -m mac --mac-source 00:11:22:33:44:55 -p tcp --dport 53 -j ACCEPT
# anything else goes to hijack
ip6tables -t nat -A prerouting_lan_rule -p udp --dport 53 -j dnshijack
ip6tables -t nat -A prerouting_lan_rule -p tcp --dport 53 -j dnshijack
# other zones
ip6tables -t nat -A prerouting_guest_rule -p tcp --dport 53 -d fd00:bbbb::2 -j ACCEPT
ip6tables -t nat -A prerouting_guest_rule -p udp --dport 53 -d fd00:bbbb::2 -j ACCEPT
ip6tables -t nat -A prerouting_guest_rule -p udp --dport 53 -j dnshijack
ip6tables -t nat -A prerouting_guest_rule -p tcp --dport 53 -j dnshijack
ip6tables -t nat -A prerouting_iot_rule -p tcp --dport 53 -d fd00:bbbb::2 -j ACCEPT
ip6tables -t nat -A prerouting_iot_rule -p udp --dport 53 -d fd00:bbbb::2 -j ACCEPT
ip6tables -t nat -A prerouting_iot_rule -p udp --dport 53 -j dnshijack
ip6tables -t nat -A prerouting_iot_rule -p tcp --dport 53 -j dnshijack
# fix "reply from unexpected source"
ip6tables -t nat -A postrouting_lan_rule -d fd00:bbbb::2 -p udp -m udp --dport 53 -m comment --comment "!fw3: DNS Pi-hole MASQUERADE" -j MASQUERADE
ip6tables -t nat -A postrouting_lan_rule -d fd00:bbbb::2 -p tcp -m tcp --dport 53 -m comment --comment "!fw3: DNS Pi-hole MASQUERADE" -j MASQUERADE
4 Likes

You are right, I as copying from IPv4, so it makes no sense in regard to IPv6. Good catch. And, yep, fixed it finally! These two rules worked for me too:

ip6tables -t nat -A zone_lan_postrouting -d fd57:11da:b11c::153 -p tcp -m tcp -m multiport --dports 53,853 -m comment --comment "MASQUERADE" -j MASQUERADE
ip6tables -t nat -A zone_lan_postrouting -d fd57:11da:b11c::153 -p udp -m udp -m multiport --dports 53,853 -m comment --comment "MASQUERADE" -j MASQUERADE

Thank you for your help as it provide insight on this matter for me, mate.

2 Likes

Thank you too for the advice to fix the replies from unexpected source!

Out of curiosity, what is running on 853 and 5353 on Pihole?

1 Like

853 is DNSoverTLS, just in case and 5353 is Multicast DNS, I removed this last one, as I do not use it in my network.

1 Like

Are they also working with Pihole or is it another server?

Yeah, nah, I added them because I am silly, what I wanted was to avoid hardcoded DoT servers in apps to reach out for them. I should be blocking them, not redirecting them, as I do not have DoT or DoH support in my Pi-hole.

1 Like

here's my version, I recently setup a second piHole so decided to hijack DNS to forward to the router which is setup with forwards to the piHoles... I prefer the cleaner 1-liners when possible. this uses "ipset" which is an add-on package, lines are in the custom firewall rules...

ipset creat dns hash:ip
ipset add dns 192.168.<DNS>.<DNS1>
ipset add dns 192.168.<DNS>.<DNS2>
iptables -t nat -I prerouting_lan_rule -m set ! --match-set dns src -p tcp --match multiport --dports 53,853,5353 -j DNAT --to 192.168.<ROUTER>.<IP>
iptables -t nat -I prerouting_lan_rule -m set ! --match-set dns src -p udp --match multiport --dports 53,853,5353 -j DNAT --to 192.168.<ROUTER>.<IP>

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.