How to configure your OpenSSH server

According to the CIS Benchmark

Why use OpenSSH?

When it comes to securely accessing remote systems, SSH is the standard – and OpenSSH is by far the most widely used implementation. It’s open-source, battle-tested, and available by default on pretty much every Linux distribution out there. Whether you’re managing a home server or maintaining a fleet of cloud machines, OpenSSH is the go-to tool for encrypted remote access.

Danger of misconfiguration

One of the biggest risks with OpenSSH (or any security-critical tool, really) is simple misconfiguration. And let’s be honest – it’s usually not because people are careless, but because they just don’t know better. A small overlooked setting, a misunderstood option, and boom — you’ve opened a door you didn’t mean to. What’s worse: these kinds of mistakes can go unnoticed for years. According to NIST, human error is one of the leading causes of SSH-related security incidents.

CIS Benchmarks

So how should you configure your SSH server? That’s where the CIS Benchmarks come in. Developed by the Center for Internet Security, these benchmarks are widely considered the industry standard for secure system configurations. There are over 140 of them, covering everything from Linux servers to cloud platforms – and yes, OpenSSH has its own dedicated set of recommendations. If you want to harden your setup without reinventing the wheel, CIS is a great place to start.

Best practices for OpenSSH

Let’s dive into the actual hardening steps. The following recommendations come straight from the CIS Benchmark for OpenSSH – a goldmine for making your SSH server more secure and less of a target.

Login behavior & user experience

  • Display a warning banner (Banner)
    This isn’t just for show. A login banner can serve as a legal notice that unauthorized access is prohibited — useful in case of legal action.
  • Limit login attempts (MaxAuthTries)
    Fewer attempts = less room for brute force attacks. The benchmark recommends setting this to 4.
  • Limit login time (LoginGraceTime)
    Give users a short window (e.g. 60 seconds) to log in before the server drops the connection.

Authentication & session handling

  • Disable root login (PermitRootLogin)
    Force admins to log in with personal accounts and escalate to root. Better audit trail, less risk.
  • Disable empty passwords (PermitEmptyPasswords)
    Sounds obvious, but it’s important: no one should be allowed to log in with a blank password.
  • Limit concurrent sessions (MaxSessions)
    Helps prevent DoS attacks by capping how many sessions a user can open.
  • Limit unauthenticated connections (MaxStartups)
    Same idea as above, but for pending connections. Keeps the daemon from being overloaded.
  • Drop idle connections (ClientAliveInterval + ClientAliveCountMax)
    These settings control how often the server checks for active connections. If a client is unresponsive, the connection is closed. This helps free up server resources.

Strengthening cryptographic settings

  • Choose strong ciphers (Ciphers)
    Remove outdated or weak encryption algorithms. Only keep modern, secure options.
  • Harden key exchange (KexAlgorithms)
    Use key exchange methods that aren’t vulnerable to downgrade attacks or short key issues.
  • Set strong MAC algorithms (MACs)
    Avoid anything MD5-based or 96-bit. Stick to SHA-2 variants or better.

Authentication mechanisms

  • Disable GSSAPI Authentication (GSSAPIAuthentication)
    It’s rarely used and can expand your attack surface unnecessarily.
  • Disable Hostbased Authentication (HostbasedAuthentication)
    This old-school mechanism relies on trusted host files. Safer to just turn it off.
  • Force password entry (IgnoreRhosts)
    Disables .rhosts file-based trust and ensures passwords are used for authentication.

Session control & security

  • Disable forwarding (DisableForwarding)
    Turning this on disables all forwarding — X11, agent, TCP — which simplifies hardening in restricted environments.
  • Disable user-defined environments (PermitUserEnvironment)
    Letting users pass environment variables via SSH can lead to all sorts of bypass tricks. Disable it.
  • Enable PAM (UsePAM)
    This enables things like IP-based access controls, session limits, or inheriting secure environment variables.

Logging

  • Set proper log level (LogLevel)
    VERBOSE gives you better insight into logins, logouts, and even the fingerprint of SSH keys used.

A configuration example

# -------------------------------
# Security Banner
# -------------------------------
Banner /etc/issue.net

# -------------------------------
# Authentication Settings
# -------------------------------
PermitRootLogin no
PermitEmptyPasswords no
IgnoreRhosts yes
HostbasedAuthentication no
GSSAPIAuthentication no
PermitUserEnvironment no
UsePAM yes

# -------------------------------
# Login Controls
# -------------------------------
LoginGraceTime 60
MaxAuthTries 4
MaxSessions 10
MaxStartups 10:30:100

# -------------------------------
# Idle Session Timeout
# -------------------------------
ClientAliveInterval 300
ClientAliveCountMax 0

# -------------------------------
# Forwarding
# -------------------------------
DisableForwarding yes

# -------------------------------
# Logging
# -------------------------------
LogLevel VERBOSE

# -------------------------------
# Strong Cryptographic Settings
# -------------------------------
Ciphers aes256-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256

# -------------------------------
# Misc
# -------------------------------
# (Other necessary settings like Port, AddressFamily, ListenAddress, etc.)