Most guides to installing AdGuard Home (AGH) on OpenWRT move dnsmasq aside to a port other than :53 (which has the side effect of disabling the DHCP dns-server option), run AGH on :53, then configure AGH to forward local names to dnsmasq at its new home, and finally configure dnsmasq to forcibly advertise the dns-server via DHCP to reverse the side effect above.
This works fine right up until you upgrade, when the AGH package is not installed yet. It also is a little inflexible (for example you may not want/need adblocking from all devices on the network or the openwrt host itself).
Switching things around, with dnsmasq up front and AGH following on, is also fragile in that DNS will still break when AGH's not installed (and you won't be able to install it, as you won't be able to resolve the openwrt package servers! Yes, trivially fixable but annoying nonetheless). And you also lose the AGH per-client config/reporting as everything to AGH is coming via dnsmasq/localhost.
Below is an arrangement that essentially makes AGH "optional", leaving the dnsmasq config operating independently of AGH for localhost. In my case I have AGH enabled for one VLAN with the others unfiltered.
The general approach is to:
- create a dummy interface (akin to loopback), excluded from dnsmasq
- run AGH on that
- configure dnsmasq to deliver the dummy's IP as the DHCP DNS server, for the VLANs you want to use AGH on by default
- clients can easily opt-out by using the router's regular interface address
1 - dummy interface
- pick any unused IP address in your network, I've used 192.168.254.254/32 and fd00::254:254/128; can be bigger than a /32 (/128) if you have grander plans
apk add kmod-dummy
echo 'options dummy numdummies=1' >> /etc/modules.conf
echo '/etc/modules.conf' >> /etc/sysupgrade.conf
uci set network.dummy=interface
uci set network.dummy.proto='static'
uci set network.dummy.device='dummy0'
uci set network.dummy.ipaddr='192.168.254.254/32'
uci set network.dummy.ip6addr='fd00::254:254/128'
uci commit network
/etc/init.d/network restart
optional, give it a name (note, can't create both v4+v6 via LuCI, UI only supports one address?):
cat <<EOF >> /etc/hosts
192.168.254.254 agh
fd00::254:254 agh
EOF
- tell dnsmasq to ignore the dummy interface:
uci add_list dhcp.@dnsmasq[0].notinterface='dummy'
uci commit dhcp
/etc/init.d/dnsmasq restart
2 - configure AGH
- in
/etc/adguardhome/adguardhome.yaml, setbind_hoststo be only the above dummy IP address(es), e.g.
dns:
bind_hosts:
- 192.168.254.254
- fd00::254:254
port: 53
- configure AGH's upstream servers to whatever you want to use for Internet names, and localhost for your local domain and unqualified names:
tls://dns.google
[/home/]127.0.0.1
[//]127.0.0.1
-
(re)start it:
service adguardhome restart -
verify you have both dnsmasq and AGH running, each to their own interfaces, and AGH's working:
# netstat -plan | grep ':53.*LISTEN'
tcp 0 0 192.168.1.1:53 0.0.0.0:* LISTEN 5195/dnsmasq
tcp 0 0 192.168.254.254:53 0.0.0.0:* LISTEN 5160/AdGuardHome
...
tcp 0 0 127.0.0.1:53 0.0.0.0:* LISTEN 5195/dnsmasq
...
tcp 0 0 ::1:53 :::* LISTEN 5195/dnsmasq
tcp 0 0 fd00::254:254:53 :::* LISTEN 5160/AdGuardHome
...
# nslookup google.com agh
Server: agh
Address: 192.168.254.254:53
Non-authoritative answer:
Name: google.com
Address: 172.217.25.174
Non-authoritative answer:
Name: google.com
Address: 2404:6800:4006:806::200e
3 - tell dnsmasq to deliver AGH as the DNS server via DHCP on your desired interfaces:
uci add_list dhcp.lan.dhcp_option="6,192.168.254.254"
uci commit dhcp
/etc/init.d/dnsmasq restart
4 - test it
on macos, check the DNS server provided via DHCP:
% ipconfig getpacket en0 | grep domain_name_server
domain_name_server (ip_mult): {192.168.254.254}
% nslookup google.com agh
Server: agh
Address: 192.168.254.254#53
Non-authoritative answer:
Name: google.com
Address: 172.217.25.174
- aside: two DNS name lookups happen in the above: the first for
aghagainst the system resolver (in turn, AGH and then dnsmasq) (A and AAAA; if you don't have an IPv6 configured for the dummy, you'll get a delay whilst macos runs through the search list to try and resolve it); the second is for google.com to AGH

