IPV6 redirect to unbound DNS bug

Started by williamjjp, March 13, 2026, 08:35:05 PM

Previous topic - Next topic
Hi All,

I think Opnsense is great, so kudos to the devs. I'm am fairly new to it, I found a small inconsistency which I'm pointing out to help others.

When configuring NAT port forward rules to redirect all DNS traffic on port 53 from LAN clients to the DNS unbound local resolver, there is an inconsistency in how the corresponding firewall rules behave between IPv4 and IPv6. For IPv4, the redirect target is the loopback address and invert destination must be enabled on both the NAT port forward rule and its corresponding firewall rule for the redirect to function correctly. For IPv6, where the redirect target is a ULA virtual IP address assigned to an interface, enabling invert destination on the corresponding firewall rule prevents the redirect from working — it should be left unchecked. The NAT rule itself still requires invert destination for both protocols. This inconsistency is not documented and may cause confusion when replicating IPv4 DNS redirect configurations for IPv6.


(I'm aware DNSmasq also allows this redirect function I just prefer having it in firewall rules.)

March 15, 2026, 01:11:36 AM #1 Last Edit: March 15, 2026, 01:14:06 AM by falken
I do not invert destination on v4 or v6 on the DNAT or the firewall rule. I'm not sure why you would need to?
I invert the source on DNAT v4/v6 to exclude the unbound server and other systems that need to be able to communicate to other DNS servers.

I think there's clearly a misconfiguration here, possibly with his IPv6 addressing or interface assignments.  We'd need the setup details to try and spot it.

@falken I prefer to redirect only the non-local requests because if something is trying to reach DNS on an internal address which does not provide DNS on my network, I don't want that to go through.  I want that blocked and logged because it's abnormal.  YMMV.
N5105 | 8/250GB | 4xi226-V | Community

For IPv6, you must have a routeable IPv6 for the redirect target, see https://forum.opnsense.org/index.php?msg=246513.

That means, ::1 or fe80::xxxxx are out of the question.
Intel N100, 4* I226-V, 2* 82559, 16 GByte, 500 GByte NVME, Leox LXT-010H-D

1100 down / 450 up, Bufferbloat A+

OP stated that the redirect target is a ULA VIP assigned to "an" interface (didn't specify further).  I assumed the routing to the VIP wasn't the issue, but I misread him as to which case is broken.

He is actually saying that the IPv6 case is the working one, and I agree with this part:

Quote from: williamjjp on March 13, 2026, 08:35:05 PMFor IPv6, where the redirect target is a ULA virtual IP address assigned to an interface, enabling invert destination on the corresponding firewall rule prevents the redirect from working — it should be left unchecked. The NAT rule itself still requires invert destination for both protocols.

... seems OK.

The NAT rule might have something like dest="!LAN net," which makes sense for matching non-local traffic.  And the redirect target is the ULA (not inverted), which should also match with the dest in the associated pass rule.

But his IPv4 case is strange:

QuoteFor IPv4, the redirect target is the loopback address and invert destination must be enabled on both the NAT port forward rule and its corresponding firewall rule for the redirect to function correctly

This is illogical.  You would not have dest="!127.0.0.1" for the associated pass rule if the NAT target was 127.0.0.1.

Only the NAT dest should be negated (e.g. !LAN net), as above.
N5105 | 8/250GB | 4xi226-V | Community

Following up on my own post — @OPNenthu was right, and my IPv4 observation was wrong. Posting the correction in case anyone finds this thread later.

Short version: the redirect was working the whole time, but not for the reason I thought. The inverted firewall rule was not the thing passing redirected traffic.

The mechanism is that opnsense translates before it filters. By the time the filter rules are evaluated, a redirected packet's destination is already the redirect target. So the associated pass rule needs to match the target, not the original destination.

My IPv4 filter rule was destination = !127.0.0.1, port 53, on the interface group. That excludes precisely the packets it was supposed to be passing. What it actually matched was port 53 traffic aimed at my own local addresses — clients querying the firewall's LAN IP directly — which is exactly the traffic the NAT rule deliberately skips. The redirected packets were being passed further down by my ordinary allow-any LAN rule.

Confirmed with logging. Pointing a client at an external resolver produced an rdr line in the firewall log, and the query showed up in Unbound as expected — but there was no corresponding pass line from my manual rule, which had logging enabled. It was never matching.

Why IPv6 looked different: same construction, different outcome. The IPv4 target is 127.0.0.1, which falls outside the negated set, so the inverted rule matched and looked load-bearing. The IPv6 target is a ULA VIP, which falls inside the negated set, so the same rule visibly failed to match. One mechanism, two results — not an inconsistency in OPNsense.

I also suspect what I read as "unchecking invert breaks the IPv4 redirect" was actually the loss of DNS to the firewall's own LAN address. Clients pointed at the gateway for DNS would break in a way that looks identical to a broken redirect from the client side.

The fix was to stop hand-writing the filter rules entirely: set the NAT rule's Firewall rule option to Register and let OPNsense generate the associated rule (destination = the redirect target, not inverted). Verified working on both protocols now, with no asymmetry between them.

@meyergru's point stands and is the one genuine IPv4/IPv6 difference here — the IPv6 redirect target has to be routable, hence a ULA VIP rather than ::1. I had that part right already, which is why the v6 side worked.

Apologies for the noise, and thanks to both of you for the pushback.