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 103 restartTriggers = [ fail2banConf jailConf ]; 104 path = [ pkgs.fail2ban pkgs.iptables ]; 105 106 preStart = 107 '' 108 mkdir -p /run/fail2ban -m 0755 109 mkdir -p /var/lib/fail2ban 110 ''; 111 112 serviceConfig = 113 { ExecStart = "${pkgs.fail2ban}/bin/fail2ban-server -f"; 114 ReadOnlyDirectories = "/"; 115 ReadWriteDirectories = "/run /var/tmp /var/lib"; 116 CapabilityBoundingSet = "CAP_DAC_READ_SEARCH CAP_NET_ADMIN CAP_NET_RAW"; 117 }; 118 119 postStart = 120 '' 121 # Wait for the server to start listening. 122 for ((n = 0; n < 20; n++)); do 123 if fail2ban-client ping; then break; fi 124 sleep 0.5 125 done 126 127 # Reload its configuration. 128 fail2ban-client reload 129 ''; 130 }; 131 132 # Add some reasonable default jails. The special "DEFAULT" jail 133 # sets default values for all other jails. 134 services.fail2ban.jails.DEFAULT = 135 '' 136 ignoreip = 127.0.0.1/8 137 bantime = 600 138 findtime = 600 139 maxretry = 3 140 backend = systemd 141 enabled = true 142 ''; 143 144 # Block SSH if there are too many failing connection attempts. 145 services.fail2ban.jails.ssh-iptables = 146 '' 147 filter = sshd 148 action = iptables[name=SSH, port=ssh, protocol=tcp] 149 maxretry = 5 150 ''; 151 152 }; 153 154}