143 lines
4.5 KiB
Nix
143 lines
4.5 KiB
Nix
{
|
|
config,
|
|
lib,
|
|
pkgs,
|
|
mylib,
|
|
...
|
|
}:
|
|
with lib;
|
|
let
|
|
allNetns = config.networking.netns;
|
|
dnsIsolatedNetns = filterAttrs (name: cfg: name != "init" && cfg.enableDNSIsolation) allNetns;
|
|
in
|
|
{
|
|
options.networking.netns = mkOption {
|
|
type = types.attrsOf (
|
|
types.submodule (
|
|
{ name, config, ... }:
|
|
{
|
|
options.enableDNSIsolation = mkOption {
|
|
type = types.bool;
|
|
default = true;
|
|
description = ''
|
|
Whether to enable DNS isolation between network namespaces. When disabled,
|
|
DNS requests in this namespace may be exposed to other namespaces.
|
|
'';
|
|
};
|
|
|
|
config = mkIf config.enableDNSIsolation {
|
|
bindMounts = {
|
|
"/run/nscd".hostPath = "/run/${name}/nscd";
|
|
"/etc/resolv.conf".hostPath = "/etc/netns/${name}/resolv.conf";
|
|
"/etc/nsswitch.conf".hostPath = "/etc/netns/${name}/nsswitch.conf";
|
|
"/etc/gai.conf".hostPath = "/etc/netns/${name}/gai.conf";
|
|
};
|
|
};
|
|
}
|
|
)
|
|
);
|
|
};
|
|
|
|
config = {
|
|
# https://flokli.de/posts/2022-11-18-nsncd
|
|
systemd.services = mapAttrs' (
|
|
name: cfg:
|
|
let
|
|
inherit (cfg) netnsPath;
|
|
in
|
|
nameValuePair "netns-${name}-nscd" {
|
|
serviceConfig = mylib.misc.serviceHardened // {
|
|
NetworkNamespacePath = netnsPath;
|
|
BindReadOnlyPaths = [
|
|
"/etc/netns/${name}/resolv.conf:/etc/resolv.conf:norbind"
|
|
"/etc/netns/${name}/nsswitch.conf:/etc/nsswitch.conf:norbind"
|
|
"/etc/netns/${name}/gai.conf:/etc/gai.conf:norbind"
|
|
];
|
|
Type = "notify";
|
|
Restart = "on-failure";
|
|
RestartSec = 5;
|
|
User = "${name}-nscd";
|
|
RuntimeDirectory = "${name}/nscd";
|
|
RuntimeDirectoryPreserve = true;
|
|
ExecStart = "${pkgs.nsncd}/bin/nsncd";
|
|
};
|
|
environment = {
|
|
LD_LIBRARY_PATH = config.system.nssModules.path;
|
|
NSNCD_SOCKET_PATH = "/run/${name}/nscd/socket";
|
|
};
|
|
before = [ "netns-${name}-mntns.service" ];
|
|
after = [
|
|
"netns-${name}.service"
|
|
"network.target"
|
|
];
|
|
partOf = [ "netns-${name}.service" ];
|
|
wantedBy = [
|
|
"multi-user.target"
|
|
"netns-${name}.service"
|
|
];
|
|
}
|
|
) dnsIsolatedNetns;
|
|
|
|
users.users = mapAttrs' (
|
|
name: _cfg:
|
|
nameValuePair "${name}-nscd" {
|
|
isSystemUser = true;
|
|
group = "${name}-nscd";
|
|
}
|
|
) dnsIsolatedNetns;
|
|
|
|
users.groups = mapAttrs' (name: _cfg: nameValuePair "${name}-nscd" { }) dnsIsolatedNetns;
|
|
|
|
environment.etc = listToAttrs (
|
|
flatten (
|
|
mapAttrsToList (name: _cfg: [
|
|
(nameValuePair "netns/${name}/resolv.conf" {
|
|
source = mkDefault (
|
|
pkgs.writeText "netns-default-resolv-conf" ''
|
|
nameserver 2606:4700:4700::1111
|
|
nameserver 2001:4860:4860::8888
|
|
nameserver 1.1.1.1
|
|
nameserver 8.8.8.8
|
|
''
|
|
);
|
|
})
|
|
(nameValuePair "netns/${name}/nsswitch.conf" {
|
|
source = mkDefault (
|
|
pkgs.writeText "netns-default-nsswitch-conf" ''
|
|
passwd: ${concatStringsSep " " config.system.nssDatabases.passwd}
|
|
group: ${concatStringsSep " " config.system.nssDatabases.group}
|
|
shadow: ${concatStringsSep " " config.system.nssDatabases.shadow}
|
|
sudoers: ${concatStringsSep " " config.system.nssDatabases.sudoers}
|
|
|
|
hosts: ${concatStringsSep " " (remove "resolve [!UNAVAIL=return]" config.system.nssDatabases.hosts)}
|
|
networks: files
|
|
|
|
ethers: files
|
|
services: ${concatStringsSep " " config.system.nssDatabases.services}
|
|
protocols: files
|
|
rpc: files
|
|
''
|
|
);
|
|
})
|
|
(nameValuePair "netns/${name}/gai.conf" {
|
|
source = mkDefault (
|
|
pkgs.writeText "netns-default-gai-conf" ''
|
|
label ::1/128 0
|
|
label ::/0 1
|
|
label 2002::/16 2
|
|
label ::/96 3
|
|
label ::ffff:0:0/96 4
|
|
precedence ::1/128 50
|
|
precedence ::/0 40
|
|
precedence 2002::/16 30
|
|
precedence ::/96 20
|
|
precedence ::ffff:0:0/96 10
|
|
''
|
|
);
|
|
})
|
|
]) dnsIsolatedNetns
|
|
)
|
|
);
|
|
};
|
|
}
|