OpenSSH - Hardened SSHD configuration
The profile is written for current OpenSSH 10.x behavior. It keeps security-sensitive policy explicit while leaving cryptographic negotiation to current OpenSSH defaults. That is preferable to freezing a long list of algorithms that can become obsolete and can accidentally disable newer protections.
Deployment assumptions:
- public-key-only administrative access;
- no direct root login;
- a modern OpenSSH 10.x server and modern clients;
- host/network firewalling is configured separately;
- placeholders such as
ssh-users,bastion-users,192.0.2.10, and example host names must be replaced before deployment; - this is a general baseline, not a substitute for platform-specific compliance requirements.
Why the cryptographic section changed
OpenSSH 10.0 made mlkem768x25519-sha256 the default key exchange. It is a hybrid post-quantum/classical construction. OpenSSH 10.0 also removed finite-field Diffie-Hellman methods from the server's default KEX list. The OpenSSH project recommends post-quantum key agreement for SSH connections.
Because current OpenSSH defaults evolve with the software, this configuration does not replace KexAlgorithms, Ciphers, MACs, or HostKeyAlgorithms with a static allow-list. A static list should be added only where a specific compliance profile requires one and should then be maintained as its own security policy.
Deployment checks
Before reloading SSH, validate both syntax and the effective configuration:
$ sshd -t $ sshd -T
Inspect the algorithms supported by the installed build when needed:
$ ssh -Q kex $ ssh -Q cipher $ ssh -Q mac $ ssh -Q key
Test from a second session before closing the existing administrative connection.
Recommended configuration
# /etc/ssh/sshd_config # # Hardened general-purpose OpenSSH server profile. # Target: OpenSSH 10.x (2026). # # Validate before reload: # sshd -t # sshd -T # # Keep an existing administrative session open while testing changes. # ----------------------------------------------------------------------------- # Network # ----------------------------------------------------------------------------- Port 22 AddressFamily any # Prefer binding through the host firewall / network policy. If a dedicated # management address is required, uncomment and replace with the real address. # ListenAddress 192.0.2.10 # ----------------------------------------------------------------------------- # Host identity # ----------------------------------------------------------------------------- # Ed25519 is the preferred compact modern host key for non-FIPS deployments. HostKey /etc/ssh/ssh_host_ed25519_key # Do not explicitly pin HostKeyAlgorithms, KexAlgorithms, Ciphers or MACs here. # OpenSSH 10.x has strong evolving defaults, including hybrid post-quantum KEX. # Avoid re-enabling legacy algorithms such as ssh-dss or ssh-rsa/SHA-1. # ----------------------------------------------------------------------------- # Authentication # ----------------------------------------------------------------------------- PermitRootLogin no PubkeyAuthentication yes AuthenticationMethods publickey PasswordAuthentication no KbdInteractiveAuthentication no PermitEmptyPasswords no HostbasedAuthentication no IgnoreRhosts yes # PAM remains useful for account/session policy on Linux even when PAM-based # password and keyboard-interactive authentication are disabled above. UsePAM yes StrictModes yes AuthorizedKeysFile .ssh/authorized_keys LoginGraceTime 30 MaxAuthTries 3 MaxSessions 4 # Replace this placeholder group with the administrative group used locally. AllowGroups ssh-users # ----------------------------------------------------------------------------- # Brute-force / unauthenticated connection resistance # ----------------------------------------------------------------------------- # Random early drop for excessive unauthenticated connections. MaxStartups 10:30:60 # Limit simultaneous unauthenticated connections from one source. PerSourceMaxStartups 3 # OpenSSH's PerSourcePenalties protection is enabled by default on current # releases. Keep it enabled unless there is a documented operational reason # to change it. # ----------------------------------------------------------------------------- # Session and environment # ----------------------------------------------------------------------------- PermitUserEnvironment no PermitUserRC no # Accept only basic locale information. Add more only when applications need it. AcceptEnv LANG LC_* ClientAliveInterval 300 ClientAliveCountMax 2 TCPKeepAlive no Compression no PrintMotd no Banner /etc/issue.net Subsystem sftp internal-sftp # ----------------------------------------------------------------------------- # Forwarding and interactive features # ----------------------------------------------------------------------------- # General servers do not need to act as SSH forwarding gateways. DisableForwarding yes AllowAgentForwarding no AllowTcpForwarding no AllowStreamLocalForwarding no GatewayPorts no PermitTunnel no X11Forwarding no # ----------------------------------------------------------------------------- # Logging # ----------------------------------------------------------------------------- SyslogFacility AUTHPRIV # VERBOSE logs additional authentication detail such as public-key fingerprints, # which is useful for security auditing. Review local privacy/log-retention rules. LogLevel VERBOSE
Notes
DisableForwarding yes provides defense in depth on a normal server where SSH is intended only for administration. The individual forwarding directives are also set to no to make the intended policy immediately visible to a reviewer.
LogLevel VERBOSE is useful for administrative auditing because OpenSSH can record additional authentication details, including key fingerprints. Where those logs are centrally collected, retention and access should follow the organization's logging and privacy policy.
PerSourceMaxStartups 3 adds a per-source ceiling in addition to the global MaxStartups limit. Current OpenSSH also has PerSourcePenalties, enabled by default, to temporarily refuse sources that exhibit suspicious authentication behavior.
References
Current practice (checked 2026-10)
- Still valid: on OpenSSH 10.x the profile matches upstream.
KbdInteractiveAuthenticationis the current name (ChallengeResponseAuthenticationis only a deprecated alias), DSA was removed in 10.0,mlkem768x25519-sha256is the default key exchange since 10.0, andPerSourcePenaltiesis enabled by default since 9.8. - Installed version: enterprise distributions ship older releases; Oracle Linux 10.2, for example, has OpenSSH 9.9p1, which supports
mlkem768x25519-sha256but predates the 10.0 defaults. Checkssh -Vbefore assuming the 10.x behavior described above. - Crypto policy on RHEL-family systems: there sshd does not use the OpenSSH built-in algorithm defaults. The system-wide crypto policy supplies
Ciphers,MACs,KexAlgorithmsandHostKeyAlgorithms; the DEFAULT policy checked here still offers finite-fielddiffie-hellman-group14-sha256andhmac-sha1. Tighten it withupdate-crypto-policiesor with a drop-in in/etc/ssh/sshd_config.d/named to sort before50-redhat.conf. - Drop-in order: sshd uses the first value obtained for each keyword. Where the distribution includes
/etc/ssh/sshd_config.d/*.confat the top ofsshd_config, a setting in a drop-in overrides the same keyword in the main file, so confirm the result withsshd -T. - DisableForwarding: before OpenSSH 10.0
DisableForwardingfailed to disable X11 and agent forwarding. On older servers the explicitX11Forwarding noandAllowAgentForwarding nolines above are what does the work; keep them. - Post-quantum host keys: OpenSSH 10.4 added an experimental composite signature scheme, ML-DSA-44 with Ed25519 (
ssh-keygen -t mldsa44-ed25519), which the 10.4 release notes describe as not enabled by default. The Ed25519 host key above remains the right choice for production.
$ ssh -V $ update-crypto-policies --show $ # sshd -T | grep -i -E '^(kexalgorithms|ciphers|macs)'
Sources: