commit
c23f10da6a
2 changed files with 231 additions and 81 deletions
|
@ -6,15 +6,32 @@ let
|
|||
|
||||
cfg = config.services.fail2ban;
|
||||
|
||||
fail2banConf = pkgs.writeText "fail2ban.conf" cfg.daemonConfig;
|
||||
fail2banConf = pkgs.writeText "fail2ban.local" cfg.daemonConfig;
|
||||
|
||||
jailConf = pkgs.writeText "jail.conf"
|
||||
(concatStringsSep "\n" (attrValues (flip mapAttrs cfg.jails (name: def:
|
||||
jailConf = pkgs.writeText "jail.local" ''
|
||||
[INCLUDES]
|
||||
|
||||
before = paths-nixos.conf
|
||||
|
||||
${concatStringsSep "\n" (attrValues (flip mapAttrs cfg.jails (name: def:
|
||||
optionalString (def != "")
|
||||
''
|
||||
[${name}]
|
||||
${def}
|
||||
''))));
|
||||
'')))}
|
||||
'';
|
||||
|
||||
pathsConf = pkgs.writeText "paths-nixos.conf" ''
|
||||
# NixOS
|
||||
|
||||
[INCLUDES]
|
||||
|
||||
before = paths-common.conf
|
||||
|
||||
after = paths-overrides.local
|
||||
|
||||
[DEFAULT]
|
||||
'';
|
||||
|
||||
in
|
||||
|
||||
|
@ -31,21 +48,135 @@ in
|
|||
description = "Whether to enable the fail2ban service.";
|
||||
};
|
||||
|
||||
package = mkOption {
|
||||
default = pkgs.fail2ban;
|
||||
type = types.package;
|
||||
example = "pkgs.fail2ban_0_11";
|
||||
description = "The fail2ban package to use for running the fail2ban service.";
|
||||
};
|
||||
|
||||
packageFirewall = mkOption {
|
||||
default = pkgs.iptables;
|
||||
type = types.package;
|
||||
example = "pkgs.nftables";
|
||||
description = "The firewall package used by fail2ban service.";
|
||||
};
|
||||
|
||||
banaction = mkOption {
|
||||
default = "iptables-multiport";
|
||||
type = types.str;
|
||||
example = "nftables-multiport";
|
||||
description = ''
|
||||
Default banning action (e.g. iptables, iptables-new, iptables-multiport,
|
||||
shorewall, etc) It is used to define action_* variables. Can be overridden
|
||||
globally or per section within jail.local file
|
||||
'';
|
||||
};
|
||||
|
||||
banaction-allports = mkOption {
|
||||
default = "iptables-allport";
|
||||
type = types.str;
|
||||
example = "nftables-allport";
|
||||
description = ''
|
||||
Default banning action (e.g. iptables, iptables-new, iptables-multiport,
|
||||
shorewall, etc) It is used to define action_* variables. Can be overridden
|
||||
globally or per section within jail.local file
|
||||
'';
|
||||
};
|
||||
|
||||
bantime-increment.enable = mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
description = ''
|
||||
Allows to use database for searching of previously banned ip's to increase
|
||||
a default ban time using special formula, default it is banTime * 1, 2, 4, 8, 16, 32...
|
||||
'';
|
||||
};
|
||||
|
||||
bantime-increment.rndtime = mkOption {
|
||||
default = "4m";
|
||||
type = types.str;
|
||||
example = "8m";
|
||||
description = ''
|
||||
"bantime-increment.rndtime" is the max number of seconds using for mixing with random time
|
||||
to prevent "clever" botnets calculate exact time IP can be unbanned again
|
||||
'';
|
||||
};
|
||||
|
||||
bantime-increment.maxtime = mkOption {
|
||||
default = "10h";
|
||||
type = types.str;
|
||||
example = "48h";
|
||||
description = ''
|
||||
"bantime-increment.maxtime" is the max number of seconds using the ban time can reach (don't grows further)
|
||||
'';
|
||||
};
|
||||
|
||||
bantime-increment.factor = mkOption {
|
||||
default = "1";
|
||||
type = types.str;
|
||||
example = "4";
|
||||
description = ''
|
||||
"bantime-increment.factor" is a coefficient to calculate exponent growing of the formula or common multiplier,
|
||||
default value of factor is 1 and with default value of formula, the ban time grows by 1, 2, 4, 8, 16 ...
|
||||
'';
|
||||
};
|
||||
|
||||
bantime-increment.formula = mkOption {
|
||||
default = "ban.Time * (1<<(ban.Count if ban.Count<20 else 20)) * banFactor";
|
||||
type = types.str;
|
||||
example = "ban.Time * math.exp(float(ban.Count+1)*banFactor)/math.exp(1*banFactor)";
|
||||
description = ''
|
||||
"bantime-increment.formula" used by default to calculate next value of ban time, default value bellow,
|
||||
the same ban time growing will be reached by multipliers 1, 2, 4, 8, 16, 32...
|
||||
'';
|
||||
};
|
||||
|
||||
bantime-increment.multipliers = mkOption {
|
||||
default = "1 2 4 8 16 32 64";
|
||||
type = types.str;
|
||||
example = "2 4 16 128";
|
||||
description = ''
|
||||
"bantime-increment.multipliers" used to calculate next value of ban time instead of formula, coresponding
|
||||
previously ban count and given "bantime.factor" (for multipliers default is 1);
|
||||
following example grows ban time by 1, 2, 4, 8, 16 ... and if last ban count greater as multipliers count,
|
||||
always used last multiplier (64 in example), for factor '1' and original ban time 600 - 10.6 hours
|
||||
'';
|
||||
};
|
||||
|
||||
bantime-increment.overalljails = mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
example = true;
|
||||
description = ''
|
||||
"bantime-increment.overalljails" (if true) specifies the search of IP in the database will be executed
|
||||
cross over all jails, if false (dafault), only current jail of the ban IP will be searched
|
||||
'';
|
||||
};
|
||||
|
||||
ignoreIP = mkOption {
|
||||
default = [ ];
|
||||
type = types.listOf types.str;
|
||||
example = [ "192.168.0.0/16" "2001:DB8::42" ];
|
||||
description = ''
|
||||
"ignoreIP" can be a list of IP addresses, CIDR masks or DNS hosts. Fail2ban will not ban a host which
|
||||
matches an address in this list. Several addresses can be defined using space (and/or comma) separator.
|
||||
'';
|
||||
};
|
||||
|
||||
daemonConfig = mkOption {
|
||||
default =
|
||||
''
|
||||
[Definition]
|
||||
loglevel = INFO
|
||||
logtarget = SYSLOG
|
||||
socket = /run/fail2ban/fail2ban.sock
|
||||
pidfile = /run/fail2ban/fail2ban.pid
|
||||
'';
|
||||
default = ''
|
||||
[Definition]
|
||||
logtarget = SYSLOG
|
||||
socket = /run/fail2ban/fail2ban.sock
|
||||
pidfile = /run/fail2ban/fail2ban.pid
|
||||
dbfile = /var/lib/fail2ban/fail2ban.sqlite3
|
||||
'';
|
||||
type = types.lines;
|
||||
description =
|
||||
''
|
||||
The contents of Fail2ban's main configuration file. It's
|
||||
generally not necessary to change it.
|
||||
'';
|
||||
description = ''
|
||||
The contents of Fail2ban's main configuration file. It's
|
||||
generally not necessary to change it.
|
||||
'';
|
||||
};
|
||||
|
||||
jails = mkOption {
|
||||
|
@ -65,88 +196,107 @@ in
|
|||
}
|
||||
'';
|
||||
type = types.attrsOf types.lines;
|
||||
description =
|
||||
''
|
||||
The configuration of each Fail2ban “jail”. A jail
|
||||
consists of an action (such as blocking a port using
|
||||
<command>iptables</command>) that is triggered when a
|
||||
filter applied to a log file triggers more than a certain
|
||||
number of times in a certain time period. Actions are
|
||||
defined in <filename>/etc/fail2ban/action.d</filename>,
|
||||
while filters are defined in
|
||||
<filename>/etc/fail2ban/filter.d</filename>.
|
||||
'';
|
||||
description = ''
|
||||
The configuration of each Fail2ban “jail”. A jail
|
||||
consists of an action (such as blocking a port using
|
||||
<command>iptables</command>) that is triggered when a
|
||||
filter applied to a log file triggers more than a certain
|
||||
number of times in a certain time period. Actions are
|
||||
defined in <filename>/etc/fail2ban/action.d</filename>,
|
||||
while filters are defined in
|
||||
<filename>/etc/fail2ban/filter.d</filename>.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
environment.systemPackages = [ pkgs.fail2ban ];
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
|
||||
environment.etc."fail2ban/fail2ban.conf".source = fail2banConf;
|
||||
environment.etc."fail2ban/jail.conf".source = jailConf;
|
||||
environment.etc."fail2ban/action.d".source = "${pkgs.fail2ban}/etc/fail2ban/action.d/*.conf";
|
||||
environment.etc."fail2ban/filter.d".source = "${pkgs.fail2ban}/etc/fail2ban/filter.d/*.conf";
|
||||
environment.etc = {
|
||||
"fail2ban/fail2ban.local".source = fail2banConf;
|
||||
"fail2ban/jail.local".source = jailConf;
|
||||
"fail2ban/fail2ban.conf".source = "${cfg.package}/etc/fail2ban/fail2ban.conf";
|
||||
"fail2ban/jail.conf".source = "${cfg.package}/etc/fail2ban/jail.conf";
|
||||
"fail2ban/paths-common.conf".source = "${cfg.package}/etc/fail2ban/paths-common.conf";
|
||||
"fail2ban/paths-nixos.conf".source = pathsConf;
|
||||
"fail2ban/action.d".source = "${cfg.package}/etc/fail2ban/action.d/*.conf";
|
||||
"fail2ban/filter.d".source = "${cfg.package}/etc/fail2ban/filter.d/*.conf";
|
||||
};
|
||||
|
||||
systemd.services.fail2ban =
|
||||
{ description = "Fail2ban Intrusion Prevention System";
|
||||
systemd.services.fail2ban = {
|
||||
description = "Fail2ban Intrusion Prevention System";
|
||||
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
partOf = optional config.networking.firewall.enable "firewall.service";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
partOf = optional config.networking.firewall.enable "firewall.service";
|
||||
|
||||
restartTriggers = [ fail2banConf jailConf ];
|
||||
path = [ pkgs.fail2ban pkgs.iptables pkgs.iproute ];
|
||||
restartTriggers = [ fail2banConf jailConf pathsConf ];
|
||||
reloadIfChanged = true;
|
||||
|
||||
preStart =
|
||||
''
|
||||
mkdir -p /var/lib/fail2ban
|
||||
'';
|
||||
path = [ cfg.package cfg.packageFirewall pkgs.iproute ];
|
||||
|
||||
unitConfig.Documentation = "man:fail2ban(1)";
|
||||
unitConfig.Documentation = "man:fail2ban(1)";
|
||||
|
||||
serviceConfig =
|
||||
{ Type = "forking";
|
||||
ExecStart = "${pkgs.fail2ban}/bin/fail2ban-client -x start";
|
||||
ExecStop = "${pkgs.fail2ban}/bin/fail2ban-client stop";
|
||||
ExecReload = "${pkgs.fail2ban}/bin/fail2ban-client reload";
|
||||
PIDFile = "/run/fail2ban/fail2ban.pid";
|
||||
Restart = "always";
|
||||
|
||||
ReadOnlyDirectories = "/";
|
||||
ReadWriteDirectories = "/run/fail2ban /var/tmp /var/lib";
|
||||
PrivateTmp = "true";
|
||||
RuntimeDirectory = "fail2ban";
|
||||
CapabilityBoundingSet = "CAP_DAC_READ_SEARCH CAP_NET_ADMIN CAP_NET_RAW";
|
||||
};
|
||||
serviceConfig = {
|
||||
ExecStart = "${cfg.package}/bin/fail2ban-server -xf start";
|
||||
ExecStop = "${cfg.package}/bin/fail2ban-server stop";
|
||||
ExecReload = "${cfg.package}/bin/fail2ban-server reload";
|
||||
Type = "simple";
|
||||
Restart = "on-failure";
|
||||
PIDFile = "/run/fail2ban/fail2ban.pid";
|
||||
# Capabilities
|
||||
CapabilityBoundingSet = [ "CAP_AUDIT_READ" "CAP_DAC_READ_SEARCH" "CAP_NET_ADMIN" "CAP_NET_RAW" ];
|
||||
# Security
|
||||
NoNewPrivileges = true;
|
||||
# Directory
|
||||
RuntimeDirectory = "fail2ban";
|
||||
RuntimeDirectoryMode = "0750";
|
||||
StateDirectory = "fail2ban";
|
||||
StateDirectoryMode = "0750";
|
||||
LogsDirectory = "fail2ban";
|
||||
LogsDirectoryMode = "0750";
|
||||
# Sandboxing
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = true;
|
||||
PrivateTmp = true;
|
||||
PrivateDevices = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectControlGroups = true;
|
||||
};
|
||||
};
|
||||
|
||||
# Add some reasonable default jails. The special "DEFAULT" jail
|
||||
# sets default values for all other jails.
|
||||
services.fail2ban.jails.DEFAULT =
|
||||
''
|
||||
ignoreip = 127.0.0.1/8
|
||||
bantime = 600
|
||||
findtime = 600
|
||||
maxretry = 3
|
||||
backend = systemd
|
||||
enabled = true
|
||||
'';
|
||||
|
||||
services.fail2ban.jails.DEFAULT = ''
|
||||
${optionalString cfg.bantime-increment.enable ''
|
||||
# Bantime incremental
|
||||
bantime.increment = ${if cfg.bantime-increment.enable then "true" else "false"}
|
||||
bantime.maxtime = ${cfg.bantime-increment.maxtime}
|
||||
bantime.factor = ${cfg.bantime-increment.factor}
|
||||
bantime.formula = ${cfg.bantime-increment.formula}
|
||||
bantime.multipliers = ${cfg.bantime-increment.multipliers}
|
||||
bantime.overalljails = ${if cfg.bantime-increment.overalljails then "true" else "false"}
|
||||
''}
|
||||
# Miscellaneous options
|
||||
ignoreip = 127.0.0.1/8 ${optionalString config.networking.enableIPv6 "::1"} ${concatStringsSep " " cfg.ignoreIP}
|
||||
maxretry = 3
|
||||
backend = systemd
|
||||
# Actions
|
||||
banaction = ${cfg.banaction}
|
||||
banaction_allports = ${cfg.banaction-allports}
|
||||
'';
|
||||
# Block SSH if there are too many failing connection attempts.
|
||||
services.fail2ban.jails.ssh-iptables =
|
||||
''
|
||||
filter = sshd
|
||||
action = iptables-multiport[name=SSH, port="${concatMapStringsSep "," (p: toString p) config.services.openssh.ports}", protocol=tcp]
|
||||
maxretry = 5
|
||||
'';
|
||||
|
||||
services.fail2ban.jails.sshd = mkDefault ''
|
||||
enabled = true
|
||||
port = ${concatMapStringsSep "," (p: toString p) config.services.openssh.ports}
|
||||
'';
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{ stdenv, fetchFromGitHub, python3, gamin }:
|
||||
|
||||
let version = "0.10.5"; in
|
||||
let version = "0.11.1"; in
|
||||
|
||||
python3.pkgs.buildPythonApplication {
|
||||
pname = "fail2ban";
|
||||
|
@ -10,7 +10,7 @@ python3.pkgs.buildPythonApplication {
|
|||
owner = "fail2ban";
|
||||
repo = "fail2ban";
|
||||
rev = version;
|
||||
sha256 = "1s8g46vkwhqnagj69v4wvcasypzkmq7awhfbxahffrypcpad5ach";
|
||||
sha256 = "0kqvkxpb72y3kgmxf6g36w67499c6gcd2a9yyblagwx12y05f1sh";
|
||||
};
|
||||
|
||||
pythonPath = with python3.pkgs;
|
||||
|
@ -50,7 +50,7 @@ python3.pkgs.buildPythonApplication {
|
|||
'';
|
||||
|
||||
meta = with stdenv.lib; {
|
||||
homepage = http://www.fail2ban.org/;
|
||||
homepage = https://www.fail2ban.org/;
|
||||
description = "A program that scans log files for repeated failing login attempts and bans IP addresses";
|
||||
license = licenses.gpl2Plus;
|
||||
maintainers = with maintainers; [ eelco lovek323 fpletz ];
|
||||
|
|
Loading…
Reference in a new issue