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.
Overview
Here we have quick overview of steps for your ease.
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
[DEFAULT]
# 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 :
[DEFAULT]
ignoreip = x.x.x.x
bantime = 24h
findtime = 30m
maxretry = 3
usedns = no
destemail = [email protected]
sendername = Fail2Ban
sender = [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
andraw
. 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
- To ban & send an e-mail with whois report to the destemail.
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]
Jails
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.
[sshd]
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
.
[pure-ftpd]
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
Status
|- 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 192.168.4.122
was blocked.
sudo iptables -nL
Sample output
iptables -nL
Chain INPUT (policy ACCEPT)
target prot opt source destination
f2b-sshd tcp -- 0.0.0.0/0 0.0.0.0/0 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 -- 192.168.4.122 0.0.0.0/0 reject-with icmp-port-unreachable
RETURN all -- 0.0.0.0/0 0.0.0.0/0
Conclusion
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.