at 18.09-beta 4.6 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.sshguard; 7in { 8 9 ###### interface 10 11 options = { 12 13 services.sshguard = { 14 enable = mkOption { 15 default = false; 16 type = types.bool; 17 description = "Whether to enable the sshguard service."; 18 }; 19 20 attack_threshold = mkOption { 21 default = 30; 22 type = types.int; 23 description = '' 24 Block attackers when their cumulative attack score exceeds threshold. Most attacks have a score of 10. 25 ''; 26 }; 27 28 blacklist_threshold = mkOption { 29 default = null; 30 example = 120; 31 type = types.nullOr types.int; 32 description = '' 33 Blacklist an attacker when its score exceeds threshold. Blacklisted addresses are loaded from and added to blacklist-file. 34 ''; 35 }; 36 37 blacklist_file = mkOption { 38 default = "/var/lib/sshguard/blacklist.db"; 39 type = types.path; 40 description = '' 41 Blacklist an attacker when its score exceeds threshold. Blacklisted addresses are loaded from and added to blacklist-file. 42 ''; 43 }; 44 45 blocktime = mkOption { 46 default = 120; 47 type = types.int; 48 description = '' 49 Block attackers for initially blocktime seconds after exceeding threshold. Subsequent blocks increase by a factor of 1.5. 50 51 sshguard unblocks attacks at random intervals, so actual block times will be longer. 52 ''; 53 }; 54 55 detection_time = mkOption { 56 default = 1800; 57 type = types.int; 58 description = '' 59 Remember potential attackers for up to detection_time seconds before resetting their score. 60 ''; 61 }; 62 63 whitelist = mkOption { 64 default = [ ]; 65 example = [ "198.51.100.56" "198.51.100.2" ]; 66 type = types.listOf types.str; 67 description = '' 68 Whitelist a list of addresses, hostnames, or address blocks. 69 ''; 70 }; 71 72 services = mkOption { 73 default = [ "sshd" ]; 74 example = [ "sshd" "exim" ]; 75 type = types.listOf types.str; 76 description = '' 77 Systemd services sshguard should receive logs of. 78 ''; 79 }; 80 81 }; 82 83 }; 84 85 86 ###### implementation 87 88 config = mkIf cfg.enable { 89 90 environment.systemPackages = [ pkgs.sshguard pkgs.iptables pkgs.ipset ]; 91 92 environment.etc."sshguard.conf".text = let 93 list_services = ( name: "-t ${name} "); 94 in '' 95 BACKEND="${pkgs.sshguard}/libexec/sshg-fw-ipset" 96 LOGREADER="LANG=C ${pkgs.systemd}/bin/journalctl -afb -p info -n1 ${toString (map list_services cfg.services)} -o cat" 97 ''; 98 99 systemd.services.sshguard = 100 { description = "SSHGuard brute-force attacks protection system"; 101 102 wantedBy = [ "multi-user.target" ]; 103 after = [ "network.target" ]; 104 partOf = optional config.networking.firewall.enable "firewall.service"; 105 106 path = [ pkgs.iptables pkgs.ipset pkgs.iproute pkgs.systemd ]; 107 108 postStart = '' 109 mkdir -p /var/lib/sshguard 110 ${pkgs.ipset}/bin/ipset -quiet create -exist sshguard4 hash:ip family inet 111 ${pkgs.ipset}/bin/ipset -quiet create -exist sshguard6 hash:ip family inet6 112 ${pkgs.iptables}/bin/iptables -I INPUT -m set --match-set sshguard4 src -j DROP 113 ${pkgs.iptables}/bin/ip6tables -I INPUT -m set --match-set sshguard6 src -j DROP 114 ''; 115 116 preStop = '' 117 ${pkgs.iptables}/bin/iptables -D INPUT -m set --match-set sshguard4 src -j DROP 118 ${pkgs.iptables}/bin/ip6tables -D INPUT -m set --match-set sshguard6 src -j DROP 119 ''; 120 121 unitConfig.Documentation = "man:sshguard(8)"; 122 123 serviceConfig = { 124 Type = "simple"; 125 ExecStart = let 126 list_whitelist = ( name: "-w ${name} "); 127 in '' 128 ${pkgs.sshguard}/bin/sshguard -a ${toString cfg.attack_threshold} ${optionalString (cfg.blacklist_threshold != null) "-b ${toString cfg.blacklist_threshold}:${cfg.blacklist_file} "}-i /run/sshguard/sshguard.pid -p ${toString cfg.blocktime} -s ${toString cfg.detection_time} ${toString (map list_whitelist cfg.whitelist)} 129 ''; 130 PIDFile = "/run/sshguard/sshguard.pid"; 131 Restart = "always"; 132 133 ReadOnlyDirectories = "/"; 134 ReadWriteDirectories = "/run/sshguard /var/lib/sshguard"; 135 RuntimeDirectory = "sshguard"; 136 StateDirectory = "sshguard"; 137 CapabilityBoundingSet = "CAP_NET_ADMIN CAP_NET_RAW"; 138 }; 139 }; 140 }; 141}