Skip to content

Harden SSH access on Linux

Move SSH to key-only authentication, disable root login, and lock down sshd with a battle-tested configuration.

Published on Updated on 2 min read

SSH is the primary remote entry point to almost every Linux server, which makes it the first thing an attacker probes and the first thing you should harden. Internet-facing hosts see thousands of automated login attempts a day, and every one of them is testing the same weak spots: password logins, the root account, and stale crypto. The goal of this guide is a server that accepts only cryptographic keys, never lets root log in directly, and exposes the smallest possible attack surface. Work through it top to bottom and keep a second session open until you have verified each change.

Use key-based authentication only

Passwords are guessable and replayable; keys are not. Generate a modern key on your workstation:

ssh-keygen -t ed25519 -a 100 -C "you@workstation"

Copy the public key to the server, then verify you can log in with it before turning passwords off:

ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server
ssh user@server   # confirm this works without a password prompt

Lock down sshd_config

Edit /etc/ssh/sshd_config (or better, a drop-in under /etc/ssh/sshd_config.d/) with the following hardened settings:

PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
PermitEmptyPasswords no
MaxAuthTries 3
LoginGraceTime 20
X11Forwarding no
AllowAgentForwarding no
ClientAliveInterval 300
ClientAliveCountMax 2

Restrict who may connect at all with an explicit allowlist — this alone blocks every service and system account:

AllowUsers deploy admin

Validate the configuration before reloading, so a typo never locks you out:

sudo sshd -t && sudo systemctl reload ssh

Constrain the key exchange

Disable legacy ciphers and MACs so a downgrade attack can't force weak crypto. On modern OpenSSH the defaults are already strong, but pinning them documents intent:

KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com

Rate-limit and firewall

Hardened auth still leaves you exposed to brute-force noise and zero-days. Put SSH behind a firewall allowlist where possible, and add fail2ban to ban hosts that fail repeatedly. See the Network & Firewall and Intrusion Detection domains for the full setup.

Verify your work

After reloading, open a new terminal (keep your current session alive as a fallback) and confirm:

ssh -v user@server 2>&1 | grep -i "Authenticated"
sudo grep "sshd" /var/log/auth.log | tail

You should see the key accepted, no password prompt offered, and root logins refused. With key-only auth, an allowlist, and a firewall in front, SSH stops being the easy way in.