the bridge resolver answers other record types for its own names locally instead of waiting on an upstream
This commit is contained in:
parent
4876acd02a
commit
89bbeb9757
3 changed files with 48 additions and 13 deletions
|
|
@ -127,7 +127,15 @@ when it runs authelia, and `hive-collector.hive` on every hive
|
||||||
is reachable, and where the hive's own collector listens). Note forge and
|
is reachable, and where the hive's own collector listens). Note forge and
|
||||||
matrix are swarm-domain names, not sub-domains of `<hive-domain>`: a swarm
|
matrix are swarm-domain names, not sub-domains of `<hive-domain>`: a swarm
|
||||||
runs one forge and one homeserver, so their names belong to the swarm rather
|
runs one forge and one homeserver, so their names belong to the swarm rather
|
||||||
than to whichever hive happens to host them. dnsmasq forwards everything else to the host's
|
than to whichever hive happens to host them.
|
||||||
|
|
||||||
|
Every domain answered this way is also `local=` for dnsmasq, so the other
|
||||||
|
record types (AAAA, TXT, MX, HTTPS) for those names get an empty answer from
|
||||||
|
dnsmasq itself instead of waiting on the host's upstream resolver. Without it,
|
||||||
|
dnsmasq 2.86 and later send them upstream, and a host whose upstream doesn't
|
||||||
|
answer leaves each lookup to its client's own timeout.
|
||||||
|
|
||||||
|
dnsmasq forwards everything else to the host's
|
||||||
own resolvers: it runs on the host and reads the host's
|
own resolvers: it runs on the host and reads the host's
|
||||||
`/etc/resolv.conf` directly. Containers don't need to know the
|
`/etc/resolv.conf` directly. Containers don't need to know the
|
||||||
upstream — they query the bridge IP and dnsmasq does the right thing
|
upstream — they query the bridge IP and dnsmasq does the right thing
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,11 @@
|
||||||
networkCfg,
|
networkCfg,
|
||||||
hyperhiveDomain,
|
hyperhiveDomain,
|
||||||
}:
|
}:
|
||||||
|
let
|
||||||
|
# The domains this resolver answers itself: the hive domain and every
|
||||||
|
# name a module contributed.
|
||||||
|
localDomains = lib.optional (hyperhiveDomain != null) hyperhiveDomain ++ lib.unique cfg.localNames;
|
||||||
|
in
|
||||||
{
|
{
|
||||||
enable = true;
|
enable = true;
|
||||||
# ON for its *plumbing*, not for the address it publishes.
|
# ON for its *plumbing*, not for the address it publishes.
|
||||||
|
|
@ -52,18 +57,25 @@
|
||||||
# Hive authoritative records — answer queries for the hive domain
|
# Hive authoritative records — answer queries for the hive domain
|
||||||
# + its sub-domains with the bridge IP, where nginx is reachable
|
# + its sub-domains with the bridge IP, where nginx is reachable
|
||||||
# from every container netns.
|
# from every container netns.
|
||||||
address =
|
#
|
||||||
lib.optional (hyperhiveDomain != null) "/${hyperhiveDomain}/${networkCfg.bridgeIp}"
|
# Names contributed by the modules that own them
|
||||||
# Names contributed by the modules that own them
|
# (`gateway.localNames`) get the same address — the bridge IP is the
|
||||||
# (`gateway.localNames`). Same address as everything above — the
|
# gateway's answer for anything it fronts, and a contributing module
|
||||||
# bridge IP is the gateway's answer for anything it fronts, and a
|
# neither knows nor should know it.
|
||||||
# contributing module neither knows nor should know it.
|
#
|
||||||
#
|
# `unique` is not tidiness: two modules claiming one name would
|
||||||
# `unique` is not tidiness: two modules claiming one name would
|
# otherwise emit two `address=` rules for it, and dnsmasq resolves
|
||||||
# otherwise emit two `address=` rules for it, and dnsmasq resolves
|
# that by precedence rather than by complaining. An assertion in
|
||||||
# that by precedence rather than by complaining. An assertion in
|
# ./default.nix makes the collision loud instead.
|
||||||
# ./default.nix makes the collision loud instead.
|
address = map (name: "/${name}/${networkCfg.bridgeIp}") localDomains;
|
||||||
++ map (name: "/${name}/${networkCfg.bridgeIp}") (lib.unique cfg.localNames);
|
# Every domain above is also `local=`. Since 2.86 an `address=` rule
|
||||||
|
# answers only the queries of its own address family and sends the rest
|
||||||
|
# upstream, so an AAAA query for a name answered with an IPv4 address
|
||||||
|
# waits on the host's upstream resolver, and a host with none that
|
||||||
|
# answers (no network) leaves the client to its own timeout. `local=`
|
||||||
|
# with the same domain keeps those queries here: the A answer is
|
||||||
|
# unchanged and the other types get an empty answer.
|
||||||
|
local = map (name: "/${name}/") localDomains;
|
||||||
# DHCP pool covering all usable host addresses on the bridge
|
# DHCP pool covering all usable host addresses on the bridge
|
||||||
# subnet — bounds computed by hive-network.nix from
|
# subnet — bounds computed by hive-network.nix from
|
||||||
# bridgeIp/bridgePrefixLength. All containers (agents and service
|
# bridgeIp/bridgePrefixLength. All containers (agents and service
|
||||||
|
|
|
||||||
|
|
@ -364,6 +364,21 @@ let
|
||||||
&& allLocal.services.hyperhive.otel.collector.host == "hive-collector.hive"
|
&& allLocal.services.hyperhive.otel.collector.host == "hive-collector.hive"
|
||||||
&& lib.elem "/hive-collector.hive/${bridge}" allLocal.services.dnsmasq.settings.address;
|
&& lib.elem "/hive-collector.hive/${bridge}" allLocal.services.dnsmasq.settings.address;
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
# An `address=` rule alone sends the other record types upstream
|
||||||
|
# (dnsmasq 2.86), so each of its domains is also `local=`, and no other
|
||||||
|
# domain is: `local=` on a domain with public records would hide them.
|
||||||
|
name = "the resolver keeps queries for every domain it answers itself, and only those, off the upstream";
|
||||||
|
ok =
|
||||||
|
let
|
||||||
|
s = allLocal.services.dnsmasq.settings;
|
||||||
|
domain = rule: builtins.elemAt (lib.splitString "/" rule) 1;
|
||||||
|
answered = map domain s.address;
|
||||||
|
in
|
||||||
|
lib.elem "hive-collector.hive" answered
|
||||||
|
&& map domain (s.local or [ ]) == answered
|
||||||
|
&& lib.all (rule: lib.hasSuffix "/" rule) (s.local or [ ]);
|
||||||
|
}
|
||||||
{
|
{
|
||||||
# The absence arm, and what makes the agents' queue address cases above able
|
# The absence arm, and what makes the agents' queue address cases above able
|
||||||
# to fail.
|
# to fail.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue