Linux Support Net All articles
Opinion

A Safer Order for SSH Hardening: Verification First, Lockdown Second

Linux Support Net
A Safer Order for SSH Hardening: Verification First, Lockdown Second

Photo: Blake Patterson, CC BY 2.0, via Wikimedia Commons

Every hardening guide on the internet tells you to disable password authentication. Almost none of them tell you what to do when the change is wrong and your only route back into the machine is the SSH connection you just broke. What follows is an ordered sequence, written so that each step is verifiable before the next one lands, and so that a mistake costs you ten minutes rather than a rebuild.

Rule zero: keep a way back in

Three things before you edit anything. First, leave your current session open. The daemon reads its configuration at connection time, so an existing shell keeps working even if the new config is fatal. Second, know how you will reach the console if SSH dies entirely: a hosting provider's web console, IPMI, a serial line, or physical access. If you do not have one, fix that before you fix anything else. Third, back up the config and schedule an automatic revert:

sudo cp /etc/ssh/sshd_config /root/sshd_config.bak
sudo systemd-run --on-active=15min --unit=ssh-revert /bin/sh -c 'cp /root/sshd_config.bak /etc/ssh/sshd_config && systemctl restart ssh'

Cancel the timer with systemctl stop ssh-revert once a fresh login succeeds. This single habit prevents nearly every self-inflicted lockout.

Step 1: Get a key that is worth trusting

Use ed25519 unless you have a specific reason otherwise, and put a passphrase on it:

ssh-keygen -t ed25519 -a 100 -C 'alice@laptop-2026'
ssh-copy-id -i ~/.ssh/id_ed25519.pub alice@server

If you can justify a hardware token, [email protected] keys are the better answer. The private key cannot be copied off the device, and the physical touch requirement makes a stolen laptop meaningfully less useful to an attacker.

Verify the key works while password authentication is still enabled, forcing the key path explicitly:

ssh -o PreferredAuthentications=publickey alice@server

If that fails, stop here. Do not proceed to step three.

Step 2: Put changes in a drop-in, not the main file

Both Debian-family and current Fedora and RHEL systems read /etc/ssh/sshd_config.d/*.conf, included near the top of the main file. Drop-ins survive package upgrades and are far easier to audit later.

One trap deserves emphasis: most sshd keywords are first-match-wins, not last. Because the include line sits at the top of the main file on Debian-family systems, a drop-in named 10-hardening.conf takes precedence over anything later in sshd_config, including a PasswordAuthentication yes that a cloud image may have quietly added. Read the include order rather than assuming it.

Step 3: Turn off what you do not use

# /etc/ssh/sshd_config.d/10-hardening.conf
PermitRootLogin prohibit-password
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitEmptyPasswords no
PubkeyAuthentication yes
X11Forwarding no
AllowAgentForwarding no
MaxAuthTries 3
LoginGraceTime 20
ClientAliveInterval 300
ClientAliveCountMax 2
AllowGroups ssh-users

Validate before reloading, every single time:

sudo sshd -t && sudo systemctl reload ssh

On RHEL and Fedora the unit is sshd rather than ssh. Validation catches typos; a reload rather than a restart leaves your existing session untouched.

The AllowGroups line deserves more attention than it usually gets. It turns SSH access from a per-user decision into an auditable list, and it means a compromised application account cannot log in over SSH at all.

Step 4: Rate limiting is now built in

OpenSSH 9.8 introduced PerSourcePenalties, which throttle and temporarily block addresses that fail authentication repeatedly. On anything current, and by 2026 every mainstream distribution ships OpenSSH 10.x, this covers a large share of what people install fail2ban to achieve:

PerSourcePenalties yes
PerSourcePenaltyExemptList 198.51.100.0/24

Keep fail2ban if you want longer bans, log-driven reporting, or reactions to patterns beyond authentication failures. If you keep it, confirm the jail is actually reading the journal on a systemd host rather than a log file that no longer exists:

sudo fail2ban-client status sshd

Step 5: Nonstandard ports are not security

Moving SSH to port 2222 is the most repeated piece of advice in this field and it is close to worthless. Any scanner worth its bandwidth sweeps all 65535 ports in minutes, and the change buys you noise reduction at the cost of firewall rules, documentation, and muscle memory. It also breaks assumptions in monitoring and backup tooling that you will discover at 2 a.m.

What works instead is restricting reachability. Put the daemon behind a firewall rule that permits only known addresses, or behind WireGuard, or behind a Tailscale tailnet, and let port 22 stay closed to the internet entirely. If you must expose it, ufw limit 22/tcp or firewalld rate limiting are honest measures. Port obscurity is not.

Step 6: Certificates, once you have more than a handful of machines

Copying authorized_keys between hosts does not scale and quietly accumulates keys nobody can attribute to a person. An SSH user CA solves both problems. Sign short-lived certificates from a CA key you keep offline:

ssh-keygen -s ca_user -I alice -n alice,deploy -V +12h alice-key.pub

Every server then needs a single line, TrustedUserCAKeys /etc/ssh/ca_user.pub, and access expires on its own. Host certificates remove the trust-on-first-use prompt as a bonus.

Step 7: If you need a second factor

AuthenticationMethods publickey,keyboard-interactive

with pam_google_authenticator or a Duo PAM module behind it. Order matters here: requiring the key first means an attacker must already hold a valid private key before the one-time-code prompt is even offered.

The part everyone skips

Log the failures, because they tell you whether any of this mattered:

sudo journalctl -u ssh --since '7 days ago' | grep -c 'Failed password'
sudo lastb -n 20

On a hardened host that count should drift toward zero within a week. On a host where it stays high, you now have evidence and a real decision to make about exposure.

Finally, write down what you changed and why. The next person to touch that server, quite possibly you at midnight eighteen months from now, will need to know how to reverse it from the console.

All Articles

Related Articles

Stop Agonizing Over Which Linux Distro to Use—Here's What Actually Shapes Your Experience

Stop Agonizing Over Which Linux Distro to Use—Here's What Actually Shapes Your Experience

One Year Without Windows: An Honest Account of Going All-In on Linux at Home

One Year Without Windows: An Honest Account of Going All-In on Linux at Home

What Is Really Eating Your Laptop Battery on Linux, and How to Stop It

What Is Really Eating Your Laptop Battery on Linux, and How to Stop It