b7a889759d
I'm not really sure which one of types.lines or types.str that fit better, but I'm going for types.lines because it behaves more like the current type (i.e. have the ability to merge).
153 lines
4.2 KiB
Nix
153 lines
4.2 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 = {
|
|
enable = mkOption {
|
|
default = false;
|
|
type = types.bool;
|
|
description = "Whether to enable the fail2ban service.";
|
|
};
|
|
|
|
daemonConfig = mkOption {
|
|
default =
|
|
''
|
|
[Definition]
|
|
loglevel = INFO
|
|
logtarget = SYSLOG
|
|
socket = /run/fail2ban/fail2ban.sock
|
|
pidfile = /run/fail2ban/fail2ban.pid
|
|
'';
|
|
type = types.lines;
|
|
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.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>.
|
|
'';
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
###### implementation
|
|
|
|
config = mkIf cfg.enable {
|
|
|
|
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
|
|
mkdir -p /var/lib/fail2ban
|
|
'';
|
|
|
|
serviceConfig =
|
|
{ ExecStart = "${pkgs.fail2ban}/bin/fail2ban-server -f";
|
|
ReadOnlyDirectories = "/";
|
|
ReadWriteDirectories = "/run /var/tmp /var/lib";
|
|
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 = systemd
|
|
'';
|
|
|
|
# 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]
|
|
maxretry = 5
|
|
'';
|
|
|
|
};
|
|
|
|
}
|