DEV Community

丁久
丁久

Posted on • Originally published at dingjiu1989-hue.github.io

SSH Security Hardening

This article was originally published on AI Study Room. For the full version with working code examples and related articles, visit the original post.

SSH Security Hardening

SSH Security Hardening

SSH is the gateway to your infrastructure. A compromised SSH key or misconfigured daemon can lead to complete server takeover. Hardening SSH is one of the highest-impact security improvements you can make.

Disable Password Authentication

Password authentication is susceptible to brute-force attacks. Disable it and use key-based authentication only:

/etc/ssh/sshd_config

PasswordAuthentication no

ChallengeResponseAuthentication no

UsePAM no

PubkeyAuthentication yes

After making changes, restart the SSH daemon:

sudo systemctl restart sshd

Always keep an active SSH session open while testing changes. If something breaks, you can debug before the session closes.

Use Ed25519 Keys

Ed25519 keys offer better security and performance than RSA:

ssh-keygen -t ed25519 -a 100 -f ~/.ssh/id_ed25519

The -a 100 option increases the KDF rounds for the private key file, making it harder to crack if the file is stolen. For legacy systems that require RSA, use at least 4096-bit keys:

ssh-keygen -t rsa -b 4096 -a 100 -f ~/.ssh/id_rsa

Restrict Key Usage

Limit what individual keys can do using the authorized_keys file:

~/.ssh/authorized_keys

restrict,command="/usr/bin/git-shell",from="192.168.1.0/24" ssh-ed25519 AAA...

The restrict keyword denies all forwarding and agent access. command= limits the key to a specific command. from= restricts which IP addresses can use this key.

Disable Root Login

Never allow direct root SSH access:

PermitRootLogin no

Use a regular user account with sudo access instead. This creates an audit trail -- every privileged command is logged with the user who ran it.

Change the Default Port

Changing the default port (22) reduces automated attack noise:

Port 2222

This is not real security (a determined attacker will find your SSH port), but it dramatically reduces log noise from automated scanners.

Use a Strong Cipher Configuration

Modern SSH supports strong ciphers. Enforce them:

Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com

MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com

KexAlgorithms curve25519-sha256,diffie-hellman-group16-sha512

HostKeyAlgorithms ssh-ed25519,rsa-sha2-512

This configuration only allows algorithms with proven security. Remove legacy algorithms like diffie-hellman-group14-sha1 and hmac-sha1.

SSH Timeout and Session Limits

Prevent idle sessions from accumulating:

ClientAliveInterval 300

ClientAliveCountMax 2

TCPKeepAlive no

MaxSessions 10

MaxStartups 10:30:60

ClientAliveInterval=300 with ClientAliveCountMax=2 means the server checks every 5 minutes and disconnects after 10 minutes of inactivity. MaxStartups limits concurrent unauthenticated connections to prevent DoS attacks.

Fail2Ban Integration

Install and configure Fail2Ban to block brute-force attempts:

sudo apt install fail2ban

/etc/fail2ban/jail.local

[sshd]

enabled = true

port = ssh

filter = sshd

logpath = /var/log/auth.log

maxretry = 3

bantime = 3600

findtime = 600

This bans IPs for one hour after three failed attempts within ten minutes. For internet-facing SSH, consider longer ban times (24 hours) to be more aggressive.

Two-Factor Authentication

Add a second factor with libpam-google-authenticator:

sudo apt install libpam-google-authenticator

google-authenticator

/etc/pam.d/sshd

auth required pam_google_authenticator.so

/etc/ssh/sshd_config

ChallengeResponseAuthentication yes

AuthenticationMethods publickey,keyboard-interactive

This requires both an SSH key and a TOTP code to authenticate. Use this for high-value jump boxes and production servers.

SSH Agent Forwarding

Be careful with agent forwarding. Use -J (jump host) instead when possible:

Instead of forwarding your agent through a chain:

ssh -J bastion.example.com target.internal

Or use ProxyJump in ~/.ssh/config:

Host internal-*

ProxyJump bastion.example.com

If you must use agent forwarding, use ssh -A with the -t flag for a single session rather than enabling forwarding globally in your config.

Key Rotation

Regularly rotate SSH keys and audit authorized keys:

!/bin/bash

audit-ssh-keys.sh

for user in $(getent passwd | cut -d: -f1); do

home=$(getent passwd "$user" | cut -d: -f6)

if [[ -f "$home/.ssh/authorized_keys" ]]; then

echo "User: $user"

cat "$home/.ssh/authorized_keys"

fi

done

Remove keys belonging to departed team members and replace keys that are over a year old. Integrate key management with your identity provider (Okta, Azure AD) using tools like ssh-ca for certificate-based auth.

Monitor SSH Access

Monitor SSH access in real-time:

Watch auth log for SSH activity

tail -f /var/log/auth.log | grep sshd

Audit currently logged-in users

w

Last login times for all users

lastlog

Set up alerts for SSH logins from unexpected IP ranges or at unusual hours using log ingestion tools.

Summary

SSH


Read the full article on AI Study Room for complete code examples, comparison tables, and related resources.

Found this useful? Check out more developer guides and tool comparisons on AI Study Room.

Top comments (0)