X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=systems%2Feldiron%2Fdns.nix;h=7645b69494261501914de5d40f80e977234104a8;hb=97787a9dd8b136c8dc327fab42aedf2aa1109ec0;hp=486fcc1ad4aa49dfac69d5afc5840048c40cc0b2;hpb=450e0db1a1ad900f93519c00f0ef132ec42a3728;p=perso%2FImmae%2FConfig%2FNix.git diff --git a/systems/eldiron/dns.nix b/systems/eldiron/dns.nix index 486fcc1..7645b69 100644 --- a/systems/eldiron/dns.nix +++ b/systems/eldiron/dns.nix @@ -1,4 +1,18 @@ { lib, pkgs, config, dns-nix, ... }: +let + zonesWithDNSSec = lib.filterAttrs (k: v: v.dnssec.enable) config.myServices.dns.zones; + zoneToFile = name: v: pkgs.runCommand "${name}.zone" { + text = v; + passAsFile = [ "text" ]; + # Automatically change the increment when relevant change + # happened (both serial and mta-sts) + } '' + mv "$textPath" $out + increment=$(( 100*($(date -u +%-H) * 60 + $(date -u +%-M))/1440 )) + sed -i -e "s/2022121902/$(date -u +%Y%m%d)$increment/g" $out + sed -i -e "s/20200109150200Z/$(date -u +%Y%m%d%H%M%SZ)/g" $out + ''; +in { options.myServices.dns = { enable = lib.mkEnableOption "enable DNS resolver"; @@ -11,7 +25,10 @@ servers = config.myEnv.servers; ips = i: { A = i.ip4; AAAA = i.ip6; }; letsencrypt = [ { tag = "issue"; value = "letsencrypt.org"; issuerCritical = false; } ]; - toKV = a: builtins.concatStringsSep ";" (builtins.attrValues (builtins.mapAttrs (n: v: "${n}=${v}") a)); + toKV = a: let + removeOrder = n: lib.last (builtins.split "__" n); + in + builtins.concatStringsSep ";" (builtins.attrValues (builtins.mapAttrs (n: v: "${removeOrder n}=${v}") a)); mailMX = { hasEmail = true; subdomains = let @@ -24,10 +41,10 @@ SOA = { # yyyymmdd?? (increment ?? at each change) serial = 2022121902; # Don't change this value, it is replaced automatically! - refresh = 10800; - retry = 3600; - expire = 604800; - minimum = 10800; # negative cache ttl + refresh = 3*60*60; + retry = 60*60; + expire = 14*24*60*60; + minimum = 3*60*60; # negative cache ttl adminEmail = "hostmaster@immae.eu"; #email-address s/@/./ nameServer = "ns1.immae.eu."; }; @@ -42,7 +59,7 @@ (toKV config.myEnv.mail.dkim.immae_eu.public) ]; }; - mailCommon = name: { + mailCommon = name: quarantine: { MX = let mxes = lib.filterAttrs (n: v: v ? mx && v.mx.enable) servers; in @@ -65,16 +82,17 @@ # MTA-STS # https://blog.delouw.ch/2018/12/16/using-mta-sts-to-enhance-email-transport-security-and-privacy/ # https://support.google.com/a/answer/9261504 - _mta-sts.TXT = [ (toKV { v = "STSv1"; id = "20200109150200Z"; }) ]; # Don't change this value, it is updated automatically! - _tls.subdomains._smtp.TXT = [ (toKV { v = "TLSRPTv1"; "rua" = "mailto:postmaster+mta-sts@immae.eu"; }) ]; + _mta-sts.TXT = [ (toKV { _00__v = "STSv1"; id = "20200109150200Z"; }) ]; # Don't change this value, it is updated automatically! + _tls.subdomains._smtp.TXT = [ (toKV { _00__v = "TLSRPTv1"; rua = "mailto:postmaster+mta-sts@immae.eu"; }) ]; mta-sts = ips servers.eldiron.ips.main; # DMARC - _dmarc.TXT = [ (toKV { v = "DMARC1"; p = "none"; adkim = "r"; aspf = "r"; fo = "1"; rua = "mailto:postmaster+rua@immae.eu"; ruf = "mailto:postmaster+ruf@immae.eu"; }) ]; + # p needs to be the first tag + _dmarc.TXT = [ (toKV { _00__v = "DMARC1"; _01__p = if quarantine then "quarantine" else "none"; adkim = "s"; aspf = "s"; fo = "1"; rua = "mailto:postmaster+rua@immae.eu"; ruf = "mailto:postmaster+ruf@immae.eu"; }) ]; }; # SPF - TXT = [ (toKV { v = "spf1 mx ~all"; }) ]; + TXT = [ (toKV { _00__v = "spf1 mx ~all"; }) ]; }; }; }; @@ -83,6 +101,14 @@ dns-nix.lib.types.zone.getSubModules ++ [ ({ name, ... }: { options = { + dnssec = lib.mkOption { + default.enable = false; + type = lib.types.submodule { + options = { + enable = lib.mkEnableOption "Configure dnssec for this domain"; + }; + }; + }; hasEmail = lib.mkEnableOption "This domain has e-mails configuration"; emailPolicies = lib.mkOption { default = {}; @@ -154,12 +180,18 @@ zoneHeader (ips servers.eldiron.ips.main) { - ns = [ "immae" ]; + dnssec.enable = true; + ns = [ "immae" "raito" ]; CAA = letsencrypt; + extraConfig = '' + notify yes; + ''; + slaves = [ "raito" ]; } ]; "immae.dev" = lib.mkMerge [ { + dnssec.enable = true; extraConfig = '' notify yes; ''; @@ -174,6 +206,7 @@ ]; "immae.eu" = lib.mkMerge [ { + dnssec.enable = true; extraConfig = '' notify yes; ''; @@ -182,7 +215,10 @@ zoneHeader (ips servers.eldiron.ips.production) { - ns = [ "immae" "raito" ]; + ns = [ "immae" ]; + # Cannot put ns2.immae.eu as glue record as it takes ages to propagate. + # And gandi only accepts NS records with glues in their interface + NS = [ "kurisu.dual.lahfa.xyz." ]; CAA = letsencrypt; # ns1 has glue records in gandi.net @@ -194,9 +230,9 @@ { # Machines local users emailPolicies.localhost.receive = false; - subdomains.localhost = lib.mkMerge [ (mailCommon "immae.eu") mailSend ]; + subdomains.localhost = lib.mkMerge [ (mailCommon "immae.eu" true) mailSend ]; emailPolicies.eldiron.receive = true; - subdomains.eldiron = lib.mkMerge [ (mailCommon "immae.eu") mailSend ]; + subdomains.eldiron = lib.mkMerge [ (mailCommon "immae.eu" true) mailSend ]; } { # For each server "server" and each server ip group "ipgroup", @@ -248,23 +284,24 @@ zones = builtins.mapAttrs (name: v: { master = true; - extraConfig = v.extraConfig; + extraConfig = v.extraConfig + lib.optionalString v.dnssec.enable '' + key-directory "/var/lib/named/dnssec_keys"; + dnssec-policy default; + inline-signing yes; + ''; masters = []; slaves = lib.flatten (map (n: builtins.attrValues config.myEnv.dns.ns.${n}) v.slaves); - file = pkgs.runCommand "${name}.zone" { - text = v; - passAsFile = [ "text" ]; - # Automatically change the increment when relevant change - # happened (both serial and mta-sts) - } '' - mv "$textPath" $out - increment=$(( 100*($(date -u +%-H) * 60 + $(date -u +%-M))/1440 )) - sed -i -e "s/2022121902/$(date -u +%Y%m%d)$increment/g" $out - sed -i -e "s/20200109150200Z/$(date -u +%Y%m%d%H%M%SZ)/g" $out - ''; + file = if v.dnssec.enable then "/var/run/named/dnssec-${name}.zone" else zoneToFile name v; }) config.myServices.dns.zones; }; + systemd.services.bind.serviceConfig.StateDirectory = "named"; + systemd.services.bind.preStart = lib.mkAfter + (builtins.concatStringsSep "\n" (lib.mapAttrsToList (name: v: '' + install -m444 ${zoneToFile name v} /var/run/named/dnssec-${name}.zone + '') zonesWithDNSSec) + '' + install -dm755 -o named /var/lib/named/dnssec_keys + ''); myServices.monitoring.fromMasterActivatedPlugins = [ "dns" ]; myServices.monitoring.fromMasterObjects.service = lib.mkMerge (lib.mapAttrsToList (name: z: lib.optional (builtins.elem "immae" z.ns) { @@ -276,14 +313,34 @@ servicegroups = "webstatus-dns"; _webstatus_name = name; } ++ - lib.optional (builtins.elem "raito" z.ns) { - service_description = "raito dns is active and authoritative for ${name}"; + lib.optionals (builtins.elem "raito" z.ns) [ + { + service_description = "raito dns is active and authoritative for ${name}"; + host_name = config.hostEnv.fqdn; + use = "dns-service"; + check_command = ["check_external_dns" "kurisu.dual.lahfa.xyz" name "-A"]; + + servicegroups = "webstatus-dns"; + _webstatus_name = "${name} (Secondary DNS Raito)"; + } + { + service_description = "raito dns is up to date for ${name}"; + host_name = config.hostEnv.fqdn; + use = "dns-service"; + check_command = ["check_dns_soa" "kurisu.dual.lahfa.xyz" name config.hostEnv.fqdn]; + + servicegroups = "webstatus-dns"; + _webstatus_name = "${name} (Secondary DNS Raito up to date)"; + } + ] ++ + lib.optional z.dnssec.enable { + service_description = "DNSSEC is active and not expired for ${name}"; host_name = config.hostEnv.fqdn; use = "dns-service"; - check_command = ["check_external_dns" "kurisu.dual.lahfa.xyz" name "-A"]; + check_command = ["check_dnssec" name]; servicegroups = "webstatus-dns"; - _webstatus_name = "${name} (Secondary DNS Raito)"; + _webstatus_name = "${name} (DNSSEC)"; } ) config.myServices.dns.zones); };