29027fd1e1
Using pkgs.lib on the spine of module evaluation is problematic because the pkgs argument depends on the result of module evaluation. To prevent an infinite recursion, pkgs and some of the modules are evaluated twice, which is inefficient. Using ‘with lib’ prevents this problem.
149 lines
4 KiB
Nix
149 lines
4 KiB
Nix
{ config, lib, pkgs, ... }:
|
|
|
|
with lib;
|
|
|
|
let
|
|
|
|
cfg = config.services.fail2ban;
|
|
|
|
fail2banConf = pkgs.writeText "fail2ban.conf" cfg.daemonConfig;
|
|
|
|
jailConf = pkgs.writeText "jail.conf"
|
|
(concatStringsSep "\n" (attrValues (flip mapAttrs cfg.jails (name: def:
|
|
optionalString (def != "")
|
|
''
|
|
[${name}]
|
|
${def}
|
|
''))));
|
|
|
|
in
|
|
|
|
{
|
|
|
|
###### interface
|
|
|
|
options = {
|
|
|
|
services.fail2ban = {
|
|
|
|
daemonConfig = mkOption {
|
|
default =
|
|
''
|
|
[Definition]
|
|
loglevel = 3
|
|
logtarget = SYSLOG
|
|
socket = /run/fail2ban/fail2ban.sock
|
|
pidfile = /run/fail2ban/fail2ban.pid
|
|
'';
|
|
type = types.string;
|
|
description =
|
|
''
|
|
The contents of Fail2ban's main configuration file. It's
|
|
generally not necessary to change it.
|
|
'';
|
|
};
|
|
|
|
jails = mkOption {
|
|
default = { };
|
|
example =
|
|
{ "apache-nohome-iptables" =
|
|
''
|
|
# Block an IP address if it accesses a non-existent
|
|
# home directory more than 5 times in 10 minutes,
|
|
# since that indicates that it's scanning.
|
|
filter = apache-nohome
|
|
action = iptables-multiport[name=HTTP, port="http,https"]
|
|
logpath = /var/log/httpd/error_log*
|
|
findtime = 600
|
|
bantime = 600
|
|
maxretry = 5
|
|
'';
|
|
};
|
|
type = types.attrsOf types.string;
|
|
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 = {
|
|
|
|
environment.systemPackages = [ pkgs.fail2ban ];
|
|
|
|
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";
|
|
|
|
systemd.services.fail2ban =
|
|
{ description = "Fail2ban intrusion prevention system";
|
|
|
|
wantedBy = [ "multi-user.target" ];
|
|
after = [ "network.target" ];
|
|
|
|
restartTriggers = [ fail2banConf jailConf ];
|
|
path = [ pkgs.fail2ban pkgs.iptables ];
|
|
|
|
preStart =
|
|
''
|
|
mkdir -p /run/fail2ban -m 0755
|
|
'';
|
|
|
|
serviceConfig =
|
|
{ ExecStart = "${pkgs.fail2ban}/bin/fail2ban-server -f";
|
|
ReadOnlyDirectories = "/";
|
|
ReadWriteDirectories = "/run /var/tmp";
|
|
CapabilityBoundingSet = "CAP_DAC_READ_SEARCH CAP_NET_ADMIN CAP_NET_RAW";
|
|
};
|
|
|
|
postStart =
|
|
''
|
|
# Wait for the server to start listening.
|
|
for ((n = 0; n < 20; n++)); do
|
|
if fail2ban-client ping; then break; fi
|
|
sleep 0.5
|
|
done
|
|
|
|
# Reload its configuration.
|
|
fail2ban-client reload
|
|
'';
|
|
};
|
|
|
|
# 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 = auto
|
|
'';
|
|
|
|
# Block SSH if there are too many failing connection attempts.
|
|
services.fail2ban.jails.ssh-iptables =
|
|
''
|
|
filter = sshd
|
|
action = iptables[name=SSH, port=ssh, protocol=tcp]
|
|
logpath = /var/log/warn
|
|
maxretry = 5
|
|
'';
|
|
|
|
};
|
|
|
|
}
|