aboutsummaryrefslogtreecommitdiff
path: root/systems/eldiron/dns.nix
diff options
context:
space:
mode:
Diffstat (limited to 'systems/eldiron/dns.nix')
-rw-r--r--systems/eldiron/dns.nix117
1 files changed, 87 insertions, 30 deletions
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 @@
1{ lib, pkgs, config, dns-nix, ... }: 1{ lib, pkgs, config, dns-nix, ... }:
2let
3 zonesWithDNSSec = lib.filterAttrs (k: v: v.dnssec.enable) config.myServices.dns.zones;
4 zoneToFile = name: v: pkgs.runCommand "${name}.zone" {
5 text = v;
6 passAsFile = [ "text" ];
7 # Automatically change the increment when relevant change
8 # happened (both serial and mta-sts)
9 } ''
10 mv "$textPath" $out
11 increment=$(( 100*($(date -u +%-H) * 60 + $(date -u +%-M))/1440 ))
12 sed -i -e "s/2022121902/$(date -u +%Y%m%d)$increment/g" $out
13 sed -i -e "s/20200109150200Z/$(date -u +%Y%m%d%H%M%SZ)/g" $out
14 '';
15in
2{ 16{
3 options.myServices.dns = { 17 options.myServices.dns = {
4 enable = lib.mkEnableOption "enable DNS resolver"; 18 enable = lib.mkEnableOption "enable DNS resolver";
@@ -11,7 +25,10 @@
11 servers = config.myEnv.servers; 25 servers = config.myEnv.servers;
12 ips = i: { A = i.ip4; AAAA = i.ip6; }; 26 ips = i: { A = i.ip4; AAAA = i.ip6; };
13 letsencrypt = [ { tag = "issue"; value = "letsencrypt.org"; issuerCritical = false; } ]; 27 letsencrypt = [ { tag = "issue"; value = "letsencrypt.org"; issuerCritical = false; } ];
14 toKV = a: builtins.concatStringsSep ";" (builtins.attrValues (builtins.mapAttrs (n: v: "${n}=${v}") a)); 28 toKV = a: let
29 removeOrder = n: lib.last (builtins.split "__" n);
30 in
31 builtins.concatStringsSep ";" (builtins.attrValues (builtins.mapAttrs (n: v: "${removeOrder n}=${v}") a));
15 mailMX = { 32 mailMX = {
16 hasEmail = true; 33 hasEmail = true;
17 subdomains = let 34 subdomains = let
@@ -24,10 +41,10 @@
24 SOA = { 41 SOA = {
25 # yyyymmdd?? (increment ?? at each change) 42 # yyyymmdd?? (increment ?? at each change)
26 serial = 2022121902; # Don't change this value, it is replaced automatically! 43 serial = 2022121902; # Don't change this value, it is replaced automatically!
27 refresh = 10800; 44 refresh = 3*60*60;
28 retry = 3600; 45 retry = 60*60;
29 expire = 604800; 46 expire = 14*24*60*60;
30 minimum = 10800; # negative cache ttl 47 minimum = 3*60*60; # negative cache ttl
31 adminEmail = "hostmaster@immae.eu"; #email-address s/@/./ 48 adminEmail = "hostmaster@immae.eu"; #email-address s/@/./
32 nameServer = "ns1.immae.eu."; 49 nameServer = "ns1.immae.eu.";
33 }; 50 };
@@ -42,7 +59,7 @@
42 (toKV config.myEnv.mail.dkim.immae_eu.public) 59 (toKV config.myEnv.mail.dkim.immae_eu.public)
43 ]; 60 ];
44 }; 61 };
45 mailCommon = name: { 62 mailCommon = name: quarantine: {
46 MX = let 63 MX = let
47 mxes = lib.filterAttrs (n: v: v ? mx && v.mx.enable) servers; 64 mxes = lib.filterAttrs (n: v: v ? mx && v.mx.enable) servers;
48 in 65 in
@@ -65,16 +82,17 @@
65 # MTA-STS 82 # MTA-STS
66 # https://blog.delouw.ch/2018/12/16/using-mta-sts-to-enhance-email-transport-security-and-privacy/ 83 # https://blog.delouw.ch/2018/12/16/using-mta-sts-to-enhance-email-transport-security-and-privacy/
67 # https://support.google.com/a/answer/9261504 84 # https://support.google.com/a/answer/9261504
68 _mta-sts.TXT = [ (toKV { v = "STSv1"; id = "20200109150200Z"; }) ]; # Don't change this value, it is updated automatically! 85 _mta-sts.TXT = [ (toKV { _00__v = "STSv1"; id = "20200109150200Z"; }) ]; # Don't change this value, it is updated automatically!
69 _tls.subdomains._smtp.TXT = [ (toKV { v = "TLSRPTv1"; "rua" = "mailto:postmaster+mta-sts@immae.eu"; }) ]; 86 _tls.subdomains._smtp.TXT = [ (toKV { _00__v = "TLSRPTv1"; rua = "mailto:postmaster+mta-sts@immae.eu"; }) ];
70 mta-sts = ips servers.eldiron.ips.main; 87 mta-sts = ips servers.eldiron.ips.main;
71 88
72 # DMARC 89 # DMARC
73 _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"; }) ]; 90 # p needs to be the first tag
91 _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"; }) ];
74 }; 92 };
75 93
76 # SPF 94 # SPF
77 TXT = [ (toKV { v = "spf1 mx ~all"; }) ]; 95 TXT = [ (toKV { _00__v = "spf1 mx ~all"; }) ];
78 }; 96 };
79 }; 97 };
80 }; 98 };
@@ -83,6 +101,14 @@
83 dns-nix.lib.types.zone.getSubModules ++ [ 101 dns-nix.lib.types.zone.getSubModules ++ [
84 ({ name, ... }: { 102 ({ name, ... }: {
85 options = { 103 options = {
104 dnssec = lib.mkOption {
105 default.enable = false;
106 type = lib.types.submodule {
107 options = {
108 enable = lib.mkEnableOption "Configure dnssec for this domain";
109 };
110 };
111 };
86 hasEmail = lib.mkEnableOption "This domain has e-mails configuration"; 112 hasEmail = lib.mkEnableOption "This domain has e-mails configuration";
87 emailPolicies = lib.mkOption { 113 emailPolicies = lib.mkOption {
88 default = {}; 114 default = {};
@@ -154,12 +180,18 @@
154 zoneHeader 180 zoneHeader
155 (ips servers.eldiron.ips.main) 181 (ips servers.eldiron.ips.main)
156 { 182 {
157 ns = [ "immae" ]; 183 dnssec.enable = true;
184 ns = [ "immae" "raito" ];
158 CAA = letsencrypt; 185 CAA = letsencrypt;
186 extraConfig = ''
187 notify yes;
188 '';
189 slaves = [ "raito" ];
159 } 190 }
160 ]; 191 ];
161 "immae.dev" = lib.mkMerge [ 192 "immae.dev" = lib.mkMerge [
162 { 193 {
194 dnssec.enable = true;
163 extraConfig = '' 195 extraConfig = ''
164 notify yes; 196 notify yes;
165 ''; 197 '';
@@ -174,6 +206,7 @@
174 ]; 206 ];
175 "immae.eu" = lib.mkMerge [ 207 "immae.eu" = lib.mkMerge [
176 { 208 {
209 dnssec.enable = true;
177 extraConfig = '' 210 extraConfig = ''
178 notify yes; 211 notify yes;
179 ''; 212 '';
@@ -182,7 +215,10 @@
182 zoneHeader 215 zoneHeader
183 (ips servers.eldiron.ips.production) 216 (ips servers.eldiron.ips.production)
184 { 217 {
185 ns = [ "immae" "raito" ]; 218 ns = [ "immae" ];
219 # Cannot put ns2.immae.eu as glue record as it takes ages to propagate.
220 # And gandi only accepts NS records with glues in their interface
221 NS = [ "kurisu.dual.lahfa.xyz." ];
186 CAA = letsencrypt; 222 CAA = letsencrypt;
187 223
188 # ns1 has glue records in gandi.net 224 # ns1 has glue records in gandi.net
@@ -194,9 +230,9 @@
194 { 230 {
195 # Machines local users 231 # Machines local users
196 emailPolicies.localhost.receive = false; 232 emailPolicies.localhost.receive = false;
197 subdomains.localhost = lib.mkMerge [ (mailCommon "immae.eu") mailSend ]; 233 subdomains.localhost = lib.mkMerge [ (mailCommon "immae.eu" true) mailSend ];
198 emailPolicies.eldiron.receive = true; 234 emailPolicies.eldiron.receive = true;
199 subdomains.eldiron = lib.mkMerge [ (mailCommon "immae.eu") mailSend ]; 235 subdomains.eldiron = lib.mkMerge [ (mailCommon "immae.eu" true) mailSend ];
200 } 236 }
201 { 237 {
202 # For each server "server" and each server ip group "ipgroup", 238 # For each server "server" and each server ip group "ipgroup",
@@ -248,23 +284,24 @@
248 zones = 284 zones =
249 builtins.mapAttrs (name: v: { 285 builtins.mapAttrs (name: v: {
250 master = true; 286 master = true;
251 extraConfig = v.extraConfig; 287 extraConfig = v.extraConfig + lib.optionalString v.dnssec.enable ''
288 key-directory "/var/lib/named/dnssec_keys";
289 dnssec-policy default;
290 inline-signing yes;
291 '';
252 masters = []; 292 masters = [];
253 slaves = 293 slaves =
254 lib.flatten (map (n: builtins.attrValues config.myEnv.dns.ns.${n}) v.slaves); 294 lib.flatten (map (n: builtins.attrValues config.myEnv.dns.ns.${n}) v.slaves);
255 file = pkgs.runCommand "${name}.zone" { 295 file = if v.dnssec.enable then "/var/run/named/dnssec-${name}.zone" else zoneToFile name v;
256 text = v;
257 passAsFile = [ "text" ];
258 # Automatically change the increment when relevant change
259 # happened (both serial and mta-sts)
260 } ''
261 mv "$textPath" $out
262 increment=$(( 100*($(date -u +%-H) * 60 + $(date -u +%-M))/1440 ))
263 sed -i -e "s/2022121902/$(date -u +%Y%m%d)$increment/g" $out
264 sed -i -e "s/20200109150200Z/$(date -u +%Y%m%d%H%M%SZ)/g" $out
265 '';
266 }) config.myServices.dns.zones; 296 }) config.myServices.dns.zones;
267 }; 297 };
298 systemd.services.bind.serviceConfig.StateDirectory = "named";
299 systemd.services.bind.preStart = lib.mkAfter
300 (builtins.concatStringsSep "\n" (lib.mapAttrsToList (name: v: ''
301 install -m444 ${zoneToFile name v} /var/run/named/dnssec-${name}.zone
302 '') zonesWithDNSSec) + ''
303 install -dm755 -o named /var/lib/named/dnssec_keys
304 '');
268 myServices.monitoring.fromMasterActivatedPlugins = [ "dns" ]; 305 myServices.monitoring.fromMasterActivatedPlugins = [ "dns" ];
269 myServices.monitoring.fromMasterObjects.service = lib.mkMerge (lib.mapAttrsToList (name: z: 306 myServices.monitoring.fromMasterObjects.service = lib.mkMerge (lib.mapAttrsToList (name: z:
270 lib.optional (builtins.elem "immae" z.ns) { 307 lib.optional (builtins.elem "immae" z.ns) {
@@ -276,14 +313,34 @@
276 servicegroups = "webstatus-dns"; 313 servicegroups = "webstatus-dns";
277 _webstatus_name = name; 314 _webstatus_name = name;
278 } ++ 315 } ++
279 lib.optional (builtins.elem "raito" z.ns) { 316 lib.optionals (builtins.elem "raito" z.ns) [
280 service_description = "raito dns is active and authoritative for ${name}"; 317 {
318 service_description = "raito dns is active and authoritative for ${name}";
319 host_name = config.hostEnv.fqdn;
320 use = "dns-service";
321 check_command = ["check_external_dns" "kurisu.dual.lahfa.xyz" name "-A"];
322
323 servicegroups = "webstatus-dns";
324 _webstatus_name = "${name} (Secondary DNS Raito)";
325 }
326 {
327 service_description = "raito dns is up to date for ${name}";
328 host_name = config.hostEnv.fqdn;
329 use = "dns-service";
330 check_command = ["check_dns_soa" "kurisu.dual.lahfa.xyz" name config.hostEnv.fqdn];
331
332 servicegroups = "webstatus-dns";
333 _webstatus_name = "${name} (Secondary DNS Raito up to date)";
334 }
335 ] ++
336 lib.optional z.dnssec.enable {
337 service_description = "DNSSEC is active and not expired for ${name}";
281 host_name = config.hostEnv.fqdn; 338 host_name = config.hostEnv.fqdn;
282 use = "dns-service"; 339 use = "dns-service";
283 check_command = ["check_external_dns" "kurisu.dual.lahfa.xyz" name "-A"]; 340 check_command = ["check_dnssec" name];
284 341
285 servicegroups = "webstatus-dns"; 342 servicegroups = "webstatus-dns";
286 _webstatus_name = "${name} (Secondary DNS Raito)"; 343 _webstatus_name = "${name} (DNSSEC)";
287 } 344 }
288 ) config.myServices.dns.zones); 345 ) config.myServices.dns.zones);
289 }; 346 };