SSH Brute Force Detection with APF and BFD

If you have administered a GNU/Linux server with SSH access within the past few years, and have regularly checked your system logs, you are no doubt familiar with SSH brute force attacks.  Automated scripts running from remote, previously broken into servers, are constantly scouring the Internet looking for new SSH servers with insecure users and passwords.  You can recognize the attempts by checking your log files that log authentication attempts, which on most GNU/Linux systems is the /var/log/auth.log file, and see dozens of the following originating from the same IP with different user attempts;

sshd[18245]: Invalid user test from 219.145.216.28

What the scripts are doing is trying to log in with common usernames and common passwords to see if one of them will work.  The actual chances of the scripts finding a username/password combination that will work, are very slim.  Still, its rather annoying to be viewing log files and even seeing them have so many attempts without reprecussion.  What we will do is set up a monitor so that when we see a certain number of these attempts, we will block the IP address permanently.

Other Preventative Methods

Of course there are other ways of preventing unauthorized access to your GNU/Linux servers.

Don’t Run SSH At All

Seriously, if you don’t need remote access to your server, then turn SSH off.  Or, if you only need access to it from your local LAN and not the Internet, you can turn off your router’s port forwarding  or configure your SSH server to only allow connections from your computer on the network.

Change SSH Listen Port

This is security by obscurity, but its a simple and somewhat effective answer.  I have no evidence to suggest that these drone machines on the Internet check for SSH running on any other port other than 22.  Simply changing your port may thwart these particular attempts.  However, if you are running a server with many users connecting in, this could be more headache than its worth with users forgetting what port they have to connect through.

Public Key Authentication

The easiest way to prevent scripts from guessing your user passwords is to not allow passwords to begin with for authentication.  Using key authentication, if a connecting user to SSH attempts to even pass a username along to the server, they will get dropped.  This is my favourite method for security, however, it can be very cumbersome if you have many users.  If its only you and a few friends connecting, this could be what you’re looking for.  I have partially covered key authentication in a previous article, but I will probably cover it in more detail at a later time.

Other

There are many other ways out there of securing your system with things like port knocking, hosts.alow/hosts.deny, etc.

Overview

What we will be doing is implementing Advanced Policy Firewall to act as our firewall, and open up the ports we need.  Then, we will configure Brute Force Detection script that works alongside APF by monitoring the auth.log file for break-in attempts, when it detects one, it adds the IP address to the APF block thus halting any current and future attempt from the IP.

The APF and BFD tools are provided by R-fx Networks. These are very complex projects that we will be utilizing for a very simple purpose. If you want to learn more about them, check out the website, they have many very in-depth tools for security.

Assumptions

For our purposes, we will not be using any distribution-specific  packages.  I have successfully set this up using Debian, Ubuntu and gentoo.  I also assume that your system logs ssh authentication attempts to /var/log/auth.log .  This wasn’t the case by default on my Gentoo system so I had to configure the sysklog to log them there.

Installing and Configuring APF

First, download the latest version of APF to anywhere on your system and extract it.  The first thing you should do is immediately read through the README.apf file.  Its long, but will probably answer any questions you have.

As root (or sudo), install APF with:

$ sh install.sh

This will install the configuration directory into /etc/apf (readable by root only) and the binary path to /usr/local/sbin/apf .  Make sure that APF starts up on bootup using whatever method your distribution has, if you need help, post in the comments.

Next step is to configure APF.  This is highly dependent on your particular setup, so I would advise going right down through the file from top to bottom.  Make sure you have the right Interface set for your external network, make sure you allow the needed TCP and UDP ports incoming, etc.  I would also advise leaving “DEVEL_MODE” set to 1 until you know 100% that your setup is good.  What this will do is re-flush the firewall settings every 5 minutes.  In a case where you accidently lock yourself out of the server by selecting a wrong option, you will be allowed back in in 5 minutes.  When you are satisfied that your new firewall is configured correctly, you can disable DEVEL_MODE and move along.

For a point of comparison, on my server, I have IG_TCP_CPORTS (inbound tcp ports) set to “22,80″ to allow only ssh and www traffic.  My IG_UDP_CPORTS is empty.

So, you should have a fully running firewall on your system.  By default, APF outputs to /var/log/apf_log so you can view what its doing.  You may want to keep an eye on this file, it can grow quite large in a short amount of time, or turn off the logging altogether if space is a concern.

Installing and Configuring BFD

Now that we have the actual firewall going, we need to set up the scripts that will detect when a brute force attack is occuring.  So, once again, grab the latest version of BFD and extract it on your system. After reading the README file, you can install it with:

$ sh install.sh

This will place BFD into /usr/local/bfd directory .  I have an edit version of the SSHD rules file that has worked well for me, you can download a copy of it and place it into your /usr/local/bfd/rules directory here. You may want to edit this file and change TRIG=”10″ to how many failed attempts that you want to trigger the block. You want this number to be high enough that it won’t accidently failed a regular user who accidently put in the wrong password a few times. Between 5-10 seems reasonable.

Next up, you can edit your conf.bfd file.  Here are a few options to keep in mind:

  • TRIG=”" – Like in the sshd rules file, you can set your global trigger amount here
  • EMAIL_ALERTS=”1″ – Set your BFD to email you when it detects an attack, may be useful if you would like notification
  • EMAIL_ADDRESS=”" – Your email address you would like notifications sent to
  • EMAIL_SUBJECT=”" – Subject of the email
  • AUTH_LOG_PATH=”/var/log/auth.log” – Make sure this points to your auth file, or wherever your system logs failed SSH login attempts, this is VERY important or else it will not work

That’s all that you should need to edit.  By default, BFDd runs every 3 minutes from /etc/cron.d/bfd and checks auth.log for login attempts.  When BFD detects an offending IP address, it adds it to your /etc/apf/deny_hosts.rules so the next time APF flushes its firewall rules (every 10 minutes by default), it will see the new IP and block it.

Any questions, comments or clarifications, please post in comments.

Comments are closed.