nixos/nsd: automatic DNSSEC using BIND toolset
This commit is contained in:
parent
089e0aaf72
commit
9826f5cc3c
|
@ -248,6 +248,46 @@ let
|
||||||
Use imports or pkgs.lib.readFile if you don't want this data in your config file.
|
Use imports or pkgs.lib.readFile if you don't want this data in your config file.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
dnssec = mkEnableOption "DNSSEC";
|
||||||
|
|
||||||
|
dnssecPolicy = {
|
||||||
|
algorithm = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "RSASHA256";
|
||||||
|
description = "Which algorithm to use for DNSSEC";
|
||||||
|
};
|
||||||
|
keyttl = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "1h";
|
||||||
|
description = "TTL for dnssec records";
|
||||||
|
};
|
||||||
|
coverage = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "1y";
|
||||||
|
description = ''
|
||||||
|
The length of time to ensure that keys will be correct; no action will be taken to create new keys to be activated after this time.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
zsk = mkOption {
|
||||||
|
type = keyPolicy;
|
||||||
|
default = { keySize = 2048;
|
||||||
|
prePublish = "1w";
|
||||||
|
postPublish = "1w";
|
||||||
|
rollPeriod = "1mo";
|
||||||
|
};
|
||||||
|
description = "Key policy for zone signing keys";
|
||||||
|
};
|
||||||
|
ksk = mkOption {
|
||||||
|
type = keyPolicy;
|
||||||
|
default = { keySize = 4096;
|
||||||
|
prePublish = "1mo";
|
||||||
|
postPublish = "1mo";
|
||||||
|
rollPeriod = "0";
|
||||||
|
};
|
||||||
|
description = "Key policy for key signing keys";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
maxRefreshSecs = mkOption {
|
maxRefreshSecs = mkOption {
|
||||||
type = types.nullOr types.int;
|
type = types.nullOr types.int;
|
||||||
|
@ -365,10 +405,61 @@ let
|
||||||
and stats_noreset.
|
and stats_noreset.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
keyPolicy = types.submodule {
|
||||||
|
options = {
|
||||||
|
keySize = mkOption {
|
||||||
|
type = types.int;
|
||||||
|
description = "Key size in bits";
|
||||||
|
};
|
||||||
|
prePublish = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = "How long in advance to publish new keys";
|
||||||
|
};
|
||||||
|
postPublish = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = "How long after deactivation to keep a key in the zone";
|
||||||
|
};
|
||||||
|
rollPeriod = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = "How frequently to change keys";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
dnssecZones = (filterAttrs (n: v: if v ? dnssec then v.dnssec else false) zoneConfigs);
|
||||||
|
|
||||||
|
dnssec = length (attrNames dnssecZones) != 0;
|
||||||
|
|
||||||
|
signZones = optionalString dnssec ''
|
||||||
|
mkdir -p ${stateDir}/dnssec
|
||||||
|
chown ${username}:${username} ${stateDir}/dnssec
|
||||||
|
chmod 0600 ${stateDir}/dnssec
|
||||||
|
|
||||||
|
${concatStrings (mapAttrsToList signZone dnssecZones)}
|
||||||
|
'';
|
||||||
|
signZone = name: zone: ''
|
||||||
|
${pkgs.bind}/bin/dnssec-keymgr -g ${pkgs.bind}/bin/dnssec-keygen -s ${pkgs.bind}/bin/dnssec-settime -K ${stateDir}/dnssec -c ${policyFile name zone.dnssecPolicy} ${name}
|
||||||
|
${pkgs.bind}/bin/dnssec-signzone -S -K ${stateDir}/dnssec -o ${name} -O full -N date ${stateDir}/zones/${name}
|
||||||
|
${nsdPkg}/sbin/nsd-checkzone ${name} ${stateDir}/zones/${name}.signed && mv -v ${stateDir}/zones/${name}.signed ${stateDir}/zones/${name}
|
||||||
|
'';
|
||||||
|
policyFile = name: policy: pkgs.writeText "${name}.policy" ''
|
||||||
|
zone ${name} {
|
||||||
|
algorithm ${policy.algorithm};
|
||||||
|
key-size zsk ${toString policy.zsk.keySize};
|
||||||
|
key-size ksk ${toString policy.ksk.keySize};
|
||||||
|
keyttl ${policy.keyttl};
|
||||||
|
pre-publish zsk ${policy.zsk.prePublish};
|
||||||
|
pre-publish ksk ${policy.ksk.prePublish};
|
||||||
|
post-publish zsk ${policy.zsk.postPublish};
|
||||||
|
post-publish ksk ${policy.ksk.postPublish};
|
||||||
|
roll-period zsk ${policy.zsk.rollPeriod};
|
||||||
|
roll-period ksk ${policy.ksk.rollPeriod};
|
||||||
|
coverage ${policy.coverage};
|
||||||
|
};
|
||||||
|
'';
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
# options are ordered alphanumerically
|
# options are ordered alphanumerically
|
||||||
|
@ -378,6 +469,14 @@ in
|
||||||
|
|
||||||
bind8Stats = mkEnableOption "BIND8 like statistics";
|
bind8Stats = mkEnableOption "BIND8 like statistics";
|
||||||
|
|
||||||
|
dnssecInterval = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "1h";
|
||||||
|
description = ''
|
||||||
|
How often to check whether dnssec key rollover is required
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
extraConfig = mkOption {
|
extraConfig = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "";
|
default = "";
|
||||||
|
@ -739,7 +838,6 @@ in
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
zones = mkOption {
|
zones = mkOption {
|
||||||
type = types.attrsOf zoneOptions;
|
type = types.attrsOf zoneOptions;
|
||||||
default = {};
|
default = {};
|
||||||
|
@ -783,7 +881,6 @@ in
|
||||||
serverGroup1.
|
serverGroup1.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
|
@ -828,9 +925,9 @@ in
|
||||||
mkdir -m 0700 -p "${stateDir}/var"
|
mkdir -m 0700 -p "${stateDir}/var"
|
||||||
|
|
||||||
cat > "${stateDir}/don't touch anything in here" << EOF
|
cat > "${stateDir}/don't touch anything in here" << EOF
|
||||||
Everything in this directory except NSD's state in var is
|
Everything in this directory except NSD's state in var and dnssec
|
||||||
automatically generated and will be purged and redeployed
|
is automatically generated and will be purged and redeployed by
|
||||||
by the nsd.service pre-start script.
|
the nsd.service pre-start script.
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
chown ${username}:${username} -R "${stateDir}/private"
|
chown ${username}:${username} -R "${stateDir}/private"
|
||||||
|
@ -844,5 +941,33 @@ in
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
nixpkgs.config = mkIf dnssec {
|
||||||
|
bind.enablePython = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.timers."nsd-dnssec" = mkIf dnssec {
|
||||||
|
description = "Automatic DNSSEC key rollover";
|
||||||
|
|
||||||
|
wantedBy = [ "nsd.service" ];
|
||||||
|
|
||||||
|
timerConfig = {
|
||||||
|
OnActiveSec = cfg.dnssecInterval;
|
||||||
|
OnUnitActiveSec = cfg.dnssecInterval;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services."nsd-dnssec" = mkIf dnssec {
|
||||||
|
description = "DNSSEC key rollover";
|
||||||
|
|
||||||
|
wantedBy = [ "nsd.service" ];
|
||||||
|
before = [ "nsd.service" ];
|
||||||
|
|
||||||
|
script = signZones;
|
||||||
|
|
||||||
|
postStop = ''
|
||||||
|
${pkgs.systemd}/bin/systemctl kill -s SIGHUP nsd.service
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
{ stdenv, lib, fetchurl, openssl, libtool, perl, libxml2
|
{ stdenv, lib, fetchurl, openssl, libtool, perl, libxml2
|
||||||
, enableSeccomp ? false, libseccomp ? null }:
|
, enableSeccomp ? false, libseccomp ? null
|
||||||
|
, enablePython ? false, python ? null }:
|
||||||
|
|
||||||
assert enableSeccomp -> libseccomp != null;
|
assert enableSeccomp -> libseccomp != null;
|
||||||
|
assert enablePython -> python != null;
|
||||||
|
|
||||||
let version = "9.11.2"; in
|
let version = "9.11.2"; in
|
||||||
|
|
||||||
|
@ -18,8 +20,9 @@ stdenv.mkDerivation rec {
|
||||||
patches = [ ./dont-keep-configure-flags.patch ./remove-mkdir-var.patch ] ++
|
patches = [ ./dont-keep-configure-flags.patch ./remove-mkdir-var.patch ] ++
|
||||||
stdenv.lib.optional stdenv.isDarwin ./darwin-openssl-linking-fix.patch;
|
stdenv.lib.optional stdenv.isDarwin ./darwin-openssl-linking-fix.patch;
|
||||||
|
|
||||||
buildInputs = [ openssl libtool perl libxml2 ] ++
|
buildInputs = [ openssl libtool perl libxml2 ]
|
||||||
stdenv.lib.optional enableSeccomp libseccomp;
|
++ lib.optional enableSeccomp libseccomp
|
||||||
|
++ lib.optional enablePython python;
|
||||||
|
|
||||||
STD_CDEFINES = [ "-DDIG_SIGCHASE=1" ]; # support +sigchase
|
STD_CDEFINES = [ "-DDIG_SIGCHASE=1" ]; # support +sigchase
|
||||||
|
|
||||||
|
@ -28,6 +31,7 @@ stdenv.mkDerivation rec {
|
||||||
"--with-libtool"
|
"--with-libtool"
|
||||||
"--with-libxml2=${libxml2.dev}"
|
"--with-libxml2=${libxml2.dev}"
|
||||||
"--with-openssl=${openssl.dev}"
|
"--with-openssl=${openssl.dev}"
|
||||||
|
(if enablePython then "--with-python" else "--without-python")
|
||||||
"--without-atf"
|
"--without-atf"
|
||||||
"--without-dlopen"
|
"--without-dlopen"
|
||||||
"--without-docbook-xsl"
|
"--without-docbook-xsl"
|
||||||
|
@ -36,7 +40,6 @@ stdenv.mkDerivation rec {
|
||||||
"--without-idnlib"
|
"--without-idnlib"
|
||||||
"--without-pkcs11"
|
"--without-pkcs11"
|
||||||
"--without-purify"
|
"--without-purify"
|
||||||
"--without-python"
|
|
||||||
] ++ lib.optional enableSeccomp "--enable-seccomp";
|
] ++ lib.optional enableSeccomp "--enable-seccomp";
|
||||||
|
|
||||||
postInstall = ''
|
postInstall = ''
|
||||||
|
|
|
@ -11462,7 +11462,10 @@ with pkgs;
|
||||||
|
|
||||||
bftpd = callPackage ../servers/ftp/bftpd {};
|
bftpd = callPackage ../servers/ftp/bftpd {};
|
||||||
|
|
||||||
bind = callPackage ../servers/dns/bind { };
|
bind = callPackage ../servers/dns/bind {
|
||||||
|
enablePython = config.bind.enablePython or false;
|
||||||
|
python = python.withPackages (ps: with ps; [ ply ]);
|
||||||
|
};
|
||||||
dnsutils = bind.dnsutils;
|
dnsutils = bind.dnsutils;
|
||||||
|
|
||||||
bird = callPackage ../servers/bird { };
|
bird = callPackage ../servers/bird { };
|
||||||
|
|
Loading…
Reference in a new issue