[Solved] User Guide: DNS hijacking

Hi!

While reading the DNS hijacking guide, I had a number of questions, which I would like to ask to get better understanding. Most of the questions stem from my ignorance of how things actually work under the hood.

This intercept rule:

# Intercept DNS traffic
uci -q delete firewall.dns_int
uci set firewall.dns_int="redirect"
uci set firewall.dns_int.name="Intercept-DNS"
uci set firewall.dns_int.src="lan"
uci set firewall.dns_int.src_dport="53"
uci set firewall.dns_int.proto="tcp udp"
uci set firewall.dns_int.family="any"
uci set firewall.dns_int.target="DNAT"
uci commit firewall
/etc/init.d/firewall restart

If a hardcoded DNS request (e.g. to 8.8.8.8) comes from any LAN client, what exactly does this rule do to it? If a DNS request from any LAN client is addressed to the router itself (e.g. to 192.168.1.1) - does the rule impact it, too? In both cases does the LAN client see DNS reply coming from 192.168.1.1?

If going away from the default OpenWrt configuration, and adding another network interface (e.g. Guest at 192.168.2.x) - will this require additional similar rule [to intercept requests from the Guest interface] or the rule above can be modified?

The extra lines:

# Configure firewall
uci set firewall.dns_int.src_mac="!11:22:33:44:55:66"
uci commit firewall
/etc/init.d/firewall restart

I assume this is the MAC address which shows up under the default LAN interface of the router? In which cases is this extra needed?

I would really appreciate if you could answer the questions above, or maybe direct me to an explanatory guide / post. Thanks!

hi,

imho it is easier to explain what is under the hood. the rule above creates similar rules:

chain dstnat_lan {
                meta nfproto ipv4 tcp dport 53 counter packets 0 bytes 0 redirect to :53 comment "!fw4: Intercept-DNS"
                meta nfproto ipv4 udp dport 53 counter packets 0 bytes 0 redirect to :53 comment "!fw4: Intercept-DNS"

# the important parts
(tcp dport 53) = a traffic which is using tcp/ip protocol and destination port is 53
(redirect to :53) = redirect to device's port 53

and the point is: whenever a client in lan zone tries to access a server via port 53 using tcp or udp protocol it gets redirected to the device's, device which runs the firewall, i.e. your router's port 53. where normally your own dns server sits with your preferable configuration.

so no matter what the client side DNS setting is, at the end it will use router's dns configuration.
by default router side dns is using upstream servers advertised by your ISP, but you can overwrite with your preference. you can test this firewall rule as per the guide https://openwrt.org/docs/guide-user/firewall/fw3_configurations/intercept_dns#testing

does this make sense to you?

and yes, if you have more zones, you should have similar rule for those zones as well in case of dns hijacking is needed.

be aware though that many smart device and modern browsers are using DNS-over-HTTP or DNS-over-TLS which are not captured by this rule as they are using different ports. and the big challenge with DoH for example as it is using a legit port, port 443 which is used for all HTTPS traffic by default you cannot hijack that. you'll need other solution. see the extra section of the guide.

hope this helps.

3 Likes

Thanks a lot for detailed reply! Indeed, looking at the rules above it is easier to see what is happening.

Do I understand correctly that with the rule 'Intercept-DNS' LAN clients will see DNS replies as if coming from their hardcoded DNS provider (but in reality these replies are served by the device)? I remember reading that some clients may get "offended" if receiving the reply from a different server. Or there is still some magic needs to be done to solve such situations?

Yes, that is the case. You can confirm on your clients by supplying a specific DNS server to, say, nslookup or dig and see that the response is "coming from" that server. Here's a Windows example where "Server:" indicates what it thinks is the responder:

$ nslookup google.com 8.8.8.8
Non-authoritative answer:
Server:  dns.google
Address:  8.8.8.8

Name:    google.com
Addresses:  2607:f8b0:4007:810::200e
          142.250.217.142

And one from ubuntu where you see "SERVER:" in the answer section:

$ dig @8.8.8.8 google.com

; <<>> DiG 9.16.1-Ubuntu <<>> @8.8.8.8 google.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 62804
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;google.com.                    IN      A

;; ANSWER SECTION:
google.com.             237     IN      A       142.250.68.46

;; Query time: 16 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Sat Oct 14 08:45:54 PDT 2023
;; MSG SIZE  rcvd: 55
2 Likes

Two pieces of information I have for you. Hopefully they may help
one is a dns leak test

the other is an EXCELLENT tutorial on guest networks

I hope this adds to the excellent advice you have already received from more experienced and knowledgeable people here

2 Likes

Thanks a lot for clarifying how to check this, too!

On a different topic, if one uses banIP to filter DoH requests, as suggested in the DNS hijacking guide and banIP guide:

# Block DoH
uci add_list banip.global.ban_feed="doh"
uci commit banip
service banip restart

Will this banIP rule cover all firewall zones, or just the lan zone?

Thanks for the link to this OneMarcFifty video! I found a number of his guides really useful for general understanding of OpenWrt.

In one of the videos, he actually recommended to watch this for a guide on nftables.

One technical question: how should the DNS intercept be amended to work for another zone (not lan)? The setup below ('dns_int_guest') currently leaves Guest zone without DNS.

network:

config interface 'lan'
	option proto 'static'
	option netmask '255.255.255.0'
	option delegate '0'
	option ipaddr '192.168.1.1'
	option device 'br-lan.11'

config interface 'GUEST'
	option proto 'static'
	option device 'br-lan.21'
	option ipaddr '192.168.2.1'
	option netmask '255.255.255.0'
	option delegate '0'

firewall:

config zone
	option name 'GuestZone'
	option input 'REJECT'
	option output 'ACCEPT'
	option forward 'ACCEPT'
	list network 'GUEST'

config forwarding
	option src 'GuestZone'
	option dest 'wan'

config rule
	option name '-Allow-DNS-DHCP-GuestZone'
	option src 'GuestZone'
	option dest_port '53 67 68'
	option target 'ACCEPT'
	list proto 'tcp'
	list proto 'udp'

config redirect 'dns_int_lan'
	option name 'Intercept-DNS-lan'
	option src 'lan'
	option src_dport '53'
	option proto 'tcp udp'
	option family 'any'
	option target 'DNAT'
	option src_mac '!11:22:33:44:55:66'

config redirect 'dns_int_guest'
	option name 'Intercept-DNS-guest'
	option src 'GuestZone'
	option src_dport '53'
	option proto 'tcp udp'
	option family 'any'
	option target 'DNAT'
	option src_mac '!11:22:33:44:55:66'

first glance it looks ok. what's your dhpc config file?

1 Like

Banip works by blocking IPs going to the wan zone, so if any of your clients attempt to contact those IPs, the packets are just dropped (or maybe rejected, I haven't looked at the specifics).

("drop" means toss the packet into the bit-bucket and don't tell anyone; "reject" means toss the packet, but send a response to the sender with something like "unreachable host" or whatever, so they can move on without waiting for a response timeout.)

2 Likes

dhcp:

config dnsmasq
	option domainneeded '1'
	option boguspriv '1'
	option filterwin2k '0'
	option localise_queries '1'
	option rebind_localhost '1'
	option local '/lan/'
	option domain 'lan'
	option expandhosts '1'
	option nonegcache '0'
	option authoritative '1'
	option readethers '1'
	option leasefile '/tmp/dhcp.leases'
	option resolvfile '/tmp/resolv.conf.d/resolv.conf.auto'
	option nonwildcard '1'
	option localservice '1'
	option ednspacket_max '1232'
	option noresolv '0'
	option cachesize '1000'
	option rebind_protection '0'
	option port '54'
	list server '192.168.1.1'

config dhcp 'lan'
	option interface 'lan'
	option start '100'
	option limit '150'
	option leasetime '12h'
	option dhcpv4 'server'
	list dhcp_option '6,192.168.1.1'
	option dhcpv6 'disabled'
	option ra 'disabled'

config dhcp 'wan'
	option interface 'wan'
	option ignore '1'

config odhcpd 'odhcpd'
	option maindhcp '0'
	option leasefile '/tmp/hosts/odhcpd'
	option leasetrigger '/usr/sbin/odhcpd-update'
	option loglevel '4'

config dhcp 'GUEST'
	option interface 'GUEST'
	option start '100'
	option limit '150'
	option leasetime '12h'
	list dhcp_option '6,192.168.1.1'

AGH yaml:

bind_host: 192.168.1.1
bind_port: 8080
beta_bind_port: 0
...
dns:
  bind_hosts:
    - 127.0.0.1
    - 192.168.1.1
  port: 53
  statistics_interval: 1
...
  use_private_ptr_resolvers: true
  local_ptr_upstreams:
    - 192.168.1.1:54
...

Actually, two changes made the DNS intercept work also for other (Guest) firewall zone:

dhcp change 'GUEST' config line:

...
	list dhcp_option '6,192.168.2.1'
...

AGH yaml add one more bind host:

...
dns:
  bind_hosts:
...
    - 192.168.2.1
...

oh, you did not mention you are using AGH, so, yes using bind_host should cover both your interface ip's.

so if you're problem solved maybe time to mark this thread resolved.

2 Likes

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