DNS hijacking with firewall - multible resolvers & IP's, questions

Hi and cheers for offering your two cents.

I have set up 2 DNS resolvers, one filtered and one unfiltered, having the unfiltered one act as upstream DNS for the filtered one.

Now I'm trying to get Firewall(4) based DNS hijacking to work but can't seem to figure it out.

  • I want every DNS request to be redirected to the ad blocking/filtered one
  • Except for requests addressed to any of the IPs the unfiltered resolver is listening on
  • For monitoring purposes, I want the source addresses of the redirected requests to stay intact, as in I don't want it to look like they came from the router

I can't wrap my head around how to achieve this, even tho to my understanding it should be "easily" achievable with a firewall.

Lets examine "default" DNAT hijack rule(s)

      chain dstnat_lan {
                udp dport 53 counter redirect to :53 comment "!fw4: Intercept-DNS"
                tcp dport 53 counter redirect to :53 comment "!fw4: Intercept-DNS"
        }

Now we need to modify those to log accesses

      chain dstnat_lan {
                tcp dport 53 counter log redirect to :53 comment "!fw4: Intercept-DNS"
                udp dport 53 counter log redirect to :53 comment "!fw4: Intercept-DNS"
        }

And exclude and still log "unfiltered" servers (example with cloudflare)

      chain dstnat_lan {
                ip daddr {1.1.1.1,1.1.1.2/31,1.0.0.1,1.0.0.2/31} meta l4proto {tcp,udp} th dport 53 counter log accepr
                tcp dport 53 counter log redirect to :53 comment "!fw4: Intercept-DNS"
                udp dport 53 counter log redirect to :53 comment "!fw4: Intercept-DNS"
        }

If not obvious either can be saved as /etc/nftabled.d/*.nft to be prepended to respective chain.

Cheers!

Guess my mistake was trying to achieve this with uci.

You can link simple rules with fwmark or ctmark but you get less efficient lengthy ruleset.

Netmask in CIDR annotation?

Do you know any good NFT tutorials?
Always felt like one step above my pay grade, but guess its time to dig in and get aquinted.

Uplearning (see test cases):
https://wiki.nftables.org/wiki-nftables/index.php/Supported_features_compared_to_xtables
Hooks:
https://wiki.nftables.org/wiki-nftables/index.php/Netfilter_hooks

Helps to do nft list ruleset on openwrt, fedora, ubuntu to learn how large scale rule conversion looks in the end.

nft -c -d netlink -f ruleset.nft
nft -c -o -f ruleset.nft

1 Like

I assume the star means give it a name and not save it named star, seems obvious but though I double-check.

Use whatever name.nft , see /usr/share/firewall4/templates/ruleset.uc for source.
Just rename file ro whatever name.nft_DISABLE and its off.

1 Like

Well, guess I stuffed up ...
No more DNS resolution at all.

What did I do: I deleted the custom port forwarding rules I had made in LUCI.
Read around in the NFT wiki.
Then I created the file below ...

cat /etc/nftables.d/intercept-DNS-and-redirect.nft :

chain dstnat_lan {
#		ip6 daddr {fd19:172:16:1::1, fd19:172:16:20::1} meta l4proto {tcp,udp} th dport 53 counter log accepr
        ip daddr {172.16.1.1,172.16.1.2/31, 172.16.20.1,172.16.20.2/31} meta l4proto {tcp,udp} th dport 53 counter log accepr
        tcp dport 53 counter log redirect to :53 comment "!fw4: Intercept-DNS"
        udp dport 53 counter log redirect to :53 comment "!fw4: Intercept-DNS"
        }

Where did I mess up?

s/accepr/accept/2

?

Replace accepr with s/accepr/accept/2 ?

replace my wrong typing accepR with correct accepT

1 Like

Haha well dam, guess I could have spotted that but assumed that's a command ..

Anyways it's still not working how it should - so sorry to pester you again!
As in, I set the DNS on my laptop to 1.1.1.1, general dns resolution is working, but none of my requests show up in the query log of the dnsCrypt( unfiltered) instance running on the router.
Nor does the resolution of my custom local domain work, provided by dnsmasq running on port 54 only forwarded to for rDNS lookups and for requests regarding the local domain.

If I change the forward to point to the adGuard container running in a mac-vLAN, dns breaks completely again.

chain dstnat_lan {
#		ip6 daddr {fd19:172:16:1::1, fd19:172:16:20::1} meta l4proto {tcp,udp} th dport 53 counter log accept
        ip daddr {172.16.1.1,172.16.1.2/31, 172.16.20.1,172.16.20.2/31} meta l4proto {tcp,udp} th dport 53 counter log accept
        tcp dport 53 counter log redirect to 172.16.20.10:53 comment "!fw4: Intercept-DNS"
        udp dport 53 counter log redirect to 172.16.20.10:53 comment "!fw4: Intercept-DNS"
        }

I understood -> direct all to filtered instance except when directly configuring peremit unfiltered.
This bypasses your unfiltered dnscrypt, should appear on filtered one.

1 Like

Yup but AdGuard is configured to use dnsCrypt as upstream so everything will show up in its query log eventually, well except if answered from the cache or filtered by a block list.

Which would mean everything can resolve my custom local domain, evertying can eaysily be configured to use or don't use the filtered DNS but also everything going outside of my network will use encrypted privacy concious lookups through dnsCrypt, and sneaky AdBlock avoiding stuff gets cought to.

But also allows to directly configure the unfiltered dns resolver to bypass filtering, in case a user wants or needs that.

Anyways I'll look at it again tomorrow, gotta go to work in ~8h, and I'm currently way too tired to think properly.

PS: thank you so much for your help so far and for ur patience.
Cheers Mate

The first list would bypass adguard completely, and for second original IP will be logged on OpenWRT doing DNAT, while adguard on other machine will get all requests from same IP.

Is there a way to redirect to adGuard without making it look like all the requests come from the router?

As in, change the mac to the router but leave the source ip intact or something like that.
I like the privacy this generates but at least while testing the setup and preferably if need I like the ability to see what each client is up to.

Otherwise, that's the exact setup I want.
It's currently not working at all, but I'm only on lunch break, so don't have time to tinker with it.

For the clients who'll actually use it: https://openwrt.org/docs/guide-user/base-system/dhcp_configuration#dhcp_options option 6.

1 Like