1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6
7 cfg = config.services.fail2ban;
8
9 fail2banConf = pkgs.writeText "fail2ban.conf" cfg.daemonConfig;
10
11 jailConf = pkgs.writeText "jail.conf"
12 (concatStringsSep "\n" (attrValues (flip mapAttrs cfg.jails (name: def:
13 optionalString (def != "")
14 ''
15 [${name}]
16 ${def}
17 ''))));
18
19in
20
21{
22
23 ###### interface
24
25 options = {
26
27 services.fail2ban = {
28 enable = mkOption {
29 default = false;
30 type = types.bool;
31 description = "Whether to enable the fail2ban service.";
32 };
33
34 daemonConfig = mkOption {
35 default =
36 ''
37 [Definition]
38 loglevel = INFO
39 logtarget = SYSLOG
40 socket = /run/fail2ban/fail2ban.sock
41 pidfile = /run/fail2ban/fail2ban.pid
42 '';
43 type = types.lines;
44 description =
45 ''
46 The contents of Fail2ban's main configuration file. It's
47 generally not necessary to change it.
48 '';
49 };
50
51 jails = mkOption {
52 default = { };
53 example = literalExample ''
54 { apache-nohome-iptables = '''
55 # Block an IP address if it accesses a non-existent
56 # home directory more than 5 times in 10 minutes,
57 # since that indicates that it's scanning.
58 filter = apache-nohome
59 action = iptables-multiport[name=HTTP, port="http,https"]
60 logpath = /var/log/httpd/error_log*
61 findtime = 600
62 bantime = 600
63 maxretry = 5
64 ''';
65 }
66 '';
67 type = types.attrsOf types.lines;
68 description =
69 ''
70 The configuration of each Fail2ban “jail”. A jail
71 consists of an action (such as blocking a port using
72 <command>iptables</command>) that is triggered when a
73 filter applied to a log file triggers more than a certain
74 number of times in a certain time period. Actions are
75 defined in <filename>/etc/fail2ban/action.d</filename>,
76 while filters are defined in
77 <filename>/etc/fail2ban/filter.d</filename>.
78 '';
79 };
80
81 };
82
83 };
84
85
86 ###### implementation
87
88 config = mkIf cfg.enable {
89
90 environment.systemPackages = [ pkgs.fail2ban ];
91
92 environment.etc."fail2ban/fail2ban.conf".source = fail2banConf;
93 environment.etc."fail2ban/jail.conf".source = jailConf;
94 environment.etc."fail2ban/action.d".source = "${pkgs.fail2ban}/etc/fail2ban/action.d/*.conf";
95 environment.etc."fail2ban/filter.d".source = "${pkgs.fail2ban}/etc/fail2ban/filter.d/*.conf";
96
97 systemd.services.fail2ban =
98 { description = "Fail2ban Intrusion Prevention System";
99
100 wantedBy = [ "multi-user.target" ];
101 after = [ "network.target" ];
102 partOf = optional config.networking.firewall.enable "firewall.service";
103
104 restartTriggers = [ fail2banConf jailConf ];
105 path = [ pkgs.fail2ban pkgs.iptables pkgs.iproute ];
106
107 preStart =
108 ''
109 mkdir -p /var/lib/fail2ban
110 '';
111
112 unitConfig.Documentation = "man:fail2ban(1)";
113
114 serviceConfig =
115 { Type = "forking";
116 ExecStart = "${pkgs.fail2ban}/bin/fail2ban-client -x start";
117 ExecStop = "${pkgs.fail2ban}/bin/fail2ban-client stop";
118 ExecReload = "${pkgs.fail2ban}/bin/fail2ban-client reload";
119 PIDFile = "/run/fail2ban/fail2ban.pid";
120 Restart = "always";
121
122 ReadOnlyDirectories = "/";
123 ReadWriteDirectories = "/run/fail2ban /var/tmp /var/lib";
124 PrivateTmp = "true";
125 RuntimeDirectory = "fail2ban";
126 CapabilityBoundingSet = "CAP_DAC_READ_SEARCH CAP_NET_ADMIN CAP_NET_RAW";
127 };
128 };
129
130 # Add some reasonable default jails. The special "DEFAULT" jail
131 # sets default values for all other jails.
132 services.fail2ban.jails.DEFAULT =
133 ''
134 ignoreip = 127.0.0.1/8
135 bantime = 600
136 findtime = 600
137 maxretry = 3
138 backend = systemd
139 enabled = true
140 '';
141
142 # Block SSH if there are too many failing connection attempts.
143 services.fail2ban.jails.ssh-iptables =
144 ''
145 filter = sshd
146 action = iptables[name=SSH, port=ssh, protocol=tcp]
147 maxretry = 5
148 '';
149
150 };
151
152}