Mitigating SSH based attacks – Top 15 Best SSH Security Practices

tips

SecurityTrails Blog · Aug 29 · SecurityTrails team

SSH is one of the most popular communication protocols on the Internet. It's widely used by developers, webmasters, and sysadmins. It allows you to gain remote access to your new Cloud or Dedicated box in just seconds using an encrypted communication channel.

Here at SecurityTrails, we use it day by day to send and receive code securely. And while SSH is way more secure than the FTP protocol (as it transmits the information unencrypted in plain text format), it can still be attacked and cracked if you don't follow the best practices to harden it properly.

That's why today we will explore the most popular ways to harden your box once your Cloud provider gives you access to the new system. Let's start with the fun part: securing SSH.

15 Best SSH Hardening Tips

Follow these steps to turn your SSH server into a rock solid communication daemon.

Note: most of thesetips will require you to restart the SSHservice to apply the changes. You can do that by issuing:

service sshd restart

1. Set a custom SSH port

This is one of the oldest and most popular ways to obscure the SSH service. Why?

Because by default, SSH comes listening on port 22, which is widely known among attackers and security tools/port scanners that launch brute force attacks against it. While this is considered security by obscurity, it helps eliminating lots of noise on port 22.

Edit your SSH main config file:

nano -w /etc/ssh/sshd_config

Search for: Port

Then set it to something different than 22, like:

Port 899

2. Use TCP Wrappers

This host-based ACL protection will help you to filter who can access the OpenSSH server.

TCP Wrappers works using two files: /etc/hosts.allow and /etc/hosts.deny

First, let's deny allconnections from unknown hosts:

nano -w /etc/hosts.deny

Then add this line:

ALL : ALL

If you want to allow access from your static home IP for example, you should add this code to the allow file:

nano -w /etc/hosts.allow

Then add this at the end of the file:

sshd : 11.22.33.44

Replace 11.22.33.44 with your real public IP, or with your private LAN IP, you can choose either.

This will help you to block the rest of the world, and allow only the specified IP addresses.

3. Filter the SSH port on your firewall

Using a server-side software firewall is one of the basic things that all servers should have configured after the OS is installed.

One of the most popular and effective firewalls we've found is CSF by ConfigServer.

Installing CSF on plan based distros (without any control panel) is easy, and filtering the ports is even easier.

Edit the main csf.conf file:

nano -w /etc/csf/csf.conf

Then search for this variables:

# Allow incoming TCP ports  
TCP_IN = "80,443,899"  

# Allow outgoing TCP ports  
TCP_OUT = "80,443"  

In this case, we added our custom 899 SSH port to the list of TCP_IN connections at the end after configuring 80 and 443 ports.

Best security practices always suggest allowing only trusted public static IPs, or private LAN connections. Your SSH port should never be opened to external untrusted connections.

If you are using your own custom iptables rules, you can open TCP incoming connections by running:

iptables -A INPUT -p tcp -s 11.22.33.44 -m tcp --dport 899 -j ACCEPT

Make sure to replace 11.22.33.44 with your allowed IP.

4. Disable Root Login

Apart from having the port set to 22 by default, SSH servers come also with root login allowed on most Linux and Unix operating systems.

This allows anyone to connect to port 22, and use the root user as default, and then launch a ton of brute force attacks against your public server IP.

If you have password authentication enabled on your SSH service and your root password is weak, chances you are going to get hacked are pretty high. That's why disabling root login is one of the oldest and most used techniques to avoid system compromise on fresh OS installations.

You can check this out by leaving the SSH installation by default,parse the /var/log/secure file and see how many brute force attacks you willreceive within a few hours- you will be surprised.

Even if you are using strong passwords, it's always recommended to disable root login and use a primary SSH user instead, so then if you need to gain root access you can do it using su command if required.

Edit SSH main config file:

nano -w /etc/ssh/sshd_config

Then search for the "PermitRootLogin" variable and set it to no:

PermitRootLogin no

If it is not present, add the AllowUsers variable to the file, and set your allowed users there:

AllowUsers sectrails9

What if you need root access from certain IPs? Is there any way to disable root access for all IP address and only allow specific ones?

Yes, it can be done by adding the root users and IPs inside the AllowUsers line, as you see below:

AllowUsers sectrails9 root@192.168.1.110

In this case, we are allowing SSH access to the system user sectrails9, and also to the root user coming from 192.168.1.110 IP address.

5. SSH Passwordless Login

Password-based logins are good if you have a strong set of characters like symbols, uppercase, lowercase, and numbers, however, they all have the risk of brute-force cracking sooner or later.

The best, in this case, is to replace the old password-based logins with key-based logins that will increase your security, but also allow you to set an immediate fast SSHlogin without any prompt in the middle, as it happens when the SSH password is requested.

Using SSH key-based logins will also allow you to run automated tasks that require SSH connections like rsync file synchronization across servers, specific file transfers, remote MySQL dumps, etc.

Create your SSH key using: ssh-keygen

It will prompt a few things, hit enter on all those.

[sectrails9@securitytrails.com ~]$ ssh-keygen  
Generating public/private rsa key pair.  
Enter file in which to save the key (/home/sectrails9/.ssh/id_rsa):  
Created directory '/home/sectrails9/.ssh'.  
Enter passphrase (empty for no passphrase):  
Enter same passphrase again:  
Your identification has been saved in /home/sectrails9/.ssh/id_rsa.  
Your public key has been saved in /home/sectrails9/.ssh/id_rsa.pub.  
The key fingerprint is:  
SHA256:u72tY6os9QxWxmBF+Iqpz7Brr9RMqCuT8cjanq4HbAQ sectrails9@securitytrails.com  
The key's randomart image is:  
+---[RSA 2048]----+  
| +o |  
|E + |  
|. . + |  
| . . = |  
|o . .o +S |  
|o+ +o = . |  
|+*o.oo +. |  
|====.. ooo. |  
|*BO=+.o.oo++. |  
+----[SHA256]-----+  
[sectrails9@server ~]$

As you see, we avoided setting the passphrase... and that's a contradiction, right? As we are setting a private key to authenticate without any passphrase, it is not as secure as you think.

What is the purpose of using a passphrase for ssh keys? Simple: encrypt your private key /home/sectrails9/.ssh/id_rsa. So in this case, if an attacker is able to find it, it will be useless unless he knows the passphrase.

But, passphrases for SSH keys are not the best if you need to run automated tasks. That's why most ssh keys don't have any passphrase set.

The workaround for this is an intermediate solution, like restrict SSH login using SSH keys to a particular IP address. Let's try it.

In order to restrict the user sectrails9 to access the SSH server remotely using ssh-keys from a single static IP, you can use the "from" variable inside the authorized_keys file from the remote system, as you see below:

nano -w /home/remoteuser/.ssh/authorized_keys

Then set this at the beginning of the file, before your private key:

from="192.168.1.105"

Replace 192.168.1.105 with your own IP.

It should look like this:

from="192.168.1.105" ssh-rsa AAAAB3NzaC1yc2EAAAA...

6. Strong passwords/passphrase for ssh users and keys

If you are not able to set an ssh-key and still need to use login passwords, or, if you decide to use a passphrase on your keys, then make sure to use strong character combination.

Try to include:

  • Uppercase & lowercase letters
  • Symbols.
  • Numbers.
  • Up to 8 characters if possible.

Avoid using:

  • Dictionary-based words.
  • Personal birthday and anniversary dates.
  • Family and pet names.

Following this tips will help you to set a strong password/passphrase and avoid getting hacked when a brute force attack is happening.

7. Set Idle Timeout Interval

Idle timeout value allows terminating ssh sessions that are not actively used.

This variable can be edited by altering the ClientAliveInterval value.

nano -w /etc/ssh/sshd_config

Set:

ClientAliveInterval 240

In this case, we set 240 which equals to 4 minutes, once the timeout has been reached, the SSH session will be logged out automatically.

8. Disable Empty Passwords

On Linux and Unix, the system allows administrators to create users with empty passwords.

And this can be a pretty bad thing if you want to keep attackers out of your SSH servers.

That's why the best thing you can do is to disable remote logins for accounts with an empty password, this can be easily done by editing the sshd_config file.

nano -w /etc/ssh/sshd_config

Then set:

PermitEmptyPasswords no

9. Set a custom SSH warning banner

A good practice for all Linux and Unix boxes is to set a custom welcome banner for SSH connections.

This is really not a security hardening tip, but just a security warning for any illegal access to your systems.

Once the user has gained access, a warning banner will be displayed, as you see below:

ALERT! You are entering a secured area! Your IP and login information  
have been recorded. System administration has been notified.  

This system is restricted to authorized access only. All activities on  
this system are recorded and logged. Unauthorized access will be fully  
investigated and reported to the appropriate law enforcement agencies.

By altering the /etc/motd file you can set a custom ASCII art banner, like the one you see below:

On most Linux distros, just editing your/etc/motd file is enough.

If that does not work, you can also uncomment this line inside the sshd_config file:

#Banner none

And set the path to something else:

Banner /etc/custombanner

10. Block SSH brute force attacks automatically

On this post, we mentioned ways to mitigate brute force attacks several times. However, the best way to actually stop a brute force attack once detected is to block the offending IPs.

How can you detect this kind of attacks against SSH service automatically?

The manual way is by parsing system logs and check who is trying to connect to the server, and then block it using the system firewall. However, there are several tools that can do those manual tasks for you in an efficient and automated way.

There are a lot of tools to prevent brute force attacks, like SSHGuard, Fail2ban, or DenyHosts.

However, if you are using CSF Firewall as we previously recommended, you already have an integrated brute force detection system called LFD.

Edit csf.conf file as you see below:

nano -w /etc/csf/csf.conf

Then search for this variables:

# [*]Enable login failure detection of sshd connections  
LF_SSHD = "5"  
LF_SSHD_PERM = "1"

LF_SSHD set to "5" is the number of max failed connections before blocking the IP address.

LF_SSHD_PERM set to "1" makes this blocking permanent.

On the other side, you can increase the brute force protection by using real time blocklists, which is a cool feature already included in CSF firewall.

All the lists can be located inside this file: /etc/csf/csf.blocklists, there you will find Dshield, Blocklist.de, among other block lists.

In this case we will use Dshield and Blocklist.de, you can do the same by just remove the comment from the following lines:

#DSHIELD|86400|0|http://www.dshield.org/block.txt

#BDEALL|86400|0|http://lists.blocklist.de/lists/all.txt

Simply remove the first character # at the beginning of the line, so it looks like this:

DSHIELD|86400|0|http://www.dshield.org/block.txt

BDEALL|86400|0| [http://lists.blocklist.de/lists/all.txt][17]

Save the file and restart CSF + LFD:

csf -r  
systemctl restart lfd

That's it, now you are protected against brute force attacks.

11. Disable OpenSSH server on the laptops and desktops

Some Linux distros come with OpenSSH Server enabled by default (and you know what that means: root login enabled, service listening on port 22, etc), and while on Dedicated, VPS and Cloud servers, SSH access is a must in order to work remotely. On home-based computers like laptops or PCs it is not really needed.

Make sure to remove OpenSSH server to avoid unnecessary attacks.

For RHEL based distros:

dnf remove openssh-server

Debian / Ubuntu based distros can do the same by using:

sudo apt-get remove openssh-server

12. Disable X11 forwarding

If you are running a remote server, having X11 (graphics server) forwarding capabilities doesn't have too much sense, as you will always stay stick to your black and white remote terminal.

In order to disable X11 forwarding, follow this steps:

nano -w /etc/ssh/sshd_config

Look for this variable:

X11Forwarding yes

Change it to be:

X11Forwarding no

Disabling the X11 protocol will help you to prevent a few types of attacks, as it was never built with security in mind, and it can be used by malicious attackers to open up a channel to the client and send remote commands that may end up really bad.

13. Limit max authentication attempts

Another good way to protect against brute force attacks is to set a low limit for the times an attacker can try to login with a failed password. MaxAuthTries variable can help you to mitigate this kind of attacks.

nano -w /etc/ssh/sshd_config

Search for MaxAuthTries.

Set it to 3, as you see below:

MaxAuthTries 3

14. Enable login notifications over email

One of the best things you can do in order to keep a close eye onyour incoming SSH connections is to set up a quick script to send an alert once someone is logged in as root via SSH.

nano -w /root/.bashrc

Paste this at the end of the file:

echo 'ALERT - Root Shell Access (ServerName) on:' `date` `who` | mail -s "Alert: Root Access from `who | cut -d'(' -f2 | cut -d')' -f1`" your@email.com

Replace your@email.com with your real email address.

In order to have this working as expected, make sure to have "mailx" package installed and working. If you don't have it, you can install it by issuing this commands:

For RHEL based distros:

dnf install mailx

Debian/Ubuntu based distros:

apt-get install mailx

15. Keep SSH updated

The basic rule that will be repeated over and over: keep your server packages updated, and that also includes OpenSSH.

For RHEL based distros, you can use DNF or yum:

dnf update openssh*
yum update openssh*

For Debian/Ubuntu based distros:

apt-get update openssh-server

This should be enough to keep your OpenSSH server patched against new vulnerabilities.


Following these SSH security tips will help you to prevent the majority of the most popular SSH attacks on your Unix/Linux operating system. Do you have any extra SSH security tips that we are missing? [Get in touch][contact] and share your knowledge with us.

Now that you have your ssh service secured, it's time to jump and start auditing and hardening other popular internet services like the DNS system: follow our Best Tips to Prevent DNS Attacks to discover ways to harden your domain name system services.

And if you want to dig manually into how much information you are exposing from your domain names and IPs, check out our SecurityTrails toolkit, as well as our [free API access][pricing] to integrate our cool cybersecurity features into your own apps.