Securing SSH: Essential Steps for Linux Servers

SSH (Secure Shell) is secure by design, but using it with default settings isn’t enough.

In my previous comprehensive Linux server hardening guide, we touched upon the necessary tweaks for SSH to enhance security.

However, in this detailed exploration, we dive deep into everything you need to know about securing SSH.

I’ll share tips from my experience to help you enhance SSH security beyond the basics.

Let’s dive in and discover how simple changes can significantly boost your server’s safety.

Preparation

To make the most of this guide, ensure you have a server up and running.

If you don’t have one, consider getting a free VPS server to follow along.

Following along on your own server will enhance your understanding and practical experience.

SSH Basics

SSH is split into two key parts: the server part, known as sshd, which runs on the server you want to access, and the client part, ssh, used to connect to that server.

Typically, you’d use an SSH client from your laptop to manage the server. For Windows users, a common choice is Putty, while Mac users can simply use the built-in terminal.

In terms of security, the server side of SSH is what matters most. It’s the server that decides on critical security aspects, like whether to allow password-based logins or not.

The server’s decisions override any preferences set by the client. The server’s SSH settings are found inside the /etc/ssh/sshd_config file.

On the client side, you’ll find configuration settings in the /etc/ssh/ssh_config file for system-wide settings, or in the ~/.ssh/config file for individual user settings.

These settings can also be adjusted when making a connection using command-line options.

This guide will primarily focus on the server side of SSH.

Key Considerations

Before we dive into the tips for securing SSH, it’s important to remember that not every tip will suit everyone. Think carefully about which tweaks fit your server’s needs.

Make sure to really understand each tip and decide if it’s right for your setup.

For instance, while disabling password authentication is a common security practice, it might reduce the necessity for tools like Fail2ban. However, I still advocate for its use as an added security layer.

Remember, we’re dealing with settings in the /etc/ssh/sshd_config file. Before making any changes, it’s wise to backup this original file to avoid any unintended disruptions.

Additionally, some server providers might include custom configurations in the /etc/ssh/sshd_config.d/ directory.

I recommend reviewing these files carefully to ensure compatibility with any adjustments you plan to make.

Lastly, it’s important to reload the SSH service instead of restarting it, as many blog posts suggest. Reloading reduces the risk of losing your connection and being unable to reconnect.

Also, always use the sudo sshd -t command after each adjustment and before reloading SSH. This helps ensure the syntax and options are correct, preventing a non-functioning service.

Securing SSH

Let’s start making SSH more secure on our server. Just open the /etc/ssh/sshd_config file in your favorite editor and follow this guide.

Note: Most variables in this file are commented out by default. Remember to uncomment them when changing any value.

Change The Default SSH Port

SSH usually runs on port 22, which is well-known to hackers and can lead to brute-force attacks. To reduce these attacks, it’s a good idea to change the default port to a less common one.

Look for the Port variable in the file, which by default is commented out and set to 22.

Uncomment it and change the value to a different number, like this:

/etc/ssh/sshd_config
...
Port 592
...

It’s important to remember that after changing the default SSH port and reloading SSH, you should use the -p option followed by the new port number when sshing into the server again.

Access Control

Scroll down a bit, and you’ll find these three variables, which are commented out:

/etc/ssh/sshd_config
...
#LoginGraceTime 2m
#MaxAuthTries 6
#MaxSessions 10
...

The LoginGraceTime variable specifies how long a user has to finish the authentication process. While the default value is set to 2 minutes, you might want to reduce this to a shorter duration, such as 20 seconds.

The MaxAuthTries variable specifies the maximum number of login attempts a user is allowed to make. The default value permits up to 6 tries. This means a user can attempt to access the server up to 6 times.

After failing all attempts, they are blocked from accessing the server. You might consider lowering this limit to, for example, 3 tries.

The MaxSessions variables controls the maximum number of concurrent sessions allowed per user connection. The default value typically allows 10 sessions. This means a user can have up to 10 active SSH sessions at the same time.

If your server doesn’t need to support many simultaneous sessions, you could consider reducing this number. For instance, setting it to 5 could be more appropriate.

/etc/ssh/sshd_config
...
LoginGraceTime 20
MaxAuthTries 3
MaxSessions 5
...

These are my recommended values for these three variables.

Prevent Empty Passwords

On a Linux server, it’s possible to create users with empty passwords, which is not recommended because they can access the server without any authentication.

By default, SSH prevents users with empty passwords from accessing the server, but it’s always good to double-check.

Look for the PermitEmptyPasswords variable and make sure it’s set to no like this:

/etc/ssh/sshd_config
...
#PermitEmptyPasswords no
...

It’s commented out by default. If it’s already set to no, you can leave it as is.

Configure Idle Timeout Interval

The idle timeout interval defines how long an SSH connection remains active when there’s no user activity.

For instance, if you ssh into the server and leave the terminal open without any interaction, this creates an idle session, which can pose a security risk.

Therefore, it’s wise to set a timeout interval that automatically closes the SSH connection if the session becomes idle.

This can be configured with the ClientAliveInterval and ClientAliveCountMax variables.

The ClientAliveInterval variable determines the time in seconds the server waits before sending a check-up message to the client to keep the SSH connection alive.

For example, setting it to 60 seconds means the server checks every 60 seconds if the client is still connected.

The ClientAliveCountMax variable sets the maximum number of check-up messages the server can send without receiving a response before terminating the connection.

For example, if it’s set to 3 and the client doesn’t respond to three messages, the server will end the session.

/etc/ssh/sshd_config
...
ClientAliveInterval 60
ClientAliveCountMax 3
...

These are my recommended values for these two variables.

So, if a client is inactive for 180 seconds (3 checks, 60 seconds each), the server will end the SSH session.

Disable Rhosts

Rhosts, though now uncommon, was once a weaker method for authentication, relying on trusting clients based on their IP address alone.

By default, Rhosts is typically disabled. However, as I often emphasize, it’s wise to double-check.

Look for the IgnoreRhosts variable and ensure it is set to yes like this:

/etc/ssh/sshd_config
...
#IgnoreRhosts yes
...

It’s commented out by default. If it’s already set to yes, you can leave it as is.

Disable X11 Forwarding

By default, SSH can forward X11 sessions, which can be useful for certain graphical applications.

Unless necessary, disable X11 forwarding in SSH, as the X11 protocol isn’t security-oriented.

Find the X11Forwarding variable and set it to no like this:

/etc/ssh/sshd_config
...
X11Forwarding no
...

Disabling non-essential features like X11 forwarding in SSH can greatly strengthen your server’s security.

Disable Agent and TCP Forwarding

SSH agent forwarding lets you use your SSH keys to move from one server to another without keeping keys on the first server. It makes connecting through multiple servers easier but can be risky for security.

SSH TCP forwarding, also known as port forwarding, lets you redirect data between your local and remote machine.

Disable these two features if you don’t need them to minimize the attack surface.

Find the AllowAgentForwarding and AllowTcpForwarding variables and set them to no like this:

/etc/ssh/sshd_config
...
AllowAgentForwarding no
AllowTcpForwarding no
...

I suggest turning them off since they are usually enabled by default, unless it’s absolutely necessary for your specific needs.

Disable Root Login

When you first access your server, you might use the root user, but this isn’t advisable. The root user has full control over the server, and it’s easy to accidentally cause damage when executing commands as root.

Using a non-root user is safer, as it requires the sudo prefix for administrative tasks and prompts for a password.

Additionally, opting for a non-root user enhances security against brute force attacks.

Since the root user is the default on all Linux servers, it’s often targeted by attackers trying to guess your password. Using a non-root user can help mitigate this risk.

Therefore, it’s always better to use a non-root user and restrict root user access to the server entirely.

If you’ve already added a non-root user with root privileges, you can now disable root user access to the server.

Locate the PermitRootLogin variable, which is usually commented out by default, and change its value to no like this:

/etc/ssh/sshd_config
...
PermitRootLogin no
...

By doing this, you can access the server only with your non-root user, whose username is not publicly known.

Disable Password Authentication

Accessing your server usually involves using a password with SSH. But a more secure method is SSH key authentication.

This uses two keys: a public key on your server and a private key you keep.

You get access when the server verifies you have the private key.

This method is safer than just using a password, as it ensures only someone with the private key can enter the server.

If you’ve already generated your key pair and copied the public key to the server, find the PasswordAuthentication variable and set its value to no like this:

/etc/ssh/sshd_config
...
PasswordAuthentication no
...

By doing this, you ensure that the server can only be accessed using SSH keys.

Always remember to keep your private key secure.

Allow SSH Access To Specific Users

When not every user needs access to the server, it’s a good practice to limit SSH access to a select few.

One method is by creating a group, adding necessary users to it, and then utilizing the AllowGroups option to permit only those in the group to ssh into the server.

However, my preferred method is using the AllowUsers option. This allows me to specify exactly which users can SSH into the server.

With AllowUsers, you’re effectively granting access to certain users while simultaneously denying it to all others.

If you wish to limit access to selected users only, scroll to the end of the file and add the AllowUsers option followed by the usernames.

/etc/ssh/sshd_config
...
AllowUsers user1 user2 user3

This ensures that only the specified users can access the server via SSH.

Allow SSH Access To Specific IP

In my previous server hardening guide, I recommended a straightforward step: limit SSH access to a single and trusted IP address using the firewall.

This means only that specific IP can connect to your server using SSH. It’s a powerful way to enhance your server’s security.

If you have a fixed, unchanging IP address, I highly recommend doing this.

However, it may not be advisable if your Internet Service Provider assigns a dynamic IP that changes periodically.

To set this up, it’s quite similar to what I explained earlier about restricting access for specific users. Just use the AllowUsers option like this:

/etc/ssh/sshd_config
...
AllowUsers user@IP

This ensures only the specified user from that specific IP can connect via SSH.

/etc/ssh/sshd_config
...
AllowUsers *@IP

This restricts access to the specified IP for all users on the server.

These simple changes add an extra layer of security by allowing SSH access only to approved users from specific IP addresses.

Mitigate Brute Force Attacks

Implement tools like Fail2Ban to automatically defend your server against brute force attacks.

Fail2Ban is an effective security tool that monitors log files for suspicious activities and blocks the IP addresses of potential attackers.

Reloading SSH

After you’ve finished securing SSH, make sure to reload the SSH service for your changes to become active.

Before that, you should verify the configuration for errors. You can do this using the following command:

sudo sshd -t

Use this command to reload SSH:

sudo systemctl reload ssh

Once the service is reloaded, your changes will be in effect.

You can also use the sudo sshd -T command to list all variables with their values, allowing you to check whether the changes have taken effect or not.

Conclusion and Final Thoughts

I hope this guide has been super helpful for you in securing SSH.

For a deeper dive into broader security practices, be sure to check out my comprehensive Linux server hardening guide, where I cover a wide array of important security topics.

If you found value in this guide or have any questions or feedback, please don’t hesitate to share your thoughts in the comments section below.

Your input is greatly appreciated, and you can also contact me directly if you prefer.

Newsletter

I'm excited to share my knowledge and experience! Subscribe to my newsletter for the latest updates. 👇

Leave a Reply

Your email address will not be published. Required fields are marked *