Skip to content

Last updated: 2026-06-25

OpenSSH Security Configuration Guide

This guide provides recommended cryptographic settings for OpenSSH servers and clients. OpenSSH uses its own protocol (not TLS), but the same principles apply: use strong key exchange algorithms, ciphers, and MACs, and disable weak or legacy options.

Prerequisites

  • OpenSSH 9.0+ (sntrup761 post-quantum key exchange); 9.9+ for the ML-KEM default (mlkem768x25519-sha256)
  • A generated set of host keys

Server Configuration

All server settings are configured in /etc/ssh/sshd_config.

Host Keys

Use only strong host key types. Remove or disable ECDSA keys if not needed (DSA support was removed entirely in OpenSSH 10.0):

HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key

Generate a new Ed25519 host key if one does not exist:

ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N ""

Host Key Algorithms

Specify the order of host key algorithms offered to clients:

HostKeyAlgorithms ssh-ed25519,ssh-ed25519-cert-v01@openssh.com,rsa-sha2-512,rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256,rsa-sha2-256-cert-v01@openssh.com

Key Exchange Algorithms

Restrict key exchange to strong algorithms:

KexAlgorithms mlkem768x25519-sha256,sntrup761x25519-sha512@openssh.com,curve25519-sha256,curve25519-sha256@libssh.org

mlkem768x25519-sha256 is the default in OpenSSH 10.0+ and provides post-quantum resistance based on the NIST-standardised ML-KEM algorithm. sntrup761x25519-sha512@openssh.com is available in OpenSSH 9.0+ and remains a supported alternative.

Version note: mlkem768x25519-sha256 requires OpenSSH 9.9+. On OpenSSH 9.0-9.8, omit it and use sntrup761x25519-sha512@openssh.com as the first entry instead. On OpenSSH 8.x, omit both post-quantum algorithms.

The finite field DH algorithms (diffie-hellman-group16-sha512, diffie-hellman-group18-sha512) are disabled by default in sshd as of OpenSSH 10.0. They are omitted here; add them back only if interoperability with legacy clients requires it.

Ciphers

Allow only authenticated encryption (AEAD) ciphers:

Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr

The CTR-mode ciphers are included for compatibility. Prefer the AEAD ciphers (ChaCha20-Poly1305, AES-GCM) when possible.

MACs

For non-AEAD ciphers, use Encrypt-then-MAC variants:

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

AEAD ciphers (ChaCha20-Poly1305, AES-GCM) handle integrity internally and ignore the MAC setting.

Authentication Hardening

Disable password authentication and enforce key-based login:

PasswordAuthentication no
ChallengeResponseAuthentication no
PubkeyAuthentication yes

OpenSSH 8.7+: ChallengeResponseAuthentication was renamed to KbdInteractiveAuthentication. On 8.7+, use KbdInteractiveAuthentication no instead. The old name still works as an alias but may be removed in future versions.

Disable root login or restrict it to key-based only:

PermitRootLogin no

Access Restrictions

Limit which users and groups can connect:

AllowUsers deploy admin
AllowGroups ssh-users

Set brute-force protections:

MaxAuthTries 3
LoginGraceTime 30
MaxSessions 5
MaxStartups 10:30:60

Additional Hardening

# Disable unused authentication methods
KbdInteractiveAuthentication no    # Requires OpenSSH 8.7+; omit on older versions
GSSAPIAuthentication no

# Disable X11 and agent forwarding if not needed
X11Forwarding no
AllowAgentForwarding no

# Disable TCP forwarding if not needed
AllowTcpForwarding no

# Log more detail for auditing
LogLevel VERBOSE

# Disconnect idle sessions
ClientAliveInterval 300
ClientAliveCountMax 2

Client Configuration

Client settings go in ~/.ssh/config or /etc/ssh/ssh_config. Match the cryptographic settings to the server:

Host *
    # Key exchange (mlkem768x25519-sha256 requires OpenSSH 9.9+; sntrup761 requires OpenSSH 9.0+)
    KexAlgorithms mlkem768x25519-sha256,sntrup761x25519-sha512@openssh.com,curve25519-sha256,curve25519-sha256@libssh.org

    # Ciphers
    Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr

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

    # Host key verification
    HostKeyAlgorithms ssh-ed25519,ssh-ed25519-cert-v01@openssh.com,rsa-sha2-512,rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256,rsa-sha2-256-cert-v01@openssh.com

    # Strict host key checking
    StrictHostKeyChecking ask
    VerifyHostKeyDNS yes
    HashKnownHosts yes

    # Prefer Ed25519 keys for authentication
    IdentityFile ~/.ssh/id_ed25519
    IdentityFile ~/.ssh/id_rsa

    # Forward agent only to trusted hosts
    ForwardAgent no

Per-Host Configuration

Override settings for specific hosts:

Host bastion
    HostName bastion.example.com
    User admin
    IdentityFile ~/.ssh/id_ed25519_bastion
    ForwardAgent no

Host internal-*
    ProxyJump bastion
    User deploy
    StrictHostKeyChecking yes

Complete Server Configuration

# /etc/ssh/sshd_config

# Network
Port 22
# Listen on both IPv4 and IPv6 where available; use "inet" or "inet6" to restrict.
AddressFamily any
ListenAddress 0.0.0.0
ListenAddress ::

# Host keys
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key

# Cryptography
KexAlgorithms mlkem768x25519-sha256,sntrup761x25519-sha512@openssh.com,curve25519-sha256,curve25519-sha256@libssh.org
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com
HostKeyAlgorithms ssh-ed25519,ssh-ed25519-cert-v01@openssh.com,rsa-sha2-512,rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256,rsa-sha2-256-cert-v01@openssh.com

# Authentication
PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no    # OpenSSH 8.7+; on older versions use "ChallengeResponseAuthentication no"
GSSAPIAuthentication no
MaxAuthTries 3
LoginGraceTime 30
AuthenticationMethods publickey

# Access control
AllowGroups ssh-users
MaxSessions 5
MaxStartups 10:30:60

# Security
X11Forwarding no
AllowAgentForwarding no
AllowTcpForwarding no
PermitTunnel no
Compression no

# Session management
ClientAliveInterval 300
ClientAliveCountMax 2
UsePAM yes

# Logging
LogLevel VERBOSE

# SFTP
# Path varies by distribution:
#   RHEL: /usr/libexec/openssh/sftp-server
#   Debian/Ubuntu: /usr/lib/openssh/sftp-server
#   SLES: /usr/lib/ssh/sftp-server
Subsystem sftp /usr/libexec/openssh/sftp-server

Security Notes

OpenSSH implements the SSH-2 protocol, not TLS. The cryptographic considerations are similar, but the attack surface is specific to SSH:

  • Weak ciphers excluded: The recommended configuration excludes arcfour (RC4), DES, 3DES, Blowfish, and other legacy symmetric ciphers.
  • Weak MACs excluded: MD5-based and SHA-1-based MACs (hmac-md5, hmac-sha1) are excluded; only HMAC-SHA2-256, HMAC-SHA2-512, and Poly1305 are recommended.
  • Weak key exchange excluded: diffie-hellman-group1-sha1 (768/1024-bit, equivalent to LOGJAM) and diffie-hellman-group14-sha1 (SHA-1) are excluded; only curve25519 and ECDH with SHA-2 are recommended.
  • SSHv1 disabled: SSHv1 is disabled by default since OpenSSH 7.0 (August 2015) and is not supported in any current release. SSHv1 had numerous protocol-level weaknesses analogous to SSL 2.0/3.0.
  • Forward secrecy: Guaranteed by the recommended key exchange algorithms (curve25519-sha256 and the ML-KEM/sntrup761 hybrids), which generate ephemeral keys per session.

The following are not applicable to SSH:

  • Heartbleed (CVE-2014-0160, 2014): Not applicable to the SSH protocol itself. OpenSSH does not use OpenSSL for its core cryptography (it uses its own libcrypto). If OpenSSL is installed on the host for other purposes, ensure it is patched.
  • POODLE / BEAST / FREAK / LOGJAM (TLS-specific forms): Not applicable. These attacks target SSL/TLS protocol specifics that do not exist in SSH-2.
  • BREACH / CRIME: Not applicable. These target HTTP-level and TLS-level compression; SSH compression (Compression no) should be disabled but for different reasons (it can aid compression oracle attacks like BREACH at the SSH layer).
  • DROWN (CVE-2016-0800, 2016): Not applicable. SSH does not use SSLv2.

Verification

Test the configuration before restarting:

sshd -t

If the syntax is valid, reload the SSH daemon:

systemctl reload sshd       # Debian/Ubuntu: systemctl reload ssh

View the active server configuration:

sshd -T

Test a connection with verbose output to see the negotiated algorithms:

ssh -vv user@server.example.com

Look for lines showing the negotiated key exchange, cipher, and MAC:

debug1: kex: algorithm: curve25519-sha256
debug1: kex: host key algorithm: ssh-ed25519
debug1: kex: server->client cipher: chacha20-poly1305@openssh.com MAC: <implicit>
debug1: kex: client->server cipher: chacha20-poly1305@openssh.com MAC: <implicit>

Audit your server with ssh-audit for a comprehensive check:

ssh-audit server.example.com

Related Guides

View all Communications & VPN guides →

Configured TLS? Now Monitor It.

Generator Labs alerts you before certificates expire, get revoked, or fail chain validation, across HTTPS, SMTPS, IMAPS, LDAPS, and more.

Certificate Monitoring →