5 ways to lock down your SSH server
Spin up a new Linux server, leave port 22 open, and check your auth logs an hour later. Automated scripts will already be trying to guess your root password.
This is not theoretical. Every publicly accessible server with port 22 open gets hammered by bots continuously, around the clock. Tools like fail2ban were built precisely because this problem is so universal. The good news: you can eliminate most of the risk in about fifteen minutes by following these five steps.
1. Turn off password logins
Passwords are the weakest link in SSH security. People reuse them, write them in notes apps, and scripts can brute-force weak ones in minutes. SSH keys solve the authentication problem entirely by making it mathematically infeasible to guess your credentials.
Before turning off password authentication, make sure you have already added your public key to ~/.ssh/authorized_keys on the server. If you turn off passwords without a working key, you will lock yourself out.
Open your SSH configuration file:
sudo nano /etc/ssh/sshd_config
Find (or add) the following line and set it to no:
PasswordAuthentication no
Also check that ChallengeResponseAuthentication is set to no:
ChallengeResponseAuthentication no
Restart the SSH service to apply changes:
sudo systemctl restart sshd
Test from a new terminal window before closing your current session. Confirm you can still log in with your key.
2. Change the default port
Moving SSH off port 22 does not protect you against a targeted attack, but it removes your server from the list of results that automated scanners act on immediately. Most bots scan for port 22 specifically. Changing to a non-standard port like 2222 or 4822 drops the volume of brute-force attempts in your logs to near zero.
In /etc/ssh/sshd_config, change the port line:
Port 2222
Before restarting SSH, open the new port in your firewall so you do not lock yourself out:
# UFW
sudo ufw allow 2222/tcp
sudo ufw delete allow 22/tcp
# firewalld (CentOS/RHEL)
sudo firewall-cmd --add-port=2222/tcp --permanent
sudo firewall-cmd --remove-service=ssh --permanent
sudo firewall-cmd --reload
If your server is hosted on AWS, Google Cloud, or DigitalOcean, update your Security Group or Cloud Firewall rules in the dashboard to reflect the new port as well.
To connect on a non-standard port, add -p to your SSH command:
ssh -p 2222 user@your-server
3. Switch to Ed25519 keys
If you generated your SSH keys years ago using the default settings, you almost certainly have RSA keys. RSA still works, but it requires very large key sizes (4096 bits) to be considered secure today, and older RSA+SHA-1 signatures are disabled in OpenSSH 8.8 and above.
Ed25519 uses elliptic-curve cryptography. The keys are tiny (68 characters for the public key versus 700+ for RSA), faster to generate, faster to verify, and provide equivalent security at a fraction of the computational cost.
Generate a new Ed25519 key pair on your local machine:
ssh-keygen -t ed25519 -C "your_email@example.com"
Save it to ~/.ssh/id_ed25519 and set a strong passphrase. Then copy the public key to your server:
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@your-server
Once confirmed working, you can remove any old RSA public keys from ~/.ssh/authorized_keys on the server. Our guide on RSA vs Ed25519 covers the cryptographic differences in more detail.
4. Install Fail2Ban
Even with password authentication disabled, bots still knock on your door. Fail2Ban watches your system logs and automatically adds temporary firewall rules to ban IP addresses that repeatedly fail to connect.
On Ubuntu or Debian:
sudo apt install fail2ban -y
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
On CentOS/RHEL:
sudo yum install fail2ban -y
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
The default configuration bans an IP for 10 minutes after 5 failed login attempts. You can tighten this in /etc/fail2ban/jail.local. A common configuration for SSH:
[sshd]
enabled = true
port = 22
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
findtime = 600
This bans an IP for 1 hour after 3 failed attempts within any 10-minute window. Restart Fail2Ban after editing the config:
sudo systemctl restart fail2ban
To see currently banned IPs:
sudo fail2ban-client status sshd
5. Block root logins
Logging in directly as the root user is a bad habit even on well-secured servers. The root account is the universal target for brute-force attacks because every Linux system has one. By forcing the use of a standard user account with sudo access, you add a layer of human intentionality to privilege escalation.
In /etc/ssh/sshd_config:
PermitRootLogin no
You should also restrict which users are allowed to log in at all using AllowUsers. This means only the listed usernames can authenticate via SSH, regardless of what keys they present:
AllowUsers yourname
Restart SSH to apply:
sudo systemctl restart sshd
Bonus: Rate-limit SSH connections at the firewall level
If you want an extra layer of protection before Fail2Ban even gets involved, you can rate-limit incoming SSH connections directly with iptables. This drops packets from IPs that are connecting too frequently:
sudo iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set
sudo iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 -j DROP
This limits new SSH connections to 3 per minute per IP. Any IP hitting the port faster than that gets silently dropped.
These five steps cover the fundamentals. Servers hardened this way — key-only authentication, non-standard port, Fail2Ban, no root login — eliminate the overwhelming majority of automated attack surface.
If you need to access your hardened server from a browser or a device where you cannot manage SSH config files, SSHDock supports key-based authentication, custom ports, and jump hosts directly from the connection UI.