Tuesday, August 28, 2018

Fail2ban on CentOS 7

I have an internet facing ssh server that I use to get into my network when away from home. The ssh server is running on port 22 but rather than opening port 22 to the internet I have port 2222 on my firewall forwarded to 22 on the internal ssh server, this helps to limit the amount of brute force ssh attempts I get but they still happen on a regular basis.

I originally wrote a script which used the lastb command and generated an email with whois info about the IP address trying to brute force and was run from cron every minute, I then grabbed the IP address from those emails and added them to a firewall rule to block them from connecting to my network. Unfortunately for me (in a time zone sense) I live in Australia, most of these attacks happen while I'm sleeping and I can wake up to 100+ emails alerting me of brute force attempts.

Setting up fail2ban seemed like a good option to help slow down these attacks while I am sleeping and it turns out the email alerts can contain whois data making my script redundant!

Fail2ban is not in the official CentOS repos but is included in EPEL (Extra Packages for Enterprise Linux), enabling EPEL is trival so lets start with that:
$ sudo su -
# yum install epel-release
# yum install -y fail2ban
That's it, fail2ban is installed, but before starting fail2ban a basic config needs to be created. Rather than editing /etc/fail2ban/jail.conf it is safer to create a new file in /etc/fail2ban/jail.d/ in case future fail2ban updates replace /etc/fail2ban/jail.conf:
# nano /etc/fail2ban/jail.d/local.conf
This is a basic configuration to get fail2ban up and running with a jail for ssh:
# 3600 seconds = 1 hour
bantime = 30

# Email config
sender = email@address.com
destemail = email@address.com

# Action "%(action_mwl)s" will ban the IP and send an email notification including whois data and log entries.
action = %(action_mwl)s

# Configure fail2ban to use firewalld for banning an IP address
banaction = firewallcmd-ipset

enabled = true
At this point we can start fail2ban:
# systemctl start fail2ban
Confirm that its running:
# systemctl status fail2ban
And lastly check that there are actives jails:
# fail2ban-client status
|- Number of jail: 1
`- Jail list: sshd
At this point you can test if fail2ban is working, fail2ban logs to /var/log/fail2ban.log, tailing this file then attempting a login from an external source with an invalid username and password will result in log entries showing what fail2ban is doing:
# /var/log/fail2ban.log
2018-08-29 12:14:21,852 fail2ban.server         [5587]: INFO    Changed logging target to /var/log/fail2ban.log for Fail2ban v0.9.7
2018-08-29 12:14:21,853 fail2ban.database       [5587]: INFO    Connected to fail2ban persistent database '/var/lib/fail2ban/fail2ban.sqlite3'
2018-08-29 12:14:21,856 fail2ban.jail           [5587]: INFO    Creating new jail 'sshd'
2018-08-29 12:14:21,887 fail2ban.jail           [5587]: INFO    Jail 'sshd' uses systemd {}
2018-08-29 12:14:21,916 fail2ban.jail           [5587]: INFO    Initiated 'systemd' backend
2018-08-29 12:14:21,918 fail2ban.filter         [5587]: INFO    Set maxRetry = 5
2018-08-29 12:14:21,919 fail2ban.filter         [5587]: INFO    Set jail log file encoding to UTF-8
2018-08-29 12:14:21,920 fail2ban.actions        [5587]: INFO    Set banTime = 30
2018-08-29 12:14:21,921 fail2ban.filter         [5587]: INFO    Set findtime = 600
2018-08-29 12:14:21,921 fail2ban.filter         [5587]: INFO    Set maxlines = 10
2018-08-29 12:14:22,112 fail2ban.filtersystemd  [5587]: INFO    Added journal match for: '_SYSTEMD_UNIT=sshd.service + _COMM=sshd'
2018-08-29 12:14:22,142 fail2ban.jail           [5587]: INFO    Jail 'sshd' started
2018-08-29 12:14:22,206 fail2ban.filter         [5587]: INFO    [sshd] Found 1.xxx.xxx.158
2018-08-29 12:14:22,209 fail2ban.filter         [5587]: INFO    [sshd] Found 1.xxx.xxx.158
2018-08-29 12:14:22,211 fail2ban.filter         [5587]: INFO    [sshd] Found 1.xxx.xxx.158
2018-08-29 12:14:22,214 fail2ban.filter         [5587]: INFO    [sshd] Found 1.xxx.xxx.158
2018-08-29 12:14:22,216 fail2ban.filter         [5587]: INFO    [sshd] Found 1.xxx.xxx.158
2018-08-29 12:14:22,219 fail2ban.filter         [5587]: INFO    [sshd] Found 1.xxx.xxx.158
2018-08-29 12:14:22,931 fail2ban.actions        [5587]: NOTICE  [sshd] Ban 1.xxx.xxx.158
2018-08-29 12:14:53,479 fail2ban.actions        [5587]: NOTICE  [sshd] Unban 1.xxx.xxx.158
I attempted sshing from my phone with a bogus username/password and as can be seen in the logs it results in a 30 second ban with corresponding email alerts.

Now that fail2ban is working it can be enabled for startup at boot time, we can also raise the bantime, I'm going to go with 8 hours so that I have enough time to get IP's addded to the block list:
# sed -i 's/bantime = 30/bantime = 28800/g' /etc/fail2ban/jail.d/local.conf
# systemctl enable fail2ban
# systemctl restart fail2ban
A final note, if you need to unban an IP it can be done with fail2ban-client:
# fail2ban-client set JAILNAME unbanip IPADDRESS
# fail2ban-client set sshd unbanip 1.xxx.xxx.158
I still plan on using the emails to block IP addresses at the firewall but this will keep me from waking up to 150 emails telling me an IP from China is trying to brute force my ssh box!

No comments:

Post a Comment

Raspberry Pi 4 heatsink testing

With all the talk of how hot the Raspberry Pi 4 runs I thought I’d do some testing to see how different heatsinks perform. I had a few heats...