SSH Hardening 2026: Algorithms, Certificates and Bastion Hosts
Modern SSH configuration with an internal CA, resistant algorithms and auditable bastion hosts to shrink the attack surface in corporate environments.
Every time we open shodan.io and filter by port:22, we find hundreds of thousands of servers still accepting ssh-rsa with SHA-1, password authentication exposed to the internet and MACs like hmac-sha1. In 2026 this is not forgotten legacy config: it is technical debt paying interest in the form of incidents. SSH hardening stopped being a six-line checklist in sshd_config and became a small subsystem covering an internal CA, an auditable bastion, key rotation and centralized telemetry. This post shows how the Basilisk team assembles that stack in a lab before shipping it to production, with concrete numbers and tools you can try today.
Start with the basics, but do them right. In a modern /etc/ssh/sshd_config, force PasswordAuthentication no, KbdInteractiveAuthentication no, PermitRootLogin no and UsePAM yes. For algorithms, restrict KexAlgorithms to sntrup761x25519-sha512@openssh.com,curve25519-sha256, Ciphers to chacha20-poly1305@openssh.com,aes256-gcm@openssh.com and MACs to hmac-sha2-512-etm@openssh.com. sntrup761 has shipped hybrid post-quantum resistance since OpenSSH 9.0, and there is no reason in 2026 not to enable it. Run ssh-audit against the host before and after: the gap between a C+ and an A grade is basically disabling diffie-hellman-group14-sha1 and friends. Treat this as a prerequisite, not a deliverable. Linux Server Hardening: Applying CIS Benchmark Without Breaking Production
The real maturity jump comes when you replace scattered authorized_keys with an internal SSH CA. You generate a CA keypair (ed25519, passphraseless only if it lives in an HSM or offline host), sign user certificates with short TTLs (4 to 12 hours) and distribute only the CA public key through TrustedUserCAKeys on the servers. Users authenticate with a certificate issued by step-ca, Vault SSH or Teleport, tied to corporate SSO. Result: revoking access for a former employee stops being a hunt for authorized_keys across 400 hosts and becomes simply not reissuing the certificate. In internal pentests, this single change breaks half the lateral movement paths based on orphan keys. Active Directory Pentest: Step-by-Step Kerberoasting in a GOAD Lab Lateral Movement in the Lab: SMB, WMI and WinRM with a Detection Focus
The bastion host should not be just any Linux box with SSH open. Think of it as an identity proxy: it accepts the user connection, validates the certificate against the CA, records the whole session (input and output) and opens a second SSH to the target through ProxyJump. Teleport, Boundary and the step-ca + auditd + tlog combo cover this case. In a typical setup we tested for a fintech client, the bastion lived in an isolated VPC with a Security Group allowing only port 22 from the corporate VPN, and internal servers rejected any SSH not coming from the bastion CIDR. That collapses the attack surface from hundreds of IPs to a single monitored chokepoint. Pivoting with Chisel and Ligolo-ng: Segmented Networks in a Pentest Lab
Centralized logging closes the loop. Enable LogLevel VERBOSE in sshd, ship /var/log/auth.log through journald-remote or Fluent Bit into Elastic or Loki, and write Sigma rules to spot patterns like repeated failures followed by success, login with a certificate expiring in under an hour, or suspicious commands via session recording. In a red team simulation it took us 11 minutes to get caught trying to reuse a stolen key because the certificate principal did not match the SSO user. Without that correlation, it would have been days. Anyone who has written detections knows SSH is one of the richest and most underused data sources. Threat Hunting with Sigma and Elastic: From Indicator to Detection Rule Hunting Living-off-the-Land Binaries on Windows with KQL
Do not forget the client side. Force ~/.ssh/config with HashKnownHosts yes, VerifyHostKeyDNS yes when applicable, and use ssh-agent with touch confirmation on a YubiKey (sk-ed25519). For service keys in pipelines, no static keys in CI: issue short certificates via GitHub Actions or GitLab OIDC against your Vault. That eliminates the whole class of incidents where a key leaked in a log stays valid for years. In parallel, audit options: AllowAgentForwarding and StreamLocalBindUnlink can almost always be turned off. Supply Chain Security: Sigstore Signing and Real SBOMs in CI/CD Passwords and MFA: Moving to Passkeys Without Breaking Your Recovery
Practical takeaway: build a lab with three VMs (CA + bastion + target) using step-ca, set an 8-hour TTL, force modern algorithms, run ssh-audit until you hit A, then try to log in with an old key. If you get in, your config is not hardened yet. Repeat the exercise quarterly, rotate the CA key annually, and keep an emergency runbook to revoke and reissue everything in under an hour. SSH remains the favorite door for attackers in 2026 precisely because we treat it as invisible infrastructure. Stop treating it that way.