SSH Is the Front Door of Every Server: A 20-Minute Hardening Audit
Every Linux server you've ever rented has the same front door: port 22, sshd, and a configuration that shipped with defaults optimized for getting you in the first time, not for keeping everyone else out. The good news is that hardening SSH is not a project. It's a checklist, and you can run it in about twenty minutes. Here's the order that actually matters.
Step 1: Keys only, no exceptions
Open /etc/ssh/sshd_config and set three lines:
PasswordAuthentication no
ChallengeResponseAuthentication no
PermitRootLogin prohibit-password
Passwords over SSH are not a convenience — they're an attack surface that never sleeps. Every brute-force botnet on the internet is hammering passwords right now, this second. Keys don't get guessed. Generate ed25519 keys (ssh-keygen -t ed25519), put the public half in ~/.ssh/authorized_keys, verify you can log in from a second session, and only then disable passwords. That "second session" rule is the difference between a hardening exercise and a lockout story you tell at meetups.
PermitRootLogin prohibit-password is the sane middle ground: root can log in, but only with a key. Full no is fine too, but don't strand yourself on a machine where you need root access before your sudo user works.
Step 2: Prune the authorized_keys you forgot about
This is the step everyone skips. Run:
find /home /root -name authorized_keys -exec echo "== {} ==" \; -exec cat {} \;
Look at every key. Ask three questions: whose is this, do they still need access, and when was it added? Stale keys from a contractor three jobs ago, a developer who left last year, a deploy key for a project you shut down — these are the real-world breach path, not zero-days. Rotate what stays, delete what doesn't. If you can't attribute a key, treat it as hostile.
Step 3: Trim the protocol surface
Defaults support old clients you don't have. Tighten the cryptography:
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group16-sha512
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes256-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
And add idle-session hygiene:
ClientAliveInterval 300
ClientAliveCountMax 2
This won't break any modern client — OpenSSH has supported all of these for years. If you still have a client from 2015 in your fleet, that's a different conversation.
Step 4: Add fail2ban (or rate-limit at the firewall)
Key-only auth stops password guessing from succeeding. It does not stop it from happening, and the log noise is real. fail2ban with the sshd jail is the standard answer: a few failed attempts, a temporary ban. Ten minutes to install, and it doubles as an early-warning system — when fail2ban starts banning aggressively, something is probing you specifically.
Don't have fail2ban? At minimum, rate-limit new connections at the firewall: iptables/nftables with a --limit rule, or your cloud provider's security group throttling. One layer is mandatory; two is better.
Step 5: The port question (and what it actually buys you)
Changing the port from 22 to something else doesn't make you secure. It makes your logs quieter, which makes real anomalies visible. That's genuinely useful — just don't pretend it's a security control. If you change it, do it after key-only auth is proven working, update your firewall rules first, and document it where future-you will find it. The number of admins who locked themselves out via a port change is a silent epidemic.
Verify, don't trust
After systemctl reload sshd, test everything from a fresh connection: key login works, password login fails, root password login fails, your automation accounts (deploy keys, backup jobs) still work. Run sshd -T to see the effective configuration — comments and includes make the raw config file lie to you.
SSH hardening isn't about paranoia. It's about acknowledging that your front door gets rattled thousands of times a day, and making sure there's nothing on the other side but a lock that can't be picked.
Sources
- OpenBSD sshd_config manual: https://man.openbsd.org/sshd_config
- fail2ban project: https://www.fail2ban.org
Reader feedback
Was this article helpful?
0 people found this article helpful.
