thelinuxvault guide

Hardening OpenSSH for a More Secure Linux Environment

OpenSSH (Open Secure Shell) is the de facto tool for secure remote access to Linux and Unix systems, enabling encrypted communication over untrusted networks. While OpenSSH is designed with security in mind, default configurations often prioritize usability over strict security, leaving systems vulnerable to attacks like brute-force attempts, credential stuffing, or exploitation of outdated protocols. Hardening OpenSSH involves refining its configuration to mitigate these risks, ensuring only authorized users access your system with minimal exposure to threats. This blog will guide you through **step-by-step best practices** to secure your SSH setup, from disabling weak authentication methods to enforcing modern cryptography and monitoring for suspicious activity.

Table of Contents

  1. Understanding Your Current SSH Configuration
  2. Key Hardening Steps
  3. Testing Your Hardened Configuration
  4. Common Pitfalls & Troubleshooting
  5. Conclusion
  6. References

1. Understanding Your Current SSH Configuration

Before making changes, audit your existing SSH setup to identify vulnerabilities. Start with these checks:

Check OpenSSH Version

Older versions may have known vulnerabilities (e.g., CVE-2024-6387). Verify your version with:

ssh -V  # Client version  
sshd -V # Server version (run as root)  

Aim for OpenSSH 8.0+ for modern features like Ed25519 keys and ChaCha20 ciphers.

Audit sshd_config

The main configuration file for the SSH server (sshd) is /etc/ssh/sshd_config. Review it for insecure defaults:

cat /etc/ssh/sshd_config | grep -v '^#' | grep -v '^$'  # Filter comments/empty lines  

Use Automated Tools

Tools like ssh-audit (a lightweight scanner) can identify weak ciphers, protocols, or misconfigurations:

# Install ssh-audit (e.g., on Ubuntu)  
sudo apt install ssh-audit  

# Scan your SSH server  
ssh-audit localhost  

2. Key Hardening Steps

2.1 Disable Password Authentication & Use SSH Keys

Passwords are vulnerable to brute-force attacks and human error (e.g., weak passwords). SSH keys offer stronger, passwordless authentication.

Step 1: Generate an SSH Key Pair

Use Ed25519 (Elliptic Curve Digital Signature Algorithm) for better security and performance than RSA. For compatibility with older systems, use RSA (4096-bit minimum).

Generate Ed25519 key (recommended):

ssh-keygen -t ed25519 -C "[email protected]"  

Generate RSA key (for legacy systems):

ssh-keygen -t rsa -b 4096 -C "[email protected]"  
  • The key pair will be saved to ~/.ssh/id_ed25519 (private key) and ~/.ssh/id_ed25519.pub (public key).
  • Never share the private key (id_ed25519).

Step 2: Copy the Public Key to the Server

Use ssh-copy-id to transfer your public key to the server’s ~/.ssh/authorized_keys file:

ssh-copy-id -i ~/.ssh/id_ed25519.pub username@server_ip  

If ssh-copy-id isn’t available, manually copy the public key:

# On your local machine, display the public key  
cat ~/.ssh/id_ed25519.pub  

# On the server, create ~/.ssh (if missing) and append the public key  
mkdir -p ~/.ssh && chmod 700 ~/.ssh  
nano ~/.ssh/authorized_keys  # Paste the public key here  
chmod 600 ~/.ssh/authorized_keys  # Restrict permissions  

Step 3: Verify Key Authentication

Test login with your key (no password prompt should appear):

ssh -i ~/.ssh/id_ed25519 username@server_ip  

Step 4: Disable Password Authentication

Edit /etc/ssh/sshd_config to disable password-based login:

sudo nano /etc/ssh/sshd_config  

Set these directives:

PasswordAuthentication no        # Disable password logins  
ChallengeResponseAuthentication no  # Disable keyboard-interactive auth  

Critical Note: Ensure key authentication works before disabling passwords—otherwise, you may lock yourself out!

2.2 Limit User and Group Access

Restrict SSH access to specific users/groups to minimize attack surface.

Disable Root Login

Never allow direct root login—use sudo from a regular user account instead:

PermitRootLogin no  # In sshd_config  

Allow/Deny Specific Users/Groups

Use AllowUsers, AllowGroups, DenyUsers, or DenyGroups to restrict access. For example:

AllowUsers alice [email protected]/24  # Allow alice (any IP) and bob (only local subnet)  
AllowGroups ssh-users               # Allow only users in the "ssh-users" group  
DenyUsers charlie                   # Block user "charlie"  

Create a dedicated ssh-users group (optional but recommended):

sudo groupadd ssh-users  
sudo usermod -aG ssh-users alice  # Add user "alice" to the group  

2.3 Change the Default SSH Port

The default SSH port (22) is a target for automated scans. Changing it to a non-standard port (e.g., 2222) reduces noise from brute-force attempts.

Step 1: Update sshd_config

Port 2222  # Replace 22 with your chosen port (1024-65535)  

Step 2: Update Firewall Rules

Allow the new port in your firewall (e.g., ufw or iptables):

Using UFW (Uncomplicated Firewall):

sudo ufw allow 2222/tcp  
sudo ufw reload  

Using iptables:

sudo iptables -A INPUT -p tcp --dport 2222 -j ACCEPT  
sudo iptables-save | sudo tee /etc/iptables/rules.v4  # Persist rules (Debian/Ubuntu)  

Step 3: Test Access on the New Port

ssh -p 2222 username@server_ip  

2.4 Configure Idle Timeout and Auto-Disconnect

Idle SSH sessions are targets for hijacking. Automatically terminate inactive sessions with:

ClientAliveInterval 300  # Send a keepalive every 300 seconds (5 minutes)  
ClientAliveCountMax 3    # Terminate after 3 failed keepalives (15 minutes total)  

2.5 Enforce Strong Ciphers, Key Exchanges, and MACs

Older ciphers (e.g., 3DES) or MACs (e.g., HMAC-MD5) are insecure. Enforce modern, cryptographically strong algorithms.

Update sshd_config

Add/modify these directives to restrict to strong options:

# Ciphers: Prioritize ChaCha20 (for low-power devices) and AES-GCM  
Ciphers [email protected],[email protected],[email protected],aes256-ctr,aes192-ctr,aes128-ctr  

# Key Exchanges: Avoid SHA1-based KEX (e.g., diffie-hellman-group1-sha1)  
KexAlgorithms [email protected],diffie-hellman-group-exchange-sha256  

# MACs: Use SHA256/512 and avoid HMAC-MD5  
MACs [email protected],[email protected],[email protected]  

2.6 Enhance Logging and Monitoring

Log SSH activity to detect suspicious behavior (e.g., repeated failed logins).

Configure Logging in sshd_config

LogLevel VERBOSE  # Log detailed info (e.g., user, IP, key used)  
SyslogFacility AUTH  # Send logs to the "AUTH" facility  

View Logs

Logs are stored in:

  • Debian/Ubuntu: /var/log/auth.log
  • RHEL/CentOS: /var/log/secure

Example:

grep "sshd" /var/log/auth.log  # Filter SSH logs  

Block Brute-Force Attacks with fail2ban

fail2ban automatically blocks IPs with repeated failed login attempts:

Install fail2ban:

# Ubuntu/Debian  
sudo apt install fail2ban  

# RHEL/CentOS  
sudo dnf install fail2ban  

Configure fail2ban:
Edit /etc/fail2ban/jail.local (create if missing):

[sshd]  
enabled = true  
port = 2222  # Use your custom SSH port  
filter = sshd  
logpath = /var/log/auth.log  # Path to your SSH logs  
maxretry = 3  # Block after 3 failed attempts  
bantime = 3600  # Block for 1 hour (3600 seconds)  

Restart fail2ban:

sudo systemctl restart fail2ban  
sudo systemctl enable fail2ban  # Start on boot  

2.7 Implement Firewall Rules

Restrict SSH access to trusted IPs/subnets (e.g., your home/office network) using a firewall.

Example with UFW

# Allow SSH only from 192.168.1.0/24 (local subnet) and 203.0.113.45 (remote IP)  
sudo ufw allow from 192.168.1.0/24 to any port 2222/tcp  
sudo ufw allow from 203.0.113.45 to any port 2222/tcp  

# Deny all other SSH traffic  
sudo ufw deny 2222/tcp  

# Enable UFW (if not already enabled)  
sudo ufw enable  

2.8 Enable Two-Factor Authentication (2FA)

Add an extra layer of security with 2FA (e.g., TOTP codes via Google Authenticator).

Step 1: Install Google Authenticator PAM Module

# Ubuntu/Debian  
sudo apt install libpam-google-authenticator  

# RHEL/CentOS  
sudo dnf install google-authenticator  

Step 2: Configure 2FA for a User

Run google-authenticator as the user who needs 2FA:

google-authenticator  
  • Answer “y” to all prompts (enable time-based tokens, save key, etc.).
  • Scan the QR code with Google Authenticator (or similar app) to generate codes.

Step 3: Update sshd_config

Enable PAM-based 2FA:

ChallengeResponseAuthentication yes  
UsePAM yes  

Update PAM SSH configuration (/etc/pam.d/sshd):

sudo nano /etc/pam.d/sshd  

Add this line (comment out other @include lines if needed to avoid conflicts):

auth required pam_google_authenticator.so  

2.9 Disable Unused Features

Disable rarely used SSH features to reduce attack surface:

X11Forwarding no          # Disable GUI forwarding (if not needed)  
AllowTcpForwarding no     # Block port forwarding (enable selectively with "yes" or "local")  
AgentForwarding no        # Disable SSH agent forwarding (risk of key theft)  
PermitTunnel no           # Disable VPN-like tunnels  
Compression no            # Disable compression (potential side-channel risks)  

2.10 Keep OpenSSH Updated

Regularly update OpenSSH to patch vulnerabilities (e.g., CVE-2024-6387):

# Ubuntu/Debian  
sudo apt update && sudo apt upgrade openssh-server  

# RHEL/CentOS  
sudo dnf update openssh-server  

3. Testing Your Hardened Configuration

After making changes, validate the configuration to avoid locking yourself out:

Step 1: Check for Syntax Errors

sudo sshd -t  # Test sshd_config for errors  

Step 2: Restart the SSH Service

# Systemd-based systems (Ubuntu 16.04+, RHEL 7+)  
sudo systemctl restart sshd  

# SysVinit (older systems)  
sudo service ssh restart  

Step 3: Test Login from a New Terminal

Always test with a second terminal session to ensure you can still connect. If you’re locked out, use a local console (e.g., physical access or IPMI) to revert changes.

4. Common Pitfalls & Troubleshooting

  • Locked Out After Disabling Passwords? Re-enable password auth temporarily via the console:
    sudo nano /etc/ssh/sshd_config  
    PasswordAuthentication yes  
    sudo systemctl restart sshd  
  • 2FA Not Working? Ensure ChallengeResponseAuthentication yes and PAM is configured correctly.
  • Firewall Blocking Access? Verify rules with sudo ufw status or sudo iptables -L.

5. Conclusion

Hardening OpenSSH is critical for securing remote access to Linux systems. By following these steps—using SSH keys, limiting access, enforcing strong cryptography, and monitoring for threats—you significantly reduce the risk of breaches. Remember, security is ongoing: regularly audit your configuration, update OpenSSH, and stay informed about new vulnerabilities.

6. References