Wachtwoordauthenticatie via SSH is het grootste blootgestelde oppervlak van een gewone server. Daar kunnen Fail2ban noch enige drempel iets tegen: duizend adressen met één poging per uur halen nooit een limiet, en ze blijven precies zolang proberen als proberen mogelijk is. Sleutels nemen die mogelijkheid zelf weg, en van de hele hardeningslijst is dit de enige instelling die de situatie wezenlijk verandert.
Slechts één ding daaraan is beangstigend: het wachtwoord uitzetten en buiten blijven staan. Dit is de volgorde waarin dat niet kan gebeuren.
De sleutel
Wordt op uw eigen machine gemaakt, niet op de server:
ssh-keygen -t ed25519 -C "werklaptop"
ed25519 in plaats van RSA: korter, sneller en zonder vragen over de lengte. RSA is alleen nodig als u iets heel ouds moet bereiken; dan -t rsa -b 4096.
Een wachtwoordzin op de sleutel zetten loont: het sleutelbestand kan van een laptop worden gestolen, en zonder wachtwoordzin werkt het meteen. Intypen hoeft u hem niet elke keer — daar zorgt ssh-agent voor, en op macOS en de meeste Linux-desktops draait die al.
Het kopiëren naar de server is één commando, zolang het wachtwoord nog werkt:
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@203.0.113.25
Is ssh-copy-id niet beschikbaar, dan wordt de inhoud van het .pub-bestand als regel toegevoegd aan ~/.ssh/authorized_keys op de server. De rechten doen ertoe: de map .ssh op 700, het bestand op 600, eigendom van de gebruiker zelf. Bij andere rechten weigert sshd stilzwijgend het bestand te lezen, en dat is de vaakst voorkomende oorzaak van «de sleutel werkt niet».
De controle die de doorslag geeft
Open, voordat u iets uitzet, een tweede verbinding zonder de eerste te sluiten:
ssh -o PasswordAuthentication=no user@203.0.113.25
De optie verbiedt de cliënt terug te vallen op een wachtwoord — lukt de aanmelding, dan lukte ze met de sleutel. Zolang dat commando niet doorkomt, gaat u niet verder. En houd de eerste verbinding tot het eind open: daarmee repareert u alles wat u stukmaakt.
Het afsluiten en één weinig voor de hand liggende valkuil
De instellingen gaan in een apart bestand zodat een pakketupdate ze niet wist. Maar de bestandsnaam doet ertoe:
sudo tee /etc/ssh/sshd_config.d/10-hardening.conf <<'EOF'
PasswordAuthentication no
PermitRootLogin no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
LogLevel VERBOSE
EOF
Het punt is dat OpenSSH de eerste verkregen waarde van een parameter gebruikt, en niet de laatste zoals vrijwel overal elders. De bestanden in sshd_config.d worden alfabetisch gelezen, en cloud-images van Ubuntu leggen daar 50-cloud-init.conf neer, waarin vaak PasswordAuthentication yes staat. Uw bestand met nummer 90 doet in die situatie niets: de instelling lijkt aanwezig en het wachtwoord blijft werken. Vandaar nummer 10 — dat wordt eerder gelezen.
Wat er werkelijk uit is gekomen ziet u zonder te gissen:
sudo sshd -T | grep -Ei 'passwordauth|permitrootlogin|pubkeyauth'
Dat commando drukt de werkzame configuratie af na alle insluitingen. Geloof dat, niet de inhoud van de bestanden.
Daarna een syntaxcontrole en een rustig herladen van de dienst:
sudo sshd -t && sudo systemctl reload ssh
sshd -t is verplicht: een tikfout in de configuratie legt de dienst bij restart plat en zet u buiten. reload verbreekt bovendien geen open sessies.
Ubuntu 24.04: de poort zit niet waar u denkt
Een valkuil eigen aan recente Ubuntu-versies: sshd wordt daar via een systemd-socket gestart. In die modus doet de regel Port in sshd_config niets — de socket luistert, niet de daemon. Wijzigt u de poort, dan moet die worden aangepast:
sudo systemctl edit ssh.socket
en ListenStream= (een lege waarde zet de vorige terug) moet de nieuwe poort noemen. Het symptoom dat het verraadt: de configuratie is gewijzigd, de dienst herstart, en de server antwoordt nog steeds op 22.
Over het wijzigen van de poort: als bescherming werkt het niet — scanners vinden een dienst op elke poort binnen minuten. Het enige effect zijn rustiger logboeken, omdat het massale raden alleen naar 22 gaat. Dat is prettig, maar verwar het niet met veiligheid.
Wie er überhaupt mag inloggen
Een nuttige aanvulling is een uitdrukkelijke lijst:
AllowUsers deploy admin
Alles wat er niet in staat wordt afgewezen nog voordat de sleutel wordt gecontroleerd. Dat dekt ook het geval waarin een pakket een systeemgebruiker met shell en thuismap aanmaakt.
Een reserve-ingang
Eén sleutel op één laptop is een enkelvoudig storingspunt. De schijf sterft, de laptop raakt kwijt, en de server is voorgoed onbereikbaar. Een redelijk minimum:
- een tweede sleutel vanaf een ander apparaat in
authorized_keys; - een kopie van de privésleutel in een wachtwoordbeheerder of op een versleutelde stick;
- een beproefde consoletoegang bij de hoster — VNC of serieel. Beproefd betekent dat u er minstens één keer via bent ingelogd, niet dat «er ergens in het paneel een knop is».
Kijk meteen ook wat er al in authorized_keys staat — zowel bij uw gebruiker als bij root. Een vreemde sleutel daar overleeft elke wachtwoordwijziging en blijft werkende toegang.
Daarna
Het raden van wachtwoorden verdwijnt niet, het wordt alleen zinloos: in de logboeken blijven duizenden regels Failed password staan, waarvan er geen enkele met succes kan eindigen. Waar u nu naar moet kijken zijn de geslaagde aanmeldingen: vanaf welk adres, onder welke gebruiker, op welk tijdstip. Een geslaagde sleutelaanmelding vanaf een onbekend adres is een veel belangrijker gebeurtenis dan een miljoen mislukkingen, en veel lastiger op te merken in de algemene stroom. Precies dat beeld toont de demopagina hieronder.