Make a module for Nebula mesh (and fix hardening module)

This commit is contained in:
minish 2024-12-14 18:15:55 -05:00
parent 7599dcac9c
commit 2575562c74
Signed by: min
SSH Key Fingerprint: SHA256:NFjjdbkd6u7aoMlcrDCVvz6o2UBtlAuPm8IQ2vhZ3Fg
11 changed files with 164 additions and 272 deletions

View File

@ -37,25 +37,6 @@
"type": "github" "type": "github"
} }
}, },
"crane_2": {
"inputs": {
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 1717383740,
"narHash": "sha256-559HbY4uhNeoYvK3H6AMZAtVfmR3y8plXZ1x6ON/cWU=",
"owner": "ipetkov",
"repo": "crane",
"rev": "b65673fce97d277934488a451724be94cc62499a",
"type": "github"
},
"original": {
"owner": "ipetkov",
"ref": "v0.17.3",
"repo": "crane",
"type": "github"
}
},
"deploy-rs": { "deploy-rs": {
"inputs": { "inputs": {
"flake-compat": "flake-compat", "flake-compat": "flake-compat",
@ -85,11 +66,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1734011192, "lastModified": 1734088167,
"narHash": "sha256-NghuiWXx6Q3gwLiudiNwDpYQ1CPEUK7J+f9dWREN8KA=", "narHash": "sha256-OIitVU+IstPbX/NWn2jLF+/sT9dVKcO2FKeRAzlyX6c=",
"owner": "nix-community", "owner": "nix-community",
"repo": "disko", "repo": "disko",
"rev": "0f31ad735e784315a22d9899d3ba24340ce64220", "rev": "d32f2d1750d61a476a236526b725ec5a32e16342",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -114,21 +95,6 @@
"type": "github" "type": "github"
} }
}, },
"flake-compat_2": {
"locked": {
"lastModified": 1696426674,
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-parts": { "flake-parts": {
"inputs": { "inputs": {
"nixpkgs-lib": "nixpkgs-lib" "nixpkgs-lib": "nixpkgs-lib"
@ -167,11 +133,11 @@
}, },
"impermanence": { "impermanence": {
"locked": { "locked": {
"lastModified": 1731242966, "lastModified": 1734200366,
"narHash": "sha256-B3C3JLbGw0FtLSWCjBxU961gLNv+BOOBC6WvstKLYMw=", "narHash": "sha256-0NursoP4BUdnc+wy+Mq3icHkXu/RgP1Sjo0MJxV2+Dw=",
"owner": "nix-community", "owner": "nix-community",
"repo": "impermanence", "repo": "impermanence",
"rev": "3ed3f0eaae9fcc0a8331e77e9319c8a4abd8a71a", "rev": "c6323585fa0035d780e3d8906eb1b24b65d19a48",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -198,11 +164,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1733730953, "lastModified": 1734017764,
"narHash": "sha256-dlK7n82FEyZlHH7BFHQAM5tua+lQO1Iv7aAtglc1O5s=", "narHash": "sha256-msOfmyJSjAHgIygI/JD0Ae3JsDv4rT54Nlfr5t6MQMQ=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "7109b680d161993918b0a126f38bc39763e5a709", "rev": "64e9404f308e0f0a0d8cdd7c358f74e34802494b",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -224,74 +190,6 @@
"url": "https://github.com/NixOS/nixpkgs/archive/5487e69da40cbd611ab2cadee0b4637225f7cfae.tar.gz" "url": "https://github.com/NixOS/nixpkgs/archive/5487e69da40cbd611ab2cadee0b4637225f7cfae.tar.gz"
} }
}, },
"nixpkgs-stable": {
"locked": {
"lastModified": 1723556749,
"narHash": "sha256-+CHVZnTnIYRLYsARInHYoWkujzcRkLY/gXm3s5bE52o=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "4a92571f9207810b559c9eac203d1f4d79830073",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-24.05",
"type": "indirect"
}
},
"nixpkgs-unstable": {
"locked": {
"lastModified": 1723637854,
"narHash": "sha256-med8+5DSWa2UnOqtdICndjDAEjxr5D7zaIiK4pn0Q7c=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "c3aa7b8938b17aebd2deecf7be0636000d62a2b9",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-unstable",
"type": "indirect"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1714656196,
"narHash": "sha256-kjQkA98lMcsom6Gbhw8SYzmwrSo+2nruiTcTZp5jK7o=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "94035b482d181af0a0f8f77823a790b256b7c3cc",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"proxmox-nixos": {
"inputs": {
"crane": "crane_2",
"flake-compat": "flake-compat_2",
"nixpkgs-stable": "nixpkgs-stable",
"nixpkgs-unstable": "nixpkgs-unstable",
"utils": "utils_2"
},
"locked": {
"lastModified": 1732473775,
"narHash": "sha256-WnckT473A+DcYYdzLFWgP4RSAvBNaSRw7fJuKySX+Og=",
"owner": "SaumonNet",
"repo": "proxmox-nixos",
"rev": "06fbc351ff461d26a8276f44088450c965195e10",
"type": "github"
},
"original": {
"owner": "SaumonNet",
"repo": "proxmox-nixos",
"type": "github"
}
},
"root": { "root": {
"inputs": { "inputs": {
"breeze": "breeze", "breeze": "breeze",
@ -301,7 +199,6 @@
"impermanence": "impermanence", "impermanence": "impermanence",
"min-rip": "min-rip", "min-rip": "min-rip",
"nixpkgs": "nixpkgs", "nixpkgs": "nixpkgs",
"proxmox-nixos": "proxmox-nixos",
"sops-nix": "sops-nix" "sops-nix": "sops-nix"
} }
}, },
@ -355,21 +252,6 @@
"type": "github" "type": "github"
} }
}, },
"systems_3": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"utils": { "utils": {
"inputs": { "inputs": {
"systems": "systems_2" "systems": "systems_2"
@ -387,24 +269,6 @@
"repo": "flake-utils", "repo": "flake-utils",
"type": "github" "type": "github"
} }
},
"utils_2": {
"inputs": {
"systems": "systems_3"
},
"locked": {
"lastModified": 1710146030,
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
} }
}, },
"root": "root", "root": "root",

View File

@ -17,8 +17,6 @@
impermanence.url = "github:nix-community/impermanence"; impermanence.url = "github:nix-community/impermanence";
proxmox-nixos.url = "github:SaumonNet/proxmox-nixos";
min-rip.url = "git+ssh://git@git.min.rip/min/min.rip.git"; min-rip.url = "git+ssh://git@git.min.rip/min/min.rip.git";
min-rip.flake = false; min-rip.flake = false;
@ -26,15 +24,6 @@
breeze.inputs.nixpkgs.follows = "nixpkgs"; breeze.inputs.nixpkgs.follows = "nixpkgs";
}; };
nixConfig = {
extra-substituters = [
"https://cache.saumon.network/proxmox-nixos"
];
extra-trusted-public-keys = [
"proxmox-nixos:nveXDuVVhFDRFx8Dn19f1WDEaNRJjPrF2CPD2D+m1ys="
];
};
outputs = inputs @ {self, ...}: outputs = inputs @ {self, ...}:
inputs.flake-parts.lib.mkFlake {inherit inputs;} { inputs.flake-parts.lib.mkFlake {inherit inputs;} {
flake = let flake = let

View File

@ -1,11 +1,5 @@
{config, ...}: let {config, ...}: let
netName = "m-infra"; inherit (import ../../modules/nebula/shared.nix) userGroup;
# https://github.com/NixOS/nixpkgs/blob/nixos-24.05/nixos/modules/services/networking/nebula.nix#L12
userGroup = "nebula-${netName}";
interface = "nebula.${netName}";
service = "nebula@${netName}.service";
lhs = {"10.13.0.1" = ["min.rip:4242"];}; # TODO: hardcoding
lhsInt = builtins.attrNames lhs;
in { in {
sops.secrets."nebula-key" = { sops.secrets."nebula-key" = {
mode = "0440"; mode = "0440";
@ -13,49 +7,14 @@ in {
group = userGroup; group = userGroup;
}; };
networking.firewall.trustedInterfaces = [interface]; gen.nebula = {
enable = true;
enableLighthouse = false;
# Make sure sshd starts after nebula
systemd.services.sshd.after = [service];
services.nebula.networks.${netName} = {
ca = ../../keys/ca.crt;
cert = ../../keys/n-srv-eidola.crt; cert = ../../keys/n-srv-eidola.crt;
key = config.sops.secrets."nebula-key".path; key = config.sops.secrets."nebula-key".path;
lighthouses = lhsInt; extraInbound = [
relays = lhsInt;
staticHostMap = lhs;
settings.punchy.punch = true;
firewall.outbound = [
{
port = "any";
proto = "any";
host = "any";
}
];
firewall.inbound = [
# Allow pings from anyone
{
port = "any";
proto = "icmp";
host = "any";
}
# Allow anything from `internal` group
{
port = "any";
proto = "any";
groups = ["internal"];
}
# Allow SSH from anyone
{
port = 22;
proto = "tcp";
host = "any";
}
# Allow iperf3 from anyone # Allow iperf3 from anyone
{ {
port = 5201; port = 5201;

View File

@ -3,7 +3,7 @@
disk = { disk = {
main = { main = {
type = "disk"; type = "disk";
device = "/dev/vda"; # TODO: hardcoding (not sure if fixable) device = "/dev/vda";
content = { content = {
type = "gpt"; type = "gpt";

View File

@ -1,5 +1,5 @@
{...}: { {...}: {
sops = { # TODO: hardcoding sops = {
defaultSopsFile = ../../../secrets/silver.yaml; defaultSopsFile = ../../../secrets/silver.yaml;
age.sshKeyPaths = ["/persist/etc/ssh/ssh_host_ed25519_key"]; age.sshKeyPaths = ["/persist/etc/ssh/ssh_host_ed25519_key"];

View File

@ -1,8 +1,5 @@
{config, ...}: let {config, ...}: let
netName = "m-infra"; # TODO: hardcoding inherit (import ../../../modules/nebula/shared.nix) userGroup;
# https://github.com/NixOS/nixpkgs/blob/nixos-24.05/nixos/modules/services/networking/nebula.nix#L12
userGroup = "nebula-${netName}";
interface = "nebula.${netName}";
in { in {
sops.secrets."svc-nebula-key" = { sops.secrets."svc-nebula-key" = {
mode = "0440"; mode = "0440";
@ -10,51 +7,15 @@ in {
group = userGroup; group = userGroup;
}; };
networking.firewall = { networking.firewall.allowedUDPPorts = [4242];
trustedInterfaces = [interface];
allowedUDPPorts = [4242]; gen.nebula = {
}; enable = true;
enableLighthouse = true;
services.nebula.networks.${netName} = {
ca = ../../../keys/ca.crt;
cert = ../../../keys/lh-silver.crt; cert = ../../../keys/lh-silver.crt;
key = config.sops.secrets."svc-nebula-key".path; key = config.sops.secrets."svc-nebula-key".path;
isLighthouse = true; extraInbound = [];
isRelay = true;
listen = {
host = "0.0.0.0";
port = 4242;
};
firewall.outbound = [
{
port = "any";
proto = "any";
host = "any";
}
];
firewall.inbound = [
# Allow pings from anyone
{
port = "any";
proto = "icmp";
host = "any";
}
# Allow anything from `internal` group
{
port = "any";
proto = "any";
groups = ["internal"];
}
# Allow SSH from anyone
{
port = 22;
proto = "tcp";
host = "any";
}
];
}; };
} }

View File

@ -2,23 +2,24 @@
config, config,
lib, lib,
... ...
}: let }:
with lib; let
baseCfg = config.gen.bootloader; baseCfg = config.gen.bootloader;
cfg = baseCfg.luksSsh; cfg = baseCfg.luksSsh;
in { in {
options.gen.bootloader.luksSsh = { options.gen.bootloader.luksSsh = {
enable = lib.mkEnableOption "use boot process with luks unlock over ssh"; enable = mkEnableOption "use boot process with luks unlock over ssh";
port = lib.mkOption { port = mkOption {
type = lib.types.port; type = types.port;
description = "port for ssh server to listen on"; description = "port for ssh server to listen on";
}; };
hostKeys = lib.mkOption { hostKeys = mkOption {
type = lib.types.listOf lib.types.path; type = types.listOf types.path;
description = "paths of host keys for the ssh server to use"; description = "paths of host keys for the ssh server to use";
}; };
}; };
config = lib.mkIf cfg.enable { config = mkIf cfg.enable {
# ### Use systemd-boot ### # ### Use systemd-boot ###
# boot.loader = { # boot.loader = {
# efi.canTouchEfiVariables = true; # efi.canTouchEfiVariables = true;

View File

@ -5,6 +5,7 @@
}: { }: {
imports = [ imports = [
./boot ./boot
./nebula
./hardening.nix ./hardening.nix
./limits.nix ./limits.nix

View File

@ -2,20 +2,21 @@
config, config,
lib, lib,
... ...
}: let }:
with lib; let
cfg = config.gen.hardening; cfg = config.gen.hardening;
in { in {
options.gen.hardening = { options.gen.hardening = {
hardenBpf = lib.mkEnableOption "place heavier restrictions on BPF"; hardenBpf = mkEnableOption "place heavier restrictions on BPF";
fullRpFilter = lib.mkEnableOption "enable full reverse path filtering. breaks dynamic routing, probably"; fullRpFilter = mkEnableOption "full reverse path filtering. (breaks dynamic routing, probably)";
ignoreIcmpEcho = lib.mkEnableOption "ignore icmp echos. obviously, this makes pings unresponsive"; ignoreIcmpEcho = mkEnableOption "ignore icmp echos. (obviously, this makes pings unresponsive)";
disableSack = lib.mkEnableOption "disable tcp sack"; disableSack = mkEnableOption "disable tcp sack";
disableConsole = lib.mkEnableOption "disable console. not recommended for test machines"; disableConsole = mkEnableOption "disable console. (not recommended for test machines)";
}; };
config = { config = {
### Sysctls ### ### Sysctls ###
boot.kernel.sysctl = boot.kernel.sysctl = mkMerge [
{ {
"kernel.kptr_restrict" = 1; "kernel.kptr_restrict" = 1;
"kernel.dmesg_restrict" = 1; "kernel.dmesg_restrict" = 1;
@ -27,22 +28,23 @@ in {
"kernel.perf_event_paranoid" = 3; "kernel.perf_event_paranoid" = 3;
"net.ipv4.tcp_rfc1337" = 1; # drop RSTs during time-wait state "net.ipv4.tcp_rfc1337" = 1; # drop RSTs during time-wait state
} }
// lib.mkIf cfg.ignoreIcmpEcho { (mkIf cfg.ignoreIcmpEcho {
"net.ipv4.icmp_echo_ignore_all" = 1; "net.ipv4.icmp_echo_ignore_all" = 1;
} })
// lib.mkIf cfg.hardenBpf { (mkIf cfg.hardenBpf {
"kernel.unprivileged_bpf_disabled" = 1; "kernel.unprivileged_bpf_disabled" = 1;
"net.core.bpf_jit_harden" = 2; "net.core.bpf_jit_harden" = 2;
} })
// lib.mkIf cfg.fullRpFilter { (mkIf cfg.fullRpFilter {
"net.ipv4.conf.all.rp_filter" = 1; "net.ipv4.conf.all.rp_filter" = 1;
"net.ipv4.conf.default.rp_filter" = 1; "net.ipv4.conf.default.rp_filter" = 1;
} })
// lib.mkIf cfg.disableSack { (mkIf cfg.disableSack {
"net.ipv4.tcp_sack" = 0; "net.ipv4.tcp_sack" = 0;
"net.ipv4.tcp_dsack" = 0; "net.ipv4.tcp_dsack" = 0;
"net.ipv4.tcp_fack" = 0; "net.ipv4.tcp_fack" = 0;
}; })
];
### Security options ### ### Security options ###
security.protectKernelImage = true; security.protectKernelImage = true;

View File

@ -0,0 +1,107 @@
{
config,
lib,
...
}:
with lib; let
inherit (import ./shared.nix) netName interface service;
ca = ../../keys/ca.crt;
baseFirewall = {
outbound = [
# Allow all outbound traffic
{
port = "any";
proto = "any";
host = "any";
}
];
inbound = [
# Allow pings from anyone
{
port = "any";
proto = "icmp";
host = "any";
}
# Allow anything from `internal` group
{
port = "any";
proto = "any";
groups = ["internal"];
}
# Allow SSH from anyone
{
port = 22;
proto = "tcp";
host = "any";
}
];
};
baseServer = {
isLighthouse = true;
isRelay = true;
listen = {
host = "0.0.0.0";
port = 4242;
};
};
baseClient = let
lhs = {"10.13.0.1" = ["min.rip:4242"];};
lhsInternal = attrNames lhs;
in {
lighthouses = lhsInternal;
relays = lhsInternal;
staticHostMap = lhs;
settings.punchy.punch = true;
};
cfg = config.gen.nebula;
in {
options.gen.nebula = {
enable = mkEnableOption "nebula mesh vpn";
enableLighthouse = mkEnableOption "lighthouse functionality";
cert = mkOption {
type = types.path;
description = "nebula node cert path";
};
key = mkOption {
type = types.path;
description = "nebula node key path";
};
extraInbound = mkOption {
type = types.listOf types.attrs;
description = "extra inbound firewall rules";
};
};
config = mkMerge [
(mkIf cfg.enable {
networking.firewall.trustedInterfaces = [interface];
services.nebula.networks.${netName} = mkMerge [
{
inherit ca;
inherit (cfg) cert key;
firewall = {
inherit (baseFirewall) outbound;
inbound = baseFirewall.inbound ++ cfg.extraInbound;
};
}
(mkIf cfg.enableLighthouse baseServer)
(mkIf (!cfg.enableLighthouse) baseClient)
];
})
(mkIf config.services.openssh.enable {
# Make sure sshd starts after nebula
# TODO: is this necessary?
systemd.services.sshd.after = [service];
})
];
}

View File

@ -0,0 +1,8 @@
rec {
netName = "m-infra";
# https://github.com/NixOS/nixpkgs/blob/nixos-24.05/nixos/modules/services/networking/nebula.nix
interface = "nebula.${netName}";
userGroup = "nebula-${netName}";
service = "nebula@${netName}.service";
}