How to Install Fail2ban in Ubuntu / Debian for Brute Force Protection in Linux

Fail2ban configuration in Debian / Ubuntu LInux

Security is an important aspect of running any kind of server on internet. Almost all servers run one or other kind of service which requires authentication to access them but this also makes them target of malicious actors who want to breach your system and exploit them.

One of the method used is called Brute Force Attack where repeated dictionary based attacks are performed in hope to guess the correct password. There are good chances that an insecure may have to face thousands of such automated attempts any moment, thus wasting significant amount of resources.

To protect Linux servers from such attacks, we can utilize an opensource tool Fail2ban thus increasing our server security.

What is Fail2ban

You can implement many security measures to protect your server effectively. One such tool is Fail2ban, its an intrusion prevention software framework and written in Python. It is designed to prevent brute-force attacks. To achieve this, it examine log files and then blocks IPs after certain number of failed attempts. It can be customized to offer protection for multiple kind of application and services running on Linux servers as long as they maintain logs for actions for authentication related activities.

Fail2ban can be very flexible and can be customized a lot, not only it can detect failed logins but also can monitor signs of malicious activities looking for exploits. And then it can use system firewall to block those malicious IPs / sources as well as can take other arbitrary actions like sending mail notifications and more.

How to Install Fail2ban on Debian / Ubuntu and on similar Linux distributions

Installation of Fail2ban is pretty quick and straightforward for Linux distribution based on Debian and Ubuntu, following steps should work on any recent version.

First of all make sure your distribution is up to date. We are assuming you have configured sudo user with admin privileges.

sudo apt update && sudo apt upgrade

Once you are done with updating your system, you may go ahead and install Fail2ban

sudo apt-get install fail2ban

Here, after installation the fail2ban service will be automatically started and enabled. You can verify it buy running following command:

sudo systemctl status fail2ban

Sample Output

fail2ban.service - Fail2Ban Service
Loaded: loaded (/lib/systemd/system/fail2ban.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2021-11-21 20:48:24 CET; 18s ago
Docs: man:fail2ban(1)
Main PID: 55134 (f2b/server)
Tasks: 5 (limit: 2282)
Memory: 13.5M
CGroup: /system.slice/fail2ban.service
└─55134 /usr/bin/python3 /usr/bin/fail2ban-server -xf start

Once fail2ban is up and running, we can now move on to configure it.

Configure Fail2ban to protect the server

Configuration of Fail2ban is done through its config files found at /etc/fail2ban/. At most basic level, fail2ban uses /etc/fail2ban/fail2ban.conf as the primary configuration profile for overall setup of fail2ban. While, the /etc/fail2ban/jail.conf contains default configuration for various jails ie. set of instructions which contains filters and actions for services where matching filters from the logs results in execution of desired actions for that service.

To put in simple words, jail.conf consist of set of instructions where we can configure brute-force protection against pure-ftpd service, ssh service etc. Although in Debian / Ubuntu, ssh protection is enabled by default.

Fail2ban reads first reads *.conf files and then overrides them with *.local files. Hence in order to customize we should create copy of fail2ban.conf as fail2ban.local and jail.conf as jail.local.

sudo cp /etc/fail2ban/fail2ban.{conf,local}
sudo cp /etc/fail2ban/jail.{conf,local}

Now we will have two new files (/etc/fail2ban/fail2ban.local and /etc/fail2ban/jail.local) copied from their .conf counterpart. Although, it is not necessary to create copy of *.conf files as *.local files, you can start with empty .local file also and add only those directives which you want to override. But we will use copy of files and then discuss directives.

The default /etc/fail2ban/fail2ban.local is suitable most of the use case and all configuration choices are well-documented. If you wish you can modify directives like loglevel which defines how much data is logged for every event. You can configure under [DEFAULT] section. Anything with “#” in front is considered comment and is ignored. For example, below loglevel is set to INFO


# Option: loglevel
# Notes.: Set the log level output.
#         CRITICAL
#         ERROR
#         WARNING
#         NOTICE
#         INFO
#         DEBUG
# Values: [ LEVEL ]  Default: ERROR
loglevel = INFO

The main action goes into the /etc/fail2ban/jail.local file. This will contain default directives which will be applied to all Jails. However, you can override per jail directive also. There are lots of things you can change from this file which is well documented through comments in file. For example, you can change some of the aspects given below :


    ignoreip = x.x.x.x
    bantime = 24h
    findtime = 30m
    maxretry = 3
    usedns = no
    destemail = [email protected]
    sendername = Fail2Ban
    sender = y[email protected]
    mta = sendmail
    action = $(action)s
  • ignoreip: It can be a list of IP addresses, CIDR masks or DNS hosts which you want to be ignored by fail2ban.
  • bantime: It is the period for which a host is banned, we have configured it to 24h.
  • findtime: A host is banned if it has generated “maxretry” during the last “findtime”. We have set is 30m, which means that within last 30 minutes if there are failed attempts equals to “maxretry” option.
  • maxretry: It is number of failures before a host get banned.
  • usedns: It can be yes, warn, no and raw. If set to yes, then will perform DNS lookup for hostname and if set to warn, it will do DNS lookup but log it as warning. Setting it to no means hostname will not used for banning. Using it with raw is used to set no-host filters and actions. We have set it to no as we just want IP addresses used for banning.
  • destemail: Specify the email address where you want Fail2ban to send reports about event, you can further customize per jail also.
  • sendername: Specify anything describing name of your server running Fail2ban
  • sender: Specify full email address as “from” address for notifications
  • mta: Which mail transport agent to use for mails, sendmail is preferred.
  • action: On match, what should be the action, here you define it on Global level, you can change it at each Jail level also. So, you can customize to enable mail notification as well other customization along with banning.
    • To ban & send an e-mail with whois report to the destemail.
      action = %(action_mw)s
    • Same as above ie. action_mw but also send relevant log lines
      action = %(action_mwl)s

Changing which firewall to be used with fail2ban

By default, iptables is used by Fail2ban for banning. We can switch to other firewalls like nftables ,ufw, shorewall, firewalld etc.

Default iptables :

banaction = iptables-multiport
banaction_allports = iptables-allports

Use nftables instead:

banaction = nftables
banaction_allports = nftables[type=allports]


By default, jail.local will have various preconfigured jails for you. For example, ssh (for port 22) is already enabled by default in Debian / Ubuntu for fail2ban. We have set enabled = true explicitly also. You also specify other settings as explained earlier like bantime, ignoreip inside each jail also.

enabled = true
port    = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s

Below we have another example jail for pure-ftpd service taken from /etc/fail2ban/jail.local . Note we have again set enabled=true.

enabled   = true
port     = ftp,ftp-data,ftps,ftps-data
logpath  = %(pureftpd_log)s
backend  = %(pureftpd_backend)s

One we have enabled our desired jails in jail.local files, we we need to restart fail2ban services in order for changes to get in effect.

sudo systemctl restart fail2ban

Checking Fail2ban status : fail2ban-client

Fail2ban comes with fail2ban-client utility which we can use for various tasks on fail2ban, like

  • start: Starts the Fail2ban server and jails.
  • reload: Reloads Fail2ban’s configuration files.
  • stop: Terminates the server.
  • status: Will show the status of the server, and enable jails.
  • status JAIL: Will show the status of the jail, including any currently-banned IPs.

For example, to view all enabled jails :

 sudo fail2ban-client status 

Sample Output

|- Number of jail:      
2 `- Jail list:   pure-ftpd, sshd 

Testing Fail2ban jail:

As you can see have 2 Jails enabled ie. pure-ftpd and sshd. We can test using some failed login attempts on sshd server. We had configured maxretry=3 in last 30 min (using findtime=30m). You can make 3 login attempts to this server’s ssh port, on fourth attempt, you should get “connection refused” error.

To verify if IP is blocked by fail2ban, you can check in /var/log/fail2ban.log file. You may also check using iptables if that IP is blocked by it. Checkout the output below where our sample IP was blocked.

sudo iptables -nL

Sample output

iptables -nL
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
f2b-sshd   tcp  --              multiport dports 22

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain f2b-sshd (1 references)
target     prot opt source               destination
REJECT     all  --            reject-with icmp-port-unreachable
RETURN     all  --  


This tutorial will sum up as basic overview of Fail2ban intrusion detection system configuration on Ubuntu / Debian and similar Linux distributions. Fail2ban can do lot more interesting things and covers a lot of applications and services. Nevertheless, its should help you to get started and you can fine tune it to suite your special needs.


No comments yet. Why don’t you start the discussion?

Leave a Reply

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