var img = document.createElement('img'); img.src = "https://easystat.de/piwik.php?idsite=13&rec=1&url=https://docs.vps2day.com" + location.pathname; img.style = "border:0"; img.alt = "tracker"; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(img,s);
Skip to main content

The SSH Security Guideline

SSH server security is one of the most common beginner topics when it comes to administrating your very own Linux server. SSH is the management interface you're connecting to in order to change your server's configuration or to install new software. It's the primary entrypoint to your server, and therefore it's important to secure it properly.

Attackers that gain access to your SSH server can cause a lot of damage. They can install malware, mine cryptocurrencies, send spam, or even use your server as a proxy for illegal activities. As you are responsible for your server's security you definitely want to avoid such incidents.

In this guideline, we'll cover the 5 most important steps to secure your SSH server.

1. Restrict SSH access to selected users

The first step is to reduce the attack surface of your SSH server by restricting the users (or groups) that are even allowed to log in. By default, all users on your server can log in via SSH. This is not necessary in most cases.

In your SSH server configuration (usually located under /etc/ssh/sshd_config) you can add the following lines to specify which users are allowed to log in:

/etc/ssh/sshd_config
AllowUsers User1 User2 UserN
AllowGroups Group1 Group2 GroupN

Those configuration parameters are not mutually exclusive, you can use both or just one of them. You can specify just a single user (or group) or multiple. If you specify multiple users (or groups), you need to separate them with a space.

It's good practice to create a dedicated and unprivileged user for your daily work and only allow that user to access your server via SSH. By doing this, attackers not only have to guess your password, but also your username. This makes it much harder for them to gain access to your server.

Create a dedicated user

In order to create a dedicated user, you can use the adduser command. It will ask you for a password and some additional information. You can just press Enter to skip those questions.

sudo adduser <USERNAME>

In order to allow that user to run commands as a privileged user (e.g. to install software), you can add it to the sudo group.

sudo usermod -aG sudo <USERNAME>

2. Restrict root access

In addition to that, you can disable root access via SSH altogether.

caution

You should only disable root access if you have a dedicated user with sudo privileges. Otherwise, you might lock yourself out of your server.

In order to completely disable root access, you can add the following line to your SSH server configuration:

/etc/ssh/sshd_config
PermitRootLogin no

This setting will even override the AllowUsers and AllowGroups directives. So even if you allow a user or group to log in via SSH, they won't be able to log in as root.

3. Enforce public key authentication

Key-based authentication is one of the greatest features of SSH. It allows you to log in to your server without entering a password. Instead, you use a private key that is stored on your local machine. This key is used to authenticate you against the server.

It's way more secure than password-based authentication because it's not possible to brute-force a private key. If you additionally use a strong passphrase to encrypt your private key, it's virtually impossible to crack it, even if the attacker somehow gains access to it.

info

If you provided at least one SSH key when you deployed your server, you can skip this step. In this case, we have already disabled password-based authentication for you while provisioning your server.

First of all, you need a so-called keypair consisting of a private and a public key. If you don't have one, yet, you can easily generate one.

Add public key to your user

Then, you need to tell the SSH server which public keys it should accept for which user. You can do this by adding the public key to the authorized_keys file in the user's .ssh directory.

mkdir -p ~/.ssh
echo "<PUBLIC_KEY>" >> ~/.ssh/authorized_keys

You need to run this command as the user you want to log in as, because it will use your home directory (~) to store the public key.

caution

Don't confuse the public key with the private key. The public key is a single line of text that looks like one of those lines:

ssh-rsa AAAAB3NzaC1yc2EAAAADAQetcetceAQQCo9+BpMRYQ/dL3DS2CyJxRF+j6ctbT3/Qp84+KeFhnii7NT7fELilKUSnxS30WAvQCCetcetcetcfgqr41mM70MB
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKHEtCmkI+hf8qGetcdSZ5L1TetcetcTOTiELHLC0h3r

Enforce public key authentication

Once you have the key(s) for your user in place, you can enforce public key authentication by adding the following line to your SSH server configuration:

/etc/ssh/sshd_config
PubkeyAuthentication yes
PasswordAuthentication no

As always, you should keep the terminal with the SSH connection you're working in open and test your changes in a new terminal. If you made a mistake, you can still revert your changes in the old terminal that is still connected to your server via SSH.

4. Automatically block attackers

Another useful mechanic to secure your SSH server is to automatically block attackers that try to brute-force your password. This is especially useful if you have password-based authentication enabled.

One of the most commonly used tool to achieve this is fail2ban. It's a mighty tool that runs in the background and monitors log files for certain patterns and automatically blocks the IP addresses that match those patterns. We can utilize it to identify the IP addresses of attackers in your /var/log/auth.log file where your SSH server is logging all authentication attempts.

Installation

Depending on your operating system you can install fail2ban using the following commands:

# Debian/Ubuntu
sudo apt install fail2ban

# CentOS
sudo yum install fail2ban

By installing fail2ban via packet manager, it will automatically start and run in the background.

Configuration

You can then go ahead and configure it to monitor your SSH server's log file. You can do this by creating the /etc/fail2ban/jail.local file. It inherits all settings from the /etc/fail2ban/jail.conf file. So you only need to add the settings you want to change.

Luckily, fail2ban comes with a default configuration for SSH servers. So all you need to do is telling it to enable the so-called jail for SSH by adding the following lines to your configuration file you just created:

/etc/fail2ban/jail.local
[sshd]
enabled = true

By default, fail2ban will block an IP address for 10 minutes if it detects three consecutive failed logins. You can change this by amending the following lines to the config you just created:

/etc/fail2ban/jail.local
[sshd]
enabled = true
maxretry = 5
bantime = 86400

In this example, you increased the amount of failed logins before action is taken from 3 to 5 but once a ban is issued, the IP address will be blocked for 24 hours (86400 seconds) instead of just 10 minutes.

caution

You should make sure that you don't accidentally lock yourself out of your server. If in doubt, you can use a lower bantime. Even just a few minutes are completely sufficient to stall an attacker's brute-force attempts.

5. Limit connections to a certain IP (range)

info

This suggestion only applies if you're connecting from a static IP address (or range) or from a VPN with a static IP (e.g. from a dedicated VPN).

In this case, there's no benefit in having the SSH port open to the whole internet. You can use your server's firewall to restrict access to your SSH port to the IP address (or range) you're usually connecting from. By doing so, you reduce the attack surface even further.

On most Linux servers, the iptables firewall package is already pre-installed by default. You can utilize it to block access to your SSH port and only allow it from certain IPs or IP ranges. You can do this by running the following commands:

sudo iptables -A INPUT -p tcp -s IP_ADDRESS --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j DROP

You need to replace the IP_ADDRESS placeholder with your static IP address or IP range in CIDR notation (e.g. 203.0.113.0/24 or 203.0.113.15 for a single IP).

Also, if you chose to change your SSH port, you need to replace the 22 placeholder with your custom SSH port.

caution

Firewall rules are applied instantly and without further warning. You can easily lock out yourself if you make a mistake. You can use our VNC Console to gain access to your server if you accidentally lock yourself out. You can then type iptables -F to flush all firewall rules and regain access to your server.