fail2ban: add jails for SSH, nginx proxy manager, and Jellyfin
Replaces bare enable flag with a dedicated service module covering: - SSH brute force via journald - Nginx Proxy Manager auth failures via Docker log files - Jellyfin auth failures via journald Includes incremental ban times (up to 1 week) and LAN ignore rules. https://claude.ai/code/session_01PwAXuaoJx7qD5FhVLsn7Sn
This commit is contained in:
parent
f5bb08d7dd
commit
16363dc887
3 changed files with 76 additions and 2 deletions
|
|
@ -30,6 +30,7 @@
|
||||||
./services/bazarr.nix
|
./services/bazarr.nix
|
||||||
./services/cloudflare-ddns.nix
|
./services/cloudflare-ddns.nix
|
||||||
./services/crowdsec.nix
|
./services/crowdsec.nix
|
||||||
|
./services/fail2ban.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
### Make build time quicker
|
### Make build time quicker
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,6 @@
|
||||||
yt-dlp
|
yt-dlp
|
||||||
];
|
];
|
||||||
|
|
||||||
services.fail2ban.enable = true;
|
|
||||||
|
|
||||||
# Enable Docker
|
# Enable Docker
|
||||||
virtualisation.docker.enable = true;
|
virtualisation.docker.enable = true;
|
||||||
|
|
||||||
|
|
|
||||||
75
services/fail2ban.nix
Normal file
75
services/fail2ban.nix
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
{
|
||||||
|
config = lib.mkIf (config.networking.hostName == "FredOS-Mediaserver") {
|
||||||
|
|
||||||
|
services.fail2ban = {
|
||||||
|
enable = true;
|
||||||
|
|
||||||
|
# Default ban settings (overridable per jail)
|
||||||
|
maxretry = 5;
|
||||||
|
bantime = "1h";
|
||||||
|
|
||||||
|
# Progressively longer bans for repeat offenders, up to 1 week
|
||||||
|
bantime-increment = {
|
||||||
|
enable = true;
|
||||||
|
multiplier = "1 2 4 8 16 32 64";
|
||||||
|
maxtime = "168h";
|
||||||
|
overalljails = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Never ban local network traffic
|
||||||
|
ignoreIP = [
|
||||||
|
"127.0.0.1/8"
|
||||||
|
"::1"
|
||||||
|
"192.168.0.0/16"
|
||||||
|
"10.0.0.0/8"
|
||||||
|
];
|
||||||
|
|
||||||
|
jails = {
|
||||||
|
|
||||||
|
# SSH brute force — uses built-in sshd filter via journald
|
||||||
|
sshd = {
|
||||||
|
settings = {
|
||||||
|
enabled = true;
|
||||||
|
filter = "sshd";
|
||||||
|
maxretry = 5;
|
||||||
|
bantime = "1h";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Nginx Proxy Manager — watches Docker-mounted log files
|
||||||
|
# Catches repeated 401/403 responses (auth failures, bad requests)
|
||||||
|
nginx-proxy-manager = {
|
||||||
|
settings = {
|
||||||
|
enabled = true;
|
||||||
|
filter = "nginx-http-auth";
|
||||||
|
logpath = "/home/fred/docker/nginx-proxy-manager/data/logs/*.log";
|
||||||
|
maxretry = 10;
|
||||||
|
bantime = "1h";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Jellyfin auth failures — uses journald backend
|
||||||
|
jellyfin = {
|
||||||
|
settings = {
|
||||||
|
enabled = true;
|
||||||
|
backend = "systemd";
|
||||||
|
journalmatch = "_SYSTEMD_UNIT=jellyfin.service";
|
||||||
|
maxretry = 5;
|
||||||
|
bantime = "2h";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Custom Jellyfin filter — matches failed auth log lines from the journal
|
||||||
|
environment.etc."fail2ban/filter.d/jellyfin.conf".text = ''
|
||||||
|
[Definition]
|
||||||
|
failregex = ^.*Authentication request for .* has been denied \(IP: "<HOST>"\).*$
|
||||||
|
^.*Error processing request from remote IP Address <HOST>.*$
|
||||||
|
ignoreregex =
|
||||||
|
'';
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue