Compare commits

..

No commits in common. "1eeb24a2e2c1e99914fbb666ff4b2fb1f2f23d78" and "20c8821823d10e47ea6dc438bcf80852364ebd93" have entirely different histories.

2 changed files with 214 additions and 250 deletions

View File

@ -1,182 +1,180 @@
{ hostName, config, lib, pkgs, self, ... }: { hostName, config, lib, pkgs, self, ... }:
let lib.mkIf config.site.hosts.${hostName}.services.dns.enable {
fqdn = "${hostName}.serv.zentralwerk.org"; services.bind =
# public servers (slaves)
publicNS = [ "ns.c3d2.de" "ns.spaceboyz.net" ];
in
{
options =
with lib;
let let
recordOpts = { fqdn = "${hostName}.serv.zentralwerk.org";
name = mkOption { # public servers (slaves)
description = "DNS label"; publicNS = [ "ns.c3d2.de" "ns.spaceboyz.net" ];
type = types.str; # allowed for zone-transfer
}; slaves = [
type = mkOption { # ns.c3d2.de
type = types.enum [ "A" "AAAA" "PTR" ]; "217.197.84.53" "2001:67c:1400:2240::a"
}; # ns.spaceboyz.net
data = mkOption { "172.22.24.4" "2a01:4f9:4b:39ec::4"
type = types.str; ];
}; # ip6.arpa aggregation size in CIDR bits
}; reverseZone6Size = 60;
zoneOpts = { serial =
name = mkOption { let
description = "DNS FQDN w/o trailing dot"; timestamp = toString self.lastModified;
type = types.str; datePkg = pkgs.runCommandLocal "date-${timestamp}" {} ''
}; date -d @${timestamp} +%Y%m%d%H > $out
ns = mkOption { '';
type = with types; listOf str; in
}; toString (import datePkg);
records = mkOption {
type = with types; listOf (submodule {
options = recordOpts;
});
};
};
in { staticZone = { name, ns, records }: {
site.dns.localZones = mkOption { inherit name;
type = with types; listOf (submodule { master = true;
options = zoneOpts; file = builtins.toFile "${name}.zone" ''
}); $ORIGIN ${name}.
}; $TTL 1h
};
config = { @ IN SOA ${fqdn}. astro.spaceboyz.net. (
site.dns.localZones = ${serial} ; serial
let 1h ; refresh
# ip6.arpa aggregation size in CIDR bits 1m ; retry
reverseZone6Size = 60; 2h ; expire
1m ; minimum
hosts4Records = hosts4:
builtins.attrValues (
builtins.mapAttrs (name: addr: {
inherit name;
type = "A";
data = addr;
}) hosts4
);
hosts6Records = hosts6:
builtins.attrValues (
builtins.mapAttrs (name: addr: {
inherit name;
type = "AAAA";
data = addr;
}) hosts6
);
# generate zones only for nets with hosts
namedNets = lib.filterAttrs (_: { hosts4, hosts6, dynamicDomain, ... }:
(hosts4 != [] && hosts6 != []) ||
dynamicDomain
) config.site.net;
# converts an IPv4 address to its reverse DNS form
ipv4ToReverse = ipv4:
builtins.concatStringsSep "." (
lib.reverseList (
builtins.filter builtins.isString (
builtins.split "\\." ipv4
)
) )
) + ".in-addr.arpa"; ${lib.concatMapStrings (ns: " IN NS ${ns}.\n") ns}
# `{ "1,0.0.127.in-addr.arpa" = "lo.core.zentralwerk.dn42"; }` ${lib.concatMapStrings ({ name, type, data }:
reverseHosts4 = builtins.foldl' (result: { hosts4, domainName, ... }: "${name} IN ${type} ${data}\n"
builtins.foldl' (result: host: result // { ) records}
"${ipv4ToReverse hosts4.${host}}" = "${host}.${domainName}"; '';
}) result (builtins.attrNames hosts4) };
) {} (builtins.attrValues namedNets);
# `[ "0.0.127.in-addr.arpa" ]` hosts4Records = hosts4:
reverseZones4 = builtins.attrNames ( builtins.attrValues (
builtins.foldl' (result: rname: builtins.mapAttrs (name: addr: {
let inherit name;
zone = builtins.head ( type = "A";
builtins.match "[[:digit:]]+\\.(.+)" rname data = addr;
); }) hosts4
in result // { );
"${zone}" = true; hosts6Records = hosts6:
} builtins.attrValues (
) {} (builtins.attrNames reverseHosts4) builtins.mapAttrs (name: addr: {
inherit name;
type = "AAAA";
data = addr;
}) hosts6
); );
# turns `::` into `0000:0000:0000:0000:0000:0000:0000:0000` # generate zones only for nets with hosts
expandIpv6 = ipv6: namedNets = lib.filterAttrs (_: { hosts4, hosts6, dynamicDomain, ... }:
if lib.hasPrefix "::" ipv6 (hosts4 != [] && hosts6 != []) ||
then expandIpv6 "0${ipv6}" dynamicDomain
) config.site.net;
else if lib.hasSuffix "::" ipv6 # converts an IPv4 address to its reverse DNS form
then expandIpv6 "${ipv6}0" ipv4ToReverse = ipv4:
builtins.concatStringsSep "." (
else let lib.reverseList (
words = builtins.filter builtins.isString ( builtins.filter builtins.isString (
builtins.split ":" ipv6 builtins.split "\\." ipv4
);
fillWordCount = 8 - builtins.length words;
fillWords = n:
if n >= 0
then [ "0000" ] ++ fillWords (n - 1)
else [];
words' = builtins.concatMap (word:
if word == ""
then fillWords fillWordCount
else [ word ]
) words;
leftPad = padding: target: s:
if builtins.stringLength s < target
then leftPad padding target "${padding}${s}"
else s;
words'' = map (leftPad "0" 4) words';
in
builtins.concatStringsSep ":" words'';
# turns `::1` into `1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa`
ipv6ToReverse = ipv6:
builtins.concatStringsSep "." (
lib.reverseList (
lib.stringToCharacters (
builtins.replaceStrings [":"] [""] (expandIpv6 ipv6)
)
) )
) + ".ip6.arpa";
# `{ dn42 = { "...ip6.arpa" = "lo.core.zentralwerk.dn42"; }; }`
reverseHosts6 = builtins.foldl' (result: net: lib.recursiveUpdate result (
builtins.mapAttrs (ctx: hosts:
builtins.foldl' (result: host:
let
domain =
if ctx == "dn42"
then namedNets.${net}.domainName
else if builtins.match "up.*" ctx != null
then "${net}.zentralwerk.org"
else throw "Invalid IPv6 context: ${ctx}";
in
lib.recursiveUpdate result {
"${ipv6ToReverse hosts.${host}}" = "${host}.${domain}";
}
) {} (builtins.attrNames hosts)
) namedNets.${net}.hosts6
)) {} (builtins.attrNames namedNets);
# `{ dn42 = [ "....ip6.arpa" ]; }`
reverseZones6 = builtins.mapAttrs (ctx: reverseHosts6ctx:
builtins.attrNames (
builtins.foldl' (result: rname: result // {
"${builtins.substring ((128 - reverseZone6Size) / 2) (72 - ((128 - reverseZone6Size) / 2)) rname}" = true;
}) {} (builtins.attrNames reverseHosts6ctx)
) )
) reverseHosts6; ) + ".in-addr.arpa";
in [ { # `{ "1,0.0.127.in-addr.arpa" = "lo.core.zentralwerk.dn42"; }`
reverseHosts4 = builtins.foldl' (result: { hosts4, domainName, ... }:
builtins.foldl' (result: host: result // {
"${ipv4ToReverse hosts4.${host}}" = "${host}.${domainName}";
}) result (builtins.attrNames hosts4)
) {} (builtins.attrValues namedNets);
# `[ "0.0.127.in-addr.arpa" ]`
reverseZones4 = builtins.attrNames (
builtins.foldl' (result: rname:
let
zone = builtins.head (
builtins.match "[[:digit:]]+\\.(.+)" rname
);
in result // {
"${zone}" = true;
}
) {} (builtins.attrNames reverseHosts4)
);
# turns `::` into `0000:0000:0000:0000:0000:0000:0000:0000`
expandIpv6 = ipv6:
if lib.hasPrefix "::" ipv6
then expandIpv6 "0${ipv6}"
else if lib.hasSuffix "::" ipv6
then expandIpv6 "${ipv6}0"
else let
words = builtins.filter builtins.isString (
builtins.split ":" ipv6
);
fillWordCount = 8 - builtins.length words;
fillWords = n:
if n >= 0
then [ "0000" ] ++ fillWords (n - 1)
else [];
words' = builtins.concatMap (word:
if word == ""
then fillWords fillWordCount
else [ word ]
) words;
leftPad = padding: target: s:
if builtins.stringLength s < target
then leftPad padding target "${padding}${s}"
else s;
words'' = map (leftPad "0" 4) words';
in
builtins.concatStringsSep ":" words'';
# turns `::1` into `1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa`
ipv6ToReverse = ipv6:
builtins.concatStringsSep "." (
lib.reverseList (
lib.stringToCharacters (
builtins.replaceStrings [":"] [""] (expandIpv6 ipv6)
)
)
) + ".ip6.arpa";
# `{ dn42 = { "...ip6.arpa" = "lo.core.zentralwerk.dn42"; }; }`
reverseHosts6 = builtins.foldl' (result: net: lib.recursiveUpdate result (
builtins.mapAttrs (ctx: hosts:
builtins.foldl' (result: host:
let
domain =
if ctx == "dn42"
then namedNets.${net}.domainName
else if builtins.match "up.*" ctx != null
then "${net}.zentralwerk.org"
else throw "Invalid IPv6 context: ${ctx}";
in
lib.recursiveUpdate result {
"${ipv6ToReverse hosts.${host}}" = "${host}.${domain}";
}
) {} (builtins.attrNames hosts)
) namedNets.${net}.hosts6
)) {} (builtins.attrNames namedNets);
# `{ dn42 = [ "....ip6.arpa" ]; }`
reverseZones6 = builtins.mapAttrs (ctx: reverseHosts6ctx:
builtins.attrNames (
builtins.foldl' (result: rname: result // {
"${builtins.substring ((128 - reverseZone6Size) / 2) (72 - ((128 - reverseZone6Size) / 2)) rname}" = true;
}) {} (builtins.attrNames reverseHosts6ctx)
)
) reverseHosts6;
in {
enable = true;
zones = [ (staticZone {
name = "zentralwerk.org"; name = "zentralwerk.org";
ns = publicNS; ns = publicNS;
records = []; records = [];
} { }) (staticZone {
name = "zentralwerk.dn42"; name = "zentralwerk.dn42";
ns = [ fqdn ]; ns = [ fqdn ];
records = [ { records = [ {
@ -184,7 +182,7 @@ in
type = "A"; type = "A";
data = config.site.net.serv.hosts4.ipa; data = config.site.net.serv.hosts4.ipa;
} ]; } ];
} { }) (staticZone {
name = "dyn.zentralwerk.org"; name = "dyn.zentralwerk.org";
ns = publicNS; ns = publicNS;
# TODO: implement dyndns # TODO: implement dyndns
@ -197,28 +195,28 @@ in
type = "A"; type = "A";
data = "24.134.252.105"; data = "24.134.252.105";
} ]; } ];
} ] ++ builtins.concatLists ( }) ] ++ builtins.concatLists (
builtins.attrValues ( builtins.attrValues (
builtins.mapAttrs (net: { dynamicDomain, hosts4, hosts6, ... }: [ builtins.mapAttrs (net: { dynamicDomain, hosts4, hosts6, ... }: [
(if dynamicDomain (if dynamicDomain
then throw "TODO" then throw "TODO"
else { else staticZone {
name = "${net}.zentralwerk.dn42"; name = "${net}.zentralwerk.dn42";
ns = [ fqdn ]; ns = [ fqdn ];
records = records =
hosts4Records hosts4 ++ hosts4Records hosts4 ++
lib.optionals (hosts6 ? dn42) (hosts6Records hosts6.dn42); lib.optionals (hosts6 ? dn42) (hosts6Records hosts6.dn42);
}) })
{ (staticZone {
name = "${net}.zentralwerk.org"; name = "${net}.zentralwerk.org";
ns = publicNS; ns = publicNS;
records = records =
lib.optionals (hosts6 ? up1) (hosts6Records hosts6.up1) ++ lib.optionals (hosts6 ? up1) (hosts6Records hosts6.up1) ++
lib.optionals (hosts6 ? up2) (hosts6Records hosts6.up2); lib.optionals (hosts6 ? up2) (hosts6Records hosts6.up2);
} })
]) namedNets ]) namedNets
) )
) ++ map (zone: { ) ++ map (zone: staticZone {
name = zone; name = zone;
ns = [ fqdn ]; ns = [ fqdn ];
records = records =
@ -234,7 +232,7 @@ in
); );
}) reverseZones4 }) reverseZones4
++ builtins.concatMap (ctx: ++ builtins.concatMap (ctx:
map (zone: { map (zone: staticZone {
name = zone; name = zone;
ns = ns =
if ctx == "dn42" if ctx == "dn42"
@ -253,51 +251,7 @@ in
); );
}) reverseZones6.${ctx} }) reverseZones6.${ctx}
) (builtins.attrNames reverseZones6); ) (builtins.attrNames reverseZones6);
};
services.bind = lib.mkIf config.site.hosts.${hostName}.services.dns.enable ( # TODO: dyn
let
serial =
let
timestamp = toString self.lastModified;
datePkg = pkgs.runCommandLocal "date-${timestamp}" {} ''
date -d @${timestamp} +%Y%m%d%H > $out
'';
in
toString (import datePkg);
generateZone = { name, ns, records }: {
inherit name;
master = true;
# allowed for zone-transfer
slaves = [
# ns.c3d2.de
"217.197.84.53" "2001:67c:1400:2240::a"
# ns.spaceboyz.net
"172.22.24.4" "2a01:4f9:4b:39ec::4"
];
file = builtins.toFile "${name}.zone" ''
$ORIGIN ${name}.
$TTL 1h
@ IN SOA ${fqdn}. astro.spaceboyz.net. (
${serial} ; serial
1h ; refresh
1m ; retry
2h ; expire
1m ; minimum
)
${lib.concatMapStrings (ns: " IN NS ${ns}.\n") ns}
${lib.concatMapStrings ({ name, type, data }:
"${name} IN ${type} ${data}\n"
) records}
'';
};
in {
enable = true;
zones = map generateZone config.site.dns.localZones;
});
# TODO: dyn
};
} }

View File

@ -39,18 +39,23 @@ lib.mkIf config.site.hosts.${hostName}.services.dnscache.enable {
insecure-lan-zones: yes insecure-lan-zones: yes
domain-insecure: "dn42" domain-insecure: "dn42"
domain-insecure: "10.in-addr.arpa" domain-insecure: "20.172.in-addr.arpa"
${lib.concatMapStrings (x: domain-insecure: "21.172.in-addr.arpa"
" domain-insecure: ${toString x}.172.in-addr.arpa\n" domain-insecure: "22.172.in-addr.arpa"
) [ domain-insecure: "99.22.172.in-addr.arpa"
16 17 18 19 domain-insecure: "23.172.in-addr.arpa"
20 21 22 23
24 25 26 27
28 29 30 31
]}
domain-insecure: "168.192.in-addr.arpa"
domain-insecure: "d.f.ip6.arpa" domain-insecure: "d.f.ip6.arpa"
domain-insecure: "ffdd" domain-insecure: "ffdd"
domain-insecure: "200.10.in-addr.arpa"
domain-insecure: "201.10.in-addr.arpa"
local-zone: "20.172.in-addr.arpa." nodefault
local-zone: "21.172.in-addr.arpa." nodefault
local-zone: "22.172.in-addr.arpa." nodefault
local-zone: "99.22.172.in-addr.arpa." nodefault
local-zone: "23.172.in-addr.arpa." nodefault
local-zone: "d.f.ip6.arpa." nodefault
local-zone: "200.10.in-addr.arpa." nodefault
local-zone: "201.10.in-addr.arpa." nodefault
forward-zone: forward-zone:
name: "." name: "."
@ -68,14 +73,37 @@ lib.mkIf config.site.hosts.${hostName}.services.dnscache.enable {
# Local networks # Local networks
${lib.concatMapStrings ({ name, ... }: '' forward-zone:
forward-zone: name: "zentralwerk.dn42"
name: "${name}" forward-host: "dns.serv.zentralwerk.org"
forward-host: "${config.site.net.serv.hosts4.dns}"
${lib.concatMapStrings (hosts6: forward-zone:
" forward-host: ${hosts6.dns}\n" name: "72.20.172.in-addr.arpa"
) (builtins.attrValues config.site.net.serv.hosts6)} forward-host: "dns.serv.zentralwerk.org"
'') config.site.dns.localZones}
forward-zone:
name: "73.20.172.in-addr.arpa"
forward-host: "dns.serv.zentralwerk.org"
forward-zone:
name: "74.20.172.in-addr.arpa"
forward-host: "dns.serv.zentralwerk.org"
forward-zone:
name: "75.20.172.in-addr.arpa"
forward-host: "dns.serv.zentralwerk.org"
forward-zone:
name: "76.20.172.in-addr.arpa"
forward-host: "dns.serv.zentralwerk.org"
forward-zone:
name: "77.20.172.in-addr.arpa"
forward-host: "dns.serv.zentralwerk.org"
forward-zone:
name: "0.0.5.0.2.d.3.c.4.2.0.0.3.2.d.f.ip6.arpa"
forward-host: "dns.serv.zentralwerk.org"
# C3D2 reverse # C3D2 reverse
@ -105,50 +133,32 @@ lib.mkIf config.site.hosts.${hostName}.services.dnscache.enable {
stub-zone: stub-zone:
name: "dn42" name: "dn42"
stub-prime: yes stub-prime: yes
stub-addr: 172.20.0.53
stub-addr: fd42:d42:d42:54::1
stub-addr: 172.23.0.53 stub-addr: 172.23.0.53
stub-addr: fd42:d42:d42:53::1
stub-zone: stub-zone:
name: "20.172.in-addr.arpa" name: "20.172.in-addr.arpa"
stub-prime: yes stub-prime: yes
stub-addr: 172.20.0.53
stub-addr: fd42:d42:d42:54::1
stub-addr: 172.23.0.53 stub-addr: 172.23.0.53
stub-addr: fd42:d42:d42:53::1
stub-zone: stub-zone:
name: "21.172.in-addr.arpa" name: "21.172.in-addr.arpa"
stub-prime: yes stub-prime: yes
stub-addr: 172.20.0.53
stub-addr: fd42:d42:d42:54::1
stub-addr: 172.23.0.53 stub-addr: 172.23.0.53
stub-addr: fd42:d42:d42:53::1
stub-zone: stub-zone:
name: "22.172.in-addr.arpa" name: "22.172.in-addr.arpa"
stub-prime: yes stub-prime: yes
stub-addr: 172.20.0.53
stub-addr: fd42:d42:d42:54::1
stub-addr: 172.23.0.53 stub-addr: 172.23.0.53
stub-addr: fd42:d42:d42:53::1
stub-zone: stub-zone:
name: "23.172.in-addr.arpa" name: "23.172.in-addr.arpa"
stub-prime: yes stub-prime: yes
stub-addr: 172.20.0.53
stub-addr: fd42:d42:d42:54::1
stub-addr: 172.23.0.53 stub-addr: 172.23.0.53
stub-addr: fd42:d42:d42:53::1
stub-zone: stub-zone:
name: "d.f.ip6.arpa" name: "d.f.ip6.arpa"
stub-prime: yes stub-prime: yes
stub-addr: 172.20.0.53
stub-addr: fd42:d42:d42:54::1
stub-addr: 172.23.0.53 stub-addr: 172.23.0.53
stub-addr: fd42:d42:d42:53::1
''; '';
}; };
} }