Redirect DNS to pi-hole

Started by louis_nichols, May 04, 2025, 05:17:43 PM

Previous topic - Next topic
Hi all!

I have a network where opnsense is the LAN gateway at 10.0.0.1. Pi-hole is the DHCP and DNS server at 10.0.0.10.

I am trying to redirect all DNS queries from LAN to pihole. I have tried so many combinations, but none of them work and it's driving me crazy. I've read various instructions online and even tried with ChatGPT (which is mostly horrible at this, btw), but now I feel lost.

The challenge here is to redirect traffic from all LAN IPs to any IP and port 53 to 10.0.0.10:53, while at the same time allowing 10.0.0.10 to access its upstream DNS.

I've tried two different paths, with many permutations in between.


1. A single port forwarding rule under Firewall: NAT: Port Forward where
  • Interface LAN
  • TCP/IP Version IPv4
  • Protocol TCP/UDP
  • Source / Invert  is ENABLED
  • Source is Single host or network 10.0.0.10/32
  • Source port range is ANY
  • Destination / Invert  is ENABLED
  • Destination is Single host or network 10.0.0.10/32
  • Destination port range is DNS
  • Redirect target IP is Single host or network 10.0.0.10/32
  • Redirect target port is DNS

2. Two rules where:
  Rule 1 is under Firewall: Rules: LAN and allows DNS traffic from 10.0.0.10
  • Action PASS
  • Quick is ENABLED
  • Interface LAN
  • Direction IN
  • TCP/IP Version IPv4
  • Protocol TCP/UDP
  • Source / Invert  is DISABLED
  • Source is Single host or network 10.0.0.10/32
  • Destination / Invert is DISABLED
  • Destination ANY
  • Destination port range DNS
  Rule 2 is under Firewall: NAT: Port Forward and redirects all traffic from LAN net to 10.0.0.10
  • Interface LAN
  • TCP/IP Version IPv4
  • Protocol TCP/UDP
  • Source / Invert  is DISABLED
  • Source is LAN NET
  • Source port range is ANY
  • Destination / Invert is ENABLED
  • Destination is Single host or network 10.0.0.10/32
  • Destination port range is DNS
  • Redirect target IP is Single host or network 10.0.0.10/32
  • Redirect target port is DNS
Then, under Firewall: Rules: LAN Rule 1 is above Rule 2.

Unfortunately, none of these work. Like, I said, I tried various permutations in between, but I either get that DNS doesn't work at all, or that it's not redirected to pi-hole and just goes out to (for example) 8.8.8.8.

I would greatly appreciate some guidance here.


You need to add an outbound NAT rule for this to work. Otherwise you will run into asymmetric routing issues.

You have to enable the hybrid outbound NAT mode and add a rule:
interface: LAN
source: LAN subnet
destination: 10.0.0.10/32
destination port: 53
translation: interface address

This lead into loosing the information about the origin clients source IP on the pihole for redirected traffic. If you need this information you have to put the pihole into different network segment.

Quote from: viragomann on May 04, 2025, 06:39:34 PMYou need to add an outbound NAT rule for this to work. Otherwise you will run into asymmetric routing issues.

You have to enable the hybrid outbound NAT mode and add a rule:
interface: LAN
source: LAN subnet
destination: 10.0.0.10/32
destination port: 53
translation: interface address

This lead into loosing the information about the origin clients source IP on the pihole for redirected traffic. If you need this information you have to put the pihole into different network segment.

Thanks for the hint. And I use this rule in addition to the port redirection?

Yes. The redirection just redirects DNS traffic to the pihole, but doesn't change the source IP. But if the DNS packets are coming from OPNsense it's required that they have the OPNsense LAN IP as source address. This part is realized by the outbound NAT.

Dude, I did it like this on mine.

I use pi-hole, I put the IP in DHCP (DNS SERVERS)


I didn't need to add any rules when forwarding ports.


In the firewall rules I just allowed local access between the LANs I have, and so everything works perfectly.


Pi-Hole

Ricardo Lanes
Information Security Analyst
ricardo@lanes.rio
------
- OPNsense 25.1.5_5/AMD64
- Alder Lake N100 @ 16GB DDR5
- NIC INTEL 1225x6 2.5G
- 128GB SATA 3.0
- UPLINK 800MB/ 500MB
- UPLINK 500MB/ 300MB

The TO uses the pihole as DHCP server as well, as he wrote in the very first line. So I expect, that the DHCP server most probably hands out its own IP as DNS server.

The concerns here might be about mulish DHCP clients, which do not care about the pushed DNS settings, but send request to other (public) DNS servers instead.

I also set pihole as the system default in System > Settings > General > Networking

I don't know if this would be the best option, but it works :)
Ricardo Lanes
Information Security Analyst
ricardo@lanes.rio
------
- OPNsense 25.1.5_5/AMD64
- Alder Lake N100 @ 16GB DDR5
- NIC INTEL 1225x6 2.5G
- 128GB SATA 3.0
- UPLINK 800MB/ 500MB
- UPLINK 500MB/ 300MB

Thank you both for the help. I had a crazy week and only managed to try this stuff today.

Indeed, the suggestion from @viragomann did the trick. I wish I understood better why, but sometimes it's like this. :)

@ricardolanes  Indeed, that doesn't apply to me because I run dhcp from pihole, not opnsense. But I truly appreciate your support regardless.

It helps to understand not only why it helped, but also the consequences.

I'm going to assume you kept some form of the 1st NAT rule in your OP.
You probably only needed to exempt Pi-hole on the source, so it can reach out upstream (not necessarily if upstream is DoH or DoT though).
!pi-hole on the destination side is probably useless.

All clients using pi-hole directly probably worked at all times (with or without NAT).
client -> pi-hole (which does its thing) then pi-hole -> client. OPN is not involved apart from allowing pi-hole through to upstream servers.

For clients not using pi-hole for DNS, my understanding is as follows:
Before NAT:
1/ client -> OPN (packet destination is OPN or !LAN, sent to GW)
2/ PF kicks in: OPN -> pi-hole (packet sent to pi-hole still has source = client)
3/ pi-hole does its thing
4/ pi-hole -> client (replies directly to client because the source of the request in 2 was client).
But the client is expecting a reply from the server it sent the request to, which is not pi-hole. Reply dropped.

After NAT:
1/ client -> OPN (packet destination is OPN or !LAN, sent to GW)
2/ PF kicks in: client -> pi-hole (packet sent to pi-hole has source = OPN because of NAT)
3/ pi-hole does its thing
4/ pi-hole -> OPN (reply).
5/ OPN -> client (reply through NAT, in reverse)

As indicated with his suggestion, the drawback is that from the perspective of pi-hole, all these requests are issued by OPN.
You won't know which client made them. You can't make client-based exceptions.

If you move pi-hole to a separate (V)LAN, all traffic goes through OPN both ways (request & reply), so NAT is not needed, and client information is preserved.
But in your case, you'd have to deal with a DHCP relay...

Using DHCP on OPN with AdGuardHome is way easier ;-)

Quote from: louis_nichols on May 11, 2025, 03:00:10 AMI wish I understood better why, but sometimes it's like this. :)

The point here is that if you only redirect DNS request to the pihole:
The client with the IP, say 10.0.0.100 requests the DNS server, say 8.8.8.8. OPNsense redirect the request packet to the pihole, which is 10.0.0.10. The pihole sees 10.0.0.100 as the source address of the request. Hence it sends the respond packet directly to this IP. The source address in the respond packet is the 10.0.0.10, but the client expects a respond from 8.8.8.8 actually and will ignore the packet.

With the outbound NAT rule, the pihole sees 10.0.0.1 as source and hence sends responses back to OPNsense. OPNsense translate the source IP back to 8.8.8.8 according to its state table.