How to Harden SSH on Linux: 10 Key Settings to Secure Your Server
How to Harden SSH on Linux: 10 Key Settings to Secure Your Server
After twenty years of managing Linux servers — from bare-metal racks in a co-location facility to fleets of cloud instances spun up and torn down in minutes — I can tell you one thing with certainty: SSH is the single most attacked service on the public internet. The moment you bring a Linux box online with port 22 open, automated bots start knocking within minutes. If you want to harden SSH properly, you can't rely on the default configuration that ships with your distribution. You need to actively lock it down.
This guide walks through the 10 settings I configure on every server I touch, whether it's a single VPS or part of a 500-node fleet. These aren't theoretical best practices pulled from a compliance checklist — they're the exact changes that stop the vast majority of real-world SSH attacks, based on two decades of incident response, log review, and painful lessons learned the hard way.
Why You Need to Secure Your SSH Server
Every internet-facing Linux server needs a secure SSH server configuration because SSH is almost always the front door to root access. A compromised SSH session doesn't just give an attacker a shell — it gives them a foothold to pivot across your network, exfiltrate data, deploy ransomware, or turn your server into part of a botnet. The default OpenSSH configuration is built for compatibility, not security. Hardening it closes off the easiest, laziest attack paths that credential-stuffing bots and script kiddies rely on every single day.
Let's get into the settings. Unless noted otherwise, all changes below go into /etc/ssh/sshd_config, and you'll need to restart the SSH service after editing:
sudo systemctl restart sshd
Important: Always keep a second terminal session open while testing SSH changes. If you lock yourself out with a bad configuration, that second session is your lifeline to fix it before it disconnects.
1. Disable Root Login Over SSH
The single highest-impact change you can make is to disable root login. Every brute-force bot on the internet tries "root" as the username first, because it's the one account guaranteed to exist on every Linux system with maximum privileges. Remove that target entirely.
PermitRootLogin no
Create a standard user account with sudo privileges instead, and log in as that user. If you genuinely need root-level access, use sudo or su after connecting — never authenticate directly as root over the network.
2. Enforce SSH Key-Only Authentication
Password authentication is inherently weaker than public-key authentication. Passwords can be guessed, phished, or leaked in a data breach. Switching to SSH key only authentication eliminates password brute-forcing as an attack vector completely, since there's no password to guess in the first place.
PasswordAuthentication no
PubkeyAuthentication yes
ChallengeResponseAuthentication no
Before you flip this switch, make sure your public key is already installed on the server:
ssh-copy-id user@your-server-ip
Test logging in with your key in a fresh terminal before restarting SSH with password authentication disabled. Generate strong keys with Ed25519 rather than older RSA keys where possible:
ssh-keygen -t ed25519 -C "your_email@example.com"
3. Change the Default SSH Port
This one gets debated a lot — some engineers call it "security through obscurity" and dismiss it. In practice, I've watched log files drop from thousands of automated login attempts per day to nearly zero after a simple port change. It doesn't replace real security controls, but it dramatically reduces noise, log clutter, and the surface area exposed to dumb, automated scanning.
Port 2222
Pick any unused port above 1024 (avoiding well-known service ports), update your firewall rules to match, and make sure any monitoring tools or client configs reflect the new port. This is a supplementary layer, not a substitute for the other steps here.
4. Restrict SSH Access to Specific Users or Groups
Even with strong authentication, you should explicitly whitelist who is allowed to connect at all. This limits the blast radius if an account is ever compromised and stops SSH from being usable by service accounts that have no business logging in interactively.
AllowUsers alice bob
AllowGroups sshusers
Create a dedicated group for SSH access and add only the accounts that genuinely need remote shell access to that group.
5. Limit Authentication Attempts and Login Grace Time
Reduce how many times a client can attempt to authenticate before the connection is dropped, and shrink the window they have to do it in:
MaxAuthTries 3
LoginGraceTime 20
This makes automated credential-stuffing tools far less efficient, since each connection attempt is cut short quickly instead of allowing dozens of guesses per session.
6. Disable Empty Passwords and Unused Authentication Methods
It sounds obvious, but I still find servers in the wild with this misconfigured. Explicitly disable empty passwords and any legacy authentication methods you don't use:
PermitEmptyPasswords no
KerberosAuthentication no
GSSAPIAuthentication no
Every authentication method you leave enabled is another potential path in. If you're not using Kerberos or GSSAPI, turn them off.
7. Enforce SSH Protocol 2 and Modern Ciphers
Modern OpenSSH versions default to Protocol 2 only, but it's worth confirming explicitly, and it's worth going further by restricting the ciphers, key exchange algorithms, and MACs to modern, secure options:
Protocol 2
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com
KexAlgorithms curve25519-sha256@libssh.org
MACs hmac-sha2-512-etm@openssh.com
This prevents downgrade attacks that try to force a connection to use weaker, older cryptographic algorithms.
8. Set Idle Timeouts to Kill Dead Sessions
Abandoned sessions — someone forgetting to log out on a shared jump box, or a hung connection over an unreliable network — are a real risk. Configure the server to automatically drop idle connections:
ClientAliveInterval 300
ClientAliveCountMax 2
This checks the client every 300 seconds and disconnects after two failed checks (10 minutes total), closing the window for a stray, unattended session to be hijacked.
9. Install and Configure Fail2ban for SSH
Even with key-only authentication, you'll still see a wall of connection attempts in your logs from bots probing your server. Running Fail2ban for SSH automatically bans IP addresses that show malicious behavior, such as repeated failed login attempts.
sudo apt install fail2ban
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
Edit /etc/fail2ban/jail.local and enable the SSH jail:
[sshd]
enabled = true
port = 2222
maxretry = 3
bantime = 3600
findtime = 600
Restart the service:
sudo systemctl restart fail2ban
Fail2ban turns your SSH logs into an active defense mechanism instead of a passive record you only check after the fact.
10. Restrict SSH Access With a Firewall
Your last line of defense is network-level access control. Even a perfectly hardened SSH daemon shouldn't be reachable from the entire internet if you can avoid it. Use ufw, firewalld, or cloud security groups to limit who can even reach the SSH port:
sudo ufw allow from 203.0.113.10 to any port 2222
sudo ufw enable
If your team connects from a small number of static IPs, or through a VPN or bastion host, restrict SSH access to only those sources. This single step eliminates almost all opportunistic scanning traffic before it ever reaches sshd.
Bonus Hardening Tips
- Enable two-factor authentication with a module like Google Authenticator PAM for an extra layer beyond keys.
- Disable X11 forwarding (
X11Forwarding no) unless you specifically need it. - Use a bastion/jump host so production servers never accept direct SSH connections from the open internet.
- Monitor auth logs regularly with
journalctl -u sshdor a centralized logging pipeline. - Keep OpenSSH updated — vulnerabilities in SSH implementations are rare but severe when they surface.
Putting It All Together
Here's a condensed example of a hardened sshd_config combining the settings above:
Port 2222
Protocol 2
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
PermitEmptyPasswords no
MaxAuthTries 3
LoginGraceTime 20
ClientAliveInterval 300
ClientAliveCountMax 2
AllowGroups sshusers
X11Forwarding no
Apply these changes gradually, test each one in a second session, and layer in Fail2ban and firewall rules on top. No single setting here is a silver bullet — the strength comes from combining all ten into overlapping layers of defense. That's the same principle that's protected every server I've hardened over the last two decades: assume any single control can fail, and make sure the next one catches it.
Frequently Asked Questions
How do I harden SSH on a Linux server?
To harden SSH, disable root login, enforce SSH key-only authentication, change the default port, restrict access by user or firewall rule, and add Fail2ban to automatically block malicious IP addresses. Combining these layers is far more effective than relying on any single change.
Why should I disable root login over SSH?
Disabling root login removes the single most targeted username in automated brute-force attacks. Since root has unrestricted privileges, blocking direct root logins forces attackers to first compromise a standard account and then escalate privileges, adding a meaningful barrier.
Is SSH key-only authentication really more secure than passwords?
Yes. SSH key-only authentication removes passwords from the equation entirely, which eliminates brute-force guessing, credential stuffing, and password reuse risks. A properly generated key pair, especially Ed25519, is effectively immune to guessing attacks.
Does changing the SSH port actually improve security?
Changing the SSH port doesn't stop a targeted attacker, but it dramatically reduces automated scanning traffic and log noise from bots that only probe the default port 22. It should be used alongside other hardening steps, not as a replacement for them.
What does Fail2ban do for SSH security?
Fail2ban monitors SSH authentication logs and automatically bans IP addresses that show patterns of repeated failed login attempts. It turns passive log data into an active defense that blocks brute-force and credential-stuffing attempts in real time.
What is the most important setting to secure an SSH server?
If you can only make one change, switch to SSH key-only authentication and disable password logins. This single step removes the most common and most automated attack vector against SSH servers.