Hærdning af SSH på Linux i 2026: FIDO2-nøgler, certifikater og post-kvante KEX

Komplet 2026-guide til SSH-hærdning på Linux: FIDO2-hardware-nøgler, certifikat-baseret CA, post-kvante mlkem768x25519, kopier-klar sshd_config og audit med ssh-audit.

SSH-hærdning på Linux 2026: FIDO2 & PQ-KEX

Opdateret: 14. juni 2026

SSH-hærdning på Linux i 2026 betyder fire ting samtidig: deaktiver password-login, kræv FIDO2- eller certifikat-baseret nøgleautentificering, aktivér post-kvante nøgleudveksling (mlkem768x25519-sha256 er standard i OpenSSH 9.9+), og afvis svage MAC- og KEX-algoritmer i sshd_config. Som penetrationstester ser jeg stadig SSH-servere med password-auth og diffie-hellman-group14-sha1 aktiveret. I denne guide angriber jeg dem først og lukker hullerne bagefter (helt ærligt, jeg er stødt på det her oftere end jeg vil indrømme).

  • OpenSSH 9.9 (september 2024) og 10.0 (april 2026) har mlkem768x25519-sha256 som default KEX. Post-kvante hybrid er nu standard, ikke eksperimentelt.
  • FIDO2-resident keys (ed25519-sk) gør private nøgler ikke-eksfiltrerbare; de lever på hardware-token og kræver fysisk touch ved hver login.
  • SSH-certifikater fra en intern CA skalerer langt bedre end authorized_keys og giver dig revokation, gyldighedsperioder og principals.
  • Match-blocks, AllowUsers og AuthenticationMethods publickey,keyboard-interactive:pam giver dig adgangskontrol uden at læne dig på fail2ban alene.
  • ssh-audit (v3.4+, 2026) er den hurtigste måde at validere både klient- og server-konfiguration mod CVE-databaser.
  • Terrapin-angrebet (CVE-2023-48795) kræver [email protected] og CBC-MACs deaktiveret, eller mindst strict-kex forhandling, som er default fra OpenSSH 9.6.

Hvad er den reelle angrebsflade på SSH i 2026?

Når jeg laver eksterne penetrationstests, er SSH stadig en af de fem hyppigste indgange, ikke fordi protokollen er svag, men fordi konfigurationen er gammel. De fire angrebsvinkler jeg bruger oftest:

  1. Credential stuffing mod password-auth. Med 60 GB lækkede credentials og en RDS-instans kan jeg prøve 200.000 par på en time. Hvis PasswordAuthentication yes står i sshd_config, vinder jeg ofte uden eksploit.
  2. Nøgle-eksfiltration fra developer-maskiner. En malware-implant på en laptop kopierer ~/.ssh/id_ed25519, og uden FIDO2 eller agent-forwarding-restriktioner er nøglen brugbar i timer.
  3. Terrapin (CVE-2023-48795) trunkerer den oprindelige KEX-handshake, hvis serveren tillader [email protected] og ikke understøtter strict-kex. På uppatchet RHEL 7 og Ubuntu 18.04 (begge stadig i drift i 2026) virker det stadig.
  4. Forwarded agent abuse. Hvis brugeren har ForwardAgent yes og logger ind på en kompromitteret jump-host, kan jeg bruge deres agent-socket til at pivote videre. (Jeg så det her gå galt i et engagement sidste år, hvor en udvikler havde fået agent-forwarding aktiveret som "midlertidig" fix tre måneder tidligere.)

Hærdnings-køreplanen herunder lukker alle fire. Hvis du allerede har læst min guide til systemd-tjeneste-hærdning, så bemærk at sshd.service selv også fortjener en drop-in med ProtectSystem=strict og NoNewPrivileges=true.

Hærdet sshd_config baseline (kopier-klar)

Læg følgende i /etc/ssh/sshd_config.d/00-hardening.conf (drop-in dir har været understøttet siden OpenSSH 8.2 og overskriver hoved-config). Testet mod OpenSSH 10.0 på Debian 13, Ubuntu 24.04 LTS og RHEL 10:

# /etc/ssh/sshd_config.d/00-hardening.conf

# --- Auth ---
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin no
PermitEmptyPasswords no
ChallengeResponseAuthentication no
UsePAM yes
AuthenticationMethods publickey
MaxAuthTries 3
LoginGraceTime 20
MaxStartups 10:30:60

# --- Krypto: post-kvante hybrid + moderne ciphers ---
KexAlgorithms mlkem768x25519-sha256,[email protected],curve25519-sha256,[email protected]
Ciphers [email protected],[email protected],[email protected]
MACs [email protected],[email protected]
HostKeyAlgorithms ssh-ed25519,[email protected],rsa-sha2-512,[email protected]

# --- Host keys: kun ed25519 og rsa-4096 ---
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key

# --- Forwarding lockdown ---
AllowAgentForwarding no
AllowTcpForwarding no
X11Forwarding no
PermitTunnel no
GatewayPorts no

# --- Sessions ---
ClientAliveInterval 300
ClientAliveCountMax 2
TCPKeepAlive no
Compression no

# --- Logning ---
LogLevel VERBOSE
SyslogFacility AUTHPRIV

Verificér konfigurationen før du genstarter sshd — en syntaksfejl her er den klassiske måde at låse dig ude på en remote server:

sudo sshd -t && sudo systemctl reload ssh

FIDO2-hardware-nøgler med ed25519-sk

FIDO2-nøgler (YubiKey 5, Token2 PIN+, Nitrokey 3) er den største enkelt-forbedring du kan lave i 2026. Den private nøgle forlader aldrig hardware-tokenen, og en typisk angriber kan ikke kopiere den uden fysisk adgang. OpenSSH har understøttet ed25519-sk siden 8.2 (2020), men adoptionen er stadig pinligt lav. Det skal vi rette.

Generér en resident nøgle (den lagres på selve tokenen og kan importeres på en ny maskine med ssh-keygen -K):

# Indsæt token, tryk når den blinker
ssh-keygen -t ed25519-sk -O resident -O application=ssh:prod   -O verify-required -C "felix@laptop-2026"   -f ~/.ssh/id_ed25519_sk

# Public key kopieres til serveren som normalt
ssh-copy-id -i ~/.ssh/id_ed25519_sk.pub [email protected]

-O verify-required tvinger PIN-verifikation oven på touch, hvilket beskytter mod stjålne tokens. -O resident betyder at hvis du sætter tokenen i en ny laptop, henter ssh-keygen -K ~/.ssh/ public-keyen tilbage.

På server-siden behøver du ingen særlig konfiguration. Public-keyen begynder bare med [email protected], og OpenSSH håndterer resten. OpenSSH 9.9 release notes beskriver de seneste forbedringer til sk-keys.

SSH-certifikater og intern CA

For mere end ~10 brugere bliver authorized_keys-spredning hurtigt et compliance-mareridt. SSH-certifikater løser det: én betroet CA-public-key på hver server, kortlivede certifikater (typisk 8 timer) til brugerne, og revokation gennem en KRL-fil.

Opret CA-nøglen (gem den i en HSM eller Vault i produktion):

# Generér CA (kun én gang)
ssh-keygen -t ed25519 -f ~/ca/ssh_user_ca -C "ssh-user-ca-2026"

# Underskriv en bruger-public-key
ssh-keygen -s ~/ca/ssh_user_ca   -I "felix-prod-2026-06-14"   -n felix,admin   -V +8h   -O clear -O permit-pty   ~/.ssh/id_ed25519_sk.pub

# Output: ~/.ssh/id_ed25519_sk-cert.pub

På hver server tilføj i sshd_config.d/00-hardening.conf:

TrustedUserCAKeys /etc/ssh/ssh_user_ca.pub
RevokedKeys /etc/ssh/ssh_revoked_keys
AuthorizedPrincipalsFile /etc/ssh/auth_principals/%u

Og opret /etc/ssh/auth_principals/felix med indholdet felix eller admin. Nu kræver login intet i authorized_keys, kun et gyldigt certifikat med rette principal. HashiCorp Vault, smallstep-CA og Teleport kan alle automatisere udstedelsen mod OIDC.

Post-kvante KEX: mlkem768x25519-sha256

Q-Day er ikke i morgen, men "harvest now, decrypt later" er en reel trussel for fortroligt SSH-traffik. Fra OpenSSH 9.9 (september 2024) er mlkem768x25519-sha256 den foretrukne KEX-algoritme by default. Det er en hybrid af NIST-standardiseret ML-KEM-768 (FIPS 203) og X25519. OpenSSH 10.0 (april 2026) fjernede DSA-host-keys og strammede yderligere op.

Verificér at din session faktisk forhandler PQ-KEX:

ssh -vv [email protected] 2>&1 | grep "kex: algorithm"
# Forventet output:
# debug1: kex: algorithm: mlkem768x25519-sha256

Hvis du ser curve25519-sha256 i stedet, er enten klient eller server på en gammel OpenSSH-version. Tjek med ssh -V: alt under 9.9 bør opgraderes. På RHEL 9 hvor stock-versionen stadig er 8.7, kan du installere openssh fra EPEL-next eller bygge fra OpenSSH portable releases.

Match-blocks og AllowUsers: segmentering inde i sshd

En global hærdet config er ikke nok hvis du har forskellige brugergrupper. Brug Match til at differentiere:

# Tilladte brugere (alt andet afvises før auth)
AllowUsers felix sysop ansible-deploy
AllowGroups ssh-users

# Ansible service-account: nøgle-only, ingen TTY, kun fra deploy-net
Match User ansible-deploy Address 10.20.0.0/24
    PermitTTY no
    ForceCommand /usr/local/bin/ansible-wrapper
    AuthorizedKeysFile /etc/ssh/keys/ansible-deploy

# Admins fra VPN må bruge agent-forwarding til intern Git
Match Group admins Address 10.99.0.0/16
    AllowAgentForwarding yes
    PermitTunnel yes

Kombinér med en stram firewall. Min nftables-guide fra 2026 viser hvordan du begrænser port 22 til en jump-host-CIDR og rate-limiter nye forbindelser. Bemærk: Match-betingelser evalueres i rækkefølge, og kun den sidst matchende blok vinder for hver direktiv. Test altid med sshd -T -C user=ansible-deploy,host=...,addr=10.20.0.5.

Audit med ssh-audit og Lynis

ssh-audit (v3.4 fra februar 2026) er det værktøj, jeg starter med på enhver engagement. Det problemtjekker mod CVE-databaser, foreslår konkret sshd_config og rapporterer i JSON eller policy-format:

# Installer fra PyPI
pipx install ssh-audit

# Audit en server, output JSON til CI
ssh-audit -j bastion.example.com > audit.json

# Generér en policy fra "kendt god" baseline og verificér efterfølgende
ssh-audit -M baseline.txt bastion.example.com
ssh-audit -P baseline.txt staging.example.com

Forvent rød markering på alt under curve25519-sha256, alle sha1-MACs og enhver CBC-cipher. Vil du have det integreret i en bredere host-audit, så kør Lynis bagefter. Den dækker også PAM, sudoers og kernel-parametre.

Skal du stadig bruge Fail2Ban i 2026?

Kort svar: hvis du har PasswordAuthentication no og kun publickey eller certifikat-auth, så nej. Fail2Ban beskytter mod et angreb, du allerede har lukket. Brute-force mod publickey-only kan ikke lykkes, uanset hvor mange forsøg der gøres.

Det Fail2Ban (og det mere moderne CrowdSec) stadig giver dig, er log-støj-reduktion. En åben port 22 på internettet får tusindvis af forsøg i timen, og uden ban-jails bliver din auth.log til hvid støj, så ægte angreb drukner. Min anbefaling:

  • Hvis SSH er på en VPN eller jump-host bag WireGuard: spring Fail2Ban over. nftables med limit rate 5/minute er nok.
  • Hvis SSH er offentlig: kør CrowdSec med crowdsecurity/sshd scenario og delt blocklist-konsensus. Det skalerer bedre end Fail2Bans regex-pr.-host model.
  • Til detection af succesfulde anomale logins: Wazuh eller auditd er det rigtige værktøj. Se min Wazuh-installationsguide.

Sikker agent-forwarding og jump-host-arkitektur

Globalt AllowAgentForwarding no i baseline-configen er det rigtige default, men i praksis har du brug for at hoppe gennem bastioner. Løsningen er ikke at åbne agent-forwarding bredt. Brug i stedet ProxyJump (alias -J), som lader klient-til-mål-tunnellen være end-to-end-krypteret uden at eksponere agent-socketet på bastion-værten:

# ~/.ssh/config (moderne jump-host syntax)
Host bastion
    HostName bastion.example.com
    User felix
    IdentityFile ~/.ssh/id_ed25519_sk
    IdentitiesOnly yes

Host prod-*
    User sysop
    ProxyJump bastion
    IdentityFile ~/.ssh/id_ed25519_sk
    IdentitiesOnly yes
    # Tving certifikat-baseret host-key verifikation
    CASignatureAlgorithms ssh-ed25519
    VerifyHostKeyDNS yes
    StrictHostKeyChecking yes

Hvis du skal forwarde en agent (f.eks. til at hente fra en intern Git-server uden at lagre en deploy-nøgle på bastion), brug da en begrænset agent via ssh-agent-fork eller en agent-confined socket. Min tommelfingerregel: bastion-værter bør køre AllowAgentForwarding no, og kun en lille mængde betroede admin-jump-hosts i et separat Match Group-blok må forwarde.

Bemærk også at ControlMaster auto + ControlPersist 10m giver dig multiplexed forbindelser (én TCP-session, flere SSH-channels). Det reducerer login-latency dramatisk uden at svække sikkerheden, da selve handshaken stadig sker én gang med fuld kryptografi.

Ofte stillede spørgsmål

Hvilke SSH-ciphers er sikre i 2026?

Brug kun [email protected], [email protected] og [email protected]. Fjern alle CBC-ciphers og alt med -sha1, da de er sårbare over for Terrapin (CVE-2023-48795) og Sweet32. ETM-MACs ([email protected]) skal foretrækkes over E&M-varianter.

Er ed25519 stadig sikker mod kvante-computere?

Ed25519 alene er ikke kvante-sikker som signatur-algoritme, men host-key-truslen er begrænset: en kvante-computer skal angribe nøglen i realtid under handshake, ikke fra logget trafik. Det er nøgleudvekslingen (KEX), der haster, og derfor mlkem768x25519-sha256. For brugersignaturer på langt sigt forventes hybrid ML-DSA i OpenSSH 11.

Hvordan deaktiverer jeg SSH password-login uden at låse mig ude?

Test publickey-login fra en anden terminal først. Sæt så PasswordAuthentication no, KbdInteractiveAuthentication no og UsePAM yes (PAM er stadig nødvendig for session-setup). Kør sshd -t, derefter systemctl reload ssh. Reload (ikke restart) bevarer eksisterende sessioner, så du har en livline, hvis noget går galt.

Hvad er forskellen på SSH-certifikater og authorized_keys?

authorized_keys kræver at hver public-key kopieres til hver server. SSH-certifikater bruger en intern CA: serveren stoler på CA'en, og brugere får kortlivede signerede certifikater (typisk 8-24 timer). Det giver dig revokation, gyldighedsperioder og principals, og det er ideelt fra ~10 brugere og opefter.

Skal jeg ændre SSH-porten fra 22 til noget tilfældigt?

Port-skifte er security-by-obscurity og stopper kun script-kiddies. Det reducerer log-støj, ikke reel risiko. Hvis du allerede har PasswordAuthentication no og rate-limiter port 22 i firewallen, vinder du ingenting. Brug i stedet en jump-host eller WireGuard.

Felix Lindqvist
Om Forfatteren Felix Lindqvist

Penetration tester and OSCP holder. Reverse engineers misconfigured servers for a living and writes about what he finds.