Integration fail2ban IDS with AbuseIPDB

Md. Mahim Bin Firoj
5 min readAug 17, 2023

--

I tried to simplify the steps from the below link.

https://www.abuseipdb.com/fail2ban.html#1

Our target is, we will protect our internet exposed linux server’s from malicious attacks as well as we will report the malicious ip to the abuseipdb. This is one of the steps of hardening our linux servers.

The nutshell of steps:

  1. Install fail2ban on a debian box (kali)
  2. Create the API key from AbuseIPDB' s website.
  3. Invoke the reporting action to abuseipdb.

From your kali machine, run the below commands one by one to install fail2ban IDS. We will not touch jail.conf file as it will be continuously updated by fail2ban service also it will be used as source settings of fail2ban. So we will transform it to jail.local

apt update -y
apt upgrade -y (optional)

apt install fail2ban -y

systemctl start fail2ban.service
systemctl enable fail2ban.service

cd /etc/fail2ban/
ls
cp jail.conf jail.local
vim jail.local

ignoreip = 127.0.0.1/8 ::1 192.168.88.0/24

You can exclude those networks, from where there is no change to coming brute force attack i.e. Your internal subnets.

bantime = 10m

This means, once the condition meets, then how long the ip will be in the firewall block list. If the attack is frequent, then you can increase this time as per your need.

Findtime = 10m

maxretry = 5

Both the above are condition’s. This means within 10 minutes of time if 5 failed logon happened, then at the time of 6th try, the ip will be blocked.

action = $(action_)s

This is the simple action to take which is ban only. This is globally ban. We can customize this on per jail. We will explain that later.

Here jail means, each service or module. i.e. apache, sshd etc.

This is very basic. If any attacker try to brute force against our server then attacker’s ip will be banned or blocked for 10 minutes.

Unblocking an ip from block list:

First you need to find the jail name. Say the jail name is sshd. Then you need to find out the ip address that is blocked under that jail. Now type the below command’s to do this:

fail2ban-client status <jail name>    (this will give you the applied jail list with the ban ip)
fail2ban-client status sshd
or
iptables -S or iptables -L -n
iptables -S | grep f2b (from here you will get the ip)

fail2ban-client set sshd unbanip 192.168.1.100
systemctl restart fail2ban.service

Now what if we want fail2ban to report the ip to the AbuseIPDB' s service !!!

To do that, now we will activate AbuseIPDB Reporting Action:

We can invoke the reporting action against all jail’s or specific jail. Recommended is for specific jail for better report. For example, we are invoking for sshd jail this time. Two parameters are needed, one is api key and another one is category. Without these parameters, the invoke will not start. The followings are the example of categories:

And following are the mandatory parameters.

%(action_abuseipdb)s[abuseipdb_apikey="you need to paste the api key here", abuseipdb_category="18,22"]

The above line of code is responsible for invoking the request to abuseipdb.

[sshd]
enabled = true

# To use more aggressive sshd modes set filter parameter "mode" in jail.local:
# normal (default), ddos, extra or aggressive (combines all).
# See "tests/files/logs/sshd" or "filter.d/sshd.conf" for usage example and details.
#mode = normal
port = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s

# Ban IP and report to AbuseIPDB for SSH Brute-Forcing
action = %(action_)s
%(action_abuseipdb)s[abuseipdb_apikey="you need to paste the api key here", abuseipdb_category="18,22"]

This can also be enabled globally for all jails. See below.

# Choose default action.  To change, just override value of 'action' with the
# interpolation to the chosen action shortcut (e.g. action_mw, action_mwl, etc) in jail.local
# globally (section [DEFAULT]) or per specific section
action = %(action_)s
%(action_abuseipdb)s[abuseipdb_apikey="you need to paste the api key here", abuseipdb_category="18"]

Once you have updated your jail.local configuration, save the file and restart or reload the Fail2Ban service to ensure your configuration is working:

fail2ban-client reload

If your configuration is correct, Fail2Ban should start running the AbuseIPDB action each time a new IP is banned. Log in and check your reported IPs page, and watch as Fail2Ban starts automatically reporting IPs to AbuseIPDB under your account!

Now let’s go to /etc/fail2ban/action.d/abuseipdb.conf to see how the invocation initiates.

At the end of line, we need to paste our api key first.

Then replace the actionban values with the following:

actionban = curl --fail 'https://api.abuseipdb.com/api/v2/report' -H 'Accept: application/json' -H 'Key: <abuseipdb_apikey>' --data-urlencode "comment=<matches>" --data-urlencode 'ip=<ip>' --data 'categories=<abuseipdversionb_category>'

Then finally actionban command will be executed when fail2ban ban any ip address.

But wait. The above actionban command parameter need to be replaced. I am telling you why.

Duplicate Reports on Restart:

Whenever Fail2Ban restarts, it calls the actionban function for each IP stored in the database file. This causes duplicate reports to AbuseIPDB. If you restart your server often, we have a script that will prevent this from happening.

Follow the steps below to modify your configuration to use the custom script:

  1. Create the file abuseipdb-fail2ban-report.sh

2. Type touch abuseipdb-fail2ban-report.sh into your terminal.

Copy the following code into the aforementioned created file, updating the path to the REPORTED_IP_LIST_FILE if necessary.

#!/bin/bash

REPORTED_IP_LIST_FILE=/home/pi/abuseipdb-reported-ip-list
FAIL2BAN_SQLITE_DB=/var/lib/fail2ban/fail2ban.sqlite3

APIKEY=$1
COMMENT=$2
IP=$3
CATEGORIES=$4
BANTIME=$5

ipMatch=`grep -Fe "IP=$IP L=[0-9\-]+" $REPORTED_IP_LIST_FILE`

shouldBanIP=1
currentTimestamp=`date +%s`

if [ -z $ipMatch ] ; then
banLength=`echo $ipMatch | sed -E 's/.*L=([0-9\-]+)/\1/'`
timeOfBan=`sqlite3 $FAIL2BAN_SQLITE_DB "SELECT timeofban FROM bans WHERE ip = '$IP'"`

if (((banLength == -1 && banLength == BANTIME) || (timeOfBan > 0 && timeOfBan + banLength > currentTimestamp))) ; then
shouldBanIP=0
else
sed -i "/^IP=$IP.*$/d" $REPORTED_IP_LIST_FILE
fi
fi

if [ $shouldBanIP -eq 1 ] ; then
echo "IP=$IP L=$BANTIME" >> $REPORTED_IP_LIST_FILE
curl --fail 'https://api.abuseipdb.com/api/v2/report' \
-H 'Accept: application/json' \
-H "Key: $APIKEY" \
--data-urlencode "comment=$COMMENT" \
--data-urlencode "ip=$IP" \
--data "categories=$CATEGORIES"
fi

3. Make the file an executable. Type chmod +x abuseipdb-fail2ban-report.sh into your terminal.
4. Modify /etc/fail2ban/action.d/abuseipdb.conf actionban to be the following:

actionban = /path/to/file/abuseipdb-fail2ban-report.sh \

"<abuseipdb_apikey>" "<matches>" "<ip>" "<abuseipdb_category>" "<bantime>"

or

actionban = /path/to/file/abuseipdb-fail2ban-report.sh "<abuseipdb_apikey>" "<matches>" "<ip>" "<abuseipdb_category>" "<bantime>"

5. Change the line:

%(action_abuseipdb)s[abuseipdb_apikey=”my-api-key”, abuseipdb_category=”18,22"] in your jail.local to:

%(action_abuseipdb)s[abuseipdb_apikey=”my-api-key”, abuseipdb_category=”18,22", bantime=”%(bantime)s”] for each jail that you would like this applied to.

6. Restart Fail2Ban using fail2ban-client reload.

I hope you will learn something new from here.

Thanks. Please Subscribe below.

LinkedIn:

https://www.linkedin.com/in/md-mahimbin-firoj-7b8a5a113/

YouTube:

https://www.youtube.com/@mahimfiroj1802/videos

--

--

No responses yet