SSH Hardening Guide: Best Practices for Linux Servers

By 

Updated on

8 min read

SSH hardening best practices for Linux servers

SSH makes remote Linux server administration easy, but defaults are not always safe. A poorly configured SSH server can be an easy target for brute-force attacks, exposed accounts, and unauthorized access.

This guide covers practical SSH hardening best practices for Linux servers. We will adjust sshd_config, test the configuration before restarting the service, and add protections that reduce the attack surface without making the server hard to manage.

Quick Reference

For a printable quick reference, see the SSH cheatsheet .

SettingValuePurpose
PasswordAuthenticationnoForce key-based authentication
KbdInteractiveAuthenticationnoDisable keyboard-interactive password prompts
PermitRootLoginnoDisable root SSH login
AllowUsersdeploy adminRestrict SSH access to listed users
PermitEmptyPasswordsnoBlock empty passwords
LoginGraceTime30Shorten the authentication window
MaxAuthTries3Limit failed login attempts
X11ForwardingnoDisable X11 forwarding
AllowAgentForwardingnoDisable agent forwarding
AllowTcpForwardingnoDisable SSH tunnels for users who do not need them
ClientAliveInterval300Set idle timeout interval
ClientAliveCountMax2Disconnect after 2 missed keep-alives

Prerequisites

All SSH server settings are configured in /etc/ssh/sshd_config. Some distributions also load files from /etc/ssh/sshd_config.d/, which is useful when you want to keep local changes separate from package defaults.

Warning
Before applying any of these changes, keep your current SSH session open and make sure you have an alternative way to access your server, such as a console connection, in case you lock yourself out.

Before editing the SSH configuration, create a backup:

Terminal
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup

After each change, test the configuration before restarting SSH:

Terminal
sudo sshd -t

If the command prints no output, the configuration syntax is valid. Then restart the SSH service:

Terminal
sudo systemctl restart ssh

On some distributions the service is named sshd:

Terminal
sudo systemctl restart sshd

Use Key-Based Authentication

Password authentication is vulnerable to brute-force attacks. Key-based authentication is more secure because it requires possession of the private key.

First, make sure you have copied your SSH key to the server and can log in without a password.

Then disable password authentication in /etc/ssh/sshd_config:

/etc/ssh/sshd_configini
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes

This forces users to authenticate with SSH keys and disables keyboard-interactive password prompts. Keep password authentication enabled until you have confirmed that your key login works from a new terminal session.

Disable Root Login

Allowing direct root login over SSH is a security risk. Attackers commonly target the root account in brute-force attacks.

Disable root login in /etc/ssh/sshd_config:

/etc/ssh/sshd_configini
PermitRootLogin no

If you need root access, log in as a regular user and use sudo or su .

If you still need root login with keys only, use:

/etc/ssh/sshd_configini
PermitRootLogin prohibit-password

This allows root login only with SSH keys, not passwords.

Restrict SSH by Firewall

If only a few IP addresses need SSH access, restrict the SSH port at the firewall. This is usually stronger than only changing the SSH port because unwanted hosts cannot reach the daemon at all.

With UFW, allow SSH from a trusted IP address:

Terminal
sudo ufw allow from 203.0.113.10 to any port 22 proto tcp

If you manage the server from more than one location, add each trusted IP address before removing broader SSH rules. Do not close the current SSH port until you have tested a new connection.

Change the Default Port

The default SSH port is 22. Changing it does not provide real security, but it reduces noise from automated bots that scan port 22.

Change the port in /etc/ssh/sshd_config:

/etc/ssh/sshd_configini
Port 2222

Make sure to open the new port in your firewall before restarting SSH:

Terminal
sudo ufw allow 2222/tcp

For more details, see our guide on how to change the SSH port .

Limit User Access

By default, all system users can log in via SSH. You can restrict access to specific users with the AllowUsers directive:

/etc/ssh/sshd_configini
AllowUsers deploy admin

Only the listed users will be able to connect. All others will be denied.

To restrict access by group instead:

/etc/ssh/sshd_configini
AllowGroups sshusers

Disable Empty Passwords

Make sure accounts with empty passwords cannot log in via SSH:

/etc/ssh/sshd_configini
PermitEmptyPasswords no

Set Login Grace Time

The LoginGraceTime setting controls how long the server waits for a user to authenticate before disconnecting. The default is 120 seconds, which is too long:

/etc/ssh/sshd_configini
LoginGraceTime 30

Limit Authentication Attempts

Reduce the number of authentication attempts per connection to slow down brute-force attacks:

/etc/ssh/sshd_configini
MaxAuthTries 3

Disable X11 Forwarding

If you do not need to forward graphical applications over SSH, disable X11 forwarding:

/etc/ssh/sshd_configini
X11Forwarding no

OpenSSH disables X11 forwarding by default on many systems, but setting it explicitly keeps the intended policy clear.

Disable Agent Forwarding

Agent forwarding lets a remote server use your local SSH agent for onward connections. Disable it unless users need to connect from this server to other hosts with forwarded credentials:

/etc/ssh/sshd_configini
AllowAgentForwarding no

Disable TCP Forwarding

If your users do not need to create SSH tunnels, disable TCP forwarding:

/etc/ssh/sshd_configini
AllowTcpForwarding no

This blocks SSH port forwarding requests. It does not stop users with shell access from running their own forwarding tools, but it removes the built-in SSH tunneling path.

Use Strong Key Types

When generating SSH keys, use Ed25519 or RSA with at least 4096 bits. Ed25519 is the recommended choice for new keys:

Terminal
ssh-keygen -t ed25519

For RSA:

Terminal
ssh-keygen -t rsa -b 4096

Older key types like DSA and ECDSA with small key sizes should be avoided.

Set Idle Timeout

Disconnect idle SSH sessions after a period of inactivity. This prevents abandoned sessions from remaining open:

/etc/ssh/sshd_configini
ClientAliveInterval 300
ClientAliveCountMax 2

This sends a keep-alive message every 300 seconds (5 minutes) and disconnects after 2 missed responses, giving a total timeout of 10 minutes.

Set Up Fail2Ban

Fail2Ban monitors authentication logs and bans IP addresses that show malicious activity, such as repeated failed login attempts. It is most useful on public SSH servers that still receive frequent connection attempts.

Install Fail2Ban:

Terminal
sudo apt install fail2ban

Create a jail override file:

Terminal
sudo nano /etc/fail2ban/jail.d/sshd.local

Add the SSH jail configuration:

/etc/fail2ban/jail.d/sshd.localini
[sshd]
enabled = true
port = ssh
filter = sshd
maxretry = 3
bantime = 3600
findtime = 600

This configuration bans an IP address for 1 hour after 3 failed login attempts within 10 minutes. The default sshd jail usually knows where your distribution writes SSH authentication logs, so you do not need to set logpath unless your server uses a custom logging setup.

If you changed SSH to a custom port, set port to that value in the jail file:

/etc/fail2ban/jail.d/sshd.localini
port = 2222

Start and enable Fail2Ban:

Terminal
sudo systemctl enable fail2ban
sudo systemctl start fail2ban

To check the status of the SSH jail:

Terminal
sudo fail2ban-client status sshd

Display a Warning Banner

You can display a legal warning banner before authentication. Create a banner file:

Terminal
sudo nano /etc/ssh/banner

Add your warning text:

/etc/ssh/bannertext
Authorized access only. All activity is monitored and logged.

Then enable it in /etc/ssh/sshd_config:

/etc/ssh/sshd_configini
Banner /etc/ssh/banner

Troubleshooting

SSH does not restart after editing sshd_config
Run sudo sshd -t to find syntax errors. If you need to revert quickly, restore the backup with sudo cp /etc/ssh/sshd_config.backup /etc/ssh/sshd_config, then test the configuration again before restarting SSH.

Password login still works after setting PasswordAuthentication no
Check whether KbdInteractiveAuthentication is still enabled. On PAM-based systems, keyboard-interactive authentication can still ask for a password, so set both PasswordAuthentication no and KbdInteractiveAuthentication no.

The service name is different on your system
Ubuntu and Debian commonly use ssh.service, while RHEL, Fedora, and many other distributions use sshd.service. Check the active unit with systemctl status ssh or systemctl status sshd.

You changed the port but cannot connect
Make sure the firewall allows the new port before restarting SSH. If you use Ubuntu socket activation, ssh.socket may still listen on port 22 unless the socket configuration is updated.

Fail2Ban does not show bans for SSH
Check the jail status with sudo fail2ban-client status sshd. If the jail is active but no failures are detected, review your authentication logs with sudo journalctl -u ssh or sudo journalctl -u sshd and confirm that Fail2Ban is using the correct backend for your distribution.

FAQ

Should I change the SSH port?
Changing the port reduces automated scanning noise but does not provide real security. It is useful as part of a defense-in-depth strategy, not as a standalone measure.

Can I lock myself out by disabling password authentication?
Yes. Before disabling password authentication, make sure you can log in with your SSH key. Keep a console connection available as a backup.

Is Fail2Ban necessary if I use key-only authentication?
It is not strictly necessary, but it still helps. Fail2Ban reduces log noise and blocks IPs that repeatedly attempt to connect, even if they cannot authenticate.

What is the most important hardening step?
Disabling password authentication and using key-based authentication. This eliminates the most common attack vector: brute-force password guessing.

How do I check my current SSH configuration?
Run sudo sshd -T to display the effective SSH server configuration, including all defaults and overrides.

Conclusion

SSH hardening starts with safe configuration changes: key-based authentication, no direct root login, limited users, firewall restrictions, timeouts, and tested sshd_config edits. Apply the settings that fit your server, and always test a new SSH session before closing the old one.

Linuxize Weekly Newsletter

A quick weekly roundup of new tutorials, news, and tips.

About the authors

Dejan Panovski

Dejan Panovski

Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 800+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.

View author page