Securing SSH: Essential Steps for Linux Servers
Learn key steps to secure SSH on Linux servers, including important configurations and best practices for enhanced security.
SSH (Secure Shell) is secure by design, but relying on its default settings is not enough.
In my guide on preparing Ubuntu servers for first use, we touched on a few essential SSH tweaks to enhance security. However, there are additional steps you can take to further secure your server.
In this detailed exploration of the sshd_config
file, we’ll dive deep into everything you need to know about securing SSH.
I'll also share tips from my own experience to help you go beyond the basics and fully enhance your SSH security.
Preparation
To make the most of this guide, ensure you have a properly set up Ubuntu server.
If you don’t have one, consider getting a free VPS server to follow along.
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 authentication 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.
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.
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. 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.
The 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 inside the /etc/ssh/sshd_config
file, which by default is commented out and set to 22
.
Uncomment it and change the value to a different number, like this:
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:
#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.
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:
#PermitEmptyPasswords no
It's commented out by default. If it's already set to no
, you can leave it as is.
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.
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.
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:
#IgnoreRhosts yes
It's commented out by default. If it's already set to yes
, you can leave it as is.
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:
X11Forwarding no
Disabling non-essential features like X11 forwarding in SSH can greatly strengthen your server's security.
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:
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.
Root Access
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.
Locate the PermitRootLogin
variable, which is usually commented out by default, and change its value to no
like this:
PermitRootLogin no
By doing this, you can access the server only with your non-root user, whose username is not publicly known.
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.
Find the PasswordAuthentication
variable and set its value to no
like this:
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.
Restrict SSH Access
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.
AllowUsers <user1> <user2> <user3>
This ensures that only the specified users can access the server via SSH.
You could also restrict SSH traffic to a single and trusted IP address. This means only that specific IP can connect to your server using SSH.
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:
AllowUsers <user>@<ip_address>
This ensures only the specified user from that specific IP can connect via SSH.
AllowUsers *@<ip_address>
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.
Reloading SSH
After you've made your changes, be sure to reload the SSH service to apply them.
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 helpful in enhancing your understanding of securing SSH beyond the basics.
By applying these tips, you can significantly strengthen your server's security.
If you found value in this guide or have any questions or feedback, please don't hesitate to share your thoughts in the discussion section.
Your input is greatly appreciated, and you can also contact me directly if you prefer.
Discussion