diff --git a/hosts/hydra/default.nix b/hosts/hydra/default.nix index 563b5a106..a4eebb19c 100644 --- a/hosts/hydra/default.nix +++ b/hosts/hydra/default.nix @@ -6,7 +6,7 @@ _: { type = "laptop"; cpu = "intel"; gpu = null; - monitors = ["eDP-1"]; + monitors = ["HDMI-A-1" "eDP-1"]; hasTPM = true; hasBluetooth = true; hasSound = true; diff --git a/lib/helpers.nix b/lib/helpers.nix index db69c0db2..83789dfa4 100644 --- a/lib/helpers.nix +++ b/lib/helpers.nix @@ -19,6 +19,9 @@ # a basic function to fetch a specified user's public keys from github .keys url fetchKeys = username: (builtins.fetchurl "https://github.com/${username}.keys"); + # convert a list of integers to a list of string + # `intListToStringList [1 2 3]` -> ["1" "2" "3"] + intListToStringList = list: map (toString list); indexOf = list: elem: let f = f: i: if i == (builtins.length list) @@ -40,5 +43,5 @@ }: builtins.all (s: builtins.any (x: x == s) list) targetStrings; in { - inherit filterNixFiles importNixFiles boolToNum fetchKeys containsStrings serializeTheme indexOf; + inherit filterNixFiles importNixFiles boolToNum fetchKeys containsStrings serializeTheme indexOf intListToStringList; } diff --git a/modules/base/common/host/os/network/blocker.nix b/modules/base/common/host/os/network/blocker.nix index 2890dafe7..f7bf28bab 100644 --- a/modules/base/common/host/os/network/blocker.nix +++ b/modules/base/common/host/os/network/blocker.nix @@ -1,5 +1,5 @@ {config, ...}: let - device = config.modules.device; + inherit (config.modules) device; in { # remove stupid sites that i just don't want to see networking.stevenblack = { diff --git a/modules/base/common/host/os/network/default.nix b/modules/base/common/host/os/network/default.nix index 77aa6d5d0..25ff51cc3 100644 --- a/modules/base/common/host/os/network/default.nix +++ b/modules/base/common/host/os/network/default.nix @@ -8,12 +8,18 @@ dev = config.modules.device; in { imports = [ + ./firewall + ./blocker.nix - ./firewall.nix ./ssh.nix ./optimise.nix ]; + users = { + groups.tcpcryptd = {}; + users.tcpcryptd.group = "tcpcryptd"; + }; + services = { # systemd DNS resolver daemon resolved.enable = true; @@ -21,15 +27,22 @@ in { networking = { # generate a host ID by hashing the hostname - hostId = builtins.substring 0 8 ( - builtins.hashString "md5" config.networking.hostName - ); + hostId = builtins.substring 0 8 (builtins.hashString "md5" config.networking.hostName); hostName = config.modules.system.hostname; # global dhcp has been deprecated upstream, so we use networkd instead # however individual interfaces are still managed through dhcp in hardware configurations - useDHCP = mkDefault false; - useNetworkd = mkDefault true; + useDHCP = mkForce false; + useNetworkd = mkForce true; + + # interfaces are assigned names that contain topology information (e.g. wlp3s0) and thus should be consistent across reboots + # this already defaults to true, we set it in case it changes upstream + usePredictableInterfaceNames = mkDefault true; + + # enable opportunistic TCP encryption + # this is NOT a pancea, however, if the receiver supports encryption and the attacker is passive + # privacy will be more plausible (but not guaranteed, unlike what the option docs suggest) + tcpcrypt.enable = true; # dns nameservers = [ @@ -45,13 +58,14 @@ in { unmanaged = ["docker0" "rndis0"]; wifi = { + # backend = "iwd"; # The below is disabled as my uni hated me for it # macAddress = "random"; # use a random mac address on every boot, this can scew with static ip powersave = true; scanRandMacAddress = true; # MAC address randomization of a Wi-Fi device during scanning }; - ethernet.macAddress = mkIf (dev.type != "server") "random"; + ethernet.macAddress = mkIf (dev.type != "server") "random"; # causes server to be unreachable over SSH }; }; diff --git a/modules/base/common/host/os/network/firewall.nix b/modules/base/common/host/os/network/firewall.nix deleted file mode 100644 index 87cc1cb8c..000000000 --- a/modules/base/common/host/os/network/firewall.nix +++ /dev/null @@ -1,114 +0,0 @@ -{ - pkgs, - lib, - config, - ... -}: let - inherit (lib) mkDefault mkForce mkIf; - inherit (config.modules) device; -in { - environment.etc."fail2ban/filter.d/vaultwarden.conf" = { - inherit (config.services.vaultwarden) enable; - text = '' - [INCLUDES] - before = common.conf - [Definition] - failregex = ^.*Username or password is incorrect\. Try again\. IP: \. Username:.*$ - ignoreregex = - ''; - }; - - environment.etc."fail2ban/filter.d/vaultwarden-admin.conf" = { - inherit (config.services.vaultwarden) enable; - text = '' - [INCLUDES] - before = common.conf - [Definition] - failregex = ^.*Invalid admin token\. IP: .*$ - ignoreregex = - ''; - }; - - services = { - # enable opensnitch firewall - # inactive until opensnitch UI is opened - opensnitch.enable = true; - - # fail2ban firewall jail - fail2ban = { - enable = true; - banaction = "iptables-multiport[blocktype=DROP]"; - maxretry = 7; - ignoreIP = [ - "127.0.0.0/8" - "10.0.0.0/8" - "192.168.86.0/16" - ]; - - jails = mkDefault { - sshd = '' - enabled = true - port = 22 - mode = aggressive - ''; - - vaultwarden = '' - enabled = true - port = 80,443,8822 - filter = vaultwarden - banaction = %(banaction_allports)s - logpath = /var/log/vaultwarden.log - maxretry = 3 - bantime = 14400 - findtime = 14400 - ''; - vaultwarden-admin = '' - enabled = true - port = 80,443 - filter = vaultwarden-admin - banaction = %(banaction_allports)s - logpath = /var/log/vaultwarden.log - maxretry = 3 - bantime = 14400 - findtime = 14400 - ''; - }; - - bantime-increment = { - enable = true; - rndtime = "12m"; - overalljails = true; - multipliers = "4 8 16 32 64 128 256 512 1024"; - maxtime = "48h"; - }; - }; - }; - networking = { - nftables.enable = false; - firewall = { - enable = mkDefault true; - package = mkDefault pkgs.iptables-nftables-compat; - allowedTCPPorts = [ - 443 - 8080 - ]; - allowedUDPPorts = []; - allowedTCPPortRanges = mkIf (device.type != "server") [ - { - from = 1714; - to = 1764; - } #KDEconnect - ]; - allowedUDPPortRanges = mkIf (device.type != "server") [ - { - from = 1714; - to = 1764; - } #KDEconnect - ]; - allowPing = mkDefault device.type == "server"; - logReversePathDrops = true; - logRefusedConnections = mkDefault false; - checkReversePath = mkForce false; # Don't filter DHCP packets, according to nixops-libvirtd - }; - }; -} diff --git a/modules/base/common/host/os/network/firewall/default.nix b/modules/base/common/host/os/network/firewall/default.nix new file mode 100644 index 000000000..fd7b7ce05 --- /dev/null +++ b/modules/base/common/host/os/network/firewall/default.nix @@ -0,0 +1,52 @@ +{ + pkgs, + lib, + config, + ... +}: let + inherit (lib) mkDefault mkForce mkIf; + inherit (config.modules) device; +in { + imports = [ + ./fail2ban.nix + ./nftables.nix + ]; + + config = { + services = { + # enable opensnitch firewall + # inactive until opensnitch UI is opened + opensnitch.enable = true; + }; + + networking = { + firewall = { + enable = mkDefault true; + package = mkDefault pkgs.iptables-nftables-compat; + allowedTCPPorts = [ + 443 + 8080 + ]; + allowedUDPPorts = []; + allowedTCPPortRanges = mkIf (device.type != "server") [ + { + #KDEconnect + from = 1714; + to = 1764; + } + ]; + allowedUDPPortRanges = mkIf (device.type != "server") [ + { + #KDEconnect + from = 1714; + to = 1764; + } + ]; + allowPing = device.type == "server"; + logReversePathDrops = true; + logRefusedConnections = false; + checkReversePath = mkForce false; # Don't filter DHCP packets, according to nixops-libvirtd + }; + }; + }; +} diff --git a/modules/base/common/host/os/network/firewall/fail2ban.nix b/modules/base/common/host/os/network/firewall/fail2ban.nix new file mode 100644 index 000000000..a16fa012e --- /dev/null +++ b/modules/base/common/host/os/network/firewall/fail2ban.nix @@ -0,0 +1,64 @@ +{ + config, + lib, + ... +}: let + inherit (lib) mkIf mkMerge concatStringsSep mkForce; + + cfg = config.modules.services; +in { + # fail2ban firewall jail + services.fail2ban = { + enable = true; + banaction = "iptables-multiport[blocktype=DROP]"; + maxretry = 7; + ignoreIP = [ + "127.0.0.0/8" + "10.0.0.0/8" + "192.168.0.0/16" + ]; + + jails = mkMerge [ + { + # sshd jail + sshd = mkForce '' + enabled = true + port = ${concatStringsSep "," (map toString config.services.openssh.ports)} + mode = aggressive + ''; + } + (mkIf cfg.vaultwarden.enable { + # vaultwarden and vaultwarden admin interface jails + vaultwarden = '' + enabled = true + port = 80,443,8822 + filter = vaultwarden + banaction = %(banaction_allports)s + logpath = /var/log/vaultwarden.log + maxretry = 3 + bantime = 14400 + findtime = 14400 + ''; + + vaultwarden-admin = '' + enabled = true + port = 80,443 + filter = vaultwarden-admin + banaction = %(banaction_allports)s + logpath = /var/log/vaultwarden.log + maxretry = 3 + bantime = 14400 + findtime = 14400 + ''; + }) + ]; + + bantime-increment = { + enable = true; + rndtime = "12m"; + overalljails = true; + multipliers = "4 8 16 32 64 128 256 512 1024 2048"; + maxtime = "192h"; # get banned for 192 hours idiot + }; + }; +} diff --git a/modules/base/common/host/os/network/firewall/nftables.nix b/modules/base/common/host/os/network/firewall/nftables.nix new file mode 100644 index 000000000..c3b1a90d8 --- /dev/null +++ b/modules/base/common/host/os/network/firewall/nftables.nix @@ -0,0 +1,14 @@ +_: { + networking.nftables = { + enable = false; + tables = { + # TODO: write a proper filter table + # accept: ssh, http, https and in the future, DNS + # block: everything else + default-filter = { + content = ""; + family = "inet"; + }; + }; + }; +}