mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-07-13 21:50:33 +03:00
Merge pull request #12487 from hrdinka/refactor/nsd
Refactor NSD service and update to 4.1.7
This commit is contained in:
commit
a9d24cedeb
3 changed files with 549 additions and 452 deletions
|
@ -226,6 +226,27 @@ programs.ibus.plugins = with pkgs; [ ibus-anthy mozc ];
|
|||
was removed. Please review the currently available options.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
The option <option>services.nsd.zones.<name>.data</option> no
|
||||
longer interpret the dollar sign ($) as a shell variable, as such it
|
||||
should not be escaped anymore. Thus the following zone data:
|
||||
</para>
|
||||
<programlisting>
|
||||
\$ORIGIN example.com.
|
||||
\$TTL 1800
|
||||
@ IN SOA ns1.vpn.nbp.name. admin.example.com. (
|
||||
</programlisting>
|
||||
<para>
|
||||
Should modified to look like the actual file expected by nsd:
|
||||
</para>
|
||||
<programlisting>
|
||||
$ORIGIN example.com.
|
||||
$TTL 1800
|
||||
@ IN SOA ns1.vpn.nbp.name. admin.example.com. (
|
||||
</programlisting>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ let
|
|||
stateDir = "/var/lib/nsd";
|
||||
pidFile = stateDir + "/var/nsd.pid";
|
||||
|
||||
# build nsd with the options needed for the given config
|
||||
nsdPkg = pkgs.nsd.override {
|
||||
bind8Stats = cfg.bind8Stats;
|
||||
ipv6 = cfg.ipv6;
|
||||
|
@ -17,74 +18,99 @@ let
|
|||
zoneStats = length (collect (x: (x.zoneStats or null) != null) cfg.zones) > 0;
|
||||
};
|
||||
|
||||
zoneFiles = pkgs.stdenv.mkDerivation {
|
||||
preferLocalBuild = true;
|
||||
|
||||
nsdEnv = pkgs.buildEnv {
|
||||
name = "nsd-env";
|
||||
buildCommand = concatStringsSep "\n"
|
||||
[ "mkdir -p $out"
|
||||
(concatStrings (mapAttrsToList (zoneName: zoneOptions: ''
|
||||
cat > "$out/${zoneName}" <<_EOF_
|
||||
${zoneOptions.data}
|
||||
_EOF_
|
||||
'') zoneConfigs))
|
||||
];
|
||||
|
||||
paths = [ configFile ]
|
||||
++ mapAttrsToList (name: zone: writeZoneData name zone.data) zoneConfigs;
|
||||
|
||||
postBuild = ''
|
||||
echo "checking zone files"
|
||||
cd $out/zones
|
||||
|
||||
for zoneFile in *; do
|
||||
${nsdPkg}/sbin/nsd-checkzone "$zoneFile" "$zoneFile" || {
|
||||
if grep -q \\\\\\$ "$zoneFile"; then
|
||||
echo zone "$zoneFile" contains escaped dollar signes \\\$
|
||||
echo Escaping them is not needed any more. Please make shure \
|
||||
to unescape them where they prefix a variable name
|
||||
fi
|
||||
|
||||
exit 1
|
||||
}
|
||||
done
|
||||
|
||||
echo "checking configuration file"
|
||||
${nsdPkg}/sbin/nsd-checkconf $out/nsd.conf
|
||||
'';
|
||||
};
|
||||
|
||||
configFile = pkgs.writeText "nsd.conf" ''
|
||||
writeZoneData = name: text: pkgs.writeTextFile {
|
||||
inherit name text;
|
||||
destination = "/zones/${name}";
|
||||
};
|
||||
|
||||
|
||||
# options are ordered alphanumerically by the nixos option name
|
||||
configFile = pkgs.writeTextDir "nsd.conf" ''
|
||||
server:
|
||||
username: ${username}
|
||||
chroot: "${stateDir}"
|
||||
username: ${username}
|
||||
|
||||
# The directory for zonefile: files. The daemon chdirs here.
|
||||
zonesdir: "${stateDir}"
|
||||
|
||||
# the list of dynamically added zones.
|
||||
zonelistfile: "${stateDir}/var/zone.list"
|
||||
database: "${stateDir}/var/nsd.db"
|
||||
pidfile: "${pidFile}"
|
||||
xfrdfile: "${stateDir}/var/xfrd.state"
|
||||
xfrdir: "${stateDir}/tmp"
|
||||
zonelistfile: "${stateDir}/var/zone.list"
|
||||
|
||||
# interfaces
|
||||
${forEach " ip-address: " cfg.interfaces}
|
||||
|
||||
server-count: ${toString cfg.serverCount}
|
||||
ip-transparent: ${yesOrNo cfg.ipTransparent}
|
||||
do-ip4: ${yesOrNo cfg.ipv4}
|
||||
do-ip6: ${yesOrNo cfg.ipv6}
|
||||
port: ${toString cfg.port}
|
||||
verbosity: ${toString cfg.verbosity}
|
||||
hide-version: ${yesOrNo cfg.hideVersion}
|
||||
identity: "${cfg.identity}"
|
||||
ip-transparent: ${yesOrNo cfg.ipTransparent}
|
||||
do-ip4: ${yesOrNo cfg.ipv4}
|
||||
ipv4-edns-size: ${toString cfg.ipv4EDNSSize}
|
||||
do-ip6: ${yesOrNo cfg.ipv6}
|
||||
ipv6-edns-size: ${toString cfg.ipv6EDNSSize}
|
||||
log-time-ascii: ${yesOrNo cfg.logTimeAscii}
|
||||
${maybeString "nsid: " cfg.nsid}
|
||||
port: ${toString cfg.port}
|
||||
reuseport: ${yesOrNo cfg.reuseport}
|
||||
round-robin: ${yesOrNo cfg.roundRobin}
|
||||
server-count: ${toString cfg.serverCount}
|
||||
${if cfg.statistics == null then "" else "statistics: ${toString cfg.statistics}"}
|
||||
tcp-count: ${toString cfg.tcpCount}
|
||||
tcp-query-count: ${toString cfg.tcpQueryCount}
|
||||
tcp-timeout: ${toString cfg.tcpTimeout}
|
||||
ipv4-edns-size: ${toString cfg.ipv4EDNSSize}
|
||||
ipv6-edns-size: ${toString cfg.ipv6EDNSSize}
|
||||
${if cfg.statistics == null then "" else "statistics: ${toString cfg.statistics}"}
|
||||
verbosity: ${toString cfg.verbosity}
|
||||
${maybeString "version: " cfg.version}
|
||||
xfrd-reload-timeout: ${toString cfg.xfrdReloadTimeout}
|
||||
zonefiles-check: ${yesOrNo cfg.zonefilesCheck}
|
||||
|
||||
rrl-size: ${toString cfg.ratelimit.size}
|
||||
rrl-ratelimit: ${toString cfg.ratelimit.ratelimit}
|
||||
rrl-whitelist-ratelimit: ${toString cfg.ratelimit.whitelistRatelimit}
|
||||
${maybeString "rrl-slip: " cfg.ratelimit.slip}
|
||||
${maybeString "rrl-ipv4-prefix-length: " cfg.ratelimit.ipv4PrefixLength}
|
||||
${maybeString "rrl-ipv6-prefix-length: " cfg.ratelimit.ipv6PrefixLength}
|
||||
rrl-ratelimit: ${toString cfg.ratelimit.ratelimit}
|
||||
${maybeString "rrl-slip: " cfg.ratelimit.slip}
|
||||
rrl-size: ${toString cfg.ratelimit.size}
|
||||
rrl-whitelist-ratelimit: ${toString cfg.ratelimit.whitelistRatelimit}
|
||||
|
||||
${keyConfigFile}
|
||||
|
||||
remote-control:
|
||||
control-enable: ${yesOrNo cfg.remoteControl.enable}
|
||||
${forEach " control-interface: " cfg.remoteControl.interfaces}
|
||||
control-port: ${toString cfg.port}
|
||||
server-key-file: "${cfg.remoteControl.serverKeyFile}"
|
||||
server-cert-file: "${cfg.remoteControl.serverCertFile}"
|
||||
control-key-file: "${cfg.remoteControl.controlKeyFile}"
|
||||
control-cert-file: "${cfg.remoteControl.controlCertFile}"
|
||||
${forEach " control-interface: " cfg.remoteControl.interfaces}
|
||||
control-port: ${toString cfg.remoteControl.port}
|
||||
server-key-file: "${cfg.remoteControl.serverKeyFile}"
|
||||
server-cert-file: "${cfg.remoteControl.serverCertFile}"
|
||||
|
||||
# zone files reside in "${zoneFiles}" linked to "${stateDir}/zones"
|
||||
${concatStrings (mapAttrsToList zoneConfigFile zoneConfigs)}
|
||||
|
||||
${cfg.extraConfig}
|
||||
|
@ -106,22 +132,23 @@ let
|
|||
secret=$(cat "${keyOptions.keyFile}")
|
||||
dest="${stateDir}/private/${keyName}"
|
||||
echo " secret: \"$secret\"" > "$dest"
|
||||
${pkgs.coreutils}/bin/chown ${username}:${username} "$dest"
|
||||
${pkgs.coreutils}/bin/chmod 0400 "$dest"
|
||||
chown ${username}:${username} "$dest"
|
||||
chmod 0400 "$dest"
|
||||
'') cfg.keys);
|
||||
|
||||
|
||||
# options are ordered alphanumerically by the nixos option name
|
||||
zoneConfigFile = name: zone: ''
|
||||
zone:
|
||||
name: "${name}"
|
||||
zonefile: "${stateDir}/zones/${name}"
|
||||
${maybeString "zonestats: " zone.zoneStats}
|
||||
${maybeString "outgoing-interface: " zone.outgoingInterface}
|
||||
${forEach " rrl-whitelist: " zone.rrlWhitelist}
|
||||
${maybeString "zonestats: " zone.zoneStats}
|
||||
|
||||
allow-axfr-fallback: ${yesOrNo zone.allowAXFRFallback}
|
||||
${forEach " allow-notify: " zone.allowNotify}
|
||||
${forEach " request-xfr: " zone.requestXFR}
|
||||
allow-axfr-fallback: ${yesOrNo zone.allowAXFRFallback}
|
||||
|
||||
${forEach " notify: " zone.notify}
|
||||
notify-retry: ${toString zone.notifyRetry}
|
||||
|
@ -152,17 +179,16 @@ let
|
|||
|
||||
childConfig = x: v: { options.children = { type = types.attrsOf x; visible = v; }; };
|
||||
|
||||
# options are ordered alphanumerically
|
||||
zoneOptionsRaw = types.submodule {
|
||||
options = {
|
||||
children = mkOption {
|
||||
default = {};
|
||||
|
||||
allowAXFRFallback = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Children zones inherit all options of their parents. Attributes
|
||||
defined in a child will overwrite the ones of its parent. Only
|
||||
leaf zones will be actually served. This way it's possible to
|
||||
define maybe zones which share most attributes without
|
||||
duplicating everything. This mechanism replaces nsd's patterns
|
||||
in a save and functional way.
|
||||
If NSD as secondary server should be allowed to AXFR if the primary
|
||||
server does not allow IXFR.
|
||||
'';
|
||||
};
|
||||
|
||||
|
@ -193,21 +219,25 @@ let
|
|||
'';
|
||||
};
|
||||
|
||||
requestXFR = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
example = [];
|
||||
children = mkOption {
|
||||
default = {};
|
||||
description = ''
|
||||
Format: <code>[AXFR|UDP] <ip-address> <key-name | NOKEY></code>
|
||||
Children zones inherit all options of their parents. Attributes
|
||||
defined in a child will overwrite the ones of its parent. Only
|
||||
leaf zones will be actually served. This way it's possible to
|
||||
define maybe zones which share most attributes without
|
||||
duplicating everything. This mechanism replaces nsd's patterns
|
||||
in a save and functional way.
|
||||
'';
|
||||
};
|
||||
|
||||
allowAXFRFallback = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
data = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
example = "";
|
||||
description = ''
|
||||
If NSD as secondary server should be allowed to AXFR if the primary
|
||||
server does not allow IXFR.
|
||||
The actual zone data. This is the content of your zone file.
|
||||
Use imports or pkgs.lib.readFile if you don't want this data in your config file.
|
||||
'';
|
||||
};
|
||||
|
||||
|
@ -238,16 +268,6 @@ let
|
|||
'';
|
||||
};
|
||||
|
||||
provideXFR = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
example = [ "192.0.2.0/24 NOKEY" "192.0.2.0/24 my_tsig_key_name" ];
|
||||
description = ''
|
||||
Allow these IPs and TSIG to transfer zones, addr TSIG|NOKEY|BLOCKED
|
||||
address range 192.0.2.0/24, 1.2.3.4&255.255.0.0, 3.0.2.20-3.0.2.40
|
||||
'';
|
||||
};
|
||||
|
||||
outgoingInterface = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
|
@ -260,6 +280,25 @@ let
|
|||
'';
|
||||
};
|
||||
|
||||
provideXFR = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
example = [ "192.0.2.0/24 NOKEY" "192.0.2.0/24 my_tsig_key_name" ];
|
||||
description = ''
|
||||
Allow these IPs and TSIG to transfer zones, addr TSIG|NOKEY|BLOCKED
|
||||
address range 192.0.2.0/24, 1.2.3.4&255.255.0.0, 3.0.2.20-3.0.2.40
|
||||
'';
|
||||
};
|
||||
|
||||
requestXFR = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
example = [];
|
||||
description = ''
|
||||
Format: <code>[AXFR|UDP] <ip-address> <key-name | NOKEY></code>
|
||||
'';
|
||||
};
|
||||
|
||||
rrlWhitelist = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
|
@ -270,16 +309,6 @@ let
|
|||
'';
|
||||
};
|
||||
|
||||
data = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
example = "";
|
||||
description = ''
|
||||
The actual zone data. This is the content of your zone file.
|
||||
Use imports or pkgs.lib.readFile if you don't want this data in your config file.
|
||||
'';
|
||||
};
|
||||
|
||||
zoneStats = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
|
@ -292,79 +321,24 @@ let
|
|||
and stats_noreset.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
in
|
||||
{
|
||||
options = {
|
||||
services.nsd = {
|
||||
# options are ordered alphanumerically
|
||||
options.services.nsd = {
|
||||
|
||||
enable = mkEnableOption "NSD authoritative DNS server";
|
||||
|
||||
bind8Stats = mkEnableOption "BIND8 like statistics";
|
||||
|
||||
rootServer = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
extraConfig = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
description = ''
|
||||
Wheter if this server will be a root server (a DNS root server, you
|
||||
usually don't want that).
|
||||
'';
|
||||
};
|
||||
|
||||
interfaces = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ "127.0.0.0" "::1" ];
|
||||
description = ''
|
||||
What addresses the server should listen to.
|
||||
'';
|
||||
};
|
||||
|
||||
serverCount = mkOption {
|
||||
type = types.int;
|
||||
default = 1;
|
||||
description = ''
|
||||
Number of NSD servers to fork. Put the number of CPUs to use here.
|
||||
'';
|
||||
};
|
||||
|
||||
ipTransparent = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Allow binding to non local addresses.
|
||||
'';
|
||||
};
|
||||
|
||||
ipv4 = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Wheter to listen on IPv4 connections.
|
||||
'';
|
||||
};
|
||||
|
||||
ipv6 = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Wheter to listen on IPv6 connections.
|
||||
'';
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
default = 53;
|
||||
description = ''
|
||||
Port the service should bind do.
|
||||
'';
|
||||
};
|
||||
|
||||
verbosity = mkOption {
|
||||
type = types.int;
|
||||
default = 0;
|
||||
description = ''
|
||||
Verbosity level.
|
||||
Extra nsd config.
|
||||
'';
|
||||
};
|
||||
|
||||
|
@ -384,6 +358,62 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
interfaces = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ "127.0.0.0" "::1" ];
|
||||
description = ''
|
||||
What addresses the server should listen to.
|
||||
'';
|
||||
};
|
||||
|
||||
ipTransparent = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Allow binding to non local addresses.
|
||||
'';
|
||||
};
|
||||
|
||||
ipv4 = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Wheter to listen on IPv4 connections.
|
||||
'';
|
||||
};
|
||||
|
||||
ipv4EDNSSize = mkOption {
|
||||
type = types.int;
|
||||
default = 4096;
|
||||
description = ''
|
||||
Preferred EDNS buffer size for IPv4.
|
||||
'';
|
||||
};
|
||||
|
||||
ipv6 = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Wheter to listen on IPv6 connections.
|
||||
'';
|
||||
};
|
||||
|
||||
ipv6EDNSSize = mkOption {
|
||||
type = types.int;
|
||||
default = 4096;
|
||||
description = ''
|
||||
Preferred EDNS buffer size for IPv6.
|
||||
'';
|
||||
};
|
||||
|
||||
logTimeAscii = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Log time in ascii, if false then in unix epoch seconds.
|
||||
'';
|
||||
};
|
||||
|
||||
nsid = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
|
@ -392,6 +422,53 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
default = 53;
|
||||
description = ''
|
||||
Port the service should bind do.
|
||||
'';
|
||||
};
|
||||
|
||||
reuseport = mkOption {
|
||||
type = types.bool;
|
||||
default = pkgs.stdenv.isLinux;
|
||||
description = ''
|
||||
Wheter to enable SO_REUSEPORT on all used sockets. This lets multiple
|
||||
processes bind to the same port. This speeds up operation especially
|
||||
if the server count is greater than one and makes fast restarts less
|
||||
prone to fail
|
||||
'';
|
||||
};
|
||||
|
||||
rootServer = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Wheter if this server will be a root server (a DNS root server, you
|
||||
usually don't want that).
|
||||
'';
|
||||
};
|
||||
|
||||
roundRobin = mkEnableOption "round robin rotation of records";
|
||||
|
||||
serverCount = mkOption {
|
||||
type = types.int;
|
||||
default = 1;
|
||||
description = ''
|
||||
Number of NSD servers to fork. Put the number of CPUs to use here.
|
||||
'';
|
||||
};
|
||||
|
||||
statistics = mkOption {
|
||||
type = types.nullOr types.int;
|
||||
default = null;
|
||||
description = ''
|
||||
Statistics are produced every number of seconds. Prints to log.
|
||||
If null no statistics are logged.
|
||||
'';
|
||||
};
|
||||
|
||||
tcpCount = mkOption {
|
||||
type = types.int;
|
||||
default = 100;
|
||||
|
@ -417,28 +494,21 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
ipv4EDNSSize = mkOption {
|
||||
verbosity = mkOption {
|
||||
type = types.int;
|
||||
default = 4096;
|
||||
default = 0;
|
||||
description = ''
|
||||
Preferred EDNS buffer size for IPv4.
|
||||
Verbosity level.
|
||||
'';
|
||||
};
|
||||
|
||||
ipv6EDNSSize = mkOption {
|
||||
type = types.int;
|
||||
default = 4096;
|
||||
description = ''
|
||||
Preferred EDNS buffer size for IPv6.
|
||||
'';
|
||||
};
|
||||
|
||||
statistics = mkOption {
|
||||
type = types.nullOr types.int;
|
||||
version = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
Statistics are produced every number of seconds. Prints to log.
|
||||
If null no statistics are logged.
|
||||
The version string replied for CH TXT version.server and version.bind
|
||||
queries. Will use the compiled package version on null.
|
||||
See hideVersion for enabling/disabling this responses.
|
||||
'';
|
||||
};
|
||||
|
||||
|
@ -459,134 +529,10 @@ in
|
|||
};
|
||||
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
description = ''
|
||||
Extra nsd config.
|
||||
'';
|
||||
};
|
||||
|
||||
|
||||
ratelimit = {
|
||||
enable = mkEnableOption "ratelimit capabilities";
|
||||
|
||||
size = mkOption {
|
||||
type = types.int;
|
||||
default = 1000000;
|
||||
description = ''
|
||||
Size of the hashtable. More buckets use more memory but lower
|
||||
the chance of hash hash collisions.
|
||||
'';
|
||||
};
|
||||
|
||||
ratelimit = mkOption {
|
||||
type = types.int;
|
||||
default = 200;
|
||||
description = ''
|
||||
Max qps allowed from any query source.
|
||||
0 means unlimited. With an verbosity of 2 blocked and
|
||||
unblocked subnets will be logged.
|
||||
'';
|
||||
};
|
||||
|
||||
whitelistRatelimit = mkOption {
|
||||
type = types.int;
|
||||
default = 2000;
|
||||
description = ''
|
||||
Max qps allowed from whitelisted sources.
|
||||
0 means unlimited. Set the rrl-whitelist option for specific
|
||||
queries to apply this limit instead of the default to them.
|
||||
'';
|
||||
};
|
||||
|
||||
slip = mkOption {
|
||||
type = types.nullOr types.int;
|
||||
default = null;
|
||||
description = ''
|
||||
Number of packets that get discarded before replying a SLIP response.
|
||||
0 disables SLIP responses. 1 will make every response a SLIP response.
|
||||
'';
|
||||
};
|
||||
|
||||
ipv4PrefixLength = mkOption {
|
||||
type = types.nullOr types.int;
|
||||
default = null;
|
||||
description = ''
|
||||
IPv4 prefix length. Addresses are grouped by netblock.
|
||||
'';
|
||||
};
|
||||
|
||||
ipv6PrefixLength = mkOption {
|
||||
type = types.nullOr types.int;
|
||||
default = null;
|
||||
description = ''
|
||||
IPv6 prefix length. Addresses are grouped by netblock.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
remoteControl = {
|
||||
enable = mkEnableOption "remote control via nsd-control";
|
||||
|
||||
interfaces = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ "127.0.0.1" "::1" ];
|
||||
description = ''
|
||||
Which interfaces NSD should bind to for remote control.
|
||||
'';
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
default = 8952;
|
||||
description = ''
|
||||
Port number for remote control operations (uses TLS over TCP).
|
||||
'';
|
||||
};
|
||||
|
||||
serverKeyFile = mkOption {
|
||||
type = types.path;
|
||||
default = "/etc/nsd/nsd_server.key";
|
||||
description = ''
|
||||
Path to the server private key, which is used by the server
|
||||
but not by nsd-control. This file is generated by nsd-control-setup.
|
||||
'';
|
||||
};
|
||||
|
||||
serverCertFile = mkOption {
|
||||
type = types.path;
|
||||
default = "/etc/nsd/nsd_server.pem";
|
||||
description = ''
|
||||
Path to the server self signed certificate, which is used by the server
|
||||
but and by nsd-control. This file is generated by nsd-control-setup.
|
||||
'';
|
||||
};
|
||||
|
||||
controlKeyFile = mkOption {
|
||||
type = types.path;
|
||||
default = "/etc/nsd/nsd_control.key";
|
||||
description = ''
|
||||
Path to the client private key, which is used by nsd-control
|
||||
but not by the server. This file is generated by nsd-control-setup.
|
||||
'';
|
||||
};
|
||||
|
||||
controlCertFile = mkOption {
|
||||
type = types.path;
|
||||
default = "/etc/nsd/nsd_control.pem";
|
||||
description = ''
|
||||
Path to the client certificate signed with the server certificate.
|
||||
This file is used by nsd-control and generated by nsd-control-setup.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
keys = mkOption {
|
||||
type = types.attrsOf (types.submodule {
|
||||
options = {
|
||||
|
||||
algorithm = mkOption {
|
||||
type = types.str;
|
||||
default = "hmac-sha256";
|
||||
|
@ -604,20 +550,143 @@ in
|
|||
user.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
});
|
||||
default = {};
|
||||
example = {
|
||||
"tsig.example.org" = {
|
||||
example = literalExample ''
|
||||
{ "tsig.example.org" = {
|
||||
algorithm = "hmac-md5";
|
||||
secret = "aaaaaabbbbbbccccccdddddd";
|
||||
keyFile = "/path/to/my/key";
|
||||
};
|
||||
};
|
||||
'';
|
||||
description = ''
|
||||
Define your TSIG keys here.
|
||||
'';
|
||||
};
|
||||
|
||||
|
||||
ratelimit = {
|
||||
|
||||
enable = mkEnableOption "ratelimit capabilities";
|
||||
|
||||
ipv4PrefixLength = mkOption {
|
||||
type = types.nullOr types.int;
|
||||
default = null;
|
||||
description = ''
|
||||
IPv4 prefix length. Addresses are grouped by netblock.
|
||||
'';
|
||||
};
|
||||
|
||||
ipv6PrefixLength = mkOption {
|
||||
type = types.nullOr types.int;
|
||||
default = null;
|
||||
description = ''
|
||||
IPv6 prefix length. Addresses are grouped by netblock.
|
||||
'';
|
||||
};
|
||||
|
||||
ratelimit = mkOption {
|
||||
type = types.int;
|
||||
default = 200;
|
||||
description = ''
|
||||
Max qps allowed from any query source.
|
||||
0 means unlimited. With an verbosity of 2 blocked and
|
||||
unblocked subnets will be logged.
|
||||
'';
|
||||
};
|
||||
|
||||
slip = mkOption {
|
||||
type = types.nullOr types.int;
|
||||
default = null;
|
||||
description = ''
|
||||
Number of packets that get discarded before replying a SLIP response.
|
||||
0 disables SLIP responses. 1 will make every response a SLIP response.
|
||||
'';
|
||||
};
|
||||
|
||||
size = mkOption {
|
||||
type = types.int;
|
||||
default = 1000000;
|
||||
description = ''
|
||||
Size of the hashtable. More buckets use more memory but lower
|
||||
the chance of hash hash collisions.
|
||||
'';
|
||||
};
|
||||
|
||||
whitelistRatelimit = mkOption {
|
||||
type = types.int;
|
||||
default = 2000;
|
||||
description = ''
|
||||
Max qps allowed from whitelisted sources.
|
||||
0 means unlimited. Set the rrl-whitelist option for specific
|
||||
queries to apply this limit instead of the default to them.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
remoteControl = {
|
||||
|
||||
enable = mkEnableOption "remote control via nsd-control";
|
||||
|
||||
controlCertFile = mkOption {
|
||||
type = types.path;
|
||||
default = "/etc/nsd/nsd_control.pem";
|
||||
description = ''
|
||||
Path to the client certificate signed with the server certificate.
|
||||
This file is used by nsd-control and generated by nsd-control-setup.
|
||||
'';
|
||||
};
|
||||
|
||||
controlKeyFile = mkOption {
|
||||
type = types.path;
|
||||
default = "/etc/nsd/nsd_control.key";
|
||||
description = ''
|
||||
Path to the client private key, which is used by nsd-control
|
||||
but not by the server. This file is generated by nsd-control-setup.
|
||||
'';
|
||||
};
|
||||
|
||||
interfaces = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ "127.0.0.1" "::1" ];
|
||||
description = ''
|
||||
Which interfaces NSD should bind to for remote control.
|
||||
'';
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
default = 8952;
|
||||
description = ''
|
||||
Port number for remote control operations (uses TLS over TCP).
|
||||
'';
|
||||
};
|
||||
|
||||
serverCertFile = mkOption {
|
||||
type = types.path;
|
||||
default = "/etc/nsd/nsd_server.pem";
|
||||
description = ''
|
||||
Path to the server self signed certificate, which is used by the server
|
||||
but and by nsd-control. This file is generated by nsd-control-setup.
|
||||
'';
|
||||
};
|
||||
|
||||
serverKeyFile = mkOption {
|
||||
type = types.path;
|
||||
default = "/etc/nsd/nsd_server.key";
|
||||
description = ''
|
||||
Path to the server private key, which is used by the server
|
||||
but not by nsd-control. This file is generated by nsd-control-setup.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
zones = mkOption {
|
||||
type = types.attrsOf zoneOptions;
|
||||
default = {};
|
||||
|
@ -650,7 +719,7 @@ in
|
|||
...
|
||||
''';
|
||||
};
|
||||
}
|
||||
};
|
||||
'';
|
||||
description = ''
|
||||
Define your zones here. Zones can cascade other zones and therefore
|
||||
|
@ -663,7 +732,6 @@ in
|
|||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
|
@ -683,31 +751,40 @@ in
|
|||
|
||||
systemd.services.nsd = {
|
||||
description = "NSD authoritative only domain name service";
|
||||
|
||||
after = [ "keys.target" "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
wants = [ "keys.target" ];
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart = "${nsdPkg}/sbin/nsd -d -c ${nsdEnv}/nsd.conf";
|
||||
PIDFile = pidFile;
|
||||
Restart = "always";
|
||||
ExecStart = "${nsdPkg}/sbin/nsd -d -c ${configFile}";
|
||||
RestartSec = "4s";
|
||||
StartLimitBurst = 4;
|
||||
StartLimitInterval = "5min";
|
||||
};
|
||||
|
||||
preStart = ''
|
||||
${pkgs.coreutils}/bin/mkdir -m 0700 -p "${stateDir}/private"
|
||||
${pkgs.coreutils}/bin/mkdir -m 0700 -p "${stateDir}/tmp"
|
||||
${pkgs.coreutils}/bin/mkdir -m 0700 -p "${stateDir}/var"
|
||||
rm -Rf "${stateDir}/private/"
|
||||
rm -Rf "${stateDir}/tmp/"
|
||||
|
||||
${pkgs.coreutils}/bin/touch "${stateDir}/don't touch anything in here"
|
||||
mkdir -m 0700 -p "${stateDir}/private"
|
||||
mkdir -m 0700 -p "${stateDir}/tmp"
|
||||
mkdir -m 0700 -p "${stateDir}/var"
|
||||
|
||||
${pkgs.coreutils}/bin/rm -f "${stateDir}/private/"*
|
||||
${pkgs.coreutils}/bin/rm -f "${stateDir}/tmp/"*
|
||||
cat > "${stateDir}/don't touch anything in here" << EOF
|
||||
Everything in this directory except NSD's state in var is
|
||||
automatically generated and will be purged and redeployed
|
||||
by the nsd.service pre-start script.
|
||||
EOF
|
||||
|
||||
${pkgs.coreutils}/bin/chown nsd:nsd -R "${stateDir}/private"
|
||||
${pkgs.coreutils}/bin/chown nsd:nsd -R "${stateDir}/tmp"
|
||||
${pkgs.coreutils}/bin/chown nsd:nsd -R "${stateDir}/var"
|
||||
chown ${username}:${username} -R "${stateDir}/private"
|
||||
chown ${username}:${username} -R "${stateDir}/tmp"
|
||||
chown ${username}:${username} -R "${stateDir}/var"
|
||||
|
||||
${pkgs.coreutils}/bin/rm -rf "${stateDir}/zones"
|
||||
${pkgs.coreutils}/bin/cp -r "${zoneFiles}" "${stateDir}/zones"
|
||||
rm -rf "${stateDir}/zones"
|
||||
cp -rL "${nsdEnv}/zones" "${stateDir}/zones"
|
||||
|
||||
${copyKeys}
|
||||
'';
|
||||
|
|
|
@ -13,11 +13,11 @@
|
|||
}:
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
name = "nsd-4.1.6";
|
||||
name = "nsd-4.1.7";
|
||||
|
||||
src = fetchurl {
|
||||
url = "http://www.nlnetlabs.nl/downloads/nsd/${name}.tar.gz";
|
||||
sha256 = "0pvpsxhil60m21h3pqlzs0l5m8qd3l6j8fkjyfg8plwmbh2j5xl8";
|
||||
sha256 = "12hskfgfbkvcgpa1xxkqd8lnc6xvln1amn97x6avfnj9kfrbxa3v";
|
||||
};
|
||||
|
||||
buildInputs = [ libevent openssl ];
|
||||
|
@ -41,7 +41,6 @@ stdenv.mkDerivation rec {
|
|||
homepage = http://www.nlnetlabs.nl;
|
||||
description = "Authoritative only, high performance, simple and open source name server";
|
||||
license = licenses.bsd3;
|
||||
|
||||
platforms = platforms.unix;
|
||||
maintainers = [ maintainers.hrdinka ];
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue