feat: add fail2ban setup for services
Signed-off-by: Chinmay D. Pai <chinmaydpai@gmail.com>
This commit is contained in:
parent
12cf2f3701
commit
4cb83f945d
@ -58,9 +58,34 @@
|
||||
forceSSL = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://localhost:8096/";
|
||||
extraConfig = ''
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.fail2ban.jails.jellyfin = {
|
||||
enabled = true;
|
||||
filter = "jellyfin";
|
||||
};
|
||||
|
||||
environment.etc = {
|
||||
jellyfin = {
|
||||
target = "fail2ban/filter.d/jellyfin.conf";
|
||||
text = ''
|
||||
[INCLUDES]
|
||||
before = common.conf
|
||||
|
||||
[Definition]
|
||||
failregex = ^.*Authentication request for .* has been denied \(IP: "<ADDR>"\)\.
|
||||
ignoreregex =
|
||||
journalmatch = _SYSTEMD_UNIT=jellyfin.service
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -22,5 +22,20 @@
|
||||
};
|
||||
};
|
||||
};
|
||||
environment.etc = {
|
||||
jellyseerr = {
|
||||
target = "fail2ban/filter.d/jellyseerr.conf";
|
||||
text = ''
|
||||
[INCLUDES]
|
||||
before = common.conf
|
||||
|
||||
[Definition]
|
||||
failregex = ^.*\[warn\]\[API\]: Failed sign-in attempt using invalid Overseerr password {"ip":"<HOST>","email":
|
||||
^.*\[warn\]\[Auth\]: Failed login attempt from user with incorrect Jellyfin credentials {"account":{"ip":"<HOST>","email":
|
||||
ignoreregex =
|
||||
journalmatch = _SYSTEMD_UNIT=jellyseerr.service
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
67
modules/nixos/services/fail2ban/default.nix
Normal file
67
modules/nixos/services/fail2ban/default.nix
Normal file
@ -0,0 +1,67 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
options.snowflake.services.fail2ban = {
|
||||
enable = lib.mkEnableOption "Enable fail2ban service";
|
||||
|
||||
extraIgnoreIPs = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [];
|
||||
description = "List of IPs to ignore for fail2ban alongside the default local subnets and loopback";
|
||||
};
|
||||
};
|
||||
|
||||
config = let
|
||||
cfg = config.snowflake.services.fail2ban;
|
||||
in
|
||||
lib.mkIf cfg.enable {
|
||||
services.fail2ban = {
|
||||
enable = true;
|
||||
maxretry = 3;
|
||||
banaction-allports = "iptables-allports";
|
||||
|
||||
bantime-increment = {
|
||||
enable = true;
|
||||
maxtime = "168h";
|
||||
factor = "4";
|
||||
};
|
||||
|
||||
ignoreIPs =
|
||||
[
|
||||
"192.168.69.0/16"
|
||||
"172.16.0.0/12"
|
||||
"127.0.0.0/8"
|
||||
]
|
||||
++ cfg.extraIgnoreIPs;
|
||||
|
||||
jails = {
|
||||
DEFAULT = {
|
||||
blocktype = "DROP";
|
||||
bantime = "6h";
|
||||
findtime = "6h";
|
||||
};
|
||||
|
||||
sshd = {
|
||||
settings = {
|
||||
enabled = true;
|
||||
findtime = "1d";
|
||||
maxretry = 4;
|
||||
mode = "aggressive";
|
||||
port = "ssh";
|
||||
logpath = "%(sshd_log)s";
|
||||
backend = "%(sshd_backend)s";
|
||||
};
|
||||
};
|
||||
|
||||
port-scan = {
|
||||
filter = "port-scan";
|
||||
action = "iptables-allports[name=port-scan]";
|
||||
bantime = 86400;
|
||||
maxretry = 2;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
@ -108,5 +108,22 @@
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.fail2ban.jails.gitea = {
|
||||
enabled = true;
|
||||
filter = "gitea";
|
||||
};
|
||||
|
||||
environment.etc = {
|
||||
gitea = {
|
||||
target = "fail2ban/filter.d/gitea.conf";
|
||||
text = ''
|
||||
[Definition]
|
||||
failregex = .*(Failed authentication attempt|invalid credentials|Attempted access of unknown user).* from <HOST>
|
||||
ignoreregex =
|
||||
journalmatch = _SYSTEMD_UNIT=gitea.service
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -47,5 +47,25 @@
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.fail2ban.jails.immich = {
|
||||
enabled = true;
|
||||
filter = "immich";
|
||||
};
|
||||
|
||||
environment.etc = {
|
||||
immich = {
|
||||
target = "fail2ban/filter.d/immich.conf";
|
||||
text = ''
|
||||
[INCLUDES]
|
||||
before = common.conf
|
||||
|
||||
[Definition]
|
||||
failregex = ^.*Username or password is incorrect\. Try again\. IP: <ADDR>\. Username:.*$
|
||||
ignoreregex =
|
||||
journalmatch = _SYSTEMD_UNIT=immich-server.service
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -1,5 +1,8 @@
|
||||
{ config, lib, ... }:
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
options.snowflake.services.miniflux = {
|
||||
enable = lib.mkEnableOption "Enable miniflux service";
|
||||
|
||||
@ -20,10 +23,9 @@
|
||||
};
|
||||
};
|
||||
|
||||
config =
|
||||
let
|
||||
cfg = config.snowflake.services.miniflux;
|
||||
in
|
||||
config = let
|
||||
cfg = config.snowflake.services.miniflux;
|
||||
in
|
||||
lib.mkIf cfg.enable {
|
||||
age.secrets.miniflux = {
|
||||
inherit (cfg.adminTokenFile) file;
|
||||
@ -49,7 +51,6 @@
|
||||
proxyPass = "http://localhost:${toString cfg.listenPort}";
|
||||
extraConfig = ''
|
||||
proxy_redirect off;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
'';
|
||||
@ -57,5 +58,22 @@
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.fail2ban.jails.miniflux = {
|
||||
enabled = true;
|
||||
filter = "miniflux";
|
||||
};
|
||||
|
||||
environment.etc = {
|
||||
miniflux = {
|
||||
target = "fail2ban/filter.d/miniflux.conf";
|
||||
text = ''
|
||||
[Definition]
|
||||
failregex = ^.*msg="[^"]*(Incorrect|Invalid) username or password[^"]*".*client_ip=<ADDR>
|
||||
ignoreregex =
|
||||
journalmatch = _SYSTEMD_UNIT=miniflux.service
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -48,7 +48,6 @@
|
||||
proxy_redirect off;
|
||||
proxy_buffering off;
|
||||
proxy_request_buffering off;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
client_max_body_size 0;
|
||||
|
@ -73,5 +73,22 @@
|
||||
echo ${path}/exported/
|
||||
'';
|
||||
};
|
||||
|
||||
services.fail2ban.jails.paperless = {
|
||||
enabled = true;
|
||||
filter = "paperless";
|
||||
};
|
||||
|
||||
environment.etc = {
|
||||
paperless-ngx = {
|
||||
target = "fail2ban/filter.d/paperless.conf";
|
||||
text = ''
|
||||
[Definition]
|
||||
failregex = Login failed for user `.*` from (?:IP|private IP) `<HOST>`\.$
|
||||
ignoreregex =
|
||||
journalmatch = _SYSTEMD_UNIT=paperless-web.service
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -77,5 +77,20 @@
|
||||
snowflake.services.backups.config.vaultwarden.paths = [
|
||||
"/var/lib/bitwarden_rs"
|
||||
];
|
||||
|
||||
environment.etc = {
|
||||
vaultwarden = {
|
||||
target = "fail2ban/filter.d/vaultwarden.conf";
|
||||
text = ''
|
||||
[INCLUDES]
|
||||
before = common.conf
|
||||
|
||||
[Definition]
|
||||
failregex = ^.*Username or password is incorrect\. Try again\. IP: <ADDR>\. Username:.*$
|
||||
ignoreregex =
|
||||
journalmatch = _SYSTEMD_UNIT=vaultwarden.service
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user