Securing SSH server with fail2ban

When you are running your SSH server on the standard port 22, you likely see brute force login attempts multiple times a day. The SSH server does not limit unsuccessfull login attempts by itself. So there are multiple ways to deal with this problem.

One option is to move the SSH daemon to a non-standard port. But this means that you might get problems connecting yourself to the server if you are working from a restricted network. So another solution would be to use certificates for login. But then you need to make sure that you carry the certificates with you when you want to login to your server.

Now a good solution is to limit access to the SSH server. One way would be to use the so called port-knocking approach. Here the access to the SSH port is blocked until you use some kind of secret knock-sequence. Then the port will be unblocked for your IP for a certain time. This is very effective but has the downside that you always need to use this knock mechanism before connecting to your server.

What I prefer is a mechanism which works the other way around. The access to the SSH port is open until there are a number of failed login attempts detected. If this is the case, the IP address these login attempts came from will be blocked for a couple of hours. This approach is less secure then the port knocking approach but is a lot more convenient for me. As long is I don’t mess up multiple times with the login, I do not even notice any security restrictions. Brute force attacks on the other hand are blocked right away.

The most common tool for this task is the excellent fail2ban. On a Debian system it can be installed via aptitude:

aptitude install fail2ban

The default configuration is already useful. It will secure the SSH daemon with a blocking time of 10 minutes after 6 failed login attempts. The configuration files can be found in the directory /etc/fail2ban.

You can change the blocking time in the file /etc/fail2ban/jail.conf:

[DEFAULT]
bantime  = 7200
maxretry = 4

This will change the default settings which apply if not specified otherwise in the application settings. The setting bantime is specified in seconds and defines how long the blocked IP will not be able to connect to the blocked service. maxretry is the number of failed login attempts.

Lets take a look at the ssh setting:

[ssh]
enabled = true
port    = ssh
filter  = sshd
logpath  = /var/log/auth.log
maxretry = 3

You can enable or disable the monitoring of specific services (ports). The ssh monitoring uses the auth.log file to detect failed login attempts.

To activate changed configuration settings, just reload the service:

/etc/init.d/fail2ban force-reload

So what happens when an IP is blocked? Once the login attempt limit has been reached, the IP address will be blocked via iptables. Here is the output of iptables on my system:

Chain INPUT (policy ACCEPT)
target     prot opt source               destination
fail2ban-ssh  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 fail2ban-ssh (1 references)
target     prot opt source               destination
DROP       all  --  123.456.789.012        0.0.0.0/0
RETURN     all  --  0.0.0.0/0            0.0.0.0/0

I have replaced the blocked IP address with some default numbers, but you can see that all traffic from this IP address to the port 22 will be blocked. This iptables rule will be automatically removed after the specified blockout time.

fail2ban is an effective tool to lock out brute force login attempts. It is really easy to setup and can be used to monitor multiple services besides SSH.

Leave a Reply