feat: improved netbird client module

This commit is contained in:
Patrick 2024-03-28 10:52:07 +01:00
parent 28b1b59e82
commit 5d681b78f3
Signed by: patrick
GPG key ID: 451F95EFB8BECD0F
4 changed files with 341 additions and 5 deletions

View file

@ -0,0 +1,15 @@
age-encryption.org/v1
-> X25519 FTk4whtXQ4QKgotU+0iBZxrUcUVQReiHyhGwv/3pC2w
PGSxFJqC21n737Jyc4pQgv/7tsblQBB47dZlfNynOC0
-> piv-p256 XTQkUA A1mVNcwBxkH0rysZRt1irvyi0k0ME5sccJox/xS1FRC4
Sy6Zz0a+Y5Z7J6F9M/b1OEKOau5JQm5JAUFsl4Ewk6k
-> piv-p256 ZFgiIw AsVavBKMJ+/39us+c0k7niiJab3Ev4Dj+SOo8SH73g3S
ZoUlA/qcdfJ6ctaCeQ/OQYu2wFrIqJ5aR0/aPXCjl4o
-> piv-p256 5vmPtQ AnX/v0upSdNStu6uCpC3nVdqWsxX/iUjTpDvKwsdJfNs
lUR+WRlyxqqRuO0hBai6hdYk4ytpEL8SbQHxmR7sK94
-> piv-p256 ZFgiIw Ax5SdGlJs1Gqusw6Lag/9bOuib7Ts3bksfdVN/FGRB4D
Euvy40vrJVrC+W27xYHb0muLuK5SIPmY0zv3+SJgAy4
-> z:&o*}s-grease 4eL2m
xIA4Vo9Z8niU+0+FsD8P6RsdLC/duMh4XtoLu3jYwuh3vA
--- TKHpQOtXIUtjoH4HNwcW5gKI8g9Ou6pXbNtt5ba0qQY
qà{+ëÝp˜l>µ¯<C2B5>]v‡í˜7„Kl£Ý…B"àP»Ð¼)Ô3oÂK[«(3õ> §ÐXU "€þ¯£å=^Ž£j”Á•²ƒ¿TUw°Ýu

226
modules/netbird-client.nix Normal file
View file

@ -0,0 +1,226 @@
{
config,
lib,
pkgs,
...
}: let
inherit
(lib)
attrNames
getExe
literalExpression
maintainers
mapAttrs'
mkDefault
mkEnableOption
mkIf
mkMerge
mkOption
mkPackageOption
nameValuePair
optional
versionOlder
;
inherit
(lib.types)
attrsOf
port
str
submodule
path
;
kernel = config.boot.kernelPackages;
cfg = config.services.netbird;
in {
meta.maintainers = with maintainers; [
misuzu
thubrecht
patrickdag
];
meta.doc = ./netbird.md;
options.services.netbird = {
enable = mkEnableOption (lib.mdDoc "Netbird daemon");
package = mkPackageOption pkgs "netbird" {};
tunnels = mkOption {
type = attrsOf (
submodule (
{
name,
config,
...
}: {
options = {
port = mkOption {
type = port;
default = 51820;
description = ''
Port for the ${name} netbird interface.
'';
};
autoStart = mkEnableOption '' automatically starting this tunnel on startup.
Need a setup key to work.
'';
environmentFile = mkOption {
type = path;
description = "An additional environment file for this service.";
};
environment = mkOption {
type = attrsOf str;
defaultText = literalExpression ''
{
NB_CONFIG = "/var/lib/''${stateDir}/config.json";
NB_LOG_FILE = "console";
NB_WIREGUARD_PORT = builtins.toString port;
NB_INTERFACE_NAME = name;
NB_DAMEON_ADDR = "/var/run/''${stateDir}"
}
'';
description = ''
Environment for the netbird service, used to pass configuration options.
'';
};
stateDir = mkOption {
type = str;
default = "netbird-${name}";
description = ''
Directory storing the netbird configuration.
'';
};
};
config.environment = builtins.mapAttrs (_: mkDefault) {
NB_CONFIG = "/var/lib/${config.stateDir}/config.json";
NB_LOG_FILE = "console";
NB_WIREGUARD_PORT = builtins.toString config.port;
NB_INTERFACE_NAME = name;
NB_DAEMON_ADDR = "unix:///var/run/${config.stateDir}/sock";
};
}
)
);
default = {};
description = ''
Attribute set of Netbird tunnels, each one will spawn a daemon listening on ...
'';
};
};
config = mkMerge [
(mkIf cfg.enable {
# For backwards compatibility
services.netbird.tunnels.wt0.stateDir = "netbird";
})
(mkIf (cfg.tunnels != {}) {
boot.extraModulePackages = optional (versionOlder kernel.kernel.version "5.6") kernel.wireguard;
environment.systemPackages = [cfg.package];
networking.dhcpcd.denyInterfaces = attrNames cfg.tunnels;
systemd.network.networks = mkIf config.networking.useNetworkd (
mapAttrs'
(
name: _:
nameValuePair "50-netbird-${name}" {
matchConfig = {
Name = name;
};
linkConfig = {
Unmanaged = true;
ActivationPolicy = "manual";
};
}
)
cfg.tunnels
);
systemd.services =
mapAttrs'
(
name: {
environment,
stateDir,
environmentFile,
autoStart,
...
}:
nameValuePair "netbird-${name}" {
description = "A WireGuard-based mesh network that connects your devices into a single private network";
documentation = ["https://netbird.io/docs/"];
after = ["network.target"];
wantedBy = ["multi-user.target"];
path = with pkgs; [openresolv];
inherit environment;
serviceConfig = {
EnvironmentFile = environmentFile;
ExecStart = "${getExe cfg.package} service run";
ExecStartPost = mkIf autoStart "${getExe cfg.package} up";
Restart = "always";
RuntimeDirectory = stateDir;
StateDirectory = stateDir;
StateDirectoryMode = "0700";
WorkingDirectory = "/var/lib/${stateDir}";
# hardening
LockPersonality = true;
MemoryDenyWriteExecute = true;
NoNewPrivileges = true;
PrivateMounts = true;
PrivateTmp = true;
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = false; # needed to load wg module for kernel-mode WireGuard
ProtectKernelTunables = false;
ProtectSystem = true;
RemoveIPC = true;
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
# Hardening
CapabilityBoundingSet = "";
PrivateUsers = true;
ProtectProc = "invisible";
ProcSubset = "pid";
RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
"AF_NETLINK"
];
SystemCallArchitectures = "native";
SystemCallFilter = [
"@system-service"
"@pkey"
];
UMask = "0077";
};
unitConfig = {
StartLimitInterval = 5;
StartLimitBurst = 10;
};
stopIfChanged = false;
}
)
cfg.tunnels;
})
];
}

View file

@ -23,6 +23,7 @@ in {
package = mkPackageOption pkgs "netbird" {}; package = mkPackageOption pkgs "netbird" {};
enableCoturn = mkEnableOption "the coturn service for running the TURN/STUN server"; enableCoturn = mkEnableOption "the coturn service for running the TURN/STUN server";
domain = mkOption { domain = mkOption {
type = types.str;
description = "The domain of your netbird instance"; description = "The domain of your netbird instance";
}; };
port = mkOption { port = mkOption {
@ -93,7 +94,8 @@ in {
Stuns = [ Stuns = [
{ {
Proto = "udp"; Proto = "udp";
Uri = "turn:${cfg.turn.domain}:${toString cfg.turn.port}"; Uri = "stun:${cfg.turn.domain}:${toString cfg.turn.port}";
# TODO fairly certain with this config anyone can use your STUN server
Username = ""; Username = "";
Password = null; Password = null;
} }
@ -102,13 +104,14 @@ in {
Turns = [ Turns = [
{ {
Proto = "udp"; Proto = "udp";
Uri = "stun:${cfg.turn.domain}:${toString cfg.turn.port}"; Uri = "turn:${cfg.turn.domain}:${toString cfg.turn.port}";
Username = cfg.turn.userName; Username = cfg.turn.userName;
Password = cfg.turn.password; Password = cfg.turn.password;
} }
]; ];
CredentialsTTL = "12h"; CredentialsTTL = "12h";
Secret = lib.trace "this should probably be an option as well" "secret"; # This is not used with the standard coturn configuration
Secret = "secret";
TimeBasedCredentials = false; TimeBasedCredentials = false;
}; };
@ -170,7 +173,7 @@ in {
# Official documentation says that external-ip has to be # Official documentation says that external-ip has to be
# an IP which is not true as [this](https://github.com/coturn/coturn/blob/9b1cca1fbe909e7cc7c7ac28865f9c190af3515b/src/client/ns_turn_ioaddr.c#L234) # an IP which is not true as [this](https://github.com/coturn/coturn/blob/9b1cca1fbe909e7cc7c7ac28865f9c190af3515b/src/client/ns_turn_ioaddr.c#L234)
# will resolve and dns name as well # will resolve a dns name as well
extraConfig = '' extraConfig = ''
fingerprint fingerprint
@ -197,6 +200,43 @@ in {
RuntimeDirectory = "netbird-mgmt"; RuntimeDirectory = "netbird-mgmt";
StateDirectory = "netbird-mgmt"; StateDirectory = "netbird-mgmt";
WorkingDirectory = "/var/lib/netbird-mgmt"; WorkingDirectory = "/var/lib/netbird-mgmt";
RestartSec = "60";
# hardening
LockPersonality = true;
MemoryDenyWriteExecute = true;
NoNewPrivileges = true;
PrivateMounts = true;
PrivateTmp = true;
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectSystem = true;
RemoveIPC = true;
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
# Hardening
CapabilityBoundingSet = "";
PrivateUsers = true;
ProtectProc = "invisible";
ProcSubset = "pid";
RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
"AF_NETLINK"
];
SystemCallArchitectures = "native";
SystemCallFilter = [
"@system-service"
"@pkey"
];
UMask = "0077";
}; };
unitConfig = { unitConfig = {
StartLimitInterval = 5; StartLimitInterval = 5;
@ -222,6 +262,7 @@ in {
]; ];
serviceConfig = { serviceConfig = {
# Should we automatically disable metrics?
ExecStart = '' ExecStart = ''
${cfg.package}/bin/netbird-mgmt management \ ${cfg.package}/bin/netbird-mgmt management \
--config ${configFile} \ --config ${configFile} \
@ -236,7 +277,7 @@ in {
--port ${builtins.toString cfg.port} \ --port ${builtins.toString cfg.port} \
--log-file console --log-file console
''; '';
# TODO add extraCOmmandLine option # TODO add extraCommandLine option
Restart = "always"; Restart = "always";
RuntimeDirectory = "netbird-mgmt"; RuntimeDirectory = "netbird-mgmt";
StateDirectory = [ StateDirectory = [
@ -244,6 +285,42 @@ in {
"netbird-mgmt/data" "netbird-mgmt/data"
]; ];
WorkingDirectory = "/var/lib/netbird-mgmt"; WorkingDirectory = "/var/lib/netbird-mgmt";
# hardening
LockPersonality = true;
MemoryDenyWriteExecute = true;
NoNewPrivileges = true;
PrivateMounts = true;
PrivateTmp = true;
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectSystem = true;
RemoveIPC = true;
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
# Hardening
CapabilityBoundingSet = "";
PrivateUsers = true;
ProtectProc = "invisible";
ProcSubset = "pid";
RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
"AF_NETLINK"
];
SystemCallArchitectures = "native";
SystemCallFilter = [
"@system-service"
"@pkey"
];
UMask = "0077";
}; };
unitConfig = { unitConfig = {
StartLimitInterval = 5; StartLimitInterval = 5;

View file

@ -3,10 +3,28 @@
lib, lib,
... ...
}: { }: {
age.secrets.netbird = {
rekeyFile = config.node.secretsDir + "/netbird-env.age";
mode = "440";
};
services.samba-wsdd = { services.samba-wsdd = {
enable = true; # make shares visible for windows 10 clients enable = true; # make shares visible for windows 10 clients
openFirewall = true; openFirewall = true;
}; };
disabledModules = ["services/networking/netbird.nix"];
imports = [../netbird-client.nix];
services.netbird.tunnels = {
samba = {
environment.NB_MANAGEMENT_URL = "https://netbird.${config.secrets.secrets.global.domains.web}";
autoStart = true;
port = 56789;
environmentFile = config.age.secrets.netbird.path;
};
};
age.secrets.resticpasswd = { age.secrets.resticpasswd = {
generator.script = "alnum"; generator.script = "alnum";
}; };