Redirect Wrong-addressed DNS Requests to Pi-hole, but Save Their Identities - UBNT Edge Router Lite

The term “Hard-coded DNS Clients” refers to clients which always wrongly-code a DNS request, sending it to a hard coded value they know instead of a DHCP recommended value. However some client make both rightly and wrongly addressed DNS requests, so here the term “Wrongly-addressed DNS requests” is used instead.

There are a number of discussions and tutorials on this topic on Reddit, UBNT community, and elsewhere. The usual solution is to implement a DNAT/SNAT pair of rules to deflect the DNS packet from the undesired external DNS server (e.g. 8.8.8.8) to the desired pihole DNS server.

The problem with that usual solution is that, under certain circumstances, the wrongly addressed requests are conglomerated and recorded by pihole as coming from a single single address, the gateway, e.g. 192.168.1.1. Using the UBNT ERLite 3 router is one such circumstance.

This post discusses a configuration to let the pihole know the seperate identity of each wrong-addressed DNS client, so each such clients statistics can be displayed seperately. In addition, for each client the rightly-addressed and wrongly-addressed DNS queries are counted seperately.

Usual Solution


The usual solution, resulting in conglomeration of all wrongly-addressed DNS requests across all clients, is show here in two psuedo-code UBNT config command rules:

The first is a DNAT rule, transforming the destination address from the external DNS server address to the internal pihole DNS server address:

source destinatation prot/port new dest
not dnssrv not dnssrv udp/53 pihole

The second is an SNAT rule, transforming the source address from the client address to the gateway address, by way of the masquerade rule.

source destinatation prot/port new source
not dnssrv pihole udp/53 masquerade

where dnssrv is a group of DNS server addresses. (In case those addresses are not contiguous, see the Appendix at the end.) As a result of the above configuration, all the wrong-addressed DNS requests will show up under the gateway address, e.g. 192.168.1.1, and it won’t be clear whic client they actually came from.

Solution to enable separate statistics per DHCP client for wrongly-addressed DNS requests


“Why is the masquerade SNAT rule even necessary, considering it obscures the original source address of the packet?” Why the SNAT rule is necessary is boyond the scope of this post, but it is. However, the SNAT rule does not have to be a masquerade rule, and that fact allows the clients to be distinguished.

The method follows. To start with keep the DNAT rule from the previous but delete the SNAT rule, or change the SNAT rule number to 5999, because we are going to create other SNAT rules which need to have higher precedence.

Suppose a wrongly-adressed DHCP client has address 192.168.1.xx, where xx is in the range 10-50.

On the router we create an a new address:

user@ubnt sudo ip address add 192.168.1.1xx

Note: This is temporary and will not carry over after reboot. A permanet solution is dicussed later.

Then we create one new SNAT rule on the router. Here it shown as a psuedo config command rule. It transforms the source address from the client address 192.168.1.xx to the new router address 192.168.1.1xx , so we don’t use the masquerade rule.

source destinatation prot/port new source
192.168.1.xx pihole udp/53 192.168.1.1xx

In UBNT configuration commands it looks something like this,

set service nat rule 5111 description 'set pihole return 11'
set service nat rule 5111 destination address 192.168.1.20
set service nat rule 5111 destination port 53
set service nat rule 5111 log enable
set service nat rule 5111 outbound-interface eth1
set service nat rule 5111 outside-address address 192.168.1.111
set service nat rule 5111 protocol udp
set service nat rule 5111 source address 192.168.1.11
set service nat rule 5111 type source

where 192.168.1.11 is the device, 192.168.1.20 is the pihole, and 192.168.1.111 is the unique convenience address used which will be displayed by the pihole for DNS queries from 192.168.1.11 not using the correct DHCP advised DNS address.

You can test one device, and if works add the rest.

Permanence of address

Create an arbitrarily named file, e.g. “init.sh”, with content something like this:

sleep 3
for xx in 11 12 14 {30..34} 39; do
ip address add 1$xx dev eth1
done

Of course change the devices to your own.

Place the file on the router in

/config/scripts/post-config.d/init.sh

Rule script

Heres a script 1rule.sh to print out configure commands for one device on a workstation (not the router):

#!/bin/bash
Clin=$1
Pihole=$2

cat <<EOF
set service nat rule 51${Clin} description 'set pihole return ${Clin}'
set service nat rule 51${Clin} source address 192.168.1.${Clin}
set service nat rule 51${Clin} destination address ${Pihole}
set service nat rule 51${Clin} destination port 53
set service nat rule 51${Clin} log enable
set service nat rule 51${Clin} outbound-interface eth1
set service nat rule 51${Clin} outside-address address 192.168.1.1${Clin}
set service nat rule 51${Clin} protocol udp
set service nat rule 51${Clin} type source
EOF

Called for each device:

for xx in 11 12 14 {30..34} 39 ; do
./1rule.sh $xx 192.168.1.20
done > commands.txt

Then you can cut and paste “commands.txt” into a router ssh session in configure mode.

Discussion


Do you see any devices sending both rightly-addressed and wrongly-addressed DNS requests? It might be the case that this behavior is more likely when some rightly-addressed DNS requests are blocked by a filter such as pihole.

As far as the future goes, DoH (DNS over HTTPS) is already here. At least Cloudflare, Google, and Quad9 are all already offering some version of DoH. In the near future if not already, devices that want to DNS “their way” will just use DoH. Monitoring/analysis/blocking of device DNS requests over DoH will not be possible for pihole in it’s present form.

Do you think Pihole should respond to this change? How so?

Appendix: Implementation in Case the dnssrv group of addresses are not contiguous.


In the above tables dnssrv represents an address group consisting of internal DNS servers. This might be just the pihole, but it can be more, e.g.:

  • dnssrv address group members
    • pihole
    • other DNS servers, e.g. a “.home.lan” domain DNS server on the gateway
    • other DNS servers which forward to the pihole
    • clients to be excluded from the pihole regime, for test purposes or an angry human user, temporarily. This list just happens to be convenient for that.

When the addresses in dnssrv are not contiguous, a clean implementation is to use the UBNT exclude config command. Again in psuedo code for DNAT rule we get:

source destinatation prot/port new dest
dnssrv udp/53 exclude
dnssrv udp/53 exclude
local-clients pihole udp/53 masquerade

Local clients is e.g. 192.168.1.0/24.