2024-02-11 16:07:12 +00:00
|
|
|
{ config, lib, pkgs, utils, ... }:
|
2019-03-13 00:12:56 +00:00
|
|
|
|
|
|
|
|
|
|
|
let
|
2024-02-11 16:07:12 +00:00
|
|
|
inherit (lib)
|
|
|
|
attrNames
|
|
|
|
concatMapStrings
|
|
|
|
concatMapStringsSep
|
|
|
|
concatStrings
|
|
|
|
concatStringsSep
|
|
|
|
elem
|
|
|
|
filter
|
|
|
|
flip
|
|
|
|
hasAttr
|
|
|
|
hasPrefix
|
|
|
|
isAttrs
|
|
|
|
isBool
|
|
|
|
isDerivation
|
|
|
|
isList
|
|
|
|
mapAttrsToList
|
|
|
|
mkChangedOptionModule
|
|
|
|
mkEnableOption
|
|
|
|
mkIf
|
|
|
|
mkOption
|
|
|
|
mkPackageOption
|
|
|
|
optionals
|
|
|
|
types
|
|
|
|
;
|
|
|
|
|
|
|
|
inherit (utils)
|
|
|
|
escapeSystemdExecArgs
|
|
|
|
;
|
|
|
|
|
2019-03-13 00:12:56 +00:00
|
|
|
cfg = config.services.knot;
|
|
|
|
|
2020-03-01 18:18:34 +00:00
|
|
|
yamlConfig = let
|
|
|
|
result = assert secsCheck; nix2yaml cfg.settings;
|
|
|
|
|
|
|
|
secAllow = n: hasPrefix "mod-" n || elem n [
|
|
|
|
"module"
|
|
|
|
"server" "xdp" "control"
|
|
|
|
"log"
|
|
|
|
"statistics" "database"
|
|
|
|
"keystore" "key" "remote" "remotes" "acl" "submission" "policy"
|
|
|
|
"template"
|
|
|
|
"zone"
|
|
|
|
"include"
|
|
|
|
];
|
|
|
|
secsCheck = let
|
|
|
|
secsBad = filter (n: !secAllow n) (attrNames cfg.settings);
|
|
|
|
in if secsBad == [] then true else throw
|
|
|
|
("services.knot.settings contains unknown sections: " + toString secsBad);
|
|
|
|
|
|
|
|
nix2yaml = nix_def: concatStrings (
|
|
|
|
# We output the config section in the upstream-mandated order.
|
|
|
|
# Ordering is important due to forward-references not being allowed.
|
|
|
|
# See definition of conf_export and 'const yp_item_t conf_schema'
|
|
|
|
# upstream for reference. Last updated for 3.3.
|
|
|
|
# When changing the set of sections, also update secAllow above.
|
|
|
|
[ (sec_list_fa "id" nix_def "module") ]
|
|
|
|
++ map (sec_plain nix_def)
|
|
|
|
[ "server" "xdp" "control" ]
|
|
|
|
++ [ (sec_list_fa "target" nix_def "log") ]
|
|
|
|
++ map (sec_plain nix_def)
|
|
|
|
[ "statistics" "database" ]
|
|
|
|
++ map (sec_list_fa "id" nix_def)
|
|
|
|
[ "keystore" "key" "remote" "remotes" "acl" "submission" "policy" ]
|
|
|
|
|
|
|
|
# Export module sections before the template section.
|
|
|
|
++ map (sec_list_fa "id" nix_def) (filter (hasPrefix "mod-") (attrNames nix_def))
|
|
|
|
|
|
|
|
++ [ (sec_list_fa "id" nix_def "template") ]
|
|
|
|
++ [ (sec_list_fa "domain" nix_def "zone") ]
|
|
|
|
++ [ (sec_plain nix_def "include") ]
|
2024-01-24 09:33:55 +00:00
|
|
|
++ [ (sec_plain nix_def "clear") ]
|
2020-03-01 18:18:34 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
# A plain section contains directly attributes (we don't really check that ATM).
|
|
|
|
sec_plain = nix_def: sec_name: if !hasAttr sec_name nix_def then "" else
|
|
|
|
n2y "" { ${sec_name} = nix_def.${sec_name}; };
|
|
|
|
|
|
|
|
# This section contains a list of attribute sets. In each of the sets
|
|
|
|
# there's an attribute (`fa_name`, typically "id") that must exist and come first.
|
|
|
|
# Alternatively we support using attribute sets instead of lists; example diff:
|
|
|
|
# -template = [ { id = "default"; /* other attributes */ } { id = "foo"; } ]
|
|
|
|
# +template = { default = { /* those attributes */ }; foo = { }; }
|
|
|
|
sec_list_fa = fa_name: nix_def: sec_name: if !hasAttr sec_name nix_def then "" else
|
|
|
|
let
|
|
|
|
elem2yaml = fa_val: other_attrs:
|
|
|
|
" - " + n2y "" { ${fa_name} = fa_val; }
|
|
|
|
+ " " + n2y " " other_attrs
|
|
|
|
+ "\n";
|
|
|
|
sec = nix_def.${sec_name};
|
|
|
|
in
|
|
|
|
sec_name + ":\n" +
|
|
|
|
(if isList sec
|
|
|
|
then flip concatMapStrings sec
|
|
|
|
(elem: elem2yaml elem.${fa_name} (removeAttrs elem [ fa_name ]))
|
|
|
|
else concatStrings (mapAttrsToList elem2yaml sec)
|
|
|
|
);
|
|
|
|
|
|
|
|
# This convertor doesn't care about ordering of attributes.
|
|
|
|
# TODO: it could probably be simplified even more, now that it's not
|
|
|
|
# to be used directly, but we might want some other tweaks, too.
|
|
|
|
n2y = indent: val:
|
|
|
|
if doRecurse val then concatStringsSep "\n${indent}"
|
|
|
|
(mapAttrsToList
|
|
|
|
# This is a bit wacky - set directly under a set would start on bad indent,
|
|
|
|
# so we start those on a new line, but not other types of attribute values.
|
|
|
|
(aname: aval: "${aname}:${if doRecurse aval then "\n${indent} " else " "}"
|
|
|
|
+ n2y (indent + " ") aval)
|
|
|
|
val
|
|
|
|
)
|
|
|
|
+ "\n"
|
|
|
|
else
|
|
|
|
/*
|
|
|
|
if isList val && stringLength indent < 4 then concatMapStrings
|
|
|
|
(elem: "\n${indent}- " + n2y (indent + " ") elem)
|
|
|
|
val
|
|
|
|
else
|
|
|
|
*/
|
|
|
|
if isList val /* and long indent */ then
|
|
|
|
"[ " + concatMapStringsSep ", " quoteString val + " ]" else
|
|
|
|
if isBool val then (if val then "on" else "off") else
|
|
|
|
quoteString val;
|
|
|
|
|
|
|
|
# We don't want paths like ./my-zone.txt be converted to plain strings.
|
|
|
|
quoteString = s: ''"${if builtins.typeOf s == "path" then s else toString s}"'';
|
|
|
|
# We don't want to walk the insides of derivation attributes.
|
|
|
|
doRecurse = val: isAttrs val && !isDerivation val;
|
|
|
|
|
|
|
|
in result;
|
|
|
|
|
2023-08-13 09:43:02 +00:00
|
|
|
configFile = if cfg.settingsFile != null then
|
2023-10-01 08:49:07 +00:00
|
|
|
# Note: with extraConfig, the 23.05 compat code did include keyFiles from settingsFile.
|
|
|
|
assert cfg.settings == {} && (cfg.keyFiles == [] || cfg.extraConfig != null);
|
2023-08-13 09:43:02 +00:00
|
|
|
cfg.settingsFile
|
2023-10-01 08:49:07 +00:00
|
|
|
else
|
|
|
|
mkConfigFile yamlConfig;
|
|
|
|
|
|
|
|
mkConfigFile = configString: pkgs.writeTextFile {
|
2020-02-12 16:35:33 +00:00
|
|
|
name = "knot.conf";
|
2023-10-01 08:49:07 +00:00
|
|
|
text = (concatMapStringsSep "\n" (file: "include: ${file}") cfg.keyFiles) + "\n" + configString;
|
nixos/knot: add support for XDP setups
The Express Data Path (XDP) is a way to circumvent the traditional Linux
networking stack and instead run an eBPF program on your NIC, that makes
the decision to provide Knot with certain packets. This is way faster
and more scalable but comes at the cost of reduced introspection.
Unfortunately the `knotc conf-check` command fails hard with missing
interfaces or IP addresses configured in `xdp.listen`, so we disable it
for now, once the `xdp` config section is set. We also promote the config
check condition to a proper option, so our conditions become public
documentation, and we allow users to deal with corner cases, that we have
not thought of yet.
We follow the pre-requisites documented in the Knot 3.3 manual, and set
up the required capabilities and allow the AF_XDP address family.
But on top of that, due to our strict hardening, we found two more
requirements, that were communicated upstream while debugging this.
- There is a requirement on AF_NETLINK, likely to query for and configure
the relevant network interface
- Running eBPF programs requires access to the `bpf` syscall, which we
deny through the `~@privileged` configuration.
In summary We now conditionally loosen the hardening of the unit once we
detect that an XDP configuration is wanted. And since we cannot
introspect arbitrary files from the `settingsFiles` option, we expose XDP
support through the `enableXDP` toggle option on the module.
2024-02-06 12:25:54 +00:00
|
|
|
checkPhase = lib.optionalString cfg.checkConfig ''
|
2020-02-12 16:35:33 +00:00
|
|
|
${cfg.package}/bin/knotc --config=$out conf-check
|
|
|
|
'';
|
|
|
|
};
|
2019-03-13 00:12:56 +00:00
|
|
|
|
2020-02-12 16:35:33 +00:00
|
|
|
socketFile = "/run/knot/knot.sock";
|
2019-03-13 00:12:56 +00:00
|
|
|
|
|
|
|
knot-cli-wrappers = pkgs.stdenv.mkDerivation {
|
|
|
|
name = "knot-cli-wrappers";
|
2022-09-24 21:28:38 +00:00
|
|
|
nativeBuildInputs = [ pkgs.makeWrapper ];
|
2019-03-13 00:12:56 +00:00
|
|
|
buildCommand = ''
|
|
|
|
mkdir -p $out/bin
|
|
|
|
makeWrapper ${cfg.package}/bin/knotc "$out/bin/knotc" \
|
|
|
|
--add-flags "--config=${configFile}" \
|
|
|
|
--add-flags "--socket=${socketFile}"
|
|
|
|
makeWrapper ${cfg.package}/bin/keymgr "$out/bin/keymgr" \
|
|
|
|
--add-flags "--config=${configFile}"
|
|
|
|
for executable in kdig khost kjournalprint knsec3hash knsupdate kzonecheck
|
|
|
|
do
|
|
|
|
ln -s "${cfg.package}/bin/$executable" "$out/bin/$executable"
|
|
|
|
done
|
|
|
|
mkdir -p "$out/share"
|
|
|
|
ln -s '${cfg.package}/share/man' "$out/share/"
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
in {
|
|
|
|
options = {
|
|
|
|
services.knot = {
|
2024-02-11 16:07:12 +00:00
|
|
|
enable = mkEnableOption "Knot authoritative-only DNS server";
|
2019-03-13 00:12:56 +00:00
|
|
|
|
nixos/knot: add support for XDP setups
The Express Data Path (XDP) is a way to circumvent the traditional Linux
networking stack and instead run an eBPF program on your NIC, that makes
the decision to provide Knot with certain packets. This is way faster
and more scalable but comes at the cost of reduced introspection.
Unfortunately the `knotc conf-check` command fails hard with missing
interfaces or IP addresses configured in `xdp.listen`, so we disable it
for now, once the `xdp` config section is set. We also promote the config
check condition to a proper option, so our conditions become public
documentation, and we allow users to deal with corner cases, that we have
not thought of yet.
We follow the pre-requisites documented in the Knot 3.3 manual, and set
up the required capabilities and allow the AF_XDP address family.
But on top of that, due to our strict hardening, we found two more
requirements, that were communicated upstream while debugging this.
- There is a requirement on AF_NETLINK, likely to query for and configure
the relevant network interface
- Running eBPF programs requires access to the `bpf` syscall, which we
deny through the `~@privileged` configuration.
In summary We now conditionally loosen the hardening of the unit once we
detect that an XDP configuration is wanted. And since we cannot
introspect arbitrary files from the `settingsFiles` option, we expose XDP
support through the `enableXDP` toggle option on the module.
2024-02-06 12:25:54 +00:00
|
|
|
enableXDP = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = lib.hasAttrByPath [ "xdp" "listen" ] cfg.settings;
|
|
|
|
defaultText = ''
|
|
|
|
Enabled when the `xdp.listen` setting is configured through `settings`.
|
|
|
|
'';
|
|
|
|
example = true;
|
|
|
|
description = ''
|
|
|
|
Extends the systemd unit with permissions to allow for the use of
|
|
|
|
the eXpress Data Path (XDP).
|
|
|
|
|
|
|
|
::: {.note}
|
|
|
|
Make sure to read up on functional [limitations](https://www.knot-dns.cz/docs/latest/singlehtml/index.html#mode-xdp-limitations)
|
|
|
|
when running in XDP mode.
|
|
|
|
:::
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
checkConfig = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
# TODO: maybe we could do some checks even when private keys complicate this?
|
|
|
|
# conf-check fails hard on missing IPs/devices with XDP
|
|
|
|
default = cfg.keyFiles == [] && !cfg.enableXDP;
|
|
|
|
defaultText = ''
|
|
|
|
Disabled when the config uses `keyFiles` or `enableXDP`.
|
|
|
|
'';
|
|
|
|
example = false;
|
|
|
|
description = ''
|
|
|
|
Toggles the configuration test at build time. It runs in a
|
|
|
|
sandbox, and therefore cannot be used in all scenarios.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2019-03-13 00:12:56 +00:00
|
|
|
extraArgs = mkOption {
|
|
|
|
type = types.listOf types.str;
|
|
|
|
default = [];
|
2024-02-11 16:07:12 +00:00
|
|
|
description = ''
|
2022-12-18 00:31:14 +00:00
|
|
|
List of additional command line parameters for knotd
|
2019-03-13 00:12:56 +00:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2020-02-12 16:35:33 +00:00
|
|
|
keyFiles = mkOption {
|
|
|
|
type = types.listOf types.path;
|
|
|
|
default = [];
|
2024-02-11 16:07:12 +00:00
|
|
|
description = ''
|
2020-02-12 16:35:33 +00:00
|
|
|
A list of files containing additional configuration
|
|
|
|
to be included using the include directive. This option
|
|
|
|
allows to include configuration like TSIG keys without
|
|
|
|
exposing them to the nix store readable to any process.
|
|
|
|
Note that using this option will also disable configuration
|
|
|
|
checks at build time.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2020-03-01 18:18:34 +00:00
|
|
|
settings = mkOption {
|
|
|
|
type = types.attrs;
|
|
|
|
default = {};
|
2024-02-11 16:07:12 +00:00
|
|
|
description = ''
|
2020-03-01 18:18:34 +00:00
|
|
|
Extra configuration as nix values.
|
2019-03-13 00:12:56 +00:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2023-08-13 09:43:02 +00:00
|
|
|
settingsFile = mkOption {
|
|
|
|
type = types.nullOr types.path;
|
|
|
|
default = null;
|
2024-02-11 16:07:12 +00:00
|
|
|
description = ''
|
2023-08-13 09:43:02 +00:00
|
|
|
As alternative to ``settings``, you can provide whole configuration
|
|
|
|
directly in the almost-YAML format of Knot DNS.
|
2023-10-01 08:49:07 +00:00
|
|
|
You might want to utilize ``pkgs.writeText "knot.conf" "longConfigString"`` for this.
|
2023-08-13 09:43:02 +00:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2023-11-27 00:19:27 +00:00
|
|
|
package = mkPackageOption pkgs "knot-dns" { };
|
2019-03-13 00:12:56 +00:00
|
|
|
};
|
|
|
|
};
|
2023-09-23 07:57:19 +00:00
|
|
|
imports = [
|
2023-10-01 08:49:07 +00:00
|
|
|
# Compatibility with NixOS 23.05.
|
2023-09-23 07:57:19 +00:00
|
|
|
(mkChangedOptionModule [ "services" "knot" "extraConfig" ] [ "services" "knot" "settingsFile" ]
|
2023-10-01 08:49:07 +00:00
|
|
|
(config: mkConfigFile config.services.knot.extraConfig)
|
2023-09-23 07:57:19 +00:00
|
|
|
)
|
|
|
|
];
|
2019-03-13 00:12:56 +00:00
|
|
|
|
|
|
|
config = mkIf config.services.knot.enable {
|
2021-12-04 01:54:50 +00:00
|
|
|
users.groups.knot = {};
|
2020-02-12 16:34:10 +00:00
|
|
|
users.users.knot = {
|
|
|
|
isSystemUser = true;
|
|
|
|
group = "knot";
|
|
|
|
description = "Knot daemon user";
|
|
|
|
};
|
|
|
|
|
2020-03-01 18:18:34 +00:00
|
|
|
environment.etc."knot/knot.conf".source = configFile; # just for user's convenience
|
|
|
|
|
2019-03-13 00:12:56 +00:00
|
|
|
systemd.services.knot = {
|
|
|
|
unitConfig.Documentation = "man:knotd(8) man:knot.conf(5) man:knotc(8) https://www.knot-dns.cz/docs/${cfg.package.version}/html/";
|
|
|
|
description = cfg.package.meta.description;
|
|
|
|
wantedBy = [ "multi-user.target" ];
|
|
|
|
wants = [ "network.target" ];
|
|
|
|
after = ["network.target" ];
|
|
|
|
|
nixos/knot: add support for XDP setups
The Express Data Path (XDP) is a way to circumvent the traditional Linux
networking stack and instead run an eBPF program on your NIC, that makes
the decision to provide Knot with certain packets. This is way faster
and more scalable but comes at the cost of reduced introspection.
Unfortunately the `knotc conf-check` command fails hard with missing
interfaces or IP addresses configured in `xdp.listen`, so we disable it
for now, once the `xdp` config section is set. We also promote the config
check condition to a proper option, so our conditions become public
documentation, and we allow users to deal with corner cases, that we have
not thought of yet.
We follow the pre-requisites documented in the Knot 3.3 manual, and set
up the required capabilities and allow the AF_XDP address family.
But on top of that, due to our strict hardening, we found two more
requirements, that were communicated upstream while debugging this.
- There is a requirement on AF_NETLINK, likely to query for and configure
the relevant network interface
- Running eBPF programs requires access to the `bpf` syscall, which we
deny through the `~@privileged` configuration.
In summary We now conditionally loosen the hardening of the unit once we
detect that an XDP configuration is wanted. And since we cannot
introspect arbitrary files from the `settingsFiles` option, we expose XDP
support through the `enableXDP` toggle option on the module.
2024-02-06 12:25:54 +00:00
|
|
|
serviceConfig = let
|
|
|
|
# https://www.knot-dns.cz/docs/3.3/singlehtml/index.html#pre-requisites
|
|
|
|
xdpCapabilities = lib.optionals (cfg.enableXDP) [
|
|
|
|
"CAP_NET_ADMIN"
|
|
|
|
"CAP_NET_RAW"
|
|
|
|
"CAP_SYS_ADMIN"
|
|
|
|
"CAP_IPC_LOCK"
|
|
|
|
] ++ lib.optionals (lib.versionOlder config.boot.kernelPackages.kernel.version "5.11") [
|
|
|
|
"CAP_SYS_RESOURCE"
|
|
|
|
];
|
|
|
|
in {
|
2019-03-13 00:12:56 +00:00
|
|
|
Type = "notify";
|
2024-02-11 16:07:12 +00:00
|
|
|
ExecStart = escapeSystemdExecArgs ([
|
|
|
|
(lib.getExe cfg.package)
|
|
|
|
"--config=${configFile}"
|
|
|
|
"--socket=${socketFile}"
|
|
|
|
] ++ cfg.extraArgs);
|
|
|
|
ExecReload = escapeSystemdExecArgs [
|
|
|
|
"${knot-cli-wrappers}/bin/knotc" "reload"
|
|
|
|
];
|
2020-02-12 16:34:10 +00:00
|
|
|
User = "knot";
|
2021-12-04 01:54:50 +00:00
|
|
|
Group = "knot";
|
|
|
|
|
|
|
|
AmbientCapabilities = [
|
|
|
|
"CAP_NET_BIND_SERVICE"
|
nixos/knot: add support for XDP setups
The Express Data Path (XDP) is a way to circumvent the traditional Linux
networking stack and instead run an eBPF program on your NIC, that makes
the decision to provide Knot with certain packets. This is way faster
and more scalable but comes at the cost of reduced introspection.
Unfortunately the `knotc conf-check` command fails hard with missing
interfaces or IP addresses configured in `xdp.listen`, so we disable it
for now, once the `xdp` config section is set. We also promote the config
check condition to a proper option, so our conditions become public
documentation, and we allow users to deal with corner cases, that we have
not thought of yet.
We follow the pre-requisites documented in the Knot 3.3 manual, and set
up the required capabilities and allow the AF_XDP address family.
But on top of that, due to our strict hardening, we found two more
requirements, that were communicated upstream while debugging this.
- There is a requirement on AF_NETLINK, likely to query for and configure
the relevant network interface
- Running eBPF programs requires access to the `bpf` syscall, which we
deny through the `~@privileged` configuration.
In summary We now conditionally loosen the hardening of the unit once we
detect that an XDP configuration is wanted. And since we cannot
introspect arbitrary files from the `settingsFiles` option, we expose XDP
support through the `enableXDP` toggle option on the module.
2024-02-06 12:25:54 +00:00
|
|
|
] ++ xdpCapabilities;
|
2021-12-04 01:54:50 +00:00
|
|
|
CapabilityBoundingSet = [
|
|
|
|
"CAP_NET_BIND_SERVICE"
|
nixos/knot: add support for XDP setups
The Express Data Path (XDP) is a way to circumvent the traditional Linux
networking stack and instead run an eBPF program on your NIC, that makes
the decision to provide Knot with certain packets. This is way faster
and more scalable but comes at the cost of reduced introspection.
Unfortunately the `knotc conf-check` command fails hard with missing
interfaces or IP addresses configured in `xdp.listen`, so we disable it
for now, once the `xdp` config section is set. We also promote the config
check condition to a proper option, so our conditions become public
documentation, and we allow users to deal with corner cases, that we have
not thought of yet.
We follow the pre-requisites documented in the Knot 3.3 manual, and set
up the required capabilities and allow the AF_XDP address family.
But on top of that, due to our strict hardening, we found two more
requirements, that were communicated upstream while debugging this.
- There is a requirement on AF_NETLINK, likely to query for and configure
the relevant network interface
- Running eBPF programs requires access to the `bpf` syscall, which we
deny through the `~@privileged` configuration.
In summary We now conditionally loosen the hardening of the unit once we
detect that an XDP configuration is wanted. And since we cannot
introspect arbitrary files from the `settingsFiles` option, we expose XDP
support through the `enableXDP` toggle option on the module.
2024-02-06 12:25:54 +00:00
|
|
|
] ++ xdpCapabilities;
|
2021-12-04 01:54:50 +00:00
|
|
|
DeviceAllow = "";
|
|
|
|
DevicePolicy = "closed";
|
|
|
|
LockPersonality = true;
|
|
|
|
MemoryDenyWriteExecute = true;
|
|
|
|
NoNewPrivileges = true;
|
|
|
|
PrivateDevices = true;
|
|
|
|
PrivateTmp = true;
|
|
|
|
PrivateUsers = false; # breaks capability passing
|
|
|
|
ProcSubset = "pid";
|
|
|
|
ProtectClock = true;
|
|
|
|
ProtectControlGroups = true;
|
|
|
|
ProtectHome = true;
|
|
|
|
ProtectHostname = true;
|
|
|
|
ProtectKernelLogs = true;
|
|
|
|
ProtectKernelModules = true;
|
|
|
|
ProtectKernelTunables = true;
|
|
|
|
ProtectProc = "invisible";
|
|
|
|
ProtectSystem = "strict";
|
|
|
|
RemoveIPC = true;
|
|
|
|
Restart = "on-abort";
|
|
|
|
RestrictAddressFamilies = [
|
|
|
|
"AF_INET"
|
|
|
|
"AF_INET6"
|
|
|
|
"AF_UNIX"
|
2024-02-11 16:07:12 +00:00
|
|
|
] ++ optionals (cfg.enableXDP) [
|
nixos/knot: add support for XDP setups
The Express Data Path (XDP) is a way to circumvent the traditional Linux
networking stack and instead run an eBPF program on your NIC, that makes
the decision to provide Knot with certain packets. This is way faster
and more scalable but comes at the cost of reduced introspection.
Unfortunately the `knotc conf-check` command fails hard with missing
interfaces or IP addresses configured in `xdp.listen`, so we disable it
for now, once the `xdp` config section is set. We also promote the config
check condition to a proper option, so our conditions become public
documentation, and we allow users to deal with corner cases, that we have
not thought of yet.
We follow the pre-requisites documented in the Knot 3.3 manual, and set
up the required capabilities and allow the AF_XDP address family.
But on top of that, due to our strict hardening, we found two more
requirements, that were communicated upstream while debugging this.
- There is a requirement on AF_NETLINK, likely to query for and configure
the relevant network interface
- Running eBPF programs requires access to the `bpf` syscall, which we
deny through the `~@privileged` configuration.
In summary We now conditionally loosen the hardening of the unit once we
detect that an XDP configuration is wanted. And since we cannot
introspect arbitrary files from the `settingsFiles` option, we expose XDP
support through the `enableXDP` toggle option on the module.
2024-02-06 12:25:54 +00:00
|
|
|
"AF_NETLINK"
|
|
|
|
"AF_XDP"
|
2021-12-04 01:54:50 +00:00
|
|
|
];
|
|
|
|
RestrictNamespaces = true;
|
|
|
|
RestrictRealtime =true;
|
|
|
|
RestrictSUIDSGID = true;
|
2019-03-13 00:12:56 +00:00
|
|
|
RuntimeDirectory = "knot";
|
|
|
|
StateDirectory = "knot";
|
|
|
|
StateDirectoryMode = "0700";
|
|
|
|
SystemCallArchitectures = "native";
|
2021-12-04 01:54:50 +00:00
|
|
|
SystemCallFilter = [
|
|
|
|
"@system-service"
|
|
|
|
"~@privileged"
|
nixos/knot: add support for XDP setups
The Express Data Path (XDP) is a way to circumvent the traditional Linux
networking stack and instead run an eBPF program on your NIC, that makes
the decision to provide Knot with certain packets. This is way faster
and more scalable but comes at the cost of reduced introspection.
Unfortunately the `knotc conf-check` command fails hard with missing
interfaces or IP addresses configured in `xdp.listen`, so we disable it
for now, once the `xdp` config section is set. We also promote the config
check condition to a proper option, so our conditions become public
documentation, and we allow users to deal with corner cases, that we have
not thought of yet.
We follow the pre-requisites documented in the Knot 3.3 manual, and set
up the required capabilities and allow the AF_XDP address family.
But on top of that, due to our strict hardening, we found two more
requirements, that were communicated upstream while debugging this.
- There is a requirement on AF_NETLINK, likely to query for and configure
the relevant network interface
- Running eBPF programs requires access to the `bpf` syscall, which we
deny through the `~@privileged` configuration.
In summary We now conditionally loosen the hardening of the unit once we
detect that an XDP configuration is wanted. And since we cannot
introspect arbitrary files from the `settingsFiles` option, we expose XDP
support through the `enableXDP` toggle option on the module.
2024-02-06 12:25:54 +00:00
|
|
|
] ++ optionals (cfg.enableXDP) [
|
|
|
|
"bpf"
|
2021-12-04 01:54:50 +00:00
|
|
|
];
|
|
|
|
UMask = "0077";
|
2019-03-13 00:12:56 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
environment.systemPackages = [ knot-cli-wrappers ];
|
|
|
|
};
|
|
|
|
}
|