Preventing brute force attacks with fail2ban

Introduction

Fail2Ban is an intrusion prevention framework written in the Python programming language. It works by reading SSH, ProFTP, Apache etc. logs and uses iptables profiles to block brute-force attempts.

The reason I prefer fail2ban over other tools is because it is one of the simplest solutions, it is surprisingly effective and there is an active community behind it.

How it works

Fail2ban scans log files (e.g. /var/log/apache/error_log) and bans IPs that show the malicious signs -- too many password failures, seeking for exploits, etc. Afterwards it is updating firewall rules to reject malicious IP addresses for a specified amount of time, although any other arbitrary action (e.g. sending an email) could also be configured. Out of the box Fail2Ban comes with filters for various services (apache, courier, ssh, etc). Fail2Ban is able to reduce the rate of incorrect authentications attempts however it cannot eliminate the risk that weak authentication presents. Configure services to use only two factor or public/private authentication mechanisms if you really want to protect services.

Installation & Configuration

To install fail2ban, type I followed the procedure below:

sudo apt-get update
sudo apt-get install fail2ban

Configuration: To configure fail2ban, make a 'local' copy the jail.conf file in /etc/fail2ban

cd /etc/fail2ban
sudo cp jail.conf jail.local

Now edit the file:

sudo nano jail.local

Set the IPs you want fail2ban to ignore, the ban time (in seconds) and maximum number of user attempts to match your needs:

[DEFAULT]
# "ignoreip" can be an IP address, a CIDR mask or a DNS host
ignoreip = 127.0.0.1
bantime  = 3600
maxretry = 3

Setting up an MTA

For an administrator email notifications are essential. For that, you will need sendmail or any other working MTA to forward emails to your address. If you have a working MTA already, you can skip this step. To install an All send-only MTA - replace sendmail with ssmtp:

sudo apt-get install sendmail
sudo apt-get install mailutils ssmtp
sudo nano /etc/ssmtp/ssmtp.conf
ssmtp panagiotis@example.com
hello world!
sudo service sendmail stop
sudo killall sendmail
which ssmtp
sudo rm -rf /usr/sbin/sendmail
sudo ln -s /usr/sbin/ssmtp /usr/sbin/sendmail
sudo service fail2ban restart

If you wish to get bans notifications by email, modify this line with your email address:

destemail = your_email@domain.com

Then find the line:

action = %(action_)s

and change it to:

action = %(action_mw)s

Jail Configuration

Jails are the rules which fail2ban is going to apply to a given application/log:

[ssh]

enabled = true
port    = ssh
filter  = sshd
logpath  = /var/log/auth.log
maxretry = 3

To enable the other profiles, such as [ssh-ddos], make sure the first line beneath the specific profile is:

enabled = true

After that, restart fail2ban to put those settings into effect:

sudo /etc/init.d/fail2ban restart

Advanced: Filters

If you wish to tweak or add log filters, you can find them under /etc/fail2ban/filter.d

Testing

To test fail2ban, look at iptable rules:

sudo iptables -L

Attempt to login to a service that fail2ban is monitoring (preferably from another machine) and look at the iptable rules again to see if that IP source gets added.

Fail2ban is really handy for blocking brute force attacks against your servers but when you have a cluster of servers, it would be quite useful to include the hostname in the subject line of the email you receive when an IP address is blocked. Since fail2ban is not doing that out of the box I followed the simple procedure below to extend the functionality to my needs.

Extending Fail2ban to include the hostname in the mail subject.

There are three steps:

Step 1: Define a variable "host" in you jail.conf, assign the hostname to it and pass it to your action.

Open up /etc/fail2ban/jail.conf and edit the action. In my case the action for dovecot-pop3imap is:

action_mw = %(banaction)s[name=%(__name__)s, 
            port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
              %(mta)s-whois[name=%(__name__)s, dest="%(destemail)s", 
              protocol="%(protocol)s", chain="%(chain)s"]

Now add the variable "host", so the action looks like:

action_mw = %(banaction)s[name=%(__name__)s, 
            port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
              %(mta)s-whois[name=%(__name__)s, 
              dest="%(destemail)s", protocol="%(protocol)s",
              chain="%(chain)s", host=db01.example.com]

Step 2: Use the value in your action.d script.

You can see in my example that the action being called is sendmail-whois. So next open /etc/fail2ban/action.d/sendmail-whois.conf. There are various sections here that send emails. They are "actionstart", "actionstop" and "actionban".

My actionstart for example looks like this:

actionstart = printf %%b "Subject: [Fail2Ban] <name>: started on <host>
              From: Fail2Ban <<sender>>
              To: <dest>\n
              Hi,\n
              The jail <name> has been started successfully.\n
              Regards,\n
              Fail2Ban" | /usr/sbin/sendmail -f <sender> <dest>

Make similar amendments to the Subject of each section and save the file.

Step 3: Restart fail2ban

For the changes to take effect, you need to restart fail2ban:

service fail2ban restart

Unban an IP

If you are trying to figure out what happens if an IP gets banned by mistake, here is the solution:

$ sudo iptables -L -n  > bans.log
$ sudo fail2ban-client status # to reveal your JAIL name (mine is ssh)
$ sudo fail2ban-client set ssh delignoreip your_ip_address
$ sudo nano /etc/hosts.deny # delete your ip address
$ sudo fail2ban-client reload

Got more questions or comments? Drop me a private message.