Forward and Input rule type not displayed correctly in UI?

I was noticing some occasional DNS leaks on port 53 after configuring DNS over TLS, so I implemented the instructions detailed here: to intercept and redirect DNS using a DNAT forward. The config suggested is:

# Intercept DNS traffic
uci -q delete firewall.dnsint
uci set firewall.dnsint="redirect"
uci set"Intercept-DNS"
uci set firewall.dnsint.src="lan"
uci set firewall.dnsint.src_dport="53"
uci set"ipv4"
uci set firewall.dnsint.proto="tcpudp"
uci set"DNAT"
uci commit firewall
service firewall restart

It works, but I'm not sure why.

I am confused by the UCI config as it doesn't specify a destination IP for the forward/DNAT rule, which is listed as a mandatory parameter for a DNAT config in the docs here Then I noticed that there is a note that if the DNAT dest_ip is the same as the router IP then the rule is interpreted as a DNAT+input rule rather than a DNAT+forward rule. I can only assume there is an undocumented default that if the dest_ip is omitted entirely, it is also interpreted as a DNAT+input rule, which makes some sense logically. Is this the case?

If so, when you view this rule in the LUCI UI, it displays like this:

With the 'Forward to' as 'any host, port 53 in any zone'. This seems... misleading? Does the UI need updating to display these rule types more accurately?

You're taking any traffic with a destination port of 53 and accepting it as input.

Since you are changing IPs or ports, it appears under forwards.

Thanks for clarifying, I do understand what is happeneing here. However, my issues is with:

  1. The documentation, that states 'dest_ip' is a required UCI parameter for a DNAT rule, but actually appears to have a hidden 'default' if it is ommitted, which makes it a redirect rule.
  2. The way this rule is displayed in LUCI which seems to imply it is being forwarded to 'any host in any zone', which to me is not indicative of it being routed to the input chain.
  1. I didn't say INPUT chain. To be clear, the target in question for this rule is REDIRECT - for more information, see:

  2. Please understand, if a rule changes port or IP it appears in Port Forwards, if it does neither, it appears in Traffic Rules. You could specify the zone, it will then read:


(My rule only specified UDP.)

I agree that perhaps the app can be better written to clarify that; but be mindful - for the record, there are more such rules that don't display in their entirety:

  • rules with "extra arguments"
  • time-based rules
  • rules with references to ipsets

Hope this helps clear any confusion.


You're abolsutely right, my terminology was off. I'm talking more about the behaviour of UCI rather than the iptables rule itself.

I did a bit more reading and the 'confusing' behaviour is as follows.

If you create a UCI 'redirect' config with a target of 'DNAT' and specify a dest_ip, then UCI turns this into a PREROUTING rule with a destination of DNAT.

config redirect
        option name 'TEST'
        option src 'lan'
        option src_dport '552'
        option family 'ipv4'
        option proto 'tcpudp'
        option target 'DNAT'
        option dest_ip ''


However, if you create the exact same UCI redirect config with a target of DNAT but omit the dest_ip, UCI turns this into a PREROUTING rule with the destination of REDIRECT.

config redirect
        option name 'Intercept-DNS'
        option src 'lan'
        option src_dport '53'
        option family 'ipv4'
        option proto 'tcpudp'
        option target 'DNAT'


I subsequently learned that anything in the 'REDIRECT' target is only allowed to go to the IP of the interface the packet was received on. So UCI 'converts' a DNAT without a dest_ip to be a REDIRECT. This is an undocumented feature of UCI fw3 as far as I can tell.

1 Like

Fixed the wiki documentation: