SSH is the most attacked service on the internet. Full stop.
I've watched honeypot logs. The noise is relentless: credential stuffing, key reuse, old protocol versions, default ports screaming "try me." Yet most Linux deployments ship with SSH wide open. Not because sysadmins are careless—because nobody tells them which changes actually matter versus security theater.
This is how to harden SSH on Linux without breaking deployments. Tested on Ubuntu 22.04 LTS and Rocky 9. Your mileage may vary on older distributions.
Disable Password Authentication Entirely
Password auth is the weakest link. Users pick bad passwords. You know this. They reuse them. Attackers know this too.
Switch to SSH keys only. Full stop.
Edit /etc/ssh/sshd_config:
PasswordAuthentication no
PubkeyAuthentication yes
PermitEmptyPasswords no
Restart SSH:
sudo systemctl restart sshd
Gotcha: Test the connection before you log out. Open a second terminal, SSH in, verify you can authenticate with your key. If you lock yourself out, you'll need console access or a reboot.
Disable Root Login
Root login over SSH is a magnet for brute force. Disable it:
PermitRootLogin no
Users can still sudo once they're in. This forces attackers to guess both a username and a password or key—and you've already killed password auth, so they're stuck.
Change the Default Port
Port 22 is the first thing every scanner hits. Moving to a non-standard port (say, 2222) cuts automated attack traffic by ~90%.
Port 2222
Update your firewall:
sudo ufw allow 2222/tcp
sudo ufw delete allow 22/tcp
Not a silver bullet: This stops script-kiddies, not determined attackers. But it's free noise reduction. I always do it.
Restrict Protocol Version
SSH protocol version 1 is dead. Use version 2 only:
Protocol 2
If you're on a modern Linux (anything post-2010), this is already the default. Check:
grep -i protocol /etc/ssh/sshd_config
If it says 1,2 or just 1, you have a problem.
Tighten Cipher and Key Exchange Settings
Weak ciphers are a slow burn—they don't cause immediate breaches, but they're a liability in audits and forensics.
Add these to sshd_config:
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
HostKeyAlgorithms ssh-ed25519
These choices prioritize speed and security. Ed25519 keys are faster and stronger than RSA-2048. If you have older clients that can't speak these algorithms, they won't connect—so test first.
Limit Authentication Attempts
Brute force is loud but effective. Slow it down:
MaxAuthTries 3
MaxSessions 5
Three failed attempts and the connection closes. This makes dictionary attacks impractical.
Disable Unused Features
SSH has features you probably don't use. Turn them off:
X11Forwarding no
AllowAgentForwarding no
AllowTcpForwarding no
PermitTunnel no
GatewayPorts no
If you need X11 forwarding for a specific user, enable it per-user in a Match block instead of globally.
Use AllowUsers or AllowGroups
Whitelist who can SSH in. Don't blacklist—that's a losing game.
Create a group:
sudo groupadd ssh-users
sudo usermod -a -G ssh-users alice
sudo usermod -a -G ssh-users bob
Then in sshd_config:
AllowGroups ssh-users
Now only members of ssh-users can authenticate. New user? Add them to the group. No more scattered DenyUsers rules.
Enable Login Grace Time and Timeout
Drop idle connections and enforce timeouts:
LoginGraceTime 30
ClientAliveInterval 300
ClientAliveCountMax 2
This closes the connection if the client doesn't complete authentication within 30 seconds, and terminates idle sessions after 10 minutes (300 seconds × 2 checks).
Set Up Logging and Monitoring
Hardening without visibility is half-baked. Enable verbose logging:
SyslogFacility AUTH
LogLevel VERBOSE
Check /var/log/auth.log (Debian/Ubuntu) or /var/log/secure (RHEL/Rocky) for failed attempts:
sudo tail -f /var/log/auth.log | grep sshd
Watch for patterns. A single IP making 50 failed attempts in an hour is noise. Fifty IPs each making one attempt is reconnaissance.
The Checklist
Before you restart SSH:
- Edit
/etc/ssh/sshd_config - Add or modify:
PasswordAuthentication no,PermitRootLogin no,Port 2222 - Add ciphers, key exchange, and MAC settings
- Set
MaxAuthTries 3,MaxSessions 5 - Disable unused features (X11, forwarding, tunnels)
- Create
ssh-usersgroup and add users - Set
LoginGraceTime 30,ClientAliveInterval 300,ClientAliveCountMax 2 - Enable
LogLevel VERBOSE - Validate syntax:
sudo sshd -t - Open a second terminal and test SSH with key auth
- Confirm you can
sudoif needed - Only then:
sudo systemctl restart sshd - Tail the logs and watch for errors
Validate Your Changes
Before restart, check syntax:
sudo sshd -t
If it says nothing, you're good. If it complains, fix the typo and try again.
After restart, verify the service is running:
sudo systemctl status sshd
Then test from a client:
ssh -v -p 2222 alice@your-server
The -v flag shows you exactly what's happening. You should see your key being offered and accepted.
One More Thing: Key Rotation
Hardening SSH is not a one-time job. Rotate your host keys every 12 months. Rotate user keys when people leave. Check /etc/ssh/ssh_host_* for modification dates:
ls -la /etc/ssh/ssh_host_*
If they're older than a year, regenerate them:
sudo ssh-keygen -A
sudo systemctl restart sshd
What to Do Tomorrow
Pull up sshd_config on your production servers. If you see PasswordAuthentication yes, PermitRootLogin yes, or default port 22, you're exposed. Start with password auth and root login—those two changes alone cut your attack surface by 80%.
Test in a staging environment first. SSH hardening is one of the few security changes where a mistake locks you out immediately, so practice the checklist. If your server is also running sluggishly under load, it may be worth reviewing how to speed up a slow Windows 11 PC if any of your management machines are on Windows—a laggy workstation makes remote administration harder than it needs to be.
Once you've hardened SSH on one server, automate it. Ansible, Puppet, or even a shell script—make it repeatable so the next server gets the same treatment without thinking. For teams deciding on a broader infrastructure stack, the comparison on storehabit.com is a reminder that platform choices upstream can affect what you're ultimately responsible for securing.
SSH is your front door. Make it count.