❄️ Dotfiles for our NixOS system configuration.

chore(services:fail2ban): test changes(??)

Chloe dd2f9409 1eb37d0a

Changed files
+37 -46
services
fail2ban
+37 -46
services/fail2ban/default.nix
··· 1 - { config, pkgs, ... }: 1 + { pkgs, ... }: 2 2 3 3 { 4 4 age.secrets.abuseipdb = { ··· 49 49 maxretry = 5; 50 50 findtime = "3600"; 51 51 bantime = "86400"; 52 - action = "iptables-multiport[name=SSH, port='ssh']\nabuseipdb[abuseipdb_apikey='$(cat /run/agenix/abuseipdb)', abuseipdb_category='18,22']"; 52 + action = "iptables-multiport[name=SSH, port='ssh']\nabuseipdb-agenix[abuseipdb_category='18,22']"; 53 53 }; 54 54 55 55 # Caddy HTTP/HTTPS protection - monitor for repeated 4xx/5xx errors ··· 62 62 maxretry = 10; 63 63 findtime = "600"; 64 64 bantime = "3600"; 65 - action = "iptables-multiport[name=Caddy, port='http,https']\nabuseipdb[abuseipdb_apikey='$(cat /run/agenix/abuseipdb)', abuseipdb_category='21']"; 65 + action = "iptables-multiport[name=Caddy, port='http,https']\nabuseipdb-agenix[abuseipdb_category='21']"; 66 66 }; 67 67 68 68 # Rate-based protection - ban on excessive requests ··· 75 75 maxretry = 50; 76 76 findtime = "60"; 77 77 bantime = "1800"; 78 - action = "iptables-multiport[name=Caddy-RateLimit, port='http,https']\nabuseipdb[abuseipdb_apikey='$(cat /run/agenix/abuseipdb)', abuseipdb_category='21']"; 78 + action = "iptables-multiport[name=Caddy-RateLimit, port='http,https']\nabuseipdb-agenix[abuseipdb_category='21']"; 79 79 }; 80 80 }; 81 81 }; 82 82 83 - # Custom filters and actions for Fail2Ban 84 - environment.etc = 85 - let 86 - abuseipdbAction = '' 87 - [Definition] 88 - actionstart = 89 - actionstop = 90 - actioncheck = 83 + # Custom filters for Fail2Ban 84 + environment.etc = { 85 + # Caddy HTTP error monitoring filter 86 + "fail2ban/filter.d/caddy-http.conf".text = '' 87 + [Definition] 88 + failregex = ^<HOST> -.*" (?:400|401|403|404|405|429|500|502|503|504) .*$ 89 + ignoreregex = 90 + ''; 91 91 92 - # Report IP to AbuseIPDB using official fail2ban pattern 93 - # The abuseipdb_apikey parameter is passed from the jail action call 94 - actionban = lgm=$(printf '%%.1000s\n...' "<matches>"); curl -sSf "https://api.abuseipdb.com/api/v2/report" \ 95 - -H "Accept: application/json" \ 96 - -H "Key: <abuseipdb_apikey>" \ 97 - --data-urlencode "comment=$lgm" \ 98 - --data-urlencode "ip=<ip>" \ 99 - --data "categories=<abuseipdb_category>" 92 + # Caddy rate limiting filter - detects repeated requests within short timeframe 93 + "fail2ban/filter.d/caddy-ratelimit.conf".text = '' 94 + [Definition] 95 + failregex = ^<HOST> -.*" \d{3} .*$ 96 + ignoreregex = 97 + ''; 100 98 101 - # No action to unban - AbuseIPDB reports are permanent 102 - actionunban = 99 + # Custom abuseipdb action that reads API key from file 100 + "fail2ban/action.d/abuseipdb-agenix.conf".text = '' 101 + [Definition] 102 + # Report IP to AbuseIPDB, reading API key from Agenix secret file 103 + # The entire command is wrapped in /bin/sh -c to ensure shell expansion of $(cat ...) 104 + actionban = /bin/sh -c 'lgm=$(printf "%%.1000s\n..." "<matches>"); curl -sSf "https://api.abuseipdb.com/api/v2/report" \ 105 + -H "Accept: application/json" \ 106 + -H "Key: $(cat /run/agenix/abuseipdb)" \ 107 + --data-urlencode "comment=$lgm" \ 108 + --data-urlencode "ip=<ip>" \ 109 + --data "categories=<abuseipdb_category>"' 103 110 104 - [Init] 105 - # Default category for abuse report 106 - abuseipdb_category = 18 107 - # API key must be provided in jail action call 108 - abuseipdb_apikey = 109 - ''; 110 - in 111 - { 112 - # Caddy HTTP error monitoring filter 113 - "fail2ban/filter.d/caddy-http.conf".text = '' 114 - [Definition] 115 - failregex = ^<HOST> -.*" (?:400|401|403|404|405|429|500|502|503|504) .*$ 116 - ignoreregex = 117 - ''; 111 + actionstart = 112 + actionstop = 113 + actioncheck = 114 + actionunban = 118 115 119 - # Caddy rate limiting filter - detects repeated requests within short timeframe 120 - "fail2ban/filter.d/caddy-ratelimit.conf".text = '' 121 - [Definition] 122 - failregex = ^<HOST> -.*" \d{3} .*$ 123 - ignoreregex = 124 - ''; 125 - 126 - # AbuseIPDB action - must be copied into action.d directory 127 - "fail2ban/action.d/abuseipdb.conf".text = abuseipdbAction; 128 - }; 116 + [Init] 117 + abuseipdb_category = 18 118 + ''; 119 + }; 129 120 130 121 # Ensure the log directory exists 131 122 systemd.tmpfiles.rules = [