[Solved] DNS hijacking and VPN

Does Wireguard VPN tunnel set up on the router prevent the DNS hijacking (plain DNS, DoH with banIP, DoT) from working? Is it possible to have the best of the two: "in-house" DNS hijacking/interception and VPN on the same router? Just trying to understand at a high level, if these two can be combined, with hopefully not much of the effort / time invested :slight_smile: .

It shouldn't - especially since you can setup a direct WG interface to Cloudflare for the things you listed.

WG is no different than any other VPN solution in that regard - you just configure traffic, etc. on your device accordingly.

3 Likes

If you're curious enough, you could set it up and look at the generated ruleset. Once you've got DNS hijacking and WG running, run nft list ruleset and chase around to see if the rules for the hijacking occur in chains, rules or locations prior to them being NATted over into the WG tunnels or vice versa.

This would definitely violate "not much effort/time invested" :muscle:t3:, but you'd learn a lot and ultimately be sure things were working the way you expect.

1 Like

Thanks for advice - indeed good to know that this is possible before deep diving :slight_smile:

I looked into nft list ruleset, there are currently two inet tables - fw4 and banIP. Checking chains/rules in these tables against Netfilter hook priorities, it seems that DNS interception / blocking indeed happens before NATing into WG.

I assumed that NATing into WG is done by this base chain:

	chain srcnat {
		type nat hook postrouting priority srcnat; policy accept;
		oifname "wan" jump srcnat_wan comment "!fw4: Handle wan IPv4/IPv6 srcnat traffic"
		oifname "WGINTERFACE" jump srcnat_WgZone comment "!fw4: Handle WgZone IPv4/IPv6 srcnat traffic"

and this regular chain:

	chain srcnat_WgZone {
		meta nfproto ipv4 masquerade comment "!fw4: Masquerade IPv4 WgZone traffic"

both with [default] priorities 100. Is this correct?

  1. Plain DNS interception

This regular chain:

	chain dstnat_lan {
		tcp dport 53 ether saddr != 11:22:33:44:55:66 counter packets 154 bytes 8020 redirect to :53 comment "!fw4: Intercept-DNS-lan"
		udp dport 53 ether saddr != 11:22:33:44:55:66 counter packets 3655 bytes 256108 redirect to :53 comment "!fw4: Intercept-DNS-lan"

Its [default] priority -100, hence earlier than WG NATing?

  1. DoT DNS blocking

This chain:

	chain forward {
		type filter hook forward priority filter; policy drop;
		ct state established,related accept comment "!fw4: Allow forwarded established and related flows"
		tcp dport 853 counter packets 0 bytes 0 jump reject_to_wan comment "!fw4: -Deny-DoT"
		udp dport 853 counter packets 0 bytes 0 jump reject_to_wan comment "!fw4: -Deny-DoT"
		iifname "br-lan.11" jump forward_lan comment "!fw4: Handle lan IPv4/IPv6 forward traffic"
		iifname "wan" jump forward_wan comment "!fw4: Handle wan IPv4/IPv6 forward traffic"
		iifname "br-lan.21" jump forward_GuestZone comment "!fw4: Handle GuestZone IPv4/IPv6 forward traffic"
		iifname "WGINTERFACE" jump forward_WgZone comment "!fw4: Handle WgZone IPv4/IPv6 forward traffic"
		jump handle_reject
	}

and this chain:

	chain reject_to_wan {
		oifname "wan" counter packets 0 bytes 0 jump handle_reject comment "!fw4: reject wan IPv4/IPv6 traffic"
	}

Not sure about the priority of the chains above, but most likely lower than 100?

I also realised that I need DoT blocking not only for wan, but also for WGINTERFACE.

  1. DoH blocking

This is done by chains in banIP table, all of them with explicitly set priority -200. banIP chains (wan-input, wan-forward and lan-forward) currently do not seem to apply to WGINTERFACE. Seems like I will need to figure out how to apply the DoH blocking to WGINTERFACE in addition to wan.

If I may ask - am I missing something in the "analysis" above? Thanks.

(I'm still pre-coffee, so forgive anything stupid I say. :coffee:)

The priority is the ordering within a hook, with the hooks being the major traversal organizer, so maybe this one is a better map for navigating the terrain: https://upload.wikimedia.org/wikipedia/commons/3/37/Netfilter-packet-flow.svg

The postrouting hook sees stuff "almost" last, and srcnat = 100* priority is also highest = latest, so the srcnat stuff happens just before egress. The dstnat_lan chain occurs on the prerouting hook, so is pretty early in the processing, so it should be the case that your packets to port 53 get intercepted first.

(* - looks like you've already found the symbol -> number table for the priorities, anyone interested search 'srcnat' here for numeric priority values: https://www.netfilter.org/projects/nftables/manpage.html)

Using a simplified path through that wikipedia diagram, you need only consider a path that looks grossly like this for local client on the lan to remote client on the wan.

lan-packet -> prerouting -> forward -> postrouting -> output -> wan-packet

(No input as we assume this packet is being forwarded.)

WG is going to srcnat those lan packets at the end of the postrouting step, then off they go into space.

So, in your item 1, unless there's something on the WG interface to direct packets into that dstnat_lan (sub)chain, I don't think WG traffic will see it at all. Try this one and see if you find a "WGINTERFACE" jump in there:

$ nft list chain inet fw4 dstnat
table inet fw4 {
        chain dstnat {
                type nat hook prerouting priority dstnat; policy accept;
                iifname "br-lan" jump dstnat_lan comment "!fw4: Handle lan IPv4/IPv6 dstnat traffic"
                iifname "eth0" jump dstnat_wan comment "!fw4: Handle wan IPv4/IPv6 dstnat traffic"
        }
}

Yup, your item 2 should be intercepting all port 853 traffic since that checks priort to any interface-specific rules.

In item 3, if the banIP rules simply ignore interface names (i.e., no iifname or oifname clauses), then they're probably applied to all traffic and should "just work."


Circling around slightly...

You can test plain DNS interception pretty easily, and the DoH by-name blocking by trying to look up one of the well known DoH servers (I always use doh.dns.apple.com, as it is always on everyone's lists).

I did this on my router, where I can bypass the rules applied to the LAN. If you do it on a client, you should see both nslookups fail to resolve, so you could test it with WG off and WG on to see if there are differences.

$ nslookup doh.dns.apple.com
Server:         127.0.0.1
Address:        127.0.0.1:53

** server can't find doh.dns.apple.com: NXDOMAIN

# I'm on the router, so I can bypass my DoH blocking and actually get a result; gives NXDOMAIN on my clients:
$ nslookup doh.dns.apple.com 9.9.9.9
Server:         9.9.9.9
Address:        9.9.9.9:53

Non-authoritative answer:
doh.dns.apple.com       canonical name = doh.dns.apple.com.v.aaplimg.com
Name:   doh.dns.apple.com.v.aaplimg.com
Address: 17.253.82.113
blah blah blah...
1 Like

Lol, well said :slight_smile:

Thanks a lot for taking your time to explain the details!

I see I had a misconception about the priorities - thanks for pointing this out!

Re item 1 (simple DNS interception):

Indeed, there was no any jump to WGINTERFACE.

Yes, simple DNS interception is working for both wan and WGINTEFACE.

Item 2 assumed all good and did not test.

banIP rules have iifname and oifname clauses. So, for item 3, I added WGINTEFACE to banIP:

uci add_list banip.global.ban_ifv4="WGINTERFACE"
uci add_list banip.global.ban_dev="WGINTERFACE"
uci commit banip
service banip restart

banIP now lists:

And, yes, DoH blocking now works for WGINTERFACE, too.

Thanks a lot, once again!

Re this:

I still want to do some more tinkering. banIP blocks by IPs, not by names, so

nslookup doh.dns.apple.com

run on a client returned a good number of IPs, and not all of them are in banIP DoH blocklist.

Probably, will look to see if there are any filters to add to AGH.

1 Like

Yeah, that's a "whack-a-mole" issue. Apple (and many others) cycle through a big collection of IP address for their DNS servers. Do that nslookup now, wait 10 minutes and do it again, you'll get a few different hosts each time, which is why I run both an IP-based block on 443 and a dnsmasq-based name blocker (adblock + DoH list).

1 Like

Very insightful, thank you @efahl!

I will mark post #3, post #5 - stressing this one particularly, and post #7 as answers to my inquiry as each of them added to understanding.

1 Like

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