dns: switch to knot

This commit is contained in:
Sandro - 2024-04-21 18:17:41 +02:00
parent d7fdfd8aa6
commit 9b2b8250c4
Signed by: sandro
GPG Key ID: 3AF5A43A3EECC2E5
1 changed files with 145 additions and 90 deletions

View File

@ -5,7 +5,7 @@ let
generateZoneFile = let
util = dns-nix.util.${pkgs.system};
in { name, ns, records, ... }: util.writeZone name (with dns-nix.lib.combinators; {
in { name, ns, records, ... }: util.writeZone name {
TTL = 60*60;
SOA = {
nameServer = "${lib.dns.ns}.";
@ -20,7 +20,7 @@ let
subdomains = lib.foldl (a: b: lib.recursiveUpdate a b) { } (map ({ name, type, data }: {
${name}.${type} = [ data ];
}) records);
});
};
in
{
options =
@ -69,108 +69,163 @@ in
config = {
site.dns.localZones = lib.dns.localZones;
services.bind = lib.mkIf config.site.hosts.${hostName}.services.dns.enable (
services.knot = lib.mkIf config.site.hosts.${hostName}.services.dns.enable (
let
generateZone = zone@{ name, dynamic, ... }: {
inherit name;
master = true;
# allowed for zone-transfer
slaves = [
# ns.c3d2.de
"217.197.84.53" "2001:67c:1400:2240::a"
config.site.net.serv.hosts4.knot
config.site.net.serv.hosts6.dn42.knot
config.site.net.serv.hosts6.up4.knot
# ns.spaceboyz.net
"172.22.24.4" "2a01:4f9:4b:39ec::4"
# ns1.supersandro.de
"188.34.196.104" "2a01:4f8:1c1c:1d38::1"
];
file =
if dynamic
then "/var/db/bind/${name}.zone"
domain = name;
template = "zentralwerk";
acl = [ "zone_xfr" ] ++ lib.optional dynamic "dyndns";
file = if dynamic
then "/var/lib/knot/zones/${name}.zone"
else generateZoneFile zone;
extraConfig = ''
also-notify {
# ns.c3d2.de
217.197.84.53;
2001:67c:1400:2240::a;
${config.site.net.serv.hosts4.knot};
${config.site.net.serv.hosts6.dn42.knot};
${config.site.net.serv.hosts6.up4.knot};
# ns.spaceboyz.net
172.22.24.4;
95.217.229.209;
2a01:4f9:4b:39ec::4;
# ns1.supersandro.de
188.34.196.104;
2a01:4f8:1c1c:1d38::1;
};
notify-source ${config.site.net.serv.hosts4.dns};
notify-source-v6 ${config.site.net.serv.hosts6.up4.dns};
'' + lib.optionalString dynamic ''
allow-update { key "dyndns"; };
'';
notify = [ "all" ];
};
in {
enable = true;
zones = map generateZone config.site.dns.localZones;
settings = {
acl = [
{
id = "dyndns";
action = "update";
}
{
id = "zone_xfr";
address = with config.site.net.serv; [
# ns.c3d2.de
hosts4.knot hosts6.dn42.knot hosts6.up4.knot
# ns.spaceboyz.net
"172.22.24.4" "2a01:4f9:4b:39ec::4"
# ns1.supersandro.de
"188.34.196.104" "2a01:4f8:1c1c:1d38::1"
];
action = "transfer";
}
];
extraConfig = ''
key "dyndns" {
algorithm hmac-sha256;
secret "${config.site.dyndnsKey}";
key = [ {
id = "dyndns";
algorithm = "hmac-sha256";
secret = config.site.dyndnsKey;
} ];
log = [ {
target = "syslog";
any = "info";
} ];
mod-stats = [ {
id = "default";
query-type = "on";
} ];
remote = let
via = with config.site.net.serv; [ hosts4.dns hosts6.up4.dns ];
in [
{
id = "ns.c3d2.de";
address = with config.site.net.serv; [ hosts4.knot hosts6.dn42.knot hosts6.up4.knot ];
inherit via;
} {
id = "ns.spaceboyz.net";
address = [ "172.22.24.4" "2a01:4f9:4b:39ec::4" ];
inherit via;
} {
id = "ns1.supersandro.de";
address = [ "188.34.196.104" "2a01:4f8:1c1c:1d38::1" ];
inherit via;
}
];
remotes = [ {
id = "all";
remote = [ "ns.c3d2.de" "ns.spaceboyz.net" "ns1.supersandro.de" ];
} ];
server = {
answer-rotation = true;
automatic-acl = true;
identity = "dns.serv.zentralwerk.org";
tcp-fastopen = true;
version = null;
};
'';
extraOptions = ''
# allow underscores in dynamic hostnames
${lib.concatMapStringsSep "\n" (type: ''
check-names ${type} ignore;
'') [ "master" "slave" "response" ]}
'';
template = [
{
# default is a magic name and is always loaded.
# Because we want to use catalog-role/catalog-zone settings for all zones *except* the catalog zone itself, we must split the templates
id = "default";
global-module = [ "mod-stats" ];
}
{
id = "zentralwerk";
catalog-role = "member";
catalog-zone = "zentralwerk.";
dnssec-signing = true;
journal-content = "all"; # required for zonefile-load=difference-no-serial and makes cold starts like zone reloads
module = "mod-stats/default";
semantic-checks = true;
serial-policy = "dateserial";
storage = "/var/lib/knot/zones";
zonefile-load = "difference-no-serial";
}
];
zone = [
{
acl = "zone_xfr";
catalog-role = "generate";
domain = "zentralwerk.";
notify = [ "ns1.supersandro.de" ];
storage = "/var/lib/knot/catalog";
}
] ++ map generateZone config.site.dns.localZones;
};
});
systemd.services.create-dynamic-zones = {
description = "Creates dynamic zone files";
requiredBy = [ "bind.service" ];
before = [ "bind.service" ];
serviceConfig.Type = "oneshot";
script = ''
mkdir -p /var/db/bind
systemd.services = {
create-dynamic-zones = {
description = "Creates dynamic zone files";
requiredBy = [ "knot.service" ];
before = [ "knot.service" ];
serviceConfig.Type = "oneshot";
script = ''
mkdir -p /var/lib/knot/zones
${lib.concatMapStringsSep "\n" (zone@{ name, ... }: ''
[ -e /var/db/bind/${name}.zone ] || \
cp ${generateZoneFile zone} /var/db/bind/${name}.zone
chown -R named /var/db/bind
chmod -R u+rwX /var/db/bind
'') (
builtins.filter ({ dynamic, ... }: dynamic) config.site.dns.localZones
)}
'';
};
systemd.services.update-dynamic-zones = {
description = "Creates initial records in dynamic zone files";
requiredBy = [ "bind.service" ];
after = [ "bind.service" ];
serviceConfig.Type = "oneshot";
path = [ pkgs.dnsutils ];
script = ''
${lib.concatMapStrings (zone: ''
nsupdate -v -y "hmac-sha256:dyndns:${config.site.dyndnsKey}" <<EOF
server localhost
${lib.concatMapStringsSep "\n" (zone@{ name, ... }: ''
[ -e /var/lib/knot/zones/${name}.zone ] || \
cp ${generateZoneFile zone} /var/lib/knot/zones/${name}.zone
chown -R knot /var/lib/knot/zones
chmod -R u+rwX /var/lib/knot/zones
'') (
builtins.filter ({ dynamic, ... }: dynamic) config.site.dns.localZones
)}
'';
};
${lib.concatMapStringsSep "\n" ({ name, type, data }: ''
delete ${name}.${zone.name}. IN ${type}
add ${name}.${zone.name}. 3600 IN ${type} ${data}
'') zone.records}
update-dynamic-zones = {
description = "Creates initial records in dynamic zone files";
requiredBy = [ "knot.service" ];
after = [ "knot.service" ];
serviceConfig.Type = "oneshot";
path = [ pkgs.dnsutils ];
script = ''
${lib.concatMapStrings (zone: ''
nsupdate -v -y "hmac-sha256:dyndns:${config.site.dyndnsKey}" <<EOF
server localhost
send
EOF
'') (
builtins.filter ({ dynamic, ... }: dynamic) config.site.dns.localZones
)}
'';
${lib.concatMapStringsSep "\n" ({ name, type, data }: ''
delete ${name}.${zone.name}. IN ${type}
add ${name}.${zone.name}. 3600 IN ${type} ${data}
'') zone.records}
send
EOF
'') (
builtins.filter ({ dynamic, ... }: dynamic) config.site.dns.localZones
)}
'';
};
};
};
}