You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The pi.hole special name (and the local <hostname>) resolves to a locally derived address. With one address per family this is unambiguous, but on a multi-homed interface the selection is arbitrary, and since #2989 added the inbound DoT/DoH server it now differs between plain and encrypted transports. This issue tracks giving both transports one consistent, usable policy.
A dummy interface with several addresses per family (host-only /32 and /128, plus shared /30 and /100 subnets):
sudo ip link add dummy0 type dummy && sudo ip link set dummy0 up
sudo ip addr add 192.168.100.10/32 dev dummy0
sudo ip addr add 192.168.100.11/32 dev dummy0
sudo ip addr add 192.168.101.1/30 dev dummy0
sudo ip addr add 192.168.101.2/30 dev dummy0
sudo ip -6 addr add 2001:db8:100::10/128 dev dummy0
sudo ip -6 addr add 2001:db8:100::11/128 dev dummy0
sudo ip -6 addr add 2001:db8:101::1/100 dev dummy0
sudo ip -6 addr add 2001:db8:101::2/100 dev dummy0
Current behavior
Plain DNS (port 53): every query, regardless of source address or family, is answered with the firstmost address in enumeration (here 192.168.100.10 for A, 2001:db8:101::2 for AAAA).
Same family as the transport: answered with the exact address the client connected to (usable, correct).
Cross family: previously returned the loopback (127.0.0.1/::1), which is plain wrong. Mitigated in 2c370df to return NODATA instead - safe, but a stopgap.
So the record hands out different answers over plain vs. encrypted DNS, and over plain DNS an address the client may not be able to reach.
Options (apply to both transports)
firstmost address only - current plain behavior; simple and predictable-ish, but a magic pick that may be unusable.
all addresses of the interface - simple, includes the usable ones (plus possibly unusable ones).
the exact connected address only - only when the family matches; known usable (current encrypted same-family behavior).
all addresses matching the client's subnet - only when the family matches; most likely to be usable.
all addresses of the same scope (IPv6) - ULA/LL/GUA relative to the connected address; effectively a broader subnet match.
Limitations
Cross-family queries are fundamentally under-informed: we do not know the client's address in the other family. A database lookup would be same-segment only and unreliable, so it is not worth it.
Returning the loopback is wrong (already fixed for the encrypted path).
Returning nothing cross-family hurts discoverability - no client expects to have to query both families.
Same family: return the addresses on the arriving interface that match the client's subnet - least arbitrary, most likely usable.
Cross family: return all of that family's addresses on the arriving interface rather than a single magic pick - gives the client fallbacks, and any leakage is bounded to the one interface the query arrived on.
The static, non-localized dns.reply.host.force4/force6 (and friends) keep overriding everything and stay positive, as today.
The encrypted-path loopback -> NODATA mitigation already shipped in #2989 (2c370df) as a stopgap; this issue is about replacing the arbitrary firstmost/magic selection with a consistent, subnet-aware policy across both transports.
Background
The
pi.holespecial name (and the local<hostname>) resolves to a locally derived address. With one address per family this is unambiguous, but on a multi-homed interface the selection is arbitrary, and since #2989 added the inbound DoT/DoH server it now differs between plain and encrypted transports. This issue tracks giving both transports one consistent, usable policy.Surfaced by @darkexplosiveqwx while reviewing #2989; the investigation below is theirs. Full write-up: #2989 (comment)
Reproducer
A dummy interface with several addresses per family (host-only
/32and/128, plus shared/30and/100subnets):Current behavior
192.168.100.10for A,2001:db8:101::2for AAAA).127.0.0.1/::1), which is plain wrong. Mitigated in 2c370df to return NODATA instead - safe, but a stopgap.So the record hands out different answers over plain vs. encrypted DNS, and over plain DNS an address the client may not be able to reach.
Options (apply to both transports)
Limitations
Proposal
Direction I agree with (per @darkexplosiveqwx's evaluation):
dns.reply.host.force4/force6(and friends) keep overriding everything and stay positive, as today.The encrypted-path loopback -> NODATA mitigation already shipped in #2989 (2c370df) as a stopgap; this issue is about replacing the arbitrary firstmost/magic selection with a consistent, subnet-aware policy across both transports.
References