fail2ban with xt_recent reloaded 1


Here is the addition to fail2ban mit xt_recent.

Fail2ban can ban ip only until the server restarts.

I therefore add the bans not only in the firewall, but store them also into a mysql database.

Basics
I´ve created the database systemlog which containing two tables – one for the configs and one for the bans. The config table must not be present, but I have so the possibility to change block-times and must not adapt one or more scripts and can therefore read all of the jails with a slip and submit them to the firewall.
Below I leave the table config outside – for those interested in this part it´s avaible on monday at the end of this post.

The table systemlog.fail2ban contains some entrys:
source
port
jail
hits
last_hit

So i can simple reinitialice the firewall and have also a quick and easy way for some statistics.

Setup
setup mysql
login into mysql as root and run:

CREATE DATABASE systemlog;
CREATE USER 'systemlog'@'localhost' IDENTIFIED BY 'MYPASSWORD';
GRANT ALL ON systemlog.* TO 'systemlog'@'localhost' IDENTIFIED BY 'MYPASSWORD';
FLUSH PRIVILEGES;
QUIT;

Import the table-structure:
mysql systemlog < fail2ban.sql

Adjust fail2ban
To add a ban not only to the firewall but also to the database, i extended ‘actionban’. I take as an example iptables.conf.

/etc/fail2ban/action.d/iptables.conf:

actionban = iptables -I fail2ban-<name> 1 -s <ip> -j DROP
actionunban = iptables -D fail2ban-<name> -s <ip> -j DROP

changes to

actionban = echo +<ip> > /proc/net/xt_recent/fail2ban-<name>
/usr/bin/mysql -usystemlog -pMYPASSWORD systemlog -e "INSERT INTO fail2ban VALUES(INET_ATON('<ip>'),<port>,'fail2ban-<name>',1,now()) ON DUPLICATE KEY UPDATE hits=hits+1;"
actionunban = echo -<ip> > /proc/net/xt_recent/fail2ban-<name>
/usr/bin/mysql -usystemlog -pMYPASSWORD systemlog -e "DELETE FROM fail2ban WHERE source=INET_ATON('<ip>') AND jail='fail2ban-<name>;"

Our new /etc/fail2ban/action.d/iptables.conf looks like (download availabe at the end of this post):


#
# Author: Cyril Jaquier
#
# $Revision: 658 $
#

[Definition]

# Option: actionstart
# Notes.: command executed once at the start of Fail2Ban.
# Values: CMD
#
actionstart =
actionstart = sleep `echo ${RANDOM:0:1}`
if [ -z `iptables -L fail2ban-<name> | grep "^Chain fail2ban-<name> "` ]; then /usr/local/sbin/iptables -N fail2ban-<name>; fi
if [ -z `iptables -L INPUT | grep "^fail2ban-<name> "` ]; then /usr/local/sbin/iptables -I INPUT -p <protocol> --dport <port> -j fail2ban-<name>; fi
if [ -z `iptables -L fail2ban-<name> | grep "^DROP .* recent: UPDATE"` ]; then /usr/local/sbin/iptables -I fail2ban-<name> -m recent --name fail2ban-<name> --update --seconds <bantime> -j DROP; fi

# Option: actionstop
# Notes.: command executed once at the end of Fail2Ban
# Values: CMD
#
actionstop =

# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck =

# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: <ip> IP address
# <failures> number of failures
# <time> unix timestamp of the ban time
# Values: CMD
#
actionban = echo +<ip> > /proc/net/xt_recent/fail2ban-<name>
/usr/bin/mysql -usystemlog -pMYPASSWORD systemlog -e "INSERT INTO fail2ban VALUES(INET_ATON('<ip>'),<port>,'fail2ban-<name>',1,now()) ON DUPLICATE KEY UPDATE hits=hits+1;"

# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: <ip> IP address
# <failures> number of failures
# <time> unix timestamp of the ban time
# Values: CMD
#
actionunban = echo -<ip> > /proc/net/xt_recent/fail2ban-<name>
/usr/bin/mysql -usystemlog -pMYPASSWORD systemlog -e "DELETE FROM fail2ban WHERE source=INET_ATON('<ip>') AND jail='fail2ban-<name>;"

[Init]

# Defaut name of the chain
#
name = default

# Option: port
# Notes.: specifies port to monitor
# Values: [ NUM | STRING ] Default:
#
port = ssh

# Option: protocol
# Notes.: internally used by config reader for interpolations.
# Values: [ tcp | udp | icmp | all ] Default: tcp
#
protocol = tcp

bantime = 14400


(The value for ‘actionunban’ isn´t realy needed since xt_recent will do the job be let a ip pass by if the ban-time is over.

To restore the bans, i use simple shell-script:


#!/bin/bash
/usr/bin/mysql -usystemlog -pMYPASSWORD systemlog -e "SELECT INET_NTOA(source) FROM fail2ban WHERE (DATE_SUB(NOW(),INTERVAL $1 hour) <= last_hit) AND jail = '$2';"|grep -v source|while read IP; do echo +$IP > /proc/net/xt_recent/$2
done

You must run this script for each jail. That´s why i added the table config. 😉

./script.sh fail2ban-pure-ftpd 2

2 is the ban-time in hours.

iptables.conf
fail2ban.sql


Leave a comment

Your email address will not be published. Required fields are marked *

One thought on “fail2ban with xt_recent reloaded