Skip to content
intermediate Phase 4 · Linux and Windows Security Administration

SSH Hardening

Restrict remote shells with key auth, disabled root, and rate limits.

50m
0 problems
Topic Progress 0%

SSH Hardening: Core Concepts

SSH Hardening: Core Concepts

Every SSH server exposed to a network is a target. Within minutes of going live, automated scanners find it and begin brute-forcing passwords. SSH hardening is the process of reducing that attack surface by eliminating weak authentication, restricting who can connect, and limiting what they can do once connected.

The Attack Surface

A default OpenSSH installation accepts password authentication for all users, allows root login, and listens on port 22. Each of these defaults is a liability:

  • Password authentication is vulnerable to brute-force and credential-stuffing attacks. Even strong passwords can be guessed given enough attempts.
  • Root login gives an attacker full system access the moment they guess one credential.
  • Port 22 is the first port every scanner probes. While changing it is not real security (security through obscurity), it reduces log noise from automated scans.

Key-Based Authentication

The single most impactful hardening step is replacing password authentication with SSH keys. An ed25519 key pair consists of a private key that stays on your machine and a public key that lives in ~/.ssh/authorized_keys on the server. The server challenges the client to prove possession of the private key without ever transmitting it.

# Generate an ed25519 key pair
ssh-keygen -t ed25519 -C "your_email@example.com"

# Copy the public key to the server
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server

# Test the connection
ssh -i ~/.ssh/id_ed25519 user@server

Ed25519 keys are preferred over RSA for several reasons: they are shorter (256-bit security in a 64-byte public key), faster to generate and verify, and resistant to certain side-channel attacks that affect RSA implementations.

Disabling Root Login

When PermitRootLogin is set to no, an attacker who compromises a user's credentials still cannot directly become root. They must also exploit a local privilege escalation vulnerability. This two-step requirement dramatically increases the difficulty of a full compromise.

# /etc/ssh/sshd_config
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes

After changing sshd_config, always validate the configuration before restarting:

sshd -t          # Test configuration syntax
systemctl restart sshd

Rate Limiting and Brute-Force Protection

Even with key-only authentication, attackers will still attempt connections. Two mechanisms limit the damage:

MaxStartups in sshd_config limits concurrent unauthenticated connections:

MaxStartups 10:30:60

This allows 10 unauthenticated connections, with a 30% chance of rejection above that, scaling linearly to 100% rejection at 60.

Fail2ban watches authentication logs and bans IPs that exceed a threshold:

# /etc/fail2ban/jail.local
[sshd]
enabled = true
maxretry = 3
bantime = 3600

With maxretry = 3, an IP is banned for one hour after three failed authentication attempts. This turns a brute-force attack from millions of attempts per day into a handful before the attacker is locked out.

Where It Fits

SSH hardening is one component of a layered defense. It works alongside firewall rules (nftables) that restrict which IPs can reach port 22, and audit logging (auditd) that records who connected and what they did. Study CIS Benchmarks first for a systematic hardening checklist, then move to nftables to control network access at the packet level.

SSH Hardening: Practice

SSH Hardening: Practice

Reading about SSH hardening does not stick until you have locked yourself out of a server at least once. The exercises below are designed to build muscle memory for the configuration changes that matter.

Exercise 1: Generate and Deploy Keys

On your local machine, generate an ed25519 key pair and deploy it to a test server:

# Generate the key pair
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -C "admin@company"

# Set proper permissions (SSH will refuse keys with loose permissions)
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub

# Deploy the public key
ssh-copy-id -i ~/.ssh/id_ed_ed25519.pub admin@192.168.1.100

# Verify key-based login works
ssh -i ~/.ssh/id_ed25519 admin@192.168.1.100

Once key-based login is confirmed, disable password authentication:

# On the server, edit /etc/ssh/sshd_config
PasswordAuthentication no

# Validate and restart
sshd -t && systemctl restart sshd

Try connecting with a password — it should be rejected. This is the moment you confirm your key works before the door closes.

Exercise 2: Restrict Root and Configure a Non-Standard Port

# /etc/ssh/sshd_config
PermitRootLogin no
Port 2222
AllowUsers admin deploy
Protocol 2

AllowUsers restricts SSH access to only the listed accounts. Combined with PermitRootLogin no, an attacker needs to compromise a specific named account rather than trying common usernames.

After changing the port, update your local SSH config to avoid retyping it:

# ~/.ssh/config
Host webserver
    HostName 192.168.1.100
    Port 2222
    User admin
    IdentityFile ~/.ssh/id_ed25519

Now ssh webserver connects with all the right parameters.

Exercise 3: Set Up Fail2ban

# Install fail2ban
apt install fail2ban    # Debian/Ubuntu
yum install fail2ban    # RHEL/CentOS

# Create a local configuration
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

# Edit jail.local
cat > /etc/fail2ban/jail.local << 'EOF'
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 3

[sshd]
enabled = true
port = 2222
EOF

# Start and enable
systemctl enable --now fail2ban

# Check status
fail2ban-client status sshd

Test it by attempting three wrong passwords from another machine. After the third failure, fail2ban-client status sshd should show your IP in the banned list.

Check Your Understanding

  • Why is sshd -t critical before restarting sshd after a configuration change?
  • What happens if you disable password authentication before confirming your key works?
  • How does MaxStartups differ from Fail2ban in the type of attack it mitigates?

SSH Hardening: Trade-offs and Interviews

SSH Hardening: Trade-offs and Interviews

SSH hardening involves real trade-offs. Understanding when to apply each control — and when a control creates more problems than it solves — is what separates a security engineer from someone who follows a checklist blindly.

The Lockout Problem

The most common operational risk of SSH hardening is locking yourself out. Disabling password authentication before confirming key-based login works, or setting AllowUsers without including your own account, can leave you with no remote access path.

Mitigation strategies:

  • Keep a backup session open while testing configuration changes. Only close it after confirming the new configuration works.
  • Use a console or out-of-band access path (IPMI, iLO, cloud instance console) as a fallback.
  • Test with sshd -t and use sshd -d (debug mode) on a secondary port to verify behavior before applying to the production port.

When Key Management Beats Hardening

In large environments, managing individual authorized_keys files across hundreds of servers does not scale. Centralized key management solutions (HashiCorp Vault, Teleport, or certificate-based SSH with short-lived certificates) replace static keys with dynamically issued credentials. This is a trade-off: more infrastructure to operate, but no key distribution problem and automatic revocation.

When SSH Hardening Is the Wrong Tool

SSH hardening controls access to the SSH protocol itself. It does not protect against:

  • Application-layer attacks against services running on the server
  • Lateral movement after an attacker compromises a different entry point
  • Insider threats from authorized users with legitimate access

For these, you need network segmentation, intrusion detection, and audit logging — not just SSH configuration changes.

How This Comes Up in Interviews

Interviewers probe whether you understand the reasoning behind each control, not just the configuration lines. Strong answers include:

  • "Walk me through hardening a new Linux server." Start with key deployment, then disable passwords, restrict root, configure Fail2ban, and finally restrict the firewall to known IPs. Explain why each step matters.
  • "A developer says disabling password authentication slows them down. How do you respond?" Acknowledge the friction, then explain that the security gain (eliminating brute-force attacks) outweighs the convenience cost, especially when combined with SSH config files and agent forwarding to minimize the friction.
  • "How do you handle SSH access in a 500-server environment?" Move beyond per-server configuration to centralized management: configuration management tools (Ansible, Puppet), certificate-based SSH, or bastion hosts that provide a single audited entry point.

Practice Problems

0 / 2 solved

Solution
Edit /etc/ssh/sshd_config with the following lines:

```
Port 2222
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
AllowUsers admin deploy
```

Then validate and restart:
```bash
sshd -t && systemctl restart sshd
```

Finally, update your local ~/.ssh/config:
```
Host webserver
    HostName <server-ip>
    Port 2222
    User admin
    IdentityFile ~/.ssh/id_ed25519
```

Solution
After the 3rd failed attempt, Fail2ban bans 10.0.0.5 for 3600 seconds (1 hour). The 4th and 5th attempts are rejected by the firewall before reaching sshd. After 1 hour, the ban is automatically lifted and the IP can attempt authentication again.

Quiz

1. Why is ed25519 preferred over RSA for SSH keys?

Question 1 options

2. What is the primary security benefit of setting PermitRootLogin to 'no'?

Question 2 options

3. What does 'MaxStartups 10:30:60' in sshd_config accomplish?

Question 3 options

4. Before restarting sshd after a configuration change, what command should you run and why?

Question 4 options

Flashcards

Question

What does PermitRootLogin no accomplish?

Answer

Prevents direct root login over SSH, forcing attackers to compromise a normal account first before attempting privilege escalation.

Question

Why use ed25519 over RSA for SSH keys?

Answer

Ed25519 provides equivalent security with shorter keys, faster generation and verification, and resistance to side-channel attacks.

Question

What does MaxStartups 10:30:60 mean?

Answer

Allows 10 concurrent unauthenticated connections, with 30% rejection probability above that, scaling to 100% rejection at 60.

Question

What is the purpose of sshd -t?

Answer

Validates sshd_config syntax without restarting the service, preventing lockout from configuration errors.

Question

What does Fail2ban do with maxretry=3?

Answer

Bans an IP address for the configured bantime after 3 failed authentication attempts within the findtime window.

Revision Notes

Key Takeaways

  • 1. Key-based authentication with ed25519 keys eliminates brute-force password attacks.
  • 2. Disabling root login forces a two-step compromise: user account first, then privilege escalation.
  • 3. sshd -t validates configuration before restart, preventing accidental lockout.
  • 4. Fail2ban bans IPs after repeated failed attempts, turning brute-force into a non-viable attack.
  • 5. MaxStartups limits concurrent unauthenticated connections to prevent connection exhaustion.

Interview Tips

  • • Explain the reasoning behind each hardening control, not just the config lines.
  • • Discuss the lockout risk and how to mitigate it (backup session, console access, sshd -t).
  • • For large environments, discuss centralized key management or certificate-based SSH.
  • • Connect SSH hardening to the broader defense-in-depth strategy: firewalls, audit logging, and network segmentation.

Cheat Sheet

SSH Hardening Cheat Sheet

Phase: Linux and Windows Security Administration | Level: intermediate

Key Configuration (/etc/ssh/sshd_config):

  • PermitRootLogin no — Block direct root SSH access
  • PasswordAuthentication no — Force key-based auth only
  • PubkeyAuthentication yes — Enable public key authentication
  • AllowUsers admin deploy — Restrict which accounts can SSH
  • Port 2222 — Non-standard port (reduces scan noise)
  • MaxStartups 10:30:60 — Rate-limit unauthenticated connections

Key Management:

  • ssh-keygen -t ed25519 — Generate ed25519 key pair
  • ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server — Deploy public key
  • chmod 600 ~/.ssh/id_ed25519 — Private key must be owner-only

Fail2ban:

  • maxretry = 3 — Ban after 3 failures
  • bantime = 3600 — 1-hour ban duration
  • fail2ban-client status sshd — Check banned IPs

Tags: linux, remote-access

Continue Learning