So I did a bunch of research on how to do this after watching the same ip address hit my cluster of web servers one after another. Since I'm using AWS I figured there might be an easy way and its working beautifully in my first two days of testing 5 servers.
First thing I recommend is temporarily disabling SELinux, we will deal with it at the end. I'm not an SELinux expert but what I did works so far.
The primary requirement is a shared file source, I use AWS EFS. Once the new drive is provisioned and mounted, I changed logtarget inside of /etc/fail2ban/fail2ban.conf to a subfolder in the EFS drive.
logtarget = /efsmount/fail2ban/server1.log
Then I wrote a simple filter and placed it in /etc/fail2ban/filter.d/fail2ban-log.conf
[Definition]
failregex = .* Ban <HOST>
ignoreregex =
Added the filter to /etc/fail2ban/jail.local
[fail2ban-log]
enabled = true
port = http,https
findtime = 86400 ; 1 day
logpath = /efsmount/fail2ban/server1.log
/efsmount/fail2ban/server2.log
/efsmount/fail2ban/server3.log
/efsmount/fail2ban/server4.log
maxretry = 1
Then restarted fail2ban
sudo fail2ban-client reload
So far so good! No the painful part is SELinux. After I let fail2ban run for a bit I ran this command that would allow fail2ban through the filters.
sudo grep fail2ban /var/log/audit/audit.log | sudo audit2allow -M fail2ban-nfs
Audit2allow will tell you to run this command
sudo semodule -i fail2ban-nfs.pp
I am still checking my SELinux logs here and there to see if there are any more denials. If anyone has a tip on how to get that clear SELinux with another method that would be awesome.
sudo cat /var/log/audit/audit.log |grep fail2ban |grep denied
At this point I was still getting errors when restarting fail2ban. There is a bug when using action=action_mwl in jail.local. After a bit of googling I found this which is working so far. From what I read its because of the line breaks in the logpath directive pointing to multiple files. I tried with commas, spaces, etc nothing else worked with action_mwl.
action_mwm = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
%(mta)s-whois-matches[name=%(__name__)s, dest="%(destemail)s", chain="%(chain)s"]
action = %(action_mwm)s
Don't forget to turn SELinux back on!