Post

OpenSSH

OpenSSH (Open Secure Shell) is a suite of secure networking utilities based on the Secure Shell (SSH) protocol. It provides encrypted communication sessions over a computer network and replaces insecure tools like telnet, rlogin, and rcp. This guide covers both client and server usage with a focus on security best practices.

OpenSSH

OpenSSH Security Guide: Comprehensive Manual and Best Practices

Remember to test your configuration thoroughly with sshd -t before applying changes to avoid locking yourself out of your server.

Table of Contents

  1. Core Components
  2. Key SSH Commands
  3. Configuration Files
  4. Authentication Methods
  5. Securing OpenSSH
  6. Advanced Configuration
  7. Troubleshooting
  8. Additional Resources

Core Components

OpenSSH consists of several key components:

  • sshd: The SSH server daemon that allows incoming SSH connections
  • ssh: The SSH client for connecting to remote machines
  • ssh-keygen: Tool for generating and managing SSH keys
  • ssh-agent: Agent for storing private keys for authentication
  • ssh-add: Tool for adding keys to the ssh-agent
  • scp: Secure copy program for transferring files
  • sftp: Secure FTP for file transfers with more functionality than scp

Key SSH Commands

Basic SSH Connection

1
2
3
4
5
6
# Connect to a remote server
ssh username@hostname

# Example:
ssh [email protected]
ssh [email protected]

Specifying a Port

1
2
3
4
5
# Connect to a non-standard SSH port
ssh -p 2222 username@hostname

# Example:
ssh -p 2222 [email protected]

Using Key-Based Authentication

1
2
3
4
5
# Connect using a specific private key
ssh -i ~/.ssh/id_ed25519 username@hostname

# Example:
ssh -i ~/.ssh/server_key [email protected]

X11 Forwarding (GUI Applications)

1
2
3
4
5
6
7
# Forward X11 to run graphical applications remotely
ssh -X username@hostname

# Example:
ssh -X [email protected]
# Then run a GUI application
firefox &

Port Forwarding (Local)

1
2
3
4
5
6
# Forward local port to remote server
ssh -L local_port:destination_host:destination_port username@hostname

# Example: Forward local port 8080 to remote web server on port 80
ssh -L 8080:localhost:80 [email protected]
# Now access the remote web server by browsing to http://localhost:8080

Port Forwarding (Remote)

1
2
3
4
5
6
# Forward remote port to local machine
ssh -R remote_port:destination_host:destination_port username@hostname

# Example: Allow remote access to a local web server
ssh -R 8080:localhost:3000 [email protected]
# Remote users can now access your local server on port 3000 by connecting to localhost:8080 on the remote machine

Running a Command on a Remote Host

1
2
3
4
5
6
# Execute a command without logging in interactively
ssh username@hostname "command args"

# Example:
ssh [email protected] "uptime"
ssh [email protected] "ls -la /var/log"

Secure File Copy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Copy a local file to remote server
scp file.txt username@hostname:/path/to/destination

# Example:
scp document.pdf [email protected]:/home/john/documents/

# Copy a remote file to local machine
scp username@hostname:/path/to/file.txt local_destination

# Example:
scp [email protected]:/home/john/logs/system.log ./downloaded_logs/

# Copy entire directories with the -r flag
scp -r local_directory username@hostname:/path/to/destination
scp -r username@hostname:/path/to/directory local_destination

Configuration Files

Client-Side Configuration Files

  • ~/.ssh/config: User-specific SSH client configuration
  • /etc/ssh/ssh_config: System-wide client configuration

Example ~/.ssh/config file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Default settings for all hosts
Host *
    ServerAliveInterval 60
    ServerAliveCountMax 3
    HashKnownHosts yes
    IdentitiesOnly yes

# Specific settings for a host
Host myserver
    HostName 192.168.1.100
    User john
    Port 2222
    IdentityFile ~/.ssh/myserver_key
    
# Example for connecting via a jump host
Host internal-server
    HostName 10.0.0.5
    User admin
    ProxyJump jumphost.example.com

Server-Side Configuration Files

  • /etc/ssh/sshd_config: SSH daemon configuration file
  • /etc/ssh/sshd_config.d/: Directory for modular configuration files

Example /etc/ssh/sshd_config file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Basic SSH server configuration
Port 22
ListenAddress 0.0.0.0
Protocol 2

# Authentication settings
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes

# Logging
SyslogFacility AUTH
LogLevel INFO

# Security settings
MaxAuthTries 3
LoginGraceTime 60
PermitEmptyPasswords no

Authentication Methods

Password Authentication

The basic authentication method where users provide their system password.

1
2
# Default SSH connection will prompt for password
ssh username@hostname

Public Key Authentication

A more secure method using cryptographic keys:

  1. Generate a key pair:
    1
    2
    3
    4
    5
    6
    7
    8
    
    # Generate a modern Ed25519 key
    ssh-keygen -t ed25519 -C "[email protected]"
       
    # Generate an RSA key with 4096 bits (for compatibility with older systems)
    ssh-keygen -t rsa -b 4096 -C "[email protected]"
       
    # Generate a key with a specific filename
    ssh-keygen -t ed25519 -f ~/.ssh/myserver_key -C "access to myserver"
    
  2. Copy public key to the server:
    1
    2
    3
    4
    5
    6
    7
    8
    
    # Automated way using ssh-copy-id
    ssh-copy-id -i ~/.ssh/id_ed25519.pub username@hostname
       
    # Example:
    ssh-copy-id -i ~/.ssh/id_ed25519.pub [email protected]
       
    # Manual method if ssh-copy-id is not available
    cat ~/.ssh/id_ed25519.pub | ssh username@hostname "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
    
  3. Verify key-based authentication:
    1
    2
    3
    4
    5
    6
    7
    8
    
    # Try connecting with the key
    ssh -i ~/.ssh/id_ed25519 username@hostname
       
    # If your key has the default name, you don't need to specify it
    ssh username@hostname
       
    # Testing with verbose output to see authentication methods used
    ssh -v username@hostname
    

Using SSH Agent

1
2
3
4
5
6
7
8
9
10
11
12
# Start the SSH agent and add your keys
eval $(ssh-agent)
ssh-add ~/.ssh/id_ed25519

# Add a key with a specific timeout (3600 seconds = 1 hour)
ssh-add -t 3600 ~/.ssh/id_ed25519

# List currently loaded keys
ssh-add -l

# Delete all keys from the agent
ssh-add -D

Securing OpenSSH

Server-Side Security Best Practices

  1. Use Modern Protocol and Ciphers

    Edit /etc/ssh/sshd_config:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
    # Only use SSHv2 protocol
    Protocol 2
       
    # Use secure ciphers
    Ciphers [email protected],[email protected],[email protected],aes256-ctr,aes192-ctr,aes128-ctr
       
    # Secure host key algorithms
    HostKeyAlgorithms ssh-ed25519,ssh-rsa
       
    # Secure key exchange algorithms
    KexAlgorithms [email protected],diffie-hellman-group-exchange-sha256
       
    # Secure MACs (Message Authentication Codes)
    MACs [email protected],[email protected],[email protected]
    

    Apply changes:

    1
    
    sudo systemctl restart sshd
    
  2. Disable Root Login

    Edit /etc/ssh/sshd_config:

    1
    
    PermitRootLogin no
    

    Apply changes:

    1
    
    sudo systemctl restart sshd
    
  3. Disable Password Authentication (after setting up key-based auth)

    Edit /etc/ssh/sshd_config:

    1
    2
    
    PasswordAuthentication no
    ChallengeResponseAuthentication no
    

    Apply changes:

    1
    
    sudo systemctl restart sshd
    
  4. Limit User Access

    Edit /etc/ssh/sshd_config:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    # Allow only specific users
    AllowUsers john mary admin
       
    # Or allow only specific groups
    AllowGroups sshusers admins
       
    # Block specific users
    DenyUsers guest test
       
    # Block specific groups
    DenyGroups guests
    

    Create an SSH group and add users to it:

    1
    2
    
    sudo groupadd sshusers
    sudo usermod -a -G sshusers john
    
  5. Change Default Port (helps avoid automated attacks)

    Edit /etc/ssh/sshd_config:

    1
    
    Port 2222
    

    Update firewall rules (example using UFW):

    1
    2
    
    sudo ufw allow 2222/tcp
    sudo ufw reload
    

    Apply changes:

    1
    
    sudo systemctl restart sshd
    
  6. Disable Empty Passwords

    Edit /etc/ssh/sshd_config:

    1
    
    PermitEmptyPasswords no
    
  7. Implement Connection Timeouts

    Edit /etc/ssh/sshd_config:

    1
    2
    3
    4
    5
    6
    7
    8
    
    # Server will send a keep-alive message every 300 seconds
    ClientAliveInterval 300
       
    # Server will disconnect after 2 failed keep-alive responses (10 minutes total)
    ClientAliveCountMax 2
       
    # User has 60 seconds to authenticate before connection is closed
    LoginGraceTime 60
    
  8. Limit Authentication Attempts

    Edit /etc/ssh/sshd_config:

    1
    2
    3
    4
    5
    
    # Allow maximum 3 authentication attempts per connection
    MaxAuthTries 3
       
    # Allow 3 unauthenticated connections, 50% probability of refusing above that, max 10 
    MaxStartups 3:50:10
    
  9. Disable Unused Features

    Edit /etc/ssh/sshd_config:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
    # Disable X11 forwarding if not needed
    X11Forwarding no
       
    # Disable TCP forwarding if not needed
    AllowTcpForwarding no
       
    # Disable tunneling if not needed
    PermitTunnel no
       
    # Disable agent forwarding if not needed
    AllowAgentForwarding no
       
    # Disable gateway ports
    GatewayPorts no
    
  10. Restrict SSH to Specific Interfaces (if necessary)

    Edit /etc/ssh/sshd_config:

    1
    2
    3
    4
    5
    6
    
    # Only listen on specific IP address
    ListenAddress 192.168.1.100
        
    # Multiple listen addresses can be specified (IPv4 and IPv6)
    ListenAddress 10.0.0.1
    ListenAddress 2001:db8::1
    
  11. Set Proper File Permissions

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
    # User's SSH directory
    chmod 700 ~/.ssh
        
    # Public keys
    chmod 644 ~/.ssh/id_ed25519.pub
        
    # Private keys
    chmod 600 ~/.ssh/id_ed25519
        
    # Authorized keys
    chmod 600 ~/.ssh/authorized_keys
        
    # Known hosts
    chmod 644 ~/.ssh/known_hosts
        
    # Server host keys
    sudo chmod 640 /etc/ssh/ssh_host_*_key
    sudo chmod 644 /etc/ssh/ssh_host_*_key.pub
    
  12. Use SSH Key Certificates (for larger deployments)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    # On CA machine: Create a CA key
    ssh-keygen -t ed25519 -f ssh_ca_key
        
    # Sign user key with the CA, valid for 52 weeks, for user "john"
    ssh-keygen -s ssh_ca_key -I "john_laptop" -n john -V +52w id_ed25519.pub
        
    # On server: Add the CA public key to trusted CAs
    echo "ssh-ed25519 AAAA..." > /etc/ssh/ca.pub
        
    # In /etc/ssh/sshd_config:
    TrustedUserCAKeys /etc/ssh/ca.pub
    
  13. Enable Key Revocation

    Create and populate the revocation list:

    1
    2
    3
    4
    5
    6
    7
    8
    
    # Create the revoked keys file
    sudo touch /etc/ssh/revoked_keys
        
    # Add a revoked key (copy the full public key line)
    echo "ssh-ed25519 AAAA..." | sudo tee -a /etc/ssh/revoked_keys
        
    # In /etc/ssh/sshd_config:
    RevokedKeys /etc/ssh/revoked_keys
    
  14. Use Two-Factor Authentication (2FA)

    Install and configure Google Authenticator:

    1
    2
    3
    4
    5
    6
    7
    
    # Install the package
    sudo apt install libpam-google-authenticator
        
    # Run the initialization tool as the user who needs 2FA
    google-authenticator
        
    # Follow the prompts, scan QR code with your authenticator app
    

    Configure PAM:

    1
    2
    3
    
    # Edit /etc/pam.d/sshd
    # Add this line at the top:
    auth required pam_google_authenticator.so
    

    Configure SSH:

    1
    2
    3
    
    # In /etc/ssh/sshd_config:
    ChallengeResponseAuthentication yes
    AuthenticationMethods publickey,keyboard-interactive
    

    Apply changes:

    1
    
    sudo systemctl restart sshd
    

Client-Side Security Best Practices

  1. Create a Custom SSH Configuration

    Create or edit ~/.ssh/config:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    
    # Default settings for all connections
    Host *
      # Use IPv4 only
      AddressFamily inet
      # Hash hostnames and addresses in known_hosts
      HashKnownHosts yes
      # Only use the specified identity file
      IdentitiesOnly yes
      # Keep connection alive
      ServerAliveInterval 60
      # Compression may improve speed on slow connections
      Compression yes
         
    # Specific host configuration
    Host myserver
      HostName example.com
      User myusername
      Port 2222
      IdentityFile ~/.ssh/id_ed25519
         
    # Example for using a jump host
    Host internal
      HostName 10.0.0.5
      User admin
      ProxyJump jumphost.example.com
         
    # Shortcut for common parameters
    Host dev
      HostName dev-server.example.com
      User developer
      ForwardAgent yes
         
    # Match pattern example
    Host *.example.com
      User admin
      IdentityFile ~/.ssh/example_key
    
  2. Use SSH Key with Passphrase

    1
    2
    3
    4
    5
    6
    7
    
    # Generate a key with increased KDF rounds for stronger protection
    ssh-keygen -t ed25519 -a 100 -C "comment"
       
    # When prompted, enter a strong passphrase
       
    # Change passphrase for an existing key
    ssh-keygen -p -f ~/.ssh/id_ed25519
    
  3. Use SSH-Agent with Timeouts

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    # Start agent if not running
    eval $(ssh-agent)
       
    # Add key with 1-hour timeout
    ssh-add -t 3600 ~/.ssh/id_ed25519
       
    # For macOS Keychain integration (remembers passphrase)
    ssh-add -K ~/.ssh/id_ed25519
       
    # For temporary access to a specific key
    ssh -o "IdentityAgent none" -i ~/.ssh/specific_key username@hostname
    
  4. Keep Your SSH Client Updated

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    # Debian/Ubuntu
    sudo apt update && sudo apt upgrade openssh-client
       
    # RHEL/CentOS
    sudo yum update openssh-clients
       
    # Fedora
    sudo dnf update openssh-clients
       
    # macOS
    brew update && brew upgrade openssh
    
  5. Configure Known Hosts Verification

    Edit ~/.ssh/config:

    1
    2
    3
    4
    5
    6
    7
    8
    
    # Strict checking rejects connections if host key changed
    StrictHostKeyChecking yes
       
    # Use DNS to verify host keys if available
    VerifyHostKeyDNS yes
       
    # Visual host key fingerprint
    VisualHostKey yes
    

Advanced Configuration

SSH Certificates for Authentication

  1. Create a CA key:
    1
    2
    3
    4
    
    # Create a certificate authority key
    ssh-keygen -t ed25519 -f ~/ca
       
    # Use a strong passphrase when prompted
    
  2. Sign a user key:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    # Sign a user's public key
    ssh-keygen -s ~/ca -I "john_laptop" -n john -V +52w id_ed25519.pub
       
    # This creates id_ed25519-cert.pub
       
    # Options explained:
    # -s ~/ca            : Sign using this CA key
    # -I "john_laptop"   : Identity/comment for this certificate
    # -n john            : Username(s) this certificate is valid for
    # -V +52w            : Valid for 52 weeks from now
    
  3. Add the public CA key to server:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    # Copy CA public key to server
    scp ~/ca.pub admin@server:/tmp/
       
    # On server
    sudo cp /tmp/ca.pub /etc/ssh/ca.pub
       
    # In /etc/ssh/sshd_config
    TrustedUserCAKeys /etc/ssh/ca.pub
       
    # Apply changes
    sudo systemctl restart sshd
    

Jump Hosts (Bastion Hosts)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# Direct in command line
ssh -J jumpuser@jumphost targetuser@targethost

# Multiple jumps
ssh -J user1@host1,user2@host2 user3@destination

# Example: Access private network behind a jump host
ssh -J [email protected] [email protected]

# In ~/.ssh/config
Host targethost
  HostName 10.0.0.2
  User targetuser
  ProxyJump jumpuser@jumphost

# Example with multiple jumps in config file
Host private-server
  HostName 192.168.1.50
  User admin
  ProxyJump jumphost1,jumphost2
  
Host jumphost1
  HostName public1.example.com
  User jumpuser1
  
Host jumphost2
  HostName 10.10.0.1
  User jumpuser2

SSH Multiplexing (Connection Sharing)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# In ~/.ssh/config
Host *
  # Enable multiplexing
  ControlMaster auto
  # Path for control socket
  ControlPath ~/.ssh/control:%h:%p:%r
  # Keep socket open for 10 minutes after last connection closes
  ControlPersist 10m
  
# Example usage:
# First connection creates the master connection
ssh server.example.com

# Subsequent connections reuse the existing connection (faster)
ssh server.example.com
scp file.txt server.example.com:/tmp/

# Force a new connection if needed
ssh -o ControlPath=none server.example.com

# Check for existing connections
ssh -O check server.example.com

# Close a persistent connection
ssh -O exit server.example.com

Restricting with SSH Keys

Specify commands or restrictions in authorized_keys:

1
2
3
4
5
6
7
8
9
10
11
# Edit ~/.ssh/authorized_keys and prepend the key with restrictions
command="uptime",no-agent-forwarding,no-port-forwarding,no-X11-forwarding ssh-ed25519 AAAA...

# Full example for a backup user limited to rsync
command="rsync --server --sender -vlogDtpre.iLsfxC . /backup",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-ed25519 AAAA...

# Example to only allow specific source IP addresses
from="192.168.1.0/24,10.0.0.5" ssh-ed25519 AAAA...

# Combine restrictions (monitoring user that can only run specific commands)
from="10.0.0.0/24",command="uptime",no-pty,no-X11-forwarding ssh-ed25519 AAAA...

Using Fail2ban to Protect SSH

Install and configure Fail2ban to block repeated login attempts:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# Install Fail2ban
sudo apt install fail2ban

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

# Edit /etc/fail2ban/jail.local
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
findtime = 600
bantime = 3600
action = iptables-multiport[name=ssh, port="ssh"]

# For custom SSH port add:
port = 2222

# Apply changes
sudo systemctl restart fail2ban

# Check status
sudo fail2ban-client status sshd

# Unban an IP if needed
sudo fail2ban-client set sshd unbanip 192.168.1.5

Troubleshooting

Verbose Logging

Increase verbosity with -v flag (up to -vvv):

1
2
3
4
5
6
7
8
# Basic verbose logging
ssh -v username@hostname

# Very verbose logging
ssh -vvv username@hostname

# Example for debugging authentication issues
ssh -vvv -i ~/.ssh/id_ed25519 [email protected]

Common Error Messages

  1. Permission denied (publickey)

    Check key permissions:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    # Fix permissions on ~/.ssh directory
    chmod 700 ~/.ssh
    chmod 600 ~/.ssh/id_ed25519
    chmod 600 ~/.ssh/authorized_keys
       
    # Verify the key is being offered
    ssh -vvv username@hostname
       
    # Check authorized_keys file for correct entry
    cat ~/.ssh/authorized_keys
    
  2. Connection refused

    Check server status:

    1
    2
    3
    4
    5
    6
    7
    8
    
    # On the server, check if sshd is running
    sudo systemctl status sshd
       
    # Check firewall rules
    sudo iptables -L | grep ssh
       
    # Check netstat to see if the port is listening
    sudo netstat -tulpn | grep ssh
    
  3. Host key verification failed

    Fix host key verification:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    # Remove the offending key from known_hosts
    ssh-keygen -R hostname
       
    # Or edit ~/.ssh/known_hosts manually
       
    # For when using HashKnownHosts, find the hash of the hostname
    ssh-keygen -H -F hostname
       
    # Accept new host key
    ssh -o StrictHostKeyChecking=accept-new username@hostname
    

Debugging Server Issues

  1. Check sshd service status:
    1
    2
    3
    4
    5
    
    # Check service status
    sudo systemctl status sshd
       
    # View recent logs
    sudo journalctl -u sshd --since "1 hour ago"
    
  2. Test configuration before restarting:
    1
    2
    3
    4
    5
    6
    7
    8
    
    # Test configuration for errors
    sudo sshd -t
       
    # For more verbose output
    sudo sshd -T
       
    # Show all actual configuration settings
    sudo sshd -T | grep -i "passwordauthentication"
    
  3. Check logs for issues:
    1
    2
    3
    4
    5
    6
    7
    8
    
    # Ubuntu/Debian systems
    sudo tail -f /var/log/auth.log | grep sshd
       
    # RHEL/CentOS systems
    sudo tail -f /var/log/secure | grep sshd
       
    # Using journalctl
    sudo journalctl -f -u sshd
    

Additional Resources

Slim OpenSSH Server Configuration Guide

Settings to Comment Out or Disable

Disable Unnecessary Features

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# Disable X11 forwarding
X11Forwarding no

# Disable TCP port forwarding if not needed
AllowTcpForwarding no

# Disable SSH agent forwarding
AllowAgentForwarding no

# Prevent listening on forwarded ports
GatewayPorts no

# Disable tunneling features
PermitTunnel no

# Disable permitopen for port forwarding
PermitOpen none

# Disable compression (saves CPU resources)
Compression no

# Disable banner messages
#Banner /etc/issue.net

# Don't print the message of the day
PrintMotd no

# Disable SFTP subsystem if file transfers not needed
#Subsystem sftp /usr/lib/openssh/sftp-server

# Disable reverse DNS lookups (improves connection time)
UseDNS no

# Disable custom environment variable setting
PermitUserEnvironment no

# Disable .rhosts files
IgnoreRhosts yes

# Disable user's ~/.ssh/known_hosts for RhostsRSAAuthentication
HostbasedAuthentication no

Streamline Cryptographic Options

Limit to modern, secure algorithms to reduce overhead:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Only use ED25519 host keys (comment out other key types)
#HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key

# Limit to modern ciphers
Ciphers [email protected],[email protected]

# Limit key exchange algorithms
KexAlgorithms [email protected],curve25519-sha256

# Limit MAC algorithms
MACs [email protected],[email protected]

# Limit authentication methods to public key only
AuthenticationMethods publickey

# Disable less secure authentication methods
PasswordAuthentication no
ChallengeResponseAuthentication no
KerberosAuthentication no
GSSAPIAuthentication no

Security Hardening Settings to Keep

These settings don’t add much overhead but provide important security benefits:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Enforce protocol 2 only
Protocol 2

# Log more details for security monitoring
LogLevel VERBOSE

# Disable empty passwords
PermitEmptyPasswords no

# Disable root login
PermitRootLogin no

# Limit authentication attempts
MaxAuthTries 3

# Timeout settings
LoginGraceTime 30
ClientAliveInterval 300
ClientAliveCountMax 2

# Allow only specific users (customize as needed)
AllowUsers user1 user2

Complete Example Configuration

A complete minimal sshd_config file might look like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# Minimal secure OpenSSH server configuration

# Protocol and basic settings
Protocol 2
Port 22
AddressFamily inet
ListenAddress 0.0.0.0

# Authentication
HostKey /etc/ssh/ssh_host_ed25519_key
AuthenticationMethods publickey
PubkeyAuthentication yes
PasswordAuthentication no
PermitEmptyPasswords no
ChallengeResponseAuthentication no
KerberosAuthentication no
GSSAPIAuthentication no
PermitRootLogin no
MaxAuthTries 3
AllowUsers user1 user2

# Cryptographic settings
Ciphers [email protected],[email protected]
KexAlgorithms [email protected],curve25519-sha256
MACs [email protected],[email protected]

# Timeout settings
LoginGraceTime 30
ClientAliveInterval 300
ClientAliveCountMax 2

# Features to disable
X11Forwarding no
AllowTcpForwarding no
AllowAgentForwarding no
GatewayPorts no
PermitTunnel no
PermitOpen none
Compression no
UseDNS no
PrintMotd no
PermitUserEnvironment no
IgnoreRhosts yes
HostbasedAuthentication no

# Logging
LogLevel VERBOSE

Memory and Performance Optimizations

Beyond configuration, you can optimize the OpenSSH daemon itself:

  1. Use minimal system libraries when compiling OpenSSH
  2. Run OpenSSH with reduced privileges
  3. Consider disabling unused authentication methods at compile time
  4. On resource-constrained systems, consider using lightweight alternatives like Dropbear SSH
This post is licensed under CC BY 4.0 by the author.