security2024-12-20·12 min·239/348

SSH Key-Based Authentication on Linux: Setup and Hardening

Complete guide to setting up SSH key-based authentication, disabling password auth, and hardening SSH security on Linux servers.

Introduction

SSH password authentication is a security liability. Automated brute-force attacks constantly target SSH servers, and weak passwords can be cracked in minutes. Key-based authentication eliminates this attack vector entirely and provides a more secure, convenient way to access remote servers. This post covers generating SSH keys, configuring servers for key-only authentication, and additional hardening steps.

Environment

The examples use OpenSSH 9.2 on Ubuntu 22.04 LTS (client) and Debian 12 (server). The goal is to configure key-based authentication for a single user while maintaining access for other administrators.

ssh -V
# OpenSSH_9.2p1 Ubuntu-2ubuntu0.5, OpenSSL 3.0.2 15 Mar 2022

Problem

The server is under constant brute-force SSH attacks:

sudo grep "Failed password" /var/log/auth.log | wc -l
# 45231

sudo lastb | head -5
# root     sshu  192.168.1.100    Sun Jan 20 03:00 - 03:00  (00:00)
# admin    sshu  192.168.1.101    Sun Jan 20 03:01 - 03:01  (00:00)

Password authentication is allowing these attacks to succeed if a weak password is found.

Solution

1. Generate an SSH key pair

# Generate an Ed25519 key (recommended)
ssh-keygen -t ed25519 -C "admin@example.com"
# Generating public/private ed25519 key pair.
# Enter file in which to save the key (/home/user/.ssh/id_ed25519):
# Enter passphrase (empty for no passphrase): [Enter a strong passphrase]
# Enter same passphrase again:
# Your identification has been saved in /home/user/.ssh/id_ed25519
# Your public key has been saved in /home/user/.ssh/id_ed25519.pub

For legacy systems that do not support Ed25519:

ssh-keygen -t rsa -b 4096 -C "admin@example.com"

2. Copy the public key to the server

# Method 1: ssh-copy-id (recommended)
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server

# Method 2: Manual
cat ~/.ssh/id_ed25519.pub | ssh user@server "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

3. Verify key-based login works

ssh -i ~/.ssh/id_ed25519 user@server
# Login successful without password prompt

4. Harden SSH server configuration

# /etc/ssh/sshd_config
# Disable password authentication (only after key auth is confirmed working)
PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM yes

# Disable root login
PermitRootLogin no

# Allow only specific users
AllowUsers admin deploy

# Change default SSH port (optional, reduces automated attacks)
Port 2222

# Limit authentication attempts
MaxAuthTries 3

# Set idle timeout
ClientAliveInterval 300
ClientAliveCountMax 2

# Disable empty passwords
PermitEmptyPasswords no

# Use only SSH protocol 2
Protocol 2

# Disable X11 forwarding (unless needed)
X11Forwarding no

5. Restrict key usage

# In ~/.ssh/authorized_keys on the server
# Restrict to specific commands
command="/usr/bin/restricted-command",no-port-forwarding,no-X11-forwarding ssh-ed25519 AAAA... admin@example.com

# Restrict from specific IPs
from="192.168.1.0/24,10.0.0.0/8" ssh-ed25519 AAAA... admin@example.com

6. Use SSH agent for key management

# Start ssh-agent
eval "$(ssh-agent -s)"
# Agent pid 12345

# Add key to agent
ssh-add ~/.ssh/id_ed25519

# List loaded keys
ssh-add -l
# 256 SHA256:xxxxx admin@example.com (ED25519)

# Disable agent forwarding on the server
# In /etc/ssh/sshd_config
AllowAgentForwarding no

7. Use a custom SSH config file

# ~/.ssh/config
Host server
    HostName 192.168.1.50
    User admin
    Port 2222
    IdentityFile ~/.ssh/id_ed25519
    IdentitiesOnly yes

Host staging
    HostName staging.example.com
    User deploy
    IdentityFile ~/.ssh/id_ed25519_staging
# Usage
ssh server    # Uses the config automatically

8. Set up SSH certificate authentication (advanced)

# Create a CA key
ssh-keygen -t ed25519 -f ~/.ssh/ca_key -C "CA Key"

# Sign a user key
ssh-keygen -s ~/.ssh/ca_key -I "admin-cert" -n admin -V +52w ~/.ssh/id_ed25519.pub
# Signed cert: ~/.ssh/id_ed25519-cert.pub

# Trust the CA on the server
echo "TrustedUserCAKeys /etc/ssh/ca_key.pub" | sudo tee -a /etc/ssh/sshd_config

9. Test the hardened configuration

# Test SSH configuration before restarting
sudo sshd -t
# Returns nothing if configuration is valid

# Restart SSH
sudo systemctl restart sshd

10. Monitor SSH access

# Check successful logins
sudo grep "Accepted" /var/log/auth.log | tail -10

# Check failed attempts
sudo grep "Failed" /var/log/auth.log | tail -10

# Install fail2ban for automatic blocking
sudo apt-get install fail2ban
sudo systemctl enable fail2ban

Lessons Learned

SSH key-based authentication is the minimum security baseline for any Linux server. Always use Ed25519 keys when possible, and always use a passphrase on your private keys. Never disable password authentication until you have confirmed key-based access works. Use AllowUsers to restrict which users can log in. And consider SSH certificates for larger teams to simplify key management.


This blog does not accept any external sponsorships, affiliate marketing, or ad revenue.