On my servers I use the nifty program Fail2Ban to perform logbased automatic firewalling of ‘bad’ ip’s.
The idea behind this is easy: Some IP performs an action I don’t approve of. This can be any number of things, e.g. requesting pages in Apache that are commonly accessed by bots and/or scanners, or trying to log in to SSH with accounts that do not exist on the system. This bad behavior gets logged, and Fail2Ban keeps tabs on those logs, and using a number of rules it determines if a host is ‘bad’ enough to temporarily or permanently ban all access to the server. It does so by adding a few chains to Iptables (one for each thing it checks for), and dynamically adding/removing IP’s to/from these chains.
This all works perfectly. However, there’s one issue; When Iptables gets reloaded, it restores its default rules, removing the Fail2Ban chains and all the rules they contain, even if the ip’s in the chain were marked as permanent.
I created a workaround for this problem, consisting of two simple steps:
-
When a ‘bad’ ip gets banned, it’s added to the Iptables chain, but also written to a file, containing all collected ‘bad’ ip’s. (I use
/etc/shitlist
for this purpose). -
Whenever Iptables gets reloaded, I run a PHP script that checks the
/etc/shitlist
file for ‘safe’ and duplicate ip’s, and writes all other ip’s to the permanent Blocklist chain. (The checking for ‘safe’ ip’s might be a bit unneeded, but with my Fail2Ban rules it’s possible that one of my own ip’s gets banned for 10 minutes if a SSH login attempt fails for 5 times. Though it’s a temporary ban, the ip will still get written to the shitlist, and would end up in the permanent Blocklist).
To make this work, I made the following changes:
Every jail
in Fail2Ban uses an action.d
script to perform (un)banning. I defaulted all actions to an action script called iptables-allports.conf
. Basically this action drops everything in Iptables if a package originates from the ‘bad’ IP.
I updated the ban action such that:
After that I created a PHP script that updates Iptables with the ip’s contained in the shitlist:
|
|
You can run the script from the commandline (as root!) simply by stating php shitlist.php
, or add it to the startup script of your Iptables installation.
Hope this helps keeping your NIC’s available for VALID traffic!
Update:
Made some changes to the script to check for already existing bans, to keep your chains clean!
Update 2:
Little tweak to the script so it now loads an array of lists, in case you have various sources.