How to install fail2ban on CentOS 6 and 7

I will show you how to install fail2ban on centos 6 and centos 7 to protect SSH brute force attacks. There are many ways to protect SSH server, the best way is to use ssh-keys authentication rather than regular password authentication. I have also written a long detailed article How to install, config and secure openssh server. In that article I have shown you several ways to secure ssh server:

  • Use SSH Protocol 2
  • Limit access to ssh server
  • Config Idle Log Out Timeout Interval
  • Disable .rhosts Files
  • Disable Host-Based Authentication
  • Disable root Login via SSH
  • Having a Warning Banner
  • Change SSH server port
  • Disable Empty Passwords
  • Use StrictModes

Fail2ban_logoTo make your ssh server more secure, you can try fail2ban. Fail2ban is a great software that let you monitor system services like SSH, Apache, proftpd, pure-ftpd, vsftpd, lighttpd-auth, sendmail, quid, cyrus-imap, … and block the ip(s) which are trying to brute force your system.

Install Fail2ban

Fail2ban is not available by default from CentOS, but you can always download and install fail2ban from Extra Packages for Enterprise Linux (EPEL) repository

For CentOS 6

# rpm -Uvh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
# yum install fail2ban

For CentOS 7

# rpm -Uvh http://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-2.noarch.rpm
# yum install fail2ban

Configure fail2ban

Fail2ban can be configured for various software, but for this article I will only show you how to configure fail2ban to protect and prevent brute force for SSH server. The default fail2ban jail file is located at /etc/fail2ban/jail.conf . You don’t want to modify this file, you want to create a new jail file named jail.local

# cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

After you created jail.local file, lets edit the file

# nano /etc/fail2ban/jail.local

The first section you can modify

ignoreip: which fail2ban will never block that IP, you should put your public IP here so fail2ban will never lock you out of your SSH server.

bantime: the time amount (in second) fail2ban will ban a hostname/IP (I suggest you set this high to decrease the chance bots/attackers brute force)

findtime: is the time window fail2ban keeps track of the failed login attempts.

maxretry: is the number failed login attempts before a host/IP get blocked.

[DEFAULT]

# "ignoreip" can be an IP address, a CIDR mask or a DNS host. Fail2ban will not
# ban a host which matches an address in this list. Several addresses can be
# defined using space separator.
ignoreip = 127.0.0.1/8

# External command that will take an tagged arguments to ignore, e.g. ,
# and return true if the IP is to be ignored. False otherwise.
#
# ignorecommand = /path/to/command 
ignorecommand =

# "bantime" is the number of seconds that a host is banned.
bantime = 600

# A host is banned if it has generated "maxretry" during the last "findtime"
# seconds.
findtime = 600

# "maxretry" is the number of failures before a host get banned.
maxretry = 3

# "backend" specifies the backend used to get files modification.
# Available options are "pyinotify", "gamin", "polling" and "auto".
# This option can be overridden in each jail as well.
#
# pyinotify: requires pyinotify (a file alteration monitor) to be installed.
# If pyinotify is not installed, Fail2ban will use auto.
# gamin: requires Gamin (a file alteration monitor) to be installed.
# If Gamin is not installed, Fail2ban will use auto.
# polling: uses a polling algorithm which does not require external libraries.
# auto: will try to use the following backends, in order:
# pyinotify, gamin, polling.
backend = auto

# "usedns" specifies if jails should trust hostnames in logs,
# warn when DNS lookups are performed, or ignore all hostnames in logs
#
# yes: if a hostname is encountered, a DNS lookup will be performed.
# warn: if a hostname is encountered, a DNS lookup will be performed,
# but it will be logged as a warning.
# no: if a hostname is encountered, will not be used for banning,
# but it will be logged as info.
usedns = warn

The next section we should look at is:

[ssh-iptables]

enabled = true
filter = sshd
action = iptables[name=SSH, port=ssh, protocol=tcp]
 sendmail-whois[name=SSH, dest=you@example.com, sender=fail2ban@example.com, sendername="Fail2Ban"]
logpath = /var/log/secure
maxretry = 5

[ssh-ddos]

enabled = false
filter = sshd-ddos
action = iptables[name=SSHDDOS, port=ssh, protocol=tcp]
logpath = /var/log/sshd.log
maxretry = 2

As you can see, the default fail2ban configuration is pretty much well configured for you, you can tweak here and there a little bit but it’s ready for you to go.

Restart fail2ban

You have to restart fail2ban to let the new configuration can take effect.
CentOS 6:

# service fail2ban restart

CentOS 7:

# systemctl restart fail2ban.service

Start fail2ban at boot

To let fail2ban starts at boot if you reboot your system
CentOS 6:

# chkconfig fail2ban on

CentOS 7:

# systemctl enable fail2ban

Check fail2ban banned IP

After a while (few days) you can check your iptables rules to see what fail2ban has banned

# iptables -L

This is an example from one of my machine

Chain fail2ban-SSH (1 references)
target prot opt source destination
REJECT all -- 122.225.109.211 anywhere reject-with icmp-port-unreachable
REJECT all -- 58.58.27.124 anywhere reject-with icmp-port-unreachable
REJECT all -- 122.225.97.109 anywhere reject-with icmp-port-unreachable
REJECT all -- 122.225.109.206 anywhere reject-with icmp-port-unreachable
REJECT all -- abts-kk-dynamic-152.191.172.122.airtelbroadband.in anywhere reject-with icmp-port-unreachable
REJECT all -- 219.230.50.51 anywhere reject-with icmp-port-unreachable
REJECT all -- 113.240.234.21 anywhere reject-with icmp-port-unreachable
REJECT all -- 122.226.131.132 anywhere reject-with icmp-port-unreachable
REJECT all -- 60.213.190.98 anywhere reject-with icmp-port-unreachable
REJECT all -- 58.221.66.24 anywhere reject-with icmp-port-unreachable
REJECT all -- 42-64-231-201.fibertel.com.ar anywhere reject-with icmp-port-unreachable
REJECT all -- 122.225.97.111 anywhere reject-with icmp-port-unreachable
REJECT all -- 117.117.198.5 anywhere reject-with icmp-port-unreachable
REJECT all -- 202.63.166.69 anywhere reject-with icmp-port-unreachable
REJECT all -- host114-72-static.18-80-b.business.telecomitalia.it anywhere reject-with icmp-port-unreachable
REJECT all -- abts-north-dynamic-147.33.163.122.airtelbroadband.in anywhere reject-with icmp-port-unreachable
REJECT all -- 115.185.145.233 anywhere reject-with icmp-port-unreachable
REJECT all -- 222.221.240.6 anywhere reject-with icmp-port-unreachable
REJECT all -- abts-kk-dynamic-244.63.179.122.airtelbroadband.in anywhere reject-with icmp-port-unreachable
REJECT all -- bfb47839.virtua.com.br anywhere reject-with icmp-port-unreachable
REJECT all -- 210.98.148.172 anywhere reject-with icmp-port-unreachable
REJECT all -- r190-64-79-146.su-static.adinet.com.uy anywhere reject-with icmp-port-unreachable
REJECT all -- 58.62.239.210 anywhere reject-with icmp-port-unreachable
REJECT all -- 189-20-94-73.customer.tdatabrasil.net.br anywhere reject-with icmp-port-unreachable
REJECT all -- 218.2.0.127 anywhere reject-with icmp-port-unreachable
REJECT all -- abts-north-dynamic-034.38.163.122.airtelbroadband.in anywhere reject-with icmp-port-unreachable
REJECT all -- 202.197.127.218 anywhere reject-with icmp-port-unreachable
REJECT all -- 58.20.53.8 anywhere reject-with icmp-port-unreachable
REJECT all -- abts-north-dynamic-190.34.163.122.airtelbroadband.in anywhere reject-with icmp-port-unreachable
REJECT all -- 58.58.27.122 anywhere reject-with icmp-port-unreachable
REJECT all -- 59.99.36.166 anywhere reject-with icmp-port-unreachable
REJECT all -- abts-north-dynamic-221.54.163.122.airtelbroadband.in anywhere reject-with icmp-port-unreachable
REJECT all -- 213.201.48.94.static.user.ono.com anywhere reject-with icmp-port-unreachable
REJECT all -- server109-228-30-49.live-servers.net anywhere reject-with icmp-port-unreachable
REJECT all -- 59.60.176.197 anywhere reject-with icmp-port-unreachable
REJECT all -- 219.142.20.182 anywhere reject-with icmp-port-unreachable
REJECT all -- 219.224.52.90 anywhere reject-with icmp-port-unreachable
REJECT all -- 112.124.50.24 anywhere reject-with icmp-port-unreachable
REJECT all -- ip-50-62-30-150.ip.secureserver.net anywhere reject-with icmp-port-unreachable
REJECT all -- ec2-54-94-160-237.sa-east-1.compute.amazonaws.com anywhere reject-with icmp-port-unreachable
REJECT all -- 14.170.14.34 anywhere reject-with icmp-port-unreachable
REJECT all -- 94.211.60.190.host.ifxnetworks.com anywhere reject-with icmp-port-unreachable
REJECT all -- 60.160.97.123 anywhere reject-with icmp-port-unreachable
REJECT all -- 183.224.97.88 anywhere reject-with icmp-port-unreachable
REJECT all -- 58.11.28.94.enforta.com anywhere reject-with icmp-port-unreachable
REJECT all -- 125-227-191-235.HINET-IP.hinet.net anywhere reject-with icmp-port-unreachable
REJECT all -- 200.166.195.52 anywhere reject-with icmp-port-unreachable
REJECT all -- static.200.219.209.134.datacenter1.com.br anywhere reject-with icmp-port-unreachable
REJECT all -- 193.253.101.67 anywhere reject-with icmp-port-unreachable
REJECT all -- 222.133.29.94 anywhere reject-with icmp-port-unreachable
REJECT all -- mail.unimedsorocaba.com.br anywhere reject-with icmp-port-unreachable
REJECT all -- 210.40.30.21 anywhere reject-with icmp-port-unreachable
REJECT all -- 58.210.170.18 anywhere reject-with icmp-port-unreachable
REJECT all -- b39bafce.virtua.com.br anywhere reject-with icmp-port-unreachable
REJECT all -- customer-static-210-94-141.iplannetworks.net anywhere reject-with icmp-port-unreachable
REJECT all -- 14.169.28.105 anywhere reject-with icmp-port-unreachable
REJECT all -- 211.206.124.4 anywhere reject-with icmp-port-unreachable
REJECT all -- 117.218.155.76 anywhere reject-with icmp-port-unreachable
REJECT all -- 136.38.202.62.static.wline.lns.sme.cust.swisscom.ch anywhere reject-with icmp-port-unreachable
REJECT all -- ec2-54-86-167-57.compute-1.amazonaws.com anywhere reject-with icmp-port-unreachable
REJECT all -- 50.97.43.46-static.reverse.softlayer.com anywhere reject-with icmp-port-unreachable
REJECT all -- 177.54.136.58 anywhere reject-with icmp-port-unreachable
REJECT all -- 218.80.194.42 anywhere reject-with icmp-port-unreachable
REJECT all -- 216.196.133.34 anywhere reject-with icmp-port-unreachable
REJECT all -- 221.125.86.204 anywhere reject-with icmp-port-unreachable
REJECT all -- 175.139.231.217 anywhere reject-with icmp-port-unreachable
REJECT all -- 121.65.252.200 anywhere reject-with icmp-port-unreachable
REJECT all -- customer-CLN-154-138.megared.net.mx anywhere reject-with icmp-port-unreachable
REJECT all -- rasoff.ru anywhere reject-with icmp-port-unreachable
REJECT all -- 26.0.95.219.kmr01-home.tm.net.my anywhere reject-with icmp-port-unreachable
REJECT all -- 220.191.230.219 anywhere reject-with icmp-port-unreachable
REJECT all -- wsip-98-172-21-240.dc.dc.cox.net anywhere reject-with icmp-port-unreachable
REJECT all -- adsl.viettel.vn anywhere reject-with icmp-port-unreachable
REJECT all -- 213.165.37.54 anywhere reject-with icmp-port-unreachable
REJECT all -- 189-68-104-134.dsl.telesp.net.br anywhere reject-with icmp-port-unreachable
REJECT all -- 210.72.245.5 anywhere reject-with icmp-port-unreachable
REJECT all -- ip-194-206.sn1.eutelia.it anywhere reject-with icmp-port-unreachable
REJECT all -- covial3.vinicolaaurora.com.br anywhere reject-with icmp-port-unreachable
REJECT all -- 39.252.9.221.adsl-pool.jlccptt.net.cn anywhere reject-with icmp-port-unreachable
REJECT all -- 117.27.158.91 anywhere reject-with icmp-port-unreachable
REJECT all -- hn.kd.ny.adsl anywhere reject-with icmp-port-unreachable
REJECT all -- 186-244-215-103.user.veloxzone.com.br anywhere reject-with icmp-port-unreachable
REJECT all -- 202.194.131.143 anywhere reject-with icmp-port-unreachable
REJECT all -- 186.215.144.88.static.gvt.net.br anywhere reject-with icmp-port-unreachable
REJECT all -- 123.127.36.162 anywhere reject-with icmp-port-unreachable
REJECT all -- 177.43.213.35.static.gvt.net.br anywhere reject-with icmp-port-unreachable
REJECT all -- host26-217-static.33-88-b.business.telecomitalia.it anywhere reject-with icmp-port-unreachable
REJECT all -- 144.0.0.51 anywhere reject-with icmp-port-unreachable
REJECT all -- 122.225.109.220 anywhere reject-with icmp-port-unreachable
REJECT all -- 122.225.109.112 anywhere reject-with icmp-port-unreachable
REJECT all -- v103-18-4-214.myvps.vn anywhere reject-with icmp-port-unreachable
REJECT all -- 218.2.0.125 anywhere reject-with icmp-port-unreachable
REJECT all -- 222.186.130.242 anywhere reject-with icmp-port-unreachable
REJECT all -- 220.51.174.61.dial.wz.zj.dynamic.163data.com.cn anywhere reject-with icmp-port-unreachable
REJECT all -- 221.228.205.196 anywhere reject-with icmp-port-unreachable
REJECT all -- 219.51.174.61.dial.wz.zj.dynamic.163data.com.cn anywhere reject-with icmp-port-unreachable
REJECT all -- ppp14-208.tis-dialog.ru anywhere reject-with icmp-port-unreachable
REJECT all -- ip72-213-191-22.ok.ok.cox.net anywhere reject-with icmp-port-unreachable
REJECT all -- static-50-122-222-171.roch.ny.frontiernet.net anywhere reject-with icmp-port-unreachable
REJECT all -- broadband-109-173-65-5.nationalcablenetworks.ru anywhere reject-with icmp-port-unreachable
REJECT all -- mx6.fund123.cn anywhere reject-with icmp-port-unreachable
REJECT all -- broadband-5-228-78-138.nationalcablenetworks.ru anywhere reject-with icmp-port-unreachable
REJECT all -- ip68-227-118-117.ok.ok.cox.net anywhere reject-with icmp-port-unreachable
REJECT all -- r75-110-184-14.unknwn.ab.dh.suddenlink.net anywhere reject-with icmp-port-unreachable
REJECT all -- broadband-178-140-6-184.nationalcablenetworks.ru anywhere reject-with icmp-port-unreachable
REJECT all -- 122.225.97.74 anywhere reject-with icmp-port-unreachable
REJECT all -- 222.186.58.241 anywhere reject-with icmp-port-unreachable
REJECT all -- 122.225.109.209 anywhere reject-with icmp-port-unreachable

Update 12/01/2014, it look like jail.local file for Centos 7 is not the same for CentOS 6 since Centos 7 uses firewalld as default rather than iptables. In jail.local file for Centos 7 you will have to uncomment a few lines to enable ssh banning ip in fail2ban.

This is the section at the very beginning of fail2ban jail.local file in CentOS 7. Uncomment the lines that I did below.

[DEFAULT]
bantime = 3600
#
[sshd]
enabled = true
#
# See jail.conf(5) man page for more information

In Centos 7, to check if fail2ban is running and working, you can use this command

# journalctl -a -f -n1000 -u fail2ban

The output:

-- Logs begin at Sun 2014-11-30 02:12:42 CET. --
Dec 01 22:55:06 sd-21451 systemd[1]: Starting Fail2ban Service...
Dec 01 22:55:11 sd-21451 fail2ban-client[12869]: 2014-12-01 22:55:11,437 fail2ban.server.server[12872]: INFO Starting Fail2ban v0.9.0
Dec 01 22:55:11 sd-21451 fail2ban-client[12869]: 2014-12-01 22:55:11,439 fail2ban.server.server[12872]: INFO Starting in daemon mode
Dec 01 22:55:12 sd-21451 systemd[1]: Started Fail2ban Service.
Dec 01 23:12:48 sd-21451 systemd[1]: Stopping Fail2ban Service...
Dec 01 23:12:48 sd-21451 fail2ban-client[13159]: Shutdown successful
Dec 01 23:12:48 sd-21451 systemd[1]: Starting Fail2ban Service...
Dec 01 23:12:52 sd-21451 fail2ban-client[13163]: 2014-12-01 23:12:52,638 fail2ban.server.server[13164]: INFO Starting Fail2ban v0.9.0
Dec 01 23:12:52 sd-21451 fail2ban-client[13163]: 2014-12-01 23:12:52,640 fail2ban.server.server[13164]: INFO Starting in daemon mode
Dec 01 23:12:53 sd-21451 systemd[1]: Started Fail2ban Service.

or

# systemctl status fail2ban -l

and the output

fail2ban.service - Fail2ban Service
 Loaded: loaded (/usr/lib/systemd/system/fail2ban.service; enabled)
 Active: active (running) since Mon 2014-12-01 23:12:53 CET; 9h ago
 Process: 13159 ExecStop=/usr/bin/fail2ban-client stop (code=exited, status=0/SUCCESS)
 Process: 13163 ExecStart=/usr/bin/fail2ban-client -x start (code=exited, status=0/SUCCESS)
 Main PID: 13166 (fail2ban-server)
 CGroup: /system.slice/fail2ban.service
 └─13166 /usr/bin/python /usr/bin/fail2ban-server -b -s /var/run/fail2ban/fail2ban.sock -p /var/run/fail2ban/fail2ban.pid -x

Dec 01 23:12:52 sd-21451 fail2ban-client[13163]: 2014-12-01 23:12:52,638 fail2ban.server.server[13164]: INFO Starting Fail2ban v0.9.0
Dec 01 23:12:52 sd-21451 fail2ban-client[13163]: 2014-12-01 23:12:52,640 fail2ban.server.server[13164]: INFO Starting in daemon mode
Dec 01 23:12:53 sd-21451 systemd[1]: Started Fail2ban Service.

 

Recommended For You

About the Author: Linux Tips

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.