Skip to main content

SSH Hardening: Secure Server Configuration Against Break-ins

Security · 19.04.2026 · 6 min read
Illustration for “SSH Hardening: Secure Server Configuration Against Break-ins”

SSH is the primary way to administer Linux servers and the main target of automated attacks. Proper hardening reduces the risk of a break-in by 95%.

Basic /etc/ssh/sshd_config configuration

Port 2222
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
MaxSessions 5
ClientAliveInterval 300
ClientAliveCountMax 2
X11Forwarding no
AllowTcpForwarding no
AllowUsers deploy admin
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group14-sha256
Ciphers aes256-gcm@openssh.com,chacha20-poly1305@openssh.com
sshd -t && systemctl reload sshd
Don't close your current session! After changing the port, open a new connection in another tab. Make sure the login works — only then close the old session.

Generating and configuring SSH keys

ssh-keygen -t ed25519 -C "server-key-2026" -f ~/.ssh/myserver_ed25519
ssh-copy-id -i ~/.ssh/myserver_ed25519.pub -p 22 user@server

Two-factor authentication (TOTP)

apt install libpam-google-authenticator -y
google-authenticator

Add to /etc/pam.d/sshd: auth required pam_google_authenticator.so

In sshd_config: ChallengeResponseAuthentication yes and AuthenticationMethods publickey,keyboard-interactive

SSH hardening checklist

SettingValuePriority
Non-standard port2222 or anotherMedium
PermitRootLogin noMandatoryHigh
PasswordAuthentication noAfter setting up keysHigh
AllowUsersOnly needed usersHigh
MaxAuthTries 3Limit attemptsMedium
fail2banBlocking attacker IPsHigh
2FA (TOTP)Additional factorMedium

Monitoring login attempts

journalctl -u ssh --since "1 hour ago" | grep "Failed"
grep "Failed password" /var/log/auth.log | awk '{print $11}' | sort | uniq -c | sort -rn | head -20
fail2ban-client status sshd
Maximum protection: Don't expose SSH to the internet at all. Use Cloudflare Access or a WireGuard VPN as a layer in front of it — SSH becomes reachable only through a secured tunnel.

Common Hardening Errors

ErrorCauseFix
sshd: no hostkeys available -- exitingA syntax error in the config, or the host key files are missing after a reinstallCheck the config: sshd -t, and regenerate keys if needed: ssh-keygen -A
Permission denied (publickey)After disabling PasswordAuthentication, the public key wasn't copied or ~/.ssh has wrong permissionsFix the permissions: chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys
Address already in useThe chosen port is already taken by another process or a stale sshd instanceFind the process: ss -tlnp | grep 2222 and stop the conflicting service
Connection refused on the new portThe firewall (ufw/iptables) doesn't allow the new SSH port yetAllow the port: ufw allow 2222/tcp before restarting sshd
WARNING: UNPROTECTED PRIVATE KEY FILE! on the clientThe private key file's permissions on the local machine are too openFix the permissions: chmod 600 ~/.ssh/myserver_ed25519

Comparing SSH Protection Methods

MethodProtects againstImplementation effort
Changing the portAutomated "default port" scanningLow, but won't stop a targeted attack
fail2banBrute-forcing based on failed-attempt logsLow, set up in 5 minutes
2FA (TOTP)A stolen or leaked private keyMedium, requires a phone for every admin
Port knocking / SPAPort reconnaissance by scanners (the port isn't visible at all)High, makes connection troubleshooting harder

When Hardening Won't Save You

  • A 0-day vulnerability in OpenSSH itself — no configuration closes a bug in the daemon's code
  • A compromised admin workstation with the private key stored on disk — the attacker gets in regardless of server settings
  • An insider with legitimate access and their own key — hardening stops outside attacks, not abuse of granted rights
  • A weak sudo password combined with physical or console access to the server (for example through a provider's panel) — SSH is not the only entry point

For brute-force protection, add Fail2ban: Protecting SSH and Nginx from Password Guessing, and a stronger second factor is covered in "Two-Factor Authentication for SSH and Web Panels".

Verifying the Result

After configuring, confirm the settings actually took effect:

# Show the active (applied, not just written) configuration
sshd -T | grep -Ei "permitrootlogin|passwordauthentication|port|maxauthtries"

# Confirm password login is actually rejected
ssh -o PubkeyAuthentication=no -o PasswordAuthentication=yes user@server
# Expected result: "Permission denied (publickey)"

# Check that the old port 22 is closed from the outside
nmap -p 22,2222 server_ip

If SSH needs to be hidden from scanners entirely, the next step is putting it behind a WireGuard VPN on a VPS and opening the port only inside the tunnel.

Frequently asked questions

What should you do if the new configuration is saved but the SSH connection stops working entirely?

If the new configuration blocks connections, first check the syntax with sshd -t and confirm the old port is still open in another terminal tab, since that is why the old session should stay open until the new one works. If access is lost entirely, the provider's console or hypervisor panel is the way to restore the previous values.

Is it safe to reuse the same private key for access to several servers?

Reusing one private key across several servers works technically, but it breaks the principle of isolation: a leak of that single key from the administrator's workstation instantly opens every server at once instead of just one. It is both simpler and safer to generate a separate key pair for each server, or at least for each distinct access role.

Should password login be disabled right away, before two-factor authentication is actually set up?

Password login should only be turned off once key-based login has actually been tested and confirmed working, otherwise any mistake in the key setup risks locking the administrator out before that point. Two-factor authentication makes more sense as an extra layer added on top of a working key-based login, not as a replacement for a temporary password.

How do you regain access to a server if AllowUsers is set incorrectly and login is locked out for everyone?

If AllowUsers has a typo or omits the needed account, SSH login closes for everyone, including the administrator, and the file can no longer be fixed through that same SSH connection. Recovery goes through the hosting provider's console or the hypervisor panel — local access that bypasses the network SSH path, letting you edit the configuration and restart the service.

Was this article helpful?
← Back to Knowledge Base Ask Support