[How-To-Updated 2021] Installing AdGuardHome on OpenWrt [Manual and opkg method]

hi,

a theoretical question pls:

current approach is to make AGH the primary DNS resolver and leave dnsmasq as local (DHCP/)DNS only by binding it to port 54 and setting AGH as its upstream server. so technically any client DNS request would go to AGH first then if it is a public request go to public DNS upstream via AGH filtered, or if it is a local query bounce back to dnsmasq (e.g. local DHCP clients PTR query).

to resolve the race condition if AGH using DoH which requires TLS which requires correct timestamp hence NTP sync should happen first, with a domain rule can be set to use a traditional DNS upstream provider, that's ok.

but this does not solve the problem when AGH is not available for whatever reason, e.g. if NTP sync happens at very early stage might AGH not started yet so will fail regardless the domain rule.

so my theoretical question is what if keep dnsmasq as primary resolver, use two upstream resolvers AGH and a public traditional one (non-DoH), and set strictorder on. AGH would be first upstream server, if it is up and running should do all the filtering magic, answer all queries as expected; if it is not then query the secondary public resolver?

There are TWO services here.

First is the Router DNS which is either provided as your upstream ISP via DHCP to the WAN or you fix it to a different service via my dns script.

Then there is the AGH DNS which uses encrypted DNS (be it DOH or otherwise) which is the upstream for your downstream LAN clients.

Dnsmasq becomes the downstream for BOTH these services (or it does now i fixed the split DNS issue.)
Using the router DNS (even it is the same DNS upstream) uses unencrypted dns. Thus NTP does not need the exclusion. It also avoids the race condition due to AGH starting later (or in the case of the opkg version, too early and thus failing to get network access)

Thanks. But your suggestion did not work. If I remove 127.0.0.1 in bind_hosts from /etc/adguardhome.yaml local DNS does not work:

root@router:/etc# uci set dhcp.@dnsmasq[0].noresolv="0"
root@router:/etc# uci commit dhcp
root@router:/etc# /etc/init.d/dnsmasq restart
root@router:/etc# nslookup www.google.com
nslookup: write to '127.0.0.1': Connection refused
nslookup: write to '::1': Connection refused
;; connection timed out; no servers could be reached

My upstream DNS in AGH is NextDNS (tls://) and my WAN DNS is manually set to 1.1.1.1.

EDIT: the code snippet below from /etc/init.d/dnsmasq does set resolv.conf to 127.0.0.1 if localuse is greater than zero:

(...)
        [ "$localuse" -gt 0 ] && {
                rm -f /tmp/resolv.conf
                [ $ADD_LOCAL_DOMAIN -eq 1 ] && [ -n "$DOMAIN" ] && {
                        echo "search $DOMAIN" >> /tmp/resolv.conf
                }
                DNS_SERVERS="$DNS_SERVERS 127.0.0.1"
                [ -e /proc/sys/net/ipv6 ] && DNS_SERVERS="$DNS_SERVERS ::1"
                for DNS_SERVER in $DNS_SERVERS ; do
                        echo "nameserver $DNS_SERVER" >> /tmp/resolv.conf
                done
        }
(...)

yes i got that.

if i understand correctly you want to handle these two services in separate ways: for the lan clients announce AGH via DHCP (and use dnsmasq as PTR responder), and router to use non-DoH-kind public DNS resolver. is this correct?

my thought was to keep as little change from default config as possible: keep dnsmasq as is to handle LAN part, by default it will use "a" public upstream server anyhow (ISP provided or manually set), just add ADH as alternative upstream server with strictorder=on to prefer ADH. this way it would solve any race condition and would provider fallback in general if ADH is not working for any reason, i.e. the public upstream would be there as backup all the time.

it may never work of course, not sure if strict order option would stop at first answering nameserver or would use all nameservers, for example. it is just "loud" thinking :wink:

@mercygroundabyss, since we do not want OpenWrt's dnsmasq server pointing to AdGuard, why ADG Wiki is recommending the setting below?

uci add_list dhcp.@dnsmasq[0].server="${NET_ADDR}"

Since NET_ADDR will be replaced by OpenWrt's IP (192.168.1.1), it is telling dnsmasq to use AGH (192.168.1.1#53) as upstream server. According to this Wiki, the server option holds the "(...)List of DNS servers to forward requests to(...)".

Considering I have 1.1.1.1/1.0.0.1 as my WAN DNS servers, I just removed the server option from the config and the dnsmasq log seems OK:

Fri Jul  1 13:43:36 2022 daemon.info dnsmasq[1]: reading /tmp/resolv.conf.d/resolv.conf.auto
Fri Jul  1 13:43:36 2022 daemon.info dnsmasq[1]: using nameserver 1.1.1.1#53
Fri Jul  1 13:43:36 2022 daemon.info dnsmasq[1]: using nameserver 1.0.0.1#53
Fri Jul  1 13:43:36 2022 daemon.info dnsmasq[1]: using only locally-known addresses for test
Fri Jul  1 13:43:36 2022 daemon.info dnsmasq[1]: using only locally-known addresses for onion
Fri Jul  1 13:43:36 2022 daemon.info dnsmasq[1]: using only locally-known addresses for localhost
Fri Jul  1 13:43:36 2022 daemon.info dnsmasq[1]: using only locally-known addresses for local
Fri Jul  1 13:43:36 2022 daemon.info dnsmasq[1]: using only locally-known addresses for invalid
Fri Jul  1 13:43:36 2022 daemon.info dnsmasq[1]: using only locally-known addresses for bind
Fri Jul  1 13:43:36 2022 daemon.info dnsmasq[1]: using only locally-known addresses for home
Fri Jul  1 13:43:36 2022 daemon.info dnsmasq[1]: read /etc/hosts - 4 addresses
Fri Jul  1 13:43:36 2022 daemon.info dnsmasq[1]: read /tmp/hosts/dhcp.cfg01411c - 19 addresses
Fri Jul  1 13:43:36 2022 daemon.info dnsmasq-dhcp[1]: read /etc/ethers - 0 addresses

So OpenWrt's dnsmasq server is running on port 54 and using WAN's DNS servers (1.1.1.1/1.0.0.10 as upstream servers as expected. To me it seems that the uci add_list dhcp.@dnsmasq[0].server="${NET_ADDR}" configuration is not needed or even wrong (since it could cause a loop between dnsmasq and AGH).

On another topic: even with dnsmasq correctly configured (as above), per my (non-conclusive) investigations OpenWrt name resolution will always use /etc/resolv.conf (regardless of dhcp/dnsmasq configs) which points by default to 127.0.0.1#53 (AGH), which only works after adding 127.0.0.1 to bind_hosts section in /etc/adguardhome.yaml.

My initial conclusion is that OpenWrt is in fact using AGH for name resolution (via /etc/resolv.conf), and dnsmasq is not looping back to AGH (per log above).

So at least in my configurations I changed the following recommendations from Wiki:

  • I am not setting uci add_list dhcp.@dnsmasq[0].server="${NET_ADDR}"
  • I am adding 127.0.0.1 to bind_hosts section in /etc/adguardhome.yaml.

For now life is good and I will call it a day.

1 Like

because you missed part of the config.

The code is thus.

uci set dhcp.@dnsmasq[0].port="54"
uci -q delete dhcp.@dnsmasq[0].server
uci add_list dhcp.@dnsmasq[0].server="${NET_ADDR}"

We are telling dnsmasq that is is on ${NET_ADDR} at port 54.

That is what i was trying to avoid by enabling split dns and thus telling dnsmasq to ignore the resolve file. However i should have also enabled the localuse option as well.

i suggest you use dig and check the chain for your setup to see what answers and from where.

1 Like

Correct. Its a surgical insertion of AGH to move dnsmasq to local resolution only (for DHCP). This could be replaced totally if AGH took over DHCP.

I'll refer you to this post on dnsmasq

https://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2009q3/003295.html

but the relevent bit i'll quote here.

You will see that the actual server used for any query is quite random.
There's a strong assumption in the design that all the available servers
are equivalent and will give the same answers, but that some may be slow
or unavailable. If different servers know different answers, it's
necessary to direct queries to the correct server with the
server=/domain/ syntax.

And this is the issue.

  • AGH as an upstream IS filtering/denying requests in order to block adverts and provide filtering.
  • Dnsmasq's upstream is not.

Thus you have two different servers providing different responses. The way around this would be to use a filtering DNS service for BOTH upstreams that would reply the same. But then we loose the control of our filters. But failing back to dnsmasq also means no filtering or adblocking. While we have dns it is still not a desirable position to be in. Admittedly no DNS at all is worse but its a "fix me. I'm broken." rather than a silent fail like no filtering (which could take time to get noticed).

I do see what you are asking. You are pondering on proper failover for a downed/not started service. Which is why as a rule you usually have 2 or more DNS servers listed.

The real answer for this is improving AGH's startup phase. Ideally as soon as networking is available we should start DNS services. Reloading the service on changes (like WAN becoming available / getting DHCP). However as I have noticed, it appears that different routers arrive at different boot stages at different times. I suspect this is why they bumped AGH down in its start position. 26 for the opkg version certainly seems too early, but 95 is too late as it misses the NTP updates. But dsouza found that 95 was still too early and is trying 99 now. Some trial and error is required.

looks strict order option is not exactly what man implies ... anyway thanks for the detailed answer.

1 Like

Im still finding the my r4s looses time after a reboot/power cut. but then openwrt cant get the time

I changed the below as I thought this made openwrt avoid using adgaurd?

After some investigations I concluded that what you did is actually the right approach. Let me try to explain:

  1. /etc/resolv.conf will always point to 127.0.0.1 when dnsmasq is installed and enabled in OpenWrt. Since it is not possible to specify a port number in /etc/resolv.conf, OpenWrt itself will always use ADG as resolver (not ideal but OK if AGH filters are configured per wiki instructions to bypass ntp name resolving)

  2. The configuration you did is then the one I personally recommend. This way, in OpenWrt itself:

    a. For resolving local names: OpenWrt (via resolv.conf) -> AGH -> dnsmasq
    b. For resolving internet names: OpenWrt (via resolv.conf) -> AGH -> configured upstream DNS in AGH (except ntp domains which should use 1.1.1.1/1.0.0.1 as documented in Wiki)

Since AGH points back to dnsmasq for local name resolution (a), the configuration you mentioned in your post is the correct one to prevent a DNS loop (per my understanding). This way, if dnsmasq cannot resolve a local name (a) and for some reason it decides to send it upstream, it will forward to the its configured upstream servers (and not to AGH which would potentially cause a loop):

c) For resolving local names: (exception/corner case, not expected to happen in common cases): OpenWrt (via resolv.conf) -> AGH -> dnsmasq -> 1.1.1.1/1.0.01

This way I believe OpenWrt AGH wiki is wrong. The following recommended command below (in the wiki) should not be executed in my understanding:

(...)
uci -q delete dhcp.@dnsmasq[0].server
uci add_list dhcp.@dnsmasq[0].server="${NET_ADDR}"
(...)
uci commit dhcp
/etc/init.d/dnsmasq restart

It can potentially result in a DNS loop between AGH and dnsmasq. So what you proposed above is the right approach, being that the equivalent command lines (that should replace the ones above in OpenWrt AGH Wiki) would be:

(...)
uci -q delete dhcp.@dnsmasq[0].server
uci add_list dhcp.@dnsmasq[0].server='1.1.1.1'
uci add_list dhcp.@dnsmasq[0].server='1.0.0.1'
(...)
uci commit dhcp
/etc/init.d/dnsmasq restart
1 Like

cheers, yeah removing

[/pool.ntp.org/]1.1.1.1
[/pool.ntp.org/]1.0.0.1
[/pool.ntp.org/]2606:4700:4700::1111
[/pool.ntp.org/]2606:4700:4700::1001

from the adguard dns settings, openwrt can update ntp

You should leave these...

but with them there, if the router looses the time, it cant access the NTP to get current time

This is not expected. Do you have IPv6 connection? If not, try removing only the two lines below:

[/pool.ntp.org/]2606:4700:4700::1111
[/pool.ntp.org/]2606:4700:4700::1001

re-ddded the ipv4 ones, didnt work, removed the ipv4 ones, now that wont update

strangly computers on network can successfully update NTP time, its just the router that fails to

If i have the DNS set to 1.1.1.1 on open wrt, should I see the below logs


Try editing /etc/adguardhome.yaml and add 127.0.0.1 to bind_hosts section per below:

dns:
  bind_hosts:
  - 192.168.1.1
  - 127.0.0.1
  port: 53

After this restart AGH (service adguardhome restart) and try again.

/etc/adguardhome.yaml

isnt a existing file?

Yes, it is AGH configuration file. It is created as part of AGH installation (at least I can confirm that the opkg install creates it).

I think the non opkg is different

The .yaml file is the standard AGH configuration file (see https://github.com/AdguardTeam/AdGuardHome/wiki/Configuration).

Check /opt/AdGuardHome/AdGuardHome.yaml

Anyway @mercygroundabyss can confirm the location of the .yaml file for manual installs.