{ pkgs, ... }: {
# References:
# https://blog.lrvt.de/configuring-fail2ban-with-traefik/
# https://nixos.wiki/wiki/Fail2ban#Extending_Fail2ban
services.logrotate = {
enable = true;
checkConfig = true;
settings = {
"/var/log/traefik/access.log" = {
frequency = "daily";
rotate = 30;
};
};
};
services.fail2ban.jails = {
traefik-general-forceful-browsing = {
settings = {
enabled = true;
filter = "traefik-general-forceful-browsing";
action = "action-ban-docker-forceful-browsing";
logpath = "/var/log/traefik/access.log";
backend = "auto";
findtime = 600;
bantime = 600;
maxretry = 5;
};
};
};
environment.etc= {
"fail2ban/filter.d/traefik-general-forceful-browsing.conf".text = pkgs.lib.mkDefault (pkgs.lib.mkAfter ''
[INCLUDES]
[Definition]
# fail regex based on traefik JSON access logs with enabled user agent logging
failregex = ^{"ClientAddr":".*","ClientHost":"","ClientPort":".*","ClientUsername":".*","DownstreamContentSize":.*,"DownstreamStatus":.*,"Duration":.*,"OriginContentSize":.*,"OriginDuration":.*,"OriginStatus":(405|404|403|402|401),"Overhead":.*,"RequestAddr":".*","RequestContentSize":.*,"RequestCount":.*,"RequestHost":".*","RequestMethod":".*","RequestPath":".*","RequestPort":".*","RequestProtocol":".*","RequestScheme":".*","RetryAttempts":.*,.*"StartLocal":".*","StartUTC":".*","TLSCipher":".*","TLSVersion":".*","entryPointName":".*","level":".*","msg":".*",("request_User-Agent":".*",){0,1}?"time":".*"}$
# custom date pattern for traefik JSON access logs
# based on https://github.com/fail2ban/fail2ban/issues/2558#issuecomment-546738270
datepattern = "StartLocal"\s*:\s*"%%Y-%%m-%%d[T]%%H:%%M:%%S\.%%f\d*(%%z)?",
# ignore common errors like missing media files or JS/CSS/TXT/ICO stuff
ignoreregex = ^{"ClientAddr":".*","ClientHost":"","ClientPort":".*","ClientUsername":".*","DownstreamContentSize":.*,"DownstreamStatus":.*,"Duration":.*,"OriginContentSize":.*,"OriginDuration":.*,"OriginStatus":(405|404|403|402|401),"Overhead":.*,"RequestAddr":".*","RequestContentSize":.*,"RequestCount":.*,"RequestHost":".*","RequestMethod":".*","RequestPath":".*(\.png|\.txt|\.jpg|\.ico|\.js|\.css|\.ttf|\.woff|\.woff2)(/)*?","RequestPort":".*","RequestProtocol":".*","RequestScheme":".*","RetryAttempts":.*,.*"StartLocal":".*","StartUTC":".*","TLSCipher":".*","TLSVersion":".*","entryPointName":".*","level":".*","msg":".*",("request_User-Agent":".*",){0,1}?"time":".*"}$
'');
"fail2ban/action.d/action-ban-docker-forceful-browsing.conf".text = pkgs.lib.mkDefault (pkgs.lib.mkAfter ''
[Definition]
actionban = ${pkgs.iptables}/bin/iptables -I DOCKER-USER -m string --algo bm --string 'X-Forwarded-For: ' -j DROP
${pkgs.iptables}/bin/iptables -A INPUT -s -j DROP
actionunban = ${pkgs.iptables}/bin/iptables -D DOCKER-USER -m string --algo bm --string 'X-Forwarded-For: ' -j DROP
${pkgs.iptables}/bin/iptables -D INPUT -s -j DROP
'');
};
}