blob: ae1fd22d23ee7e86308abf2021da2b3519dcfb9c (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
{ config, pkgs, ... }:
with pkgs.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
'';
};
}
|