Using fail2ban to lock out unwanted visitors to your SSH daemon


I have a number of digital ocean droplets and AWS instances that I use for personal projects. For convenience I leave SSH open to the world so I can access these systems wherever I’m at. This DEFINITELY isn’t a best practice but my personal instances don’t contain anything sensitive and can be rebuilt in minutes with ansible. A wide open TCP port 22 doesn’t come without issues though. If you leave your SSH daemon open to the world you are going to see a myriad of failed log attempts in /var/log/secure:

***Jan 25 16:10:35 oscar sshd[10450]: Failed password for root from 116.31.116.46 port 23476 ssh2***

To enhance the security of my SSH daemon I enforce key-based authentication, update openssh hourly w/ an ansible playbook and enable fail2ban to blacklist IPs that try to log into my servers too many times. Setting up fail2ban on a CentOS 7 Linux host is extremely easy. First, you need to install the packages:

$ yum -y install fail2ban fail2ban-systemd jwhois

Once the packages are installed you will should review the default fail2ban configuration settings in /etc/fail2ban/jail.conf. This file shouldn’t be edited directly since system updates will replace it and flush away any changes you made. Customizations should go into /etc/fail2ban/jail.local. Changes made to this file will override the system defaults. Here is a sample /etc/fail2ban/jail.local file to get you started:

[DEFAULT]
# Ban hosts for one hour:
bantime = 3600

# Use the multiport iptables action
banaction = iptables-multiport

# Who to send e-mail to when an IP is banned
destemail = EMAIL_ADDRESS_TO_SEND_TO
sendername = fail2ban@oscar
mta = sendmail

# Where to send info if an IP is banned (e-mail, logs, etc.)
action = %(action_mwl)s

[sshd]
enabled = true

Once this file is in place you will need to enable and start the service:

$ systemctl enable fail2ban
$ systemctl enable fail2ban

If you didn’t encounter an error the fail2ban-client should list the jail it created for the SSH service:

$ fail2ban-client status

Status
|- Number of jail: 1
`- Jail list: sshd

To see IPs that are being blacklisted you can grep for Ban in /var/log/fail2ban.log:

$ grep Ban fail2ban.log

2017-01-25 15:57:25,365 fail2ban.actions [10213]: NOTICE [sshd] Ban 116.31.116.46

Or run iptables to list the IPs it added to the f2b-sshd chain:

$ sudo iptables -S f2b-sshd

-N f2b-sshd
-A f2b-sshd -s 116.31.116.46/32 -j REJECT --reject-with icmp-port-unreachable
-A f2b-sshd -j RETURN

If e-mail notifications are configured via the “action” directive you will receive an e-mail each time fail2ban blacklists an IP. Now that you see how easy it is to set this up I would like to provide a bit more detail on the terminology I used above. A fail2ban “jail” is a combination of filters and actions. Filters are the criteria fail2ban uses to figure out if something bad is happening and are defined in /etc/fail2ban/filter.d/.conf. Actions describe what to do (add an iptables rule to reject traffic from a source IP, add a blackhole route, etc.) if a filter matches. All of the actions are defined in /etc/fail2ban/action.d. The manual pages are terrific and all of the files in /etc/fail2ban are THOROUGHLY commented. If you use ansible you can automate the fail2ban installation with a fail2ban.yml playbook. This is a great utility and super easy to use!

This article was posted by Matty on 2017-01-25 13:23:00 -0400 -0400