AdGuardHome
AdGuardHome copied to clipboard
DS requests don't respect domain-specific upstreams - this might result in giving out wrong IP addresses
Prerequisites
-
[X] I have checked the Wiki and Discussions and found no answer
-
[X] I have searched other issues and found no duplicates
-
[X] I want to report a bug and not ask a question or ask for help
-
[X] I have set up AdGuard Home correctly and configured clients to use it. (Use the Discussions for help with installing and configuring clients.)
Platform (OS and CPU architecture)
Linux, ARM64
Installation
Snapcraft
Setup
On one machine
AdGuard Home version
v0.108.0-b.53
Action
tl;dr:
Specifying an upstream for a specific domain only seems to work for A/AAAA records, other request, like DS, are forwarded to the global upstreams. This might be a security issue.
Long explanation:
AVM routers usually are reachable by fritz.box
, so an Adguard configuration would look like
[/fritz.box/]192.168.78.1
h3://dns.google/dns-query
https://dns11.quad9.net/dns-query
to forward requests for fritz.box
to the router, which then returns local addresses.
Recently someone registered a real fritz.box
domain:
$ host fritz.box. 8.8.8.8
Using domain server:
Name: 8.8.8.8
Address: 8.8.8.8#53
Aliases:
fritz.box is an alias for example.com.
example.com has address 93.184.216.34
example.com has IPv6 address 2606:2800:220:1:248:1893:25c8:1946
example.com mail is handled by 0 .
With the Adguard config given above, resolving fritz.box
now gives these global addresses. This is a security issue because nothing stops the owner of the fritz.box
domain from mimicking the AVM login page and start collecting credentials.
I can reproduce the problem with the MacOS resolver and Linux' systemd-resolved (when DNSSEC is enabled) but not with a simple host/dig call directly:
$ host fritz.box 192.168.78.58 # correct result
Using domain server:
Name: 192.168.78.58
Address: 192.168.78.58#53
Aliases:
fritz.box has address 192.168.78.1
fritz.box has IPv6 address fd00::4e37:12ff:febc:1b67
fritz.box has IPv6 address 2001:26e0:285:d500:3e37:12ff:febc:1b67
$ host -t ds fritz.box 192.168.78.58 # this goes to a global upstream
Using domain server:
Name: 192.168.78.58
Address: 192.168.78.58#53
Aliases:
fritz.box is an alias for example.com.
example.com has DS record 370 13 2 BE74359954660069D5C63D200C39F5603827D7DD02B56F120EE9F3A8 6764247C
$ host -t ds fritz.box 192.168.78.1 # as the router returns nothing for the request
Using domain server:
Name: 192.168.78.1
Address: 192.168.78.1#53
Aliases:
fritz.box has no DS record
$ ping -4n fritz.box # the OS resolver gets the global address instead of the local one
PING (93.184.216.34) 56(84) bytes of data.
64 bytes from 93.184.216.34: icmp_seq=1 ttl=55 time=106 ms
64 bytes from 93.184.216.34: icmp_seq=2 ttl=55 time=105 ms
^C
--- ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 105.320/105.685/106.050/0.365 ms
The DS request which is sent to the global upstreams
seems to break the restriction of fritz.box
to the the local upstream given in the configuration.
Expected result
Specifying an upstream for a specific domain should redirect all requests for the given domain to the given upstream.
Actual result
At least DS request don't respect the configured local upstream.
Additional information and/or screenshots
No response
i can´t reproduce it - maybe cause i use unbound ?
root@HomeNetDNS:~# host -t ds fritz.box 192.168.178.10
Using domain server:
Name: 192.168.178.10
Address: 192.168.178.10#53
Aliases:
fritz.box has no DS record
root@HomeNetDNS:~# host -t ds fritz.box 192.168.178.1
Using domain server:
Name: 192.168.178.1
Address: 192.168.178.1#53
Aliases:
fritz.box has no DS record
Ping is the same behaviour...
root@HomeNetDNS:~# ping -4n fritz.box
PING (93.184.216.34) 56(84) bytes of data.
64 bytes from 93.184.216.34: icmp_seq=1 ttl=53 time=107 ms
64 bytes from 93.184.216.34: icmp_seq=2 ttl=53 time=106 ms
64 bytes from 93.184.216.34: icmp_seq=3 ttl=53 time=105 ms
^C
--- ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 104.803/105.816/106.719/0.786 ms
@jkreileder, hello and apologies for the late response. We've pushed the edge
build, that fixes the behavior of TLD domain specifications. I suppose something like the following will work well in your case:
[/box/]192.168.78.1
[/fritz.box/]192.168.78.1
[/*.box/]#
h3://dns.google/dns-query
https://dns11.quad9.net/dns-query
Could you please try it?
@EugeneOne1 I've tried:
adguard-home v0.108.0-a.895+b9d5e5ba 6878 latest/edge ameshkov✓ -
with the suggested config and I'm still getting wrong results:
MacOS:
$ host pi5.fritz.box 192.168.78.58
Using domain server:
Name: 192.168.78.58
Address: 192.168.78.58#53
Aliases:
pi5.fritz.box has address 192.168.78.58
pi5.fritz.box has IPv6 address fd00::da3a:ddff:fea1:efa6
pi5.fritz.box has IPv6 address 2001:16e0:285:d500:da3a:ddff:fea1:efa6
$ ping pi5.fritz.box
PING pi5.fritz.box (45.76.93.104): 56 data bytes
Request timeout for icmp_seq 0
64 bytes from 45.76.93.104: icmp_seq=1 ttl=56 time=170.933 ms
So the resolver still doesn't get 192.168.78.58
.
Linux with systemd-resolved and DNSSEC enabled:
$ ping pi5.fritz.box
ping: pi5.fritz.box: Name or service not known
$ resolvectl query pi5.fritz.box
pi5.fritz.box: resolve call failed: DNSSEC validation failed: no-signature
And this in the logs:
2024-04-26T16:13:42.208218+02:00 pi5 systemd[1]: Started systemd-resolved.service - Network Name Resolution.
2024-04-26T16:13:42.211316+02:00 pi5 systemd-resolved[539]: DNSSEC validation failed for question fritz.box IN SOA: no-signature
2024-04-26T16:13:42.211328+02:00 pi5 systemd-resolved[539]: DNSSEC validation failed for question pi5.fritz.box IN DS: no-signature
2024-04-26T16:13:42.211336+02:00 pi5 systemd-resolved[539]: DNSSEC validation failed for question pi5.fritz.box IN SOA: no-signature
2024-04-26T16:13:42.211343+02:00 pi5 systemd-resolved[539]: DNSSEC validation failed for question pi5.fritz.box IN AAAA: no-signature
2024-04-26T16:13:42.211351+02:00 pi5 systemd-resolved[539]: DNSSEC validation failed for question pi5.fritz.box IN A: no-signature
@jkreileder, hello again. We've pushed another edge, since the previous one actually contains a bug with matching, sorry about that. Could you please check if the latest edge routes as intended?
@EugeneOne1 using v0.108.0-a.901+c05bce7a
and the configuration above, I'm still seeing DS request going to external servers.
A, AAAA and SOA correctly go to 192.168.78.1:
But DS doesn't:
So I'm still getting:
$ resolvectl query --cache=no fritz.box
fritz.box: resolve call failed: DNSSEC validation failed: no-signature
$ ping fritz.box
ping: fritz.box: Name or service not known
@jkreileder, the latest edge
build is actually v0.108.0-a.902+17c4eeb6
, it has just been uploaded to Snapstore, sorry for the delay.
@EugeneOne1 v0.108.0-a.902+17c4eeb6
does better but still not completely fine.
Using the config given above
[/box/]192.168.78.1
[/fritz.box/]192.168.78.1
[/*.box/]#
h3://dns.google/dns-query
https://dns11.quad9.net/dns-query
DS request for *.fritz.box
go to 192.168.78.1
now. But DS
requests for box
still go to external servers. So the first line of the config doesn't seem to work for DS
requests (removing the third line doesn't change anything) -- it does work for other request types.
Because of this resolved still shows DNSSEC errors:
$ resolvectl query --cache=no no.fritz.box
no.fritz.box: resolve call failed: DNSSEC validation failed: no-signature
@jkreileder, well, the thing is that according to RFC 4035 (See also #6156):
A DS RR SHOULD point to a DNSKEY RR that is present in the child's apex DNSKEY RRset, and the child's apex DNSKEY RRset SHOULD be signed by the corresponding private key.
So DS
requests are routed to the parent of the zone. So a DS
request for box
will be routed to the root zone, which is the default upstream set. As far as I can see, there is no way to both satisfy the RFC requirements and specify an upstream for resolving DS
requests for TLDs. Maybe we can add a dnsmasq-like trust-anchor mechanism for such cases, or support the DS
/DNSKEY
types in $dnsrewrite
rules, but DNSSEC is a pretty big topic.
Until then, I think you'll need some kind of proxy to redirect DS box.
requests to the appropriate server.
BTW, the [/*.box/]#
line should route all non *.fritz.box
(like DS abc.example.box
) requests to the default servers. Not sure if there is such requirement in your network.