SSH Hardening and Key Management: The Complete Security Guide

Secure your SSH infrastructure with modern hardening techniques. Covers key types, agent forwarding, certificate-based auth, jump hosts, and automated key...

Y
Yash Pritwani
14 min read

SSH Is Your Front Door

SSH is the most common entry point into servers. A poorly configured SSH setup is an open invitation for attackers. Credential stuffing, brute force, and stolen keys account for over 60% of server compromises. Let us fix that.

FirewallWAFSSO / MFATLS/SSLRBACAudit Logs

Defense in depth: multiple security layers protect your infrastructure from threats.

Key Generation — Use Ed25519

RSA keys are still common, but Ed25519 is superior in every way:

# Generate an Ed25519 key (recommended)
ssh-keygen -t ed25519 -C "[email protected]" -f ~/.ssh/id_ed25519_prod

# If you need RSA compatibility (legacy systems), use 4096 bits minimum
ssh-keygen -t rsa -b 4096 -C "[email protected]" -f ~/.ssh/id_rsa_legacy

Why Ed25519:

  • Faster: Key generation, signing, and verification are all faster
  • Smaller keys: 256-bit vs 3072-4096-bit RSA
  • No weak key risk: RSA keys can be generated poorly; Ed25519 cannot
  • Constant-time: Resistant to side-channel attacks

SSH Server Hardening

Edit /etc/ssh/sshd_config with these security settings:

# /etc/ssh/sshd_config — Hardened Configuration

# Disable password authentication entirely
PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM yes
PubkeyAuthentication yes

# Disable root login (use sudo instead)
PermitRootLogin no

# Restrict to specific users/groups
AllowGroups ssh-users

# Use only protocol 2
Protocol 2

# Strong key exchange algorithms
KexAlgorithms [email protected],curve25519-sha256,[email protected]
Ciphers [email protected],[email protected],[email protected]
MACs [email protected],[email protected]

# Disable unused features
X11Forwarding no
AllowTcpForwarding no
AllowAgentForwarding no
PermitTunnel no

# Rate limiting
MaxAuthTries 3
MaxSessions 5
LoginGraceTime 30

# Idle timeout (disconnect after 10 min idle)
ClientAliveInterval 300
ClientAliveCountMax 2

# Logging
LogLevel VERBOSE
SyslogFacility AUTH

Get more insights on Security

Join 2,000+ engineers who get our weekly deep-dives. No spam, unsubscribe anytime.

After editing, validate and restart:

# Validate config before restarting (prevents lockout!)
sshd -t

# Restart SSH
sudo systemctl restart sshd

SSH Config for Clients

Organize your connections with ~/.ssh/config:

# ~/.ssh/config

# Default settings for all hosts
Host *
    ServerAliveInterval 60
    ServerAliveCountMax 3
    AddKeysToAgent yes
    IdentitiesOnly yes

# Production server via jump host
Host prod
    HostName 10.0.1.50
    User deploy
    IdentityFile ~/.ssh/id_ed25519_prod
    ProxyJump jump.example.com

# Jump/Bastion host
Host jump.example.com
    User jumpuser
    IdentityFile ~/.ssh/id_ed25519_jump
    ForwardAgent no

# Development server
Host dev
    HostName dev.example.com
    User developer
    IdentityFile ~/.ssh/id_ed25519_dev
    LocalForward 5432 localhost:5432
    LocalForward 6379 localhost:6379

SSH Certificate Authority

For teams larger than 3 people, SSH certificates are far superior to distributing public keys:

# Create a CA key pair (do this once, guard the private key)
ssh-keygen -t ed25519 -f /etc/ssh/ca_key -C "SSH CA"

# Sign a user's public key (valid 8 hours, for user "deploy")
ssh-keygen -s /etc/ssh/ca_key \
  -I "deploy@company" \
  -n deploy \
  -V +8h \
  ~/.ssh/id_ed25519.pub

# Sign a host key (valid 1 year)
ssh-keygen -s /etc/ssh/ca_key \
  -I "web1.example.com" \
  -h \
  -n web1.example.com \
  -V +52w \
  /etc/ssh/ssh_host_ed25519_key.pub

Configure the server to trust the CA:

# /etc/ssh/sshd_config
TrustedUserCAKeys /etc/ssh/ca_key.pub

Configure clients to trust host certificates:

# ~/.ssh/known_hosts
@cert-authority *.example.com ssh-ed25519 AAAA...

Now you never need to manage authorized_keys files or deal with host key verification warnings again.

Hello WorldPlaintextEncryptAES-256🔑x8f2...k9zCiphertextDecryptAES-256🔑Symmetric Encryption: same key encrypts and decrypts

Encryption transforms readable plaintext into unreadable ciphertext, reversible only with the correct key.

Fail2Ban Configuration

# /etc/fail2ban/jail.d/sshd.conf
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
findtime = 600
ignoreip = 192.168.1.0/24

Automated Key Rotation

Create a script to rotate SSH keys quarterly:

#!/bin/bash
# rotate-ssh-keys.sh
KEY_DIR="\$HOME/.ssh"
OLD_KEY="\$KEY_DIR/id_ed25519_prod"
NEW_KEY="\$KEY_DIR/id_ed25519_prod_new"
SERVERS="web1 web2 db1"

# Generate new key
ssh-keygen -t ed25519 -f "\$NEW_KEY" -N "" -C "deploy@company-\$(date +%Y%m)"

# Deploy new key to all servers
for server in \$SERVERS; do
    ssh-copy-id -i "\$NEW_KEY.pub" "\$server"
    echo "Deployed to \$server"
done

# Test new key works
for server in \$SERVERS; do
    ssh -i "\$NEW_KEY" "\$server" "echo 'New key works'" || {
        echo "FAILED on \$server — aborting rotation"
        exit 1
    }
done

# Remove old key from servers
for server in \$SERVERS; do
    OLD_PUB=\$(cat "\$OLD_KEY.pub")
    ssh -i "\$NEW_KEY" "\$server" "sed -i '\\|\$OLD_PUB|d' ~/.ssh/authorized_keys"
done

# Replace old key locally
mv "\$OLD_KEY" "\$OLD_KEY.bak.\$(date +%Y%m%d)"
mv "\$OLD_KEY.pub" "\$OLD_KEY.pub.bak.\$(date +%Y%m%d)"
mv "\$NEW_KEY" "\$OLD_KEY"
mv "\$NEW_KEY.pub" "\$OLD_KEY.pub"

echo "Key rotation complete"

Port Knocking (Defense in Depth)

Add port knocking as an additional layer:

Free Resource

Infrastructure Security Audit Template

The exact audit template we use with clients: 60+ checks across network, identity, secrets management, and compliance.

Get the Template
# Install knockd
sudo apt install knockd

# /etc/knockd.conf
[options]
    UseSyslog

[openSSH]
    sequence    = 7000,8000,9000
    seq_timeout = 5
    command     = ufw allow from %IP% to any port 22
    tcpflags    = syn

[closeSSH]
    sequence    = 9000,8000,7000
    seq_timeout = 5
    command     = ufw delete allow from %IP% to any port 22
    tcpflags    = syn

Audit Logging

Track who logged in, when, and what they did:

# Enable session recording with script command
# Add to /etc/profile
if [ -n "\$SSH_CONNECTION" ]; then
    LOGDIR="/var/log/ssh-sessions"
    mkdir -p "\$LOGDIR"
    LOGFILE="\$LOGDIR/\$(whoami)_\$(date +%Y%m%d_%H%M%S)_\$\$.log"
    script -qf "\$LOGFILE"
fi
UserIdentityVerifyPolicyEngineAccessProxyAppMFA + DeviceLeast PrivilegeEncrypted TunnelNever Trust, Always Verify

Zero Trust architecture: every request is verified through identity, policy, and access proxy layers.

Security Checklist

  • Disable password authentication
  • Use Ed25519 keys exclusively
  • Set PermitRootLogin to no
  • Configure AllowGroups
  • Install Fail2Ban with strict limits
  • Enable verbose logging
  • Use SSH certificates for teams
  • Rotate keys quarterly
  • Use jump hosts for internal servers
  • Monitor auth logs with alerting

At TechSaaS, we follow all of these practices. Our servers are accessible only via Ed25519 keys through a jump host, with CrowdSec providing real-time intrusion prevention. Security is not a feature — it is the foundation.

Need an SSH security audit? Reach out at [email protected].

#ssh#security#hardening#key-management#linux

Related Service

Security & Compliance

Zero-trust architecture, compliance automation, and incident response planning.

Need help with security?

TechSaaS provides expert consulting and managed services for cloud infrastructure, DevOps, and AI/ML operations.

We Will Build You a Demo Site — For Free

Like it? Pay us. Do not like it? Walk away, zero complaints. You will spend way less than hiring developers or any agency.

47+ companies trusted us
99.99% uptime
< 48hr response

No spam. No contracts. Just a free demo.