A small bash script to create an ipset blacklist from banned IP addresses from (multiple) fail2ban jails, and incorporate it into an iptables rule. This project was inspired by ipset-blacklist, which creates ipset blacklists from published blocklists.
Banned IP addresses are fetched from fail2ban and written to an ipset blacklist. A rule is then added to iptables to DROP packets coming from any source that matches this blacklist.
The script can automatically remove blacklisted IP addresses from the fail2ban jails they originally came from. This helps keep iptables clean and ensures the use of ipset's fast hash table lookup for source matching.
Each time the script runs, banned IPs fetched from fail2ban are also written to a blacklist file. This file is used in subsequent runs to build the banned IP list. If you configure the script to automatically remove IPs from fail2ban, make sure this blacklist file is placed somewhere safe, since it is what the script uses to remember past banned IPs that have been removed from fail2ban. Since the script builds its banned IP list from both the blacklist file and fail2ban, and then writes this list back to the blacklist file (after removing duplicates and private IPs), the file is effectively self updating.
- fail2ban: If not already installed, install with
sudo apt-get install fail2ban
- ipset: If not already installed, install with
sudo apt-get install ipset
- Grab the ipset-fail2ban.sh and save it somewhere that makes sense. Make it executable.
sudo wget -O /usr/local/sbin/ipset-fail2ban.sh https://raw.githubusercontent.com/ritsu/ipset-fail2ban/master/ipset-fail2ban.sh && sudo chmod +x /usr/local/sbin/ipset-fail2ban.sh
- You can run the script without a configuration file to test. Replace
JAIL1,JAIL2,JAIL3
with your fail2ban jails. Use-h
to see a list of options.sudo /usr/local/sbin/ipset-fail2ban.sh -j JAIL1,JAIL2,JAIL3 sudo /usr/local/sbin/ipset-fail2ban.sh -h
- Grab the default configuration file.
sudo mkdir -p /etc/ipset-fail2ban && sudo wget -O /etc/ipset-fail2ban/ipset-fail2ban.conf https://raw.githubusercontent.com/ritsu/ipset-fail2ban/master/ipset-fail2ban.conf
- Modify ipset-fail2ban.conf according to your needs. Particularly,
JAILS
will need to be set according to your fail2ban setupBLACKLIST_FILE
by default saves to/etc/ipset-fail2ban/ipset-fail2ban.list
IPSET_RESTORE_FILE
by default saves to/etc/ipset-fail2ban/ipset-fail2ban.restore
CLEANUP
is set tofalse
by default, so banned IPs will remain in fail2ban jails even after being added to the ipset blacklist. It is recommended to set this totrue
after you have settled on a working configuration for your system.
- Once your config is set, run ipset-fail2ban with the configuration file and check iptables for the blacklist rule.
sudo /usr/local/sbin/ipset-fail2ban.sh /etc/ipset-fail2ban/ipset-fail2ban.conf sudo iptables -L INPUT -v --line-numbers | grep match-set 1 5209 327K DROP all -- any any anywhere anywhere match-set blacklist-fail2ban src
- Add the script to a cron job if you want it to automatically update.
sudo crontab -e PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin 0 0 * * * /usr/local/sbin/ipset-fail2ban.sh /etc/ipset-fail2ban/ipset-fail2ban.conf
Since the ipset blacklist and iptables rule are stored in memory, they are lost after a reboot. A simple way to make
them persistent is to edit /etc/rc.local
to create the blacklist and add the rule at startup:
ipset restore < /etc/ipset-fail2ban/ipset-fail2ban.restore
iptables -I INPUT 1 -m set --match-set blacklist-fail2ban src -j DROP
You could also instead use a firewall script of your choice and packages like iptables-persistent and netfilter-persistent. Just make sure the ipset blacklist is created before the blacklist rule is added to iptables.
One of the reasons we use ipset-fail2ban is to avoid the long list of fail2ban rules in iptables. Therefore, it is
better if the ipset-fail2ban rule is inserted before the fail2ban rules in the iptables INPUT chain. However, fail2ban
has a tendency to insert its rules at the top of the INPUT chain whenever it restarts. We can get around this by
changing the default rule position in fail2ban's action configs in /etc/fail2ban/action.d/
. Depending on which
actions your jails use, add one or more of the files:
sudo tee << EOF /etc/fail2ban/action.d/iptables-allports.local
[Definition]
actionstart = <iptables> -N f2b-<name>
<iptables> -A f2b-<name> -j <returntype>
<iptables> -I <chain> 2 -p <protocol> -j f2b-<name>
EOF
sudo tee << EOF /etc/fail2ban/action.d/iptables-multiport.local
[Definition]
actionstart = <iptables> -N f2b-<name>
<iptables> -A f2b-<name> -j <returntype>
<iptables> -I <chain> 2 -p <protocol> -m multiport --dports <port> -j f2b-<name>
EOF
If you use additional actions, create those files accordingly.
Besides creating ipset blacklists from fail2ban jails, you can also create ipset blacklists from published blocklists with ipset-blacklist to preemptively block bad IPs.
Both scripts can run independently on the same machine to generate two separate blacklists, which can be useful for keeping track of separate stats. Or, you can combine them into one blacklist by having ipset-fail2ban write to a local blacklist file instead of an ipset blacklist, and importing that into the ipset-blacklist script. To do that, first modify ipset-fail2ban.conf:
BLACKLIST_FILE="/etc/ipset-fail2ban/ipset-fail2ban.list"
IPSET_BLACKLIST="" # Leaving this empty will prevent any of the ipset functions from running
Then add the following line to the BLACKLISTS array in ipset-blacklist's ipset-blacklist.conf:
BLACKLISTS=(
"file:///etc/ipset-fail2ban/ipset-fail2ban.list"
...
)
Now simply run ipset-fail2ban before running ipset-blacklist, either manually or in a cron job.