How to add locally hosted DNS server while preserving default LAN DNS

dnsNetwork

My question is very similar to How do I add custom DNS server and preserving default DNS of ISP in OS X Mountain Lion however I am looking to filter and resolve all dns requests via my resolver, so adding a domain specific file to /etc/resolver/ won't work, unless there's a way to target all domains (https://serverfault.com/a/164215/203355 seems interesting but doesn't seem to work in my testing).

I don't want to use a hard-coded public dns as the upstream dns for my local resolver because I have a dnat rule on my local network to redirect all dns traffic to my pihole, however when this rule is in use, the traffic appears to the pihole to be from the router and messes up my analytics.

My current setup is:

dnsmasq has resolv-file=/etc/resolv.conf in its config so that it uses the DHCP provided dns as its upstream (after doing filtering).

I have a file /etc/resolver/root which contains this:

nameserver 127.0.0.1
domain .
search_order 1000

scutil --dns lists my 127.0.0.1 resolver (as #8), the order value is the lowest in the list, though resolver #1 (from dhcp) does not have an order value.

resolver #1
  nameserver[0] : 10.0.1.204
  if_index : 11 (en10)
  flags    : Request A records, Request AAAA records
  reach    : 0x00020002 (Reachable,Directly Reachable Address)
[...]
resolver #8
  nameserver[0] : 127.0.0.1
  flags    : Request A records, Request AAAA records
  reach    : 0x00030002 (Reachable,Local Address,Directly Reachable Address)
  order    : 1000

I don't know if unbound can use the DHCP provided dns server as an upstream any easier than dnsmasq but I could switch if that would be easier. Otherwise I'm just trying to configure the macOS resolver system to prioritize my local resolver.

Best Answer

I eventually devised this script to keep a separate resolv.conf file for dnsmasq that is updated on network changes.

#!/usr/local/bin/bash

mkfifo P
exec 3>P # open file descriptor 3 writing to the pipe
scutil < P | fgrep notification | \
    xargs -L 1 bash -c 'echo "nameserver $(ipconfig getoption $(route -n get default | fgrep interface | awk "{print \$2}") domain_name_server)" > /usr/local/etc/dnsmasq.d/resolv-dnsmasq.conf'
echo -e "n.add State:/Network/Global/IPv4\nn.watch" > P

I may need to add in a dnsmasq restart too, depending on testing results.