Can I improve my DNS DNAT setup?

My setup is a little strange. I have WAN from modem in a VLAN connected to two ports so OpenWrt (EA7500V1) and my main router sit in parallel with two separate public IP's. br-lan is connected to main LAN as a client. Mostly used to monitor WAN side traffic from main router.

Recently decided to move IOT junk to it's own vlan (br-guest) using the 2G radio which main router can't do properly. Mostly works great I can control both inbound and outbound traffic and allow one-way access from LAN->IOT.

My issue is with DNS capture. Many of the devices hard-code DNS and fail if I simply block the traffic so I have to DNAT it to DNS server (pihole) on br-lan. That also fails unless I masquerade the traffic. ( Return routing works but client complains about response from wrong server ).

config redirect
        option target 'DNAT'
        option name 'Intercept DNS'
        option src 'guest'
        option dest_ip '192.168.2.100'
        option dest_port '53'
        option src_dport '53'
        option dest 'lan'
        option src_dip '! 192.168.2.100'

config nat
        option name 'DNS NAT Masq'
        list proto 'tcp'
        list proto 'udp'
        option src 'lan'
        option src_ip '172.30.10.0/255.255.255.0'
        option dest_port '53'
        option target 'MASQUERADE'
        option mark '0x03/0xff'

src 'lan' is confusing to me but generated rules are correct e.g. use lan as destination by cramming rule in zone_lan_postrouting. GUI reference to parameter as "Outbound" / "To" is easier to understand.

That feels wrong because I had to make custom rules to mark the traffic e.g. so DNS server see's real source IP for everyone honoring their DHCP settings.

iptables -t mangle -A PREROUTING -i br-guest ! -d 192.168.2.100  -p tcp -m tcp --dport 53  -m comment --comment "!fw3: Mark DNAT" -j MARK --set-xmark 0x3/0xff
iptables -t mangle -A PREROUTING -i br-guest ! -d 192.168.2.100  -p udp -m udp --dport 53  -m comment --comment "!fw3: Mark DNAT" -j MARK --set-xmark 0x3/0xff

Is there a way I can coax my system into only using SNAT/MASQ for the traffic that hits the DNAT rule without resorting to custom iptables ? Preferably compatible with LuCI so I can use GUI to update/modify rules.

My understanding is that by the time packet hits br-lan postrouting chain destination has already been changed so I can't just cram ! 192.168.2.100 in the MASQ rule ?

Does pihole has to be on the same network (br-lan)? Because if it's on another network then it will send the DNS traffic via the OpenWrt router which will translate the source address back to the address expected by the client.

2 Likes

Hmm the return path without masq is: 192.168.2.100 -> 192.168.1.1 -> 192.168.1.10 ( br-lan ) -> 172.30.10.x (br-guest / wifi ).

I thought that was enough to "un-DNAT" but it did not seem to work without MASQ. Now I disable the MASQ and device ( roku hard coding 8.8.8.8 and failing with "no network" ) appears to be working. Perhaps what was really wrong is I had gorfed something in the FILTER chain.

BTW -- also just noticed that you have to press "save" in custom tab after every "save and apply" so that MASQ was even worse than I thought.

Thanks for help. Will mark as solution until/unless I can reproduce an actual problem.

In case you aren't 100% satisfied with your current setup, heres an alternate approach that should work.

I have DNS redirect working using the following in the firewall config:

config redirect
        option name 'Redirect-DNS'
        option target 'DNAT'
        option src 'lan'
        option src_ip '!10.0.0.1'
        option dest_port '53'
        option src_dport '53'
        list proto 'tcp'
        list proto 'udp'

This redirects all port 53 DNS traffic back to the router (whose IP is 10.0.0.1), where a local DNS resolver (unbound in my case) picks up those DNS requests and resolves them. When this redirect is active I havent had any applications complain of "getting a response from the wrong server". , Id guess because I dont redirect to a different IP, i just redirect to the router (which is where the DNS request was initially going anyways).

For your use case, if you set up a locally running (on the router) DNS stub resolver whose only forwarding source was the pihole at 192.168.2.100, I believe that this type of redirect would work.

Compared to directly redirecting DNS to another device on your local network, this has the disadvantage of requiring a DNS stub resolver running on the router (though it can be a lightweight one). This method has the advantage though that you dont need to do anything complicated like masquerading or custom iptables rules to get devices to not complain about getting a response from the wrong server. It also helps keep different zones separated a little better since instead of forwarding DNS queries between zones your local DNS resolver on the router can directly serve DNS requests from multiple zones.

drop the pihole for adguardhome and run that directly on the router. simplifies your routing

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