How to Prevent Malicious SSH Login Attempts

Linux |

Updated on

I’m not a server guy but I had to deploy a few web sites and web services recently and it has been an interesting journey so far, although sometimes it feels a bit scary: it’s like stepping into the unknown. I have to ask myself many questions, such as: how do I know that my servers are secure? That’s an important question but “security” is such a vague term that it makes it hard to grasp and answer this question confidently.

sshd logs

journalctl --since '24 hours ago'

How to Secure a Server?

Security is a complex topic and an optimal solution usually depends on who or what we might need to secure our servers from. For instance, my hosting provider might access my servers and there is nothing I can do about that, aside from going fully self hosted which has its own drawbacks which I’m not ready to accept at the moment.

I picked a simple strategy which I believe should serve my goals pretty well. This strategy consists of 4 steps:

  • keeping operating system up to date
  • making sure that only the necessary ports are open (in my case, ssh and http(s))
  • for each open port, keep a close look on who connects to it and log every interaction
  • blocking clearly malicious attempts to use any of the open ports, if possible

SSH Login Attempts

I have a few Scaleway virtual servers and they have quite a limited disk space of 20 GB, which is more than enough for my needs but I’ve noticed that the free space started to decrease rapidly on a server running Ubuntu 18.04 with a default configuration. I’ve decided to check what takes all of that space and the most active abuser turned out to be sshd.

journalctl --since "24 hours ago" | wc -l

There were more than 75,000 log entries and most of them looked like this:

Sep 22 09:51:17 server sshd[11616]: Failed password for root from 222.186.52.124 port 42788 ssh2
Sep 22 09:51:17 server sshd[11616]: Received disconnect from 222.186.52.124 port 42788:11:  [preauth]
Sep 22 09:51:17 server sshd[11616]: Disconnected from authenticating user root 222.186.52.124 port 42788 [preauth]
Sep 22 09:51:17 server sshd[11616]: PAM 2 more authentication failures; logname= uid=0 euid=0 tty=ssh ruser= rhost=222.186.52.124  user=root
Sep 22 09:51:30 server sshd[11620]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=49.88.112.111  user=
Sep 22 09:51:32 server sshd[11620]: Failed password for root from 49.88.112.111 port 19567 ssh2
Sep 22 09:51:33 server sshd[11620]: Failed password for root from 49.88.112.111 port 19567 ssh2
Sep 22 09:51:35 server sshd[11620]: Failed password for root from 49.88.112.111 port 19567 ssh2
Sep 22 09:51:35 server sshd[11620]: Received disconnect from 49.88.112.111 port 19567:11:  [preauth]
Sep 22 09:51:35 server sshd[11620]: Disconnected from authenticating user root 49.88.112.111 port 19567 [preauth]

Most of those logs are failed attempts to authenticate using a password. That was strange, since Scaleway didn’t provide me with any passwords and I use public key auth which is more secure. I filed a ticket and asked them why their instances claim to accept passwords and they declined to answer this question twice but they said that I can turn off password auth if I wish to, which I did by changing the line PasswordAuthentication yes to PasswordAuthentication no in a file located by a following path:

/etc/ssh/sshd_config

You may need to restart sshd or reboot your server for changes to be applied.

Now, there should be less logs but it doesn’t solve the problem: anyone can still try to log in as many times as possible which bloats the logs and I don’t like that. Fortunately, there is a tool that can detect the most active abusers and update the system’s firewall in order to deny them future connections. Strictly speaking, there are many tools, but Fail2ban is one of the most popular, reliable and easy to use.

Installing Fail2ban

Fail2ban is accessible from a default Ubuntu package list. I used Ubuntu 18.04 but I guess the setup process wouldn’t be much different with any other version of Ubuntu.

apt-get update && apt-get install fail2ban

Fail2ban is much more than SSH “guard”, it can be used to parse many different types of logs in order to detect malicious patterns and to ban any bad actors. If you have HTTP pages that are protected with HTTP auth, you can consider using Fail2ban to put a cap on how many login attempts are allowed from a single IP address during a certain period of time. OK, back to our SSH now:

nano /etc/fail2ban/jail.local

This file will override Fail2ban default configs so we can specify our preferences here. All Fail2ban modules are disabled by default so we have to explicitly enable an sshd module:

[DEFAULT]
bantime = 1d  
findtime = 1d  
maxretry = 3

[sshd]
enabled = true
backend = systemd

This configuration file states that Fail2ban should give anyone 3 “chances” to offer valid login credentials and if they fail 3 times during 1 day, they will be banned for the next 24 hours. That config seemed to work for me but you can adjust it for your needs: it can be probably made a lot harsher.

Now, it’s time to start Fail2ban service:

service fail2ban start

You can always check the status of sshd module by using the following command:

fail2ban-client status sshd

Here is an example output:

Status for the jail: sshd
|- Filter
|  |- Currently failed:	67
|  |- Total failed:	542
|  `- Journal matches:	_SYSTEMD_UNIT=sshd.service + _COMM=sshd
`- Actions
   |- Currently banned:	6
   |- Total banned:	76
   `- Banned IP list:	37.49.225.93 188.92.77.12 92.222.136.169 193.201.224.232 116.110.219.162 171.254.227.12

We can also watch Fail2ban in action in the real time:

tail -f /var/log/fail2ban.log

And finally, if you decide to change Fail2ban config later, don’t forget to reload it in order for changes to take effect:

fail2ban-client reload

Conclusion

It’s relatively easy to weed out the bad actors from your SSH port by disabling the password login and banning anyone who tries to mess with your server using Fail2ban. One of the additional benefits of having an active banning tool is that it helps to keep your server logs lightweight and easy to read.

This site doesn't have ads and the reasons are simple:

  • Most people don't want to see ads, that's not what they look for when they open web pages.
  • Ad scripts can track visitors, exposing private data to third parties.

If you found this post valuable and you wish to leave a tip, you can do it with Bitcoin:

34CXtg7c4Vbw8DZjAwFQVsrbu9eDEbTzbA