summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--hosts/apocalypse/default.nix2
-rw-r--r--hosts/apocalypse/firewall.nix29
-rw-r--r--hosts/omega-relay/firewall.nix47
-rw-r--r--hosts/tacitus/network.nix26
-rw-r--r--inventory.nix60
-rw-r--r--modules/default.nix1
-rw-r--r--modules/firewall.nix132
-rw-r--r--modules/prometheus.nix185
9 files changed, 361 insertions, 124 deletions
diff --git a/.gitignore b/.gitignore
index 9e91979..150aa83 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,4 +3,5 @@
*.pass
*_ed25519.pub
*_ed25519
-secrets/*.pem
+secrets/*.pem
+.hidden
diff --git a/hosts/apocalypse/default.nix b/hosts/apocalypse/default.nix
index cb81aa7..238ab09 100644
--- a/hosts/apocalypse/default.nix
+++ b/hosts/apocalypse/default.nix
@@ -13,6 +13,8 @@
"127.0.0.1" = [ "apocalypse.local" ];
};
+ wilkuu.services.prometheus.enableExporters = true;
+
services.logind.settings.Login = {
HandleLidSwitch = "suspend";
HandleLidSwitchExternalPower = "lock";
diff --git a/hosts/apocalypse/firewall.nix b/hosts/apocalypse/firewall.nix
index f45d4f7..4bc4b32 100644
--- a/hosts/apocalypse/firewall.nix
+++ b/hosts/apocalypse/firewall.nix
@@ -3,6 +3,7 @@ let
baseTCP = [
22000 # Syncthng
5352 # Zeroconf for spotifyd
+ 22 # ssh
];
baseUDP = [
22000 # Syncthing
@@ -24,7 +25,6 @@ let
];
secureTCP = [
- 22
80
433
5900 # SSH HTTP VNC
@@ -42,23 +42,28 @@ let
];
in
{
- environment.etc.hosts.mode = "0644";
- networking.nftables.enable = true;
- networking.firewall = {
- enable = false;
- checkReversePath = false;
- allowedTCPPorts = baseTCP;
- allowedUDPPorts = baseUDP;
- allowedUDPPortRanges = baseUDPRanges;
- allowedTCPPortRanges = baseTCPRanges;
- interfaces = {
- "nix-laptop" = {
+ wilkuu.firewall = {
+ enable = true;
+ defaultLayer = "external";
+ layers = {
+ internal = {
allowedTCPPorts = secureTCP;
allowedUDPPorts = secureUDP;
allowedUDPPortRanges = secureUDPRanges;
allowedTCPPortRanges = secureTCPRanges;
};
+ external = {
+ allowedTCPPorts = baseTCP;
+ allowedUDPPorts = baseUDP;
+ allowedUDPPortRanges = baseUDPRanges;
+ allowedTCPPortRanges = baseTCPRanges;
+ };
};
+ };
+ environment.etc.hosts.mode = "0644";
+ networking.nftables.enable = true;
+ networking.firewall = {
+ enable = true;
trustedInterfaces = [
"docker0"
"br-*"
diff --git a/hosts/omega-relay/firewall.nix b/hosts/omega-relay/firewall.nix
index 0e82fea..8e35fa3 100644
--- a/hosts/omega-relay/firewall.nix
+++ b/hosts/omega-relay/firewall.nix
@@ -1,5 +1,12 @@
-{ config, lib, ... }:
+{
+ config,
+ lib,
+ inventory,
+ self_name,
+ ...
+}:
let
+ net = inventory.${self_name}.interfaces;
wgHomePort = 16888;
baseTCP = [
20
@@ -23,16 +30,7 @@ let
secureTCP = [
# config.wilkuu.services.mysql.port
- ]
- ++ lib.mapAttrsToList (_: opt: opt.port) (
- lib.filterAttrs (
- _: e:
- let
- evaluated = builtins.tryEval e;
- in
- evaluated.success && e ? enable && e.enable
- ) config.services.prometheus.exporters
- );
+ ];
secureUDP = [
];
@@ -63,7 +61,7 @@ in
useNetworkd = true;
interfaces = {
wg-home = {
- ips = [ "192.168.80.100/24" ];
+ ips = [ "${net.wg-home.ip}/24" ];
extraOptions = {
DNS = "192.168.88.1";
};
@@ -113,24 +111,27 @@ in
linkConfig.RequiredForOnline = "routable";
};
- networking.useDHCP = false;
- networking.useNetworkd = true;
- networking.nftables.enable = true;
- networking.firewall = {
+ wilkuu.firewall = {
enable = true;
- checkReversePath = false;
- allowedTCPPorts = baseTCP;
- allowedUDPPorts = baseUDP;
- allowedUDPPortRanges = baseUDPRanges;
- allowedTCPPortRanges = baseTCPRanges;
- interfaces = {
- "wg-home" = {
+ defaultLayer = "external";
+ layers = {
+ external = {
+ allowedTCPPorts = baseTCP;
+ allowedUDPPorts = baseUDP;
+ allowedUDPPortRanges = baseUDPRanges;
+ allowedTCPPortRanges = baseTCPRanges;
+ };
+ internal = {
allowedTCPPorts = secureTCP;
allowedUDPPorts = secureUDP;
allowedUDPPortRanges = secureUDPRanges;
allowedTCPPortRanges = secureTCPRanges;
};
};
+ };
+ networking.useDHCP = false;
+ networking.useNetworkd = true;
+ networking.firewall = {
trustedInterfaces = [
"docker0"
"br-*"
diff --git a/hosts/tacitus/network.nix b/hosts/tacitus/network.nix
index 513d89c..9b3beef 100644
--- a/hosts/tacitus/network.nix
+++ b/hosts/tacitus/network.nix
@@ -48,27 +48,21 @@ in
];
};
};
- networking = {
- useNetworkd = true;
- nftables.enable = true;
- useDHCP = true;
- firewall = {
- # check enable = true;
- checkReversePath = false;
+
+ wilkuu.firewall = {
+ enable = true;
+ defaultLayer = "internal";
+ layers.internal = {
allowedTCPPorts = baseTCP;
allowedUDPPorts = baseUDP;
allowedUDPPortRanges = baseUDPRanges;
allowedTCPPortRanges = baseTCPRanges;
- # TODO: Figure out how to do FW that allows only on the internal ip range
- #interfaces = {
- # "wg-home" = {
- # allowedTCPPorts = secureTCP;
- # allowedUDPPorts = secureUDP;
- # allowedUDPPortRanges = secureUDPRanges;
- # allowedTCPPortRanges = secureTCPRanges;
- # };
- #};
};
};
+ networking = {
+ useNetworkd = true;
+ nftables.enable = true;
+ useDHCP = true;
+ };
}
diff --git a/inventory.nix b/inventory.nix
index db3d3f9..a476191 100644
--- a/inventory.nix
+++ b/inventory.nix
@@ -7,7 +7,27 @@
./users/wilkuu-server.nix
inputs.stalwart-nix.nixosModules.default
];
- interfaces = { };
+ monitoring = {
+ internal = [
+ "wireguard"
+ "fail2ban"
+ "node"
+ ];
+ };
+ interfaces = {
+ wg-home = {
+ type = "wireguard";
+ layer = "internal";
+ ip = "192.168.80.100";
+ };
+ enp6s18 = {
+ type = "eth-networkd";
+ layer = "external";
+ ip = "45.136.141.133";
+ ip6 = "2a12:bec0:650:128::133/64";
+ };
+ };
+
};
apocalypse = {
type = "desktop";
@@ -16,8 +36,24 @@
nix-modules = [
./users/wilkuu.nix
];
- interfaces = { };
+ monitoring = {
+ internal = [ "node" ];
+ };
+ interfaces = {
+ nix-laptop = {
+ type = "wireguard";
+ layer = "internal";
+ ip = "192.168.80.99";
+ };
+ wifi = {
+ type = "roaming";
+ };
+ eth = {
+ type = "roaming";
+ };
+ };
};
+
tacitus = {
type = "desktop";
system = "x86_64-linux";
@@ -25,7 +61,25 @@
nix-modules = [
./users/wilkuu-server.nix
];
- interfaces = { };
+ monitoring = {
+ local = [
+ "node"
+ "mikrotik"
+ ];
+ };
+ interfaces = {
+ enp7s0 = {
+ type = "eth-networkd";
+ layer = "internal";
+ ip = "192.168.88.5";
+ };
+ lo = {
+ # A little workaround for not needing to go over the net to get own stats
+ type = "roaming"; # TODO Set to something more sensible
+ layer = "local";
+ ip = "localhost";
+ };
+ };
};
# TODO: Support for live images as packages
diff --git a/modules/default.nix b/modules/default.nix
index 6cc52d8..39915dd 100644
--- a/modules/default.nix
+++ b/modules/default.nix
@@ -17,6 +17,7 @@
./test_endpoint.nix
./prometheus.nix
./mjmap.nix
+ ./firewall.nix
];
nixpkgs.overlays = [
diff --git a/modules/firewall.nix b/modules/firewall.nix
new file mode 100644
index 0000000..575de7d
--- /dev/null
+++ b/modules/firewall.nix
@@ -0,0 +1,132 @@
+{
+ config,
+ inventory,
+ self_name,
+ lib,
+ ...
+}:
+let
+ inherit (lib)
+ mkOption
+ types
+ mkIf
+ mkEnableOption
+ mkDefault
+ ;
+ inv = inventory.${self_name};
+ net = inv.interfaces;
+ cfg = config.wilkuu.firewall;
+
+ portRangeType = types.addCheck (types.submodule {
+ options = {
+ from = mkOption {
+ type = types.port;
+ example = 100;
+ description = "lowest part of the range (inclusive)";
+ };
+ to = mkOption {
+ type = types.port;
+ example = 200;
+ description = "highest part of the range (inclusive)";
+ };
+ };
+ }) (range: range.from < range.to);
+
+ mkPortsOption =
+ protocol:
+ mkOption {
+ type = types.listOf types.port;
+ default = [ ];
+ example = [ 1234 ];
+ description = "List of ${protocol} ports to accept";
+ };
+
+ mkPortRangesOption =
+ protocol:
+ mkOption {
+ type = types.listOf portRangeType;
+ default = [ ];
+ example = [ 1234 ];
+ description = "List of ${protocol} port ranges to accept";
+ };
+
+ layerAssertions = lib.mapAttrsToList (
+ layerName: layerConfig:
+ let
+ missing = builtins.filter (importLayer: !(cfg.layers ? ${importLayer})) layerConfig.import-layer;
+ in
+ {
+ assertion = missing == [ ];
+ message = "Layer ${layerName} imports undefined layer(s): ${toString missing}";
+ }
+ ) cfg.layers;
+in
+{
+ options.wilkuu.firewall = {
+ enable = mkEnableOption "firewall module";
+ defaultLayer = lib.mkOption {
+ type = types.str;
+ default = "external";
+ example = "eth";
+ };
+ layers = mkOption {
+ default = { };
+ description = "Layers and which ports should be open";
+ type = types.attrsOf (
+ types.submodule {
+ options = {
+ import-layer = mkOption {
+ type = types.listOf types.str;
+ default = [ ];
+ example = [ "external" ];
+ description = "Layer names which ports will also be opened on this layer";
+ };
+ allowedTCPPorts = mkPortsOption "TCP";
+ allowedUDPPorts = mkPortsOption "UDP";
+ allowedTCPPortRanges = mkPortRangesOption "TCP";
+ allowedUDPPortRanges = mkPortRangesOption "UDP";
+ };
+ }
+ );
+ };
+ };
+
+ config = mkIf cfg.enable {
+ assertions = layerAssertions;
+ networking.nftables.enable = true;
+ networking.firewall =
+ let
+ # TODO: reconsider doing this as this will only do a flat-import anything more complex would require building an import tree.
+ resolvedLayers = lib.mapAttrs (
+ _: l1:
+ lib.foldl' (acc: set2: {
+ allowedTCPPorts = acc.allowedTCPPorts ++ set2.allowedTCPPorts;
+ allowedUDPPorts = acc.allowedUDPPorts ++ set2.allowedUDPPorts;
+ allowedTCPPortRanges = acc.allowedTCPPortRanges ++ set2.allowedTCPPortRanges;
+ allowedUDPPortRanges = acc.allowedUDPPortRanges ++ set2.allowedUDPPortRanges;
+ }) l1 (map (lk: cfg.layers.${lk}) l1.import-layer)
+ ) cfg.layers;
+
+ interfaces = lib.mapAttrs (_n: interface: {
+ inherit (resolvedLayers.${interface.layer})
+ allowedTCPPorts
+ allowedUDPPorts
+ allowedTCPPortRanges
+ allowedUDPPortRanges
+ ;
+ }) (lib.filterAttrs (_n: interface: !(builtins.elem interface.type [ "roaming" ])) net);
+
+ in
+ {
+ enable = true;
+ checkReversePath = mkDefault false;
+ inherit interfaces;
+ inherit (resolvedLayers.${cfg.defaultLayer})
+ allowedTCPPorts
+ allowedUDPPorts
+ allowedTCPPortRanges
+ allowedUDPPortRanges
+ ;
+ };
+ };
+}
diff --git a/modules/prometheus.nix b/modules/prometheus.nix
index 63b761f..83eda86 100644
--- a/modules/prometheus.nix
+++ b/modules/prometheus.nix
@@ -1,11 +1,18 @@
-{ lib, config, ... }:
+{
+ lib,
+ config,
+ inventory,
+ self_name,
+ options,
+ ...
+}:
let
cfg = config.wilkuu.services.prometheus;
+ mon = inventory.${self_name}.monitoring;
inherit (lib)
mkEnableOption
mkIf
mkMerge
- mkDefault
;
in
{
@@ -15,16 +22,45 @@ in
};
config = mkMerge [
- (mkIf cfg.enableExporters {
- services.prometheus.exporters = {
- wireguard.enable = mkDefault config.networking.wireguard.enable;
- fail2ban.enable = mkDefault config.services.fail2ban.enable;
- node = {
+ (mkIf cfg.enableExporters (
+ let
+ data = lib.mapAttrs (
+ _name: mn:
+ let
+ default = (builtins.filter (a: builtins.isString a) mn);
+ custom = (builtins.filter (a: builtins.isAttrs a) mn);
+ in
+ {
+ ports =
+ builtins.map (n: options.services.prometheus.exporters.value.${n}.port) default
+ ++ (builtins.map (a: a.port) custom);
+ custom_port_mappings = builtins.listToAttrs (
+ map ({ name, port, ... }: {
+ inherit name;
+ value = port;
+ }) custom
+ );
+ exporter_services =
+ default
+ ++ (builtins.map (a: a.name) (builtins.filter ((a: !(a.skipExporterConfig or false))) custom));
+ }
+ ) mon;
+ data_all = (lib.foldl lib.recursiveUpdate { } (lib.attrValues data));
+ in
+ {
+ # Enable all the exporters outlined in the inventory
+ services.prometheus.exporters = lib.genAttrs data_all.exporter_services (name: {
enable = true;
- };
- };
+ port = lib.mkIf (data_all.custom_port_mappings ? name) data_all.custom_port_mappings.${name};
+
+ });
+ # Let all the exporters export on all layers
+ wilkuu.firewall.layers = lib.mapAttrs (_n: a: {
+ allowedTCPPorts = a.ports;
+ }) data;
+ }
+ ))
- })
(mkIf cfg.enableScraper {
sops.secrets = {
"prometheus/stalwart-pass" = {
@@ -52,76 +88,87 @@ in
services.prometheus =
let
- omega-relay-ip = "192.168.80.100";
+ nets_in_layer = inv: layer: lib.filterAttrs (_n: ifi: (ifi.layer or "") == layer) inv.interfaces;
+ dests_in_layer =
+ inv: layer: port:
+ (map (net: "${net.ip}:${toString port}") (lib.attrValues (nets_in_layer inv layer)));
+
+ job_destinations = (
+ builtins.foldl'
+ (
+ acc: perHost:
+ (builtins.foldl' (
+ acc2: hostMonitorName:
+ let
+ current = acc2.${hostMonitorName} or [ ];
+ new = perHost.${hostMonitorName};
+ in
+ acc2 // { ${hostMonitorName} = current ++ new; }
+ ) acc (lib.attrNames perHost))
+ )
+ { }
+ (
+ lib.mapAttrsToList (
+ _host: inv:
+ (lib.foldl' (a: b: a // b) { } (
+ lib.mapAttrsToList (
+
+ layer: lst:
+ (lib.listToAttrs (
+ builtins.map (
+ a:
+ let
+ ifSimple =
+ a: t: f:
+ if builtins.isString a then t else f;
+ name = ifSimple a a a.name;
+ port = ifSimple a options.services.prometheus.exporters.value.${a}.port (
+ a.port or options.services.prometheus.exporters.${a.name}.port.default
+ );
+ in
+ {
+ inherit name;
+ value = (dests_in_layer inv layer port);
+ }
+ ) lst
+ ))
+ ) inv.monitoring
+ ))
+ ) inventory
+ )
+ );
+
in
{
enable = true;
globalConfig = {
scrape_interval = "10s";
};
- scrapeConfigs = [
- {
- job_name = "node";
- static_configs =
- let
- port = toString config.services.prometheus.exporters.node.port;
- in
- [
- {
- targets = [
- "localhost:${port}"
- "${omega-relay-ip}:${port}"
- ];
- }
- ];
- }
- {
- job_name = "wireguard";
- static_configs =
- let
- port = toString config.services.prometheus.exporters.wireguard.port;
- in
- [
- { targets = [ "${omega-relay-ip}:${port}" ]; }
- ];
- }
- {
- job_name = "fail2ban";
- static_configs =
- let
- port = toString config.services.prometheus.exporters.fail2ban.port;
- in
- [
- { targets = [ "${omega-relay-ip}:${port}" ]; }
- ];
-
- }
- {
- job_name = "stalwart";
- metrics_path = "/metrics/prometheus";
- scheme = "https";
- basic_auth = {
- username = "prometheus_wilkuu";
- password_file = config.sops.secrets."prometheus/stalwart-pass".path;
- };
+ scrapeConfigs =
+ (lib.mapAttrsToList (name: dests: {
+ job_name = name;
static_configs = [
{
- targets = [ "mail.wilkuu.xyz:443" ];
+ targets = dests;
}
];
- }
- {
- job_name = "mikrotik";
- static_configs =
- let
- port = toString config.services.prometheus.exporters.mikrotik.port;
- in
- [
- { targets = [ "localhost:${port}" ]; }
+ }) job_destinations)
+ ++ [
+ {
+ job_name = "stalwart";
+ metrics_path = "/metrics/prometheus";
+ scheme = "https";
+ basic_auth = {
+ username = "prometheus_wilkuu";
+ password_file = config.sops.secrets."prometheus/stalwart-pass".path;
+ };
+ static_configs = [
+ {
+ targets = [ "mail.wilkuu.xyz:443" ];
+ }
];
-
- }
- ];
+ }
+ ];
};
})
];