From 46fd27f76892b5ae02c3993e508d70042001be12 Mon Sep 17 00:00:00 2001 From: Leyla Becker Date: Mon, 6 Jan 2025 14:06:26 -0600 Subject: [PATCH] added fail2ban --- .../nixos/defiant/configuration.nix | 3 + modules/nixos-modules/server/default.nix | 1 + modules/nixos-modules/server/fail2ban.nix | 90 +++++++++++++++++++ modules/nixos-modules/server/nextcloud.nix | 8 ++ 4 files changed, 102 insertions(+) create mode 100644 modules/nixos-modules/server/fail2ban.nix diff --git a/configurations/nixos/defiant/configuration.nix b/configurations/nixos/defiant/configuration.nix index a5e9c7d..f65421c 100644 --- a/configurations/nixos/defiant/configuration.nix +++ b/configurations/nixos/defiant/configuration.nix @@ -28,6 +28,9 @@ ]; }; }; + fail2ban = { + enable = true; + }; network_storage = { enable = true; directories = [ diff --git a/modules/nixos-modules/server/default.nix b/modules/nixos-modules/server/default.nix index b44eec7..c8e17a9 100644 --- a/modules/nixos-modules/server/default.nix +++ b/modules/nixos-modules/server/default.nix @@ -1,5 +1,6 @@ {...}: { imports = [ + ./fail2ban.nix ./network_storage ./reverse_proxy.nix ./postgres.nix diff --git a/modules/nixos-modules/server/fail2ban.nix b/modules/nixos-modules/server/fail2ban.nix new file mode 100644 index 0000000..f68ef9d --- /dev/null +++ b/modules/nixos-modules/server/fail2ban.nix @@ -0,0 +1,90 @@ +{ + lib, + config, + ... +}: { + options.host.fail2ban = { + enable = lib.mkEnableOption "should fail 2 ban be enabled on this server"; + }; + + config = lib.mkIf config.host.fail2ban.enable (lib.mkMerge [ + { + services.fail2ban = { + enable = true; + maxretry = 5; + ignoreIP = [ + # Whitelist local networks + "10.0.0.0/8" + "172.16.0.0/12" + "192.168.0.0/16" + ]; + bantime = "24h"; # Ban IPs for one day on the first ban + bantime-increment = { + enable = true; # Enable increment of bantime after each violation + formula = "ban.Time * math.exp(float(ban.Count+1)*banFactor)/math.exp(1*banFactor)"; + maxtime = "168h"; # Do not ban for more than 1 week + overalljails = true; # Calculate the ban time based on all the violations + }; + jails = { + nginx-iptables.settings = lib.mkIf config.services.nginx.enable { + filter = "nginx"; + action = ''iptables-multiport[name=HTTP, port="http,https"]''; + backend = "auto"; + failregex = "limiting requests, excess:.* by zone.*client: "; + findtime = 600; + bantime = 600; + maxretry = 5; + }; + jellyfin-iptables.settings = lib.mkIf config.services.jellyfin.enable { + filter = "jellyfin"; + action = ''iptables-multiport[name=HTTP, port="http,https"]''; + logpath = "${config.services.jellyfin.dataDir}/log/*.log"; + backend = "auto"; + failregex = "^.*Authentication request for .* has been denied \\\(IP: \"\"\\\)\\\."; + findtime = 600; + bantime = 600; + maxretry = 5; + }; + nextcloud-iptables.settings = lib.mkIf config.services.nextcloud.enable { + filter = "nextcloud"; + action = ''iptables-multiport[name=HTTP, port="http,https"]''; + logpath = "${config.services.nextcloud.datadir}/*.log"; + backend = "auto"; + failregex = '' + ^{"reqId":".*","remoteAddr":".*","app":"core","message":"Login failed: '.*' \(Remote IP: ''\)","level":2,"time":".*"}$ + ^{"reqId":".*","level":2,"time":".*","remoteAddr":".*","user,:".*","app":"no app in context".*","method":".*","message":"Login failed: '.*' \(Remote IP: ''\)".*}$ + ^{"reqId":".*","level":2,"time":".*","remoteAddr":".*","user":".*","app":".*","method":".*","url":".*","message":"Login failed: .* \(Remote IP: \).*}$ + ''; + findtime = 600; + bantime = 600; + maxretry = 5; + }; + forgejo-iptables.settings = lib.mkIf config.services.forgejo.enable { + filter = "forgejo"; + action = ''iptables-multiport[name=HTTP, port="http,https"]''; + logpath = "${config.services.forgejo.stateDir}/log/*.log"; + backend = "auto"; + failregex = ".*(Failed authentication attempt|invalid credentials|Attempted access of unknown user).* from "; + findtime = 600; + bantime = 600; + maxretry = 5; + }; + home-assistant-iptables.settings = lib.mkIf config.services.home-assistant.enable { + filter = "home-assistant"; + action = ''iptables-multiport[name=HTTP, port="http,https"]''; + logpath = "${config.services.home-assistant.configDir}/*.log"; + backend = "auto"; + failregex = "^%(__prefix_line)s.*Login attempt or request with invalid authentication from .*$"; + findtime = 600; + bantime = 600; + maxretry = 5; + }; + # TODO; figure out if there is any fail2ban things we can do on searx + # searx-iptables.settings = lib.mkIf config.services.searx.enable {}; + }; + }; + } + (lib.mkIf config.host.impermanence.enable { + }) + ]); +} diff --git a/modules/nixos-modules/server/nextcloud.nix b/modules/nixos-modules/server/nextcloud.nix index 126ddd5..a1ad0cf 100644 --- a/modules/nixos-modules/server/nextcloud.nix +++ b/modules/nixos-modules/server/nextcloud.nix @@ -32,6 +32,7 @@ in { enable = true; package = pkgs.nextcloud30; hostName = "${config.host.nextcloud.subdomain}.${config.host.reverse_proxy.hostname}"; + settings.log_type = "file"; config = { adminpassFile = config.sops.secrets."services/nextcloud_adminpass".path; }; @@ -39,6 +40,13 @@ in { }; } (lib.mkIf config.host.impermanence.enable { + assertions = [ + { + assertion = config.services.nextcloud.datadir == dataDir; + message = "nextcloud data directory does not match persistence"; + } + ]; + environment.persistence."/persist/system/root" = { enable = true; hideMounts = true;