SSH beveiligen: inloggen met sleutel, rootlogin blokkeren, wachtwoordlogin uitschakelen

Gepubliceerd op 16 min leestijd

ed25519 onder Linux, macOS en Windows, de cloud-init-valkuil in /etc/ssh/sshd_config.d, socketactivering onder Ubuntu 24.04, het bewijs via sudo sshd -T en de weg terug via de console.

Een net opgezette server staat een paar minuten na de eerste bereikbaarheid al in de lijsten van de scanners. Wat daar binnenkomt, is bijna altijd hetzelfde: geautomatiseerd uitproberen van gebruikersnamen en wachtwoorden op poort 22. Wie de wachtwoordauthenticatie uitschakelt en uitsluitend sleutels toelaat, ontneemt die hele categorie aanvallen de basis. Niet afgezwakt, maar volledig.

De basisstappen kennen de meesten wel. Wat in de gebruikelijke handleidingen ontbreekt, is het deel daarna: waarom PasswordAuthentication no op cloud-images geregeld zonder effect blijft, waarom een systemctl reload ssh op een server met een actieve ssh.socket niet meer doet wat u verwacht, en hoe u aantoont in plaats van hoopt dat de wijziging echt aankomt. Precies daar gaat dit artikel over. Alle gegevens hebben betrekking op Debian 13, Debian 12, Ubuntu 24.04 en Ubuntu 22.04.

De regel die alles redt: twee sessies

Open een tweede terminalvenster en log daarin eveneens op de server in, voordat u ook maar iets aan de SSH-configuratie verandert. Die tweede sessie blijft open totdat u de nieuwe configuratie met een derde, volledig nieuwe verbinding met succes hebt getest.

De reden is technisch: een herstart van de SSH-service beëindigt bestaande sessies niet. Lopende verbindingen worden bediend door kindprocessen die al waren afgesplitst, en die overleven de herstart van het bovenliggende proces. Een kapotte configuratie merkt u dus pas bij de volgende verbindingsopbouw, en dan is de oude sessie uw enige weg terug. Wie die sluit om "even netjes opnieuw in te loggen", krijgt daar met enige regelmaat spijt van.

Controleer daarnaast welke OpenSSH-versie u voor u hebt, want daar hangen meerdere details van af:

ssh -V
SysteemOpenSSHListener standaard
Debian 13 (trixie)10.0p2ssh.service
Debian 12 (bookworm)9.2p1ssh.service
Ubuntu 24.04 LTS9.6p1ssh.socket
Ubuntu 22.04 LTS8.9p1ssh.service

Ontbreekt de serverdienst helemaal, bijvoorbeeld in een minimale image, installeer hem dan alsnog:

sudo apt update
sudo apt install -y openssh-server

Sleutels aanmaken: ed25519 onder Linux, macOS en Windows

Neem ed25519. Kort, snel te controleren, ruime veiligheidsmarge, en elke hier behandelde OpenSSH-versie ondersteunt het. RSA hebt u alleen nog nodig voor oude systemen die niets anders accepteren, en dan met minimaal 4096 bit.

Linux en macOS

ssh-keygen -t ed25519 -a 100 -C "hani@notebook" -f ~/.ssh/id_ed25519

-a 100 verhoogt het aantal KDF-rondes voor de wachtwoordzin en maakt offline aanvallen op het sleutelbestand aanzienlijk duurder. -C zet een commentaar dat later in authorized_keys staat en u verklapt welke sleutel van welk apparaat komt. Geef een wachtwoordzin op. Een sleutel zonder wachtwoordzin is een bestand dat iedereen kan meenemen die even achter uw computer zit.

Zodat u de wachtwoordzin niet bij elke verbinding hoeft in te typen, neemt de agent het tijdelijk opslaan over:

eval "$(ssh-agent -s)" && ssh-add ~/.ssh/id_ed25519

Onder macOS legt u de wachtwoordzin in plaats daarvan in de sleutelbos. De vroegere schakelaar -K heet sinds macOS 12 --apple-use-keychain:

ssh-add --apple-use-keychain ~/.ssh/id_ed25519

Wilt u dat dit een herstart overleeft, dan hoort het volgende in ~/.ssh/config:

Host *
    UseKeychain yes
    AddKeysToAgent yes
    IdentityFile ~/.ssh/id_ed25519

Windows

Windows 10 vanaf versie 1809, Windows 11 en Windows Server vanaf 2019 leveren de OpenSSH-client mee. In PowerShell:

ssh -V
ssh-keygen -t ed25519 -a 100 -C "hani@windows"

De sleutel belandt in C:\Users\UwNaam\.ssh\. Ontbreekt de client, installeer hem dan alsnog als Windows-onderdeel:

Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0

De agent is onder Windows een systeemservice en staat bij levering uitgeschakeld:

Get-Service ssh-agent | Set-Service -StartupType Automatic
Start-Service ssh-agent
ssh-add $env:USERPROFILE\.ssh\id_ed25519

De publieke sleutel naar de server brengen

Op de server hoort uitsluitend het bestand met de extensie .pub. Het bestand zonder extensie is de private sleutel en verlaat uw computer nooit.

De comfortabele weg onder Linux

ssh-copy-id -i ~/.ssh/id_ed25519.pub root@203.0.113.10

ssh-copy-id maakt ~/.ssh aan, zet de rechten correct, hangt de sleutel achter authorized_keys en controleert daarbij of hij er al staat. Onder macOS zit het gereedschap niet in elke versie. Controleer dat even met command -v ssh-copy-id en wijk anders uit naar de handmatige weg.

De Windows-weg zonder ssh-copy-id

De OpenSSH-client van Microsoft bevat ssh-copy-id niet. Het origineel is een shellscript en is nooit geport. Hetzelfde resultaat bereikt u met een pipe:

type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh root@203.0.113.10 "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

Hier schuilt een detail dat veel uren kost: PowerShell hangt er bij het doorgeven aan een extern programma regeleinden in Windows-formaat achter. In authorized_keys staat dan een onzichtbaar regelterugloopteken aan het einde van de regel. Zolang u de sleutel met -C van commentaar hebt voorzien, belandt dat teken in het commentaarveld en stoort het niet. Zonder commentaar plakt het aan het Base64-blok en mislukt het inloggen zonder bruikbare melding. Dus: altijd een commentaar meegeven, en bij twijfel op de server even opruimen.

sed -i 's/\r$//' ~/.ssh/authorized_keys

De handmatige weg, die overal werkt

mkdir -p ~/.ssh && chmod 700 ~/.ssh && touch ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys

Voeg daarna de inhoud van het .pub-bestand als één enkele regel toe. Staat het bestand al op de server, bijvoorbeeld omdat u het hebt geüpload, dan kan dat rechtstreeks:

cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys

Controleer vervolgens wat er werkelijk in het bestand terecht is gekomen:

ssh-keygen -lf ~/.ssh/authorized_keys

De uitvoer somt de vingerafdruk en het commentaar van elke geldige regel op. Wat hier niet verschijnt, is afgebroken of beschadigd. Vergelijk de vingerafdruk met die van uw lokale sleutel:

ssh-keygen -l -f ~/.ssh/id_ed25519.pub

Komen beide overeen, dan is het transport netjes verlopen. Test nu, voordat u ook maar iets uitschakelt, of het inloggen met de sleutel daadwerkelijk werkt. Pas wanneer een nieuwe verbinding zonder wachtwoordvraag doorkomt, gaat u verder.

De valkuil: /etc/ssh/sshd_config.d en cloud-init

Dit is het punt waar de meeste handleidingen ophouden, en de meest voorkomende reden voor de zin "ik heb het uitgeschakeld en toch werkt het nog".

Sinds Debian 11 en Ubuntu 22.04 staat helemaal bovenaan in /etc/ssh/sshd_config een regel die een hele map inleest. Kijk zelf na op welke positie die staat:

grep -n Include /etc/ssh/sshd_config

Op alle vier de hier behandelde systemen staat de Include-regel aan het begin, niet aan het eind. En dan komt de eigenaardigheid van OpenSSH die u uit vrijwel geen enkele andere configuratietaal kent: de eerst gevonden waarde wint, niet de laatste. Wat in een bestand onder /etc/ssh/sshd_config.d/ staat, wordt dus vóór het hoofdbestand gelezen en verslaat elke latere regel in sshd_config.

Cloud-init gebruikt precies die map. Bij de eerste start schrijft het /etc/ssh/sshd_config.d/50-cloud-init.conf, en afhankelijk van de uitrol staat daar PasswordAuthentication yes in. U kunt daarna in sshd_config zo vaak PasswordAuthentication no zetten als u wilt: de wachtwoordauthenticatie blijft open. Begin daarom met een overzicht:

ls -la /etc/ssh/sshd_config.d/
sudo grep -riE 'passwordauthentication|permitrootlogin|kbdinteractive' /etc/ssh/sshd_config /etc/ssh/sshd_config.d/

Daaruit volgt de eigenlijke aanbeveling: raak sshd_config helemaal niet aan. Maak in plaats daarvan een eigen bestand aan waarvan de naam alfabetisch vóór alles sorteert wat de automatisering daar neerzet. De bestanden worden in gesorteerde volgorde ingelezen, 01- komt vóór 50-, en omdat de eerste waarde wint, mag cloud-init zijn bestand daarna zo vaak herschrijven als het wil zonder uw hardening te ondermijnen. Dat is het verschil met het wijdverbreide advies om een 99-hardening.conf aan te maken: die verliest van cloud-init, en wel geruisloos. Dezelfde mechaniek kan zich echter ook tegen u keren: een bestand met een lager nummer, bijvoorbeeld 00-cloud.conf, wint van uw 01-, omdat OpenSSH de eerst gelezen waarde neemt. Een blik in de map loont daarom ook na de hardening.

De hardening schrijven, met een tijdklok als terugvaloptie

Bouw eerst het vangnet. Het volgende commando verwijdert uw nieuwe bestand over tien minuten automatisch en start SSH opnieuw, als u het tot dan toe niet hebt afgebroken:

sudo systemd-run --on-active=10min --unit=ssh-rollback /bin/sh -c 'rm -f /etc/ssh/sshd_config.d/01-hardening.conf; systemctl try-restart ssh.socket ssh.service'

Nu de eigenlijke configuratie:

sudo tee /etc/ssh/sshd_config.d/01-hardening.conf >/dev/null <<'EOF'
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin prohibit-password
PermitEmptyPasswords no
MaxAuthTries 3
EOF
sudo chmod 644 /etc/ssh/sshd_config.d/01-hardening.conf

Twee regels verdienen uitleg. KbdInteractiveAuthentication no is geen bijzaak: blijft die op yes staan, dan kan PAM de wachtwoordvraag via de omweg van de interactieve toetsenbordinvoer alsnog aanbieden, hoewel PasswordAuthentication op no staat. Precies daarom zijn er servers die ondanks een uitgeschakelde wachtwoordauthenticatie toch om een wachtwoord vragen.

En PermitRootLogin prohibit-password in plaats van no: daarmee blijft de toegang als root via een sleutel behouden, terwijl wachtwoorden voor root uitgesloten zijn. Hebt u een eigen gebruiker met sudo ingericht en het inloggen met sleutel daarvan aantoonbaar getest, zet dan PermitRootLogin no. Eerder niet.

Wat u niet moet overnemen, ook al staat het in oudere handleidingen: ChallengeResponseAuthentication. De optie is sinds OpenSSH 8.7 nog slechts een verouderde aliasnaam voor KbdInteractiveAuthentication en levert in actuele versies een deprecated-melding in het log op. Laat hem weg.

Syntaxcontrole vóór het activeren, zonder uitzondering:

sudo sshd -t

Geen uitvoer betekent: het bestand is syntactisch in orde. Het betekent niet dat het inhoudelijk doet wat u wilt. Daarvoor is zo meteen sudo sshd -T aan de beurt.

Meldt de test in plaats daarvan Missing privilege separation directory: /run/sshd, dan heeft sshd sinds de start van het systeem nog geen enkele keer gedraaid, want die map ontstaat pas met ssh.service. Dat treft vooral Ubuntu 24.04 met socketactivering en is met sudo mkdir -p /run/sshd of sudo systemctl start ssh.service op te lossen. Op een server waarop u op dat moment via SSH bent ingelogd, doet het zich sowieso niet voor.

Activeren: ssh.service, ssh.socket en de verschillen per distributie

Hier lopen de vier systemen uiteen, en de oude gewoonte systemctl reload ssh is overal waar ssh.socket de poort vasthoudt het verkeerde antwoord.

Ubuntu zet sinds 22.10 in op socketactivering en Ubuntu 24.04 levert die standaard uit: daar is ssh.socket ingeschakeld en ssh.service uitgeschakeld. Debian doet het van huis uit precies andersom. Debian 13 en Debian 12 leveren ssh.service ingeschakeld en ssh.socket uitgeschakeld uit, in tegenstelling tot de wijdverbreide aanname dat Debian 13 bij een nieuwe installatie op de socket overstapt. Bij socketactivering luistert systemd zelf op poort 22 en start het pas bij een binnenkomende verbinding een nieuwe sshd. Dat heeft een prettig neveneffect: wijzigingen in sshd_config werken bij de volgende verbinding sowieso, omdat elk verbindingsproces de configuratie opnieuw inleest. Opnieuw laden hebt u alleen nodig voor instellingen die de listener zelf betreffen, dus Port en ListenAddress.

Gok dus niet, maar vraag het systeem welke unit bij u de dienst verzorgt:

systemctl is-enabled ssh.socket ssh.service
Systeemssh.socketssh.serviceBijzonderheid
Ubuntu 24.04 LTSenableddisabledSocketactivering standaard, ListenStream op 0.0.0.0:22 en [::]:22
Debian 13 (trixie)disabledenabledAccept=no
Debian 12 (bookworm)disabledenabledAccept=no
Ubuntu 22.04 LTS (en eveneens Debian 11)disabledenabledAccept=yes, dus een eigen proces per verbinding via ssh@.service

En dan een commando dat op alle vier de systemen klopt:

sudo sshd -t && sudo systemctl try-restart ssh.socket ssh.service

try-restart herstart een unit alleen wanneer die daadwerkelijk actief is en laat de andere ongemoeid. Zo hoeft u niet te gokken. Beide delen hebben root nodig: sshd staat onder /usr/sbin en zit op Debian niet in het PATH van een gewone gebruiker, en try-restart spreekt sowieso systemd aan. Zonder sudo eindigt de aanroep afhankelijk van het systeem met sshd: command not found of met sshd: no hostkeys available, omdat de hostsleutels onder /etc/ssh alleen voor root leesbaar zijn.

Net zo bewust geen los systemctl restart ssh.socket, ook al staat dat commando in veel handleidingen. Op Debian 13 en Debian 12 breekt het af met Job failed. See journalctl -xe for details., en in het journal staat daarbij ssh.socket: Socket service ssh.service already active, refusing. De nieuwe configuratie wordt daarbij niet actief, de tegenproef meldt nog steeds Permission denied (publickey,password). Op Ubuntu 22.04 en Debian 11 loopt het weliswaar zonder foutmelding door, maar stopt het daarbij ssh.service en zet het de host om op socketactivering. Omdat ssh.socket daar uitgeschakeld blijft, springt bij de volgende herstart weer ssh.service aan, de bedrijfsmodus wisselt dus ongemerkt heen en weer. try-restart op beide units voorkomt beide problemen.

Bewust ook geen reload: op een systeem waarop ssh.socket de poort vasthoudt, antwoordt een systemctl reload ssh met

fatal: Cannot bind any address.

Daarna staat de dienst in de foutstatus en heeft hij zijn poort losgelaten. Een herstart heeft dat probleem niet en beëindigt bestaande sessies evenmin.

Wilt u de poort verplaatsen, dan stuit u op het volgende verschil tussen de distributies. Ubuntu 24.04 maakt de socketconfiguratie via een systemd-generator uit sshd_config, daar volstaat na de poortwijziging:

sudo systemctl daemon-reload
sudo systemctl try-restart ssh.socket ssh.service

Bent u op Debian daarentegen bewust op ssh.socket overgestapt, dan staat de poort in de unit zelf en blijft een wijziging in sshd_config zonder effect. U legt hem vast via een aanvullend bestand met sudo systemctl edit ssh.socket, met een lege ListenStream= om terug te zetten en een tweede regel met de nieuwe waarde. Toets het resultaat daarna aan de werkelijkheid, niet aan de configuratie:

sudo ss -tlnp

Bewijs: sshd -T en de tegenproef

Een commando dat zonder fout doorloopt, is geen bewijs. Het bewijs is de volledig uitgewerkte configuratie, waarin alle ingelezen bestanden al zijn verrekend:

sudo sshd -T | grep -E '^(passwordauthentication|kbdinteractiveauthentication|pubkeyauthentication|permitrootlogin|usepam|port|authorizedkeysfile)'

Verwacht wordt een uitvoer in deze trant:

port 22
permitrootlogin prohibit-password
pubkeyauthentication yes
passwordauthentication no
kbdinteractiveauthentication no
usepam yes
authorizedkeysfile .ssh/authorized_keys .ssh/authorized_keys2

Staat daar ondanks uw bestand passwordauthentication yes, dan ligt er in de map een bestand dat alfabetisch vóór het uwe sorteert. Terug naar het onderdeel over de volgorde.

Voor een losse controle volstaat hetzelfde commando met een nauwer filter:

sudo sshd -T | grep -i passwordauthentication

Er zijn twee redenen om er sudo voor te zetten. Ten eerste leest sshd -T de hostsleutels, die onder /etc/ssh alleen voor root leesbaar zijn. Ten tweede staat sshd zelf onder /usr/sbin, en die map hoort op Debian niet bij het PATH van een gewone gebruiker, waardoor de aanroep zonder sudo daar met sshd: command not found eindigt. Wie de weg via sudo wil vermijden, schrijft het volledige pad /usr/sbin/sshd.

Vanaf OpenSSH 9.3, dus op Ubuntu 24.04 (9.6p1) en Debian 13 (10.0p2), bestaat daarnaast sshd -G. De optie evalueert dezelfde configuratie, maar vraagt geen leesbare hostsleutels en geen bestaande /run/sshd, wat de schakelaar bruikbaar maakt voor controles in automatisering en containers. Op Debian 12 (9.2p1), Ubuntu 22.04 (8.9p1) en Debian 11 (8.4p1) bestaat hij nog niet, daar wijst sshd hem af als onbekende optie. Voor een handleiding die overal geldt, blijft sudo sshd -T daarom de juiste keuze.

Nu de tegenproef, en wel vanuit een nieuw terminalvenster, terwijl de oude sessie open blijft. Forceer het inloggen met wachtwoord en schakel sleutels voor deze poging uit:

ssh -o PubkeyAuthentication=no -o PreferredAuthentications=password,keyboard-interactive root@203.0.113.10

Goed is het wanneer u onmiddellijk en zonder enige wachtwoordvraag wordt afgewezen:

root@203.0.113.10: Permission denied (publickey).

Doorslaggevend is wat er tussen de haakjes staat. Staat daar (publickey,password) of verschijnt er een wachtwoordvraag, dan is de wachtwoordauthenticatie nog altijd open. Pas wanneer de tegenproef netjes mislukt en een gewone verbinding met sleutel nog steeds lukt, sluit u de oude sessie en stopt u de tijdklok:

sudo systemctl stop ssh-rollback.timer

Foutmeldingen letterlijk

Permission denied (publickey). De server accepteert alleen sleutels en die van u past niet. Roep ssh -v aan en kijk na welk bestand er eigenlijk is aangeboden. Meest voorkomende oorzaken: een verkeerde gebruikersnaam, de sleutel in de authorized_keys van de verkeerde gebruiker, of u hebt root geblokkeerd en logt nog altijd als root in.

Authentication refused: bad ownership or modes for directory /home/hani/.ssh Deze regel staat niet op uw scherm, maar in het log van de server, zichtbaar via sudo journalctl -u ssh -n 50 --no-pager. Filter daarbij niet op -t sshd: vanaf OpenSSH 9.8, op Debian 13 dus al bij levering, draaien de sessies in het eigen proces sshd-session, en onder de tag sshd blijven dan alleen meldingen van de listener over en geen enkele inlogpoging. Wie op tags wil filteren, neemt sudo journalctl -t sshd -t sshd-session -n 50 --no-pager. OpenSSH weigert sleutels wanneer de thuismap, .ssh of authorized_keys schrijfbaar zijn voor de groep of voor anderen. De correctie:

chmod go-w ~ && chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys

WARNING: UNPROTECTED PRIVATE KEY FILE! oftewel Load key "/home/hani/.ssh/id_ed25519": bad permissions. Hetzelfde probleem aan de clientkant. chmod 600 ~/.ssh/id_ed25519 lost het op.

Too many authentication failures Uw agent biedt om de beurt alle geladen sleutels aan en overschrijdt daarbij MaxAuthTries. Beperk de verbinding tot één enkele sleutel: ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519 hani@203.0.113.10.

sign_and_send_pubkey: no mutual signature supported Een oude RSA-sleutel met SHA-1-handtekening komt uit bij een server die dat niet meer accepteert. Maak een ed25519-sleutel aan in plaats van aan PubkeyAcceptedAlgorithms te sleutelen.

Bad owner or permissions on C:\Users\hani\.ssh\config De Windows-client controleert de toegangsrechten van zijn configuratiebestand. Verwijder in de bestandseigenschappen onder Beveiliging de overerving en alle vermeldingen behalve uw eigen gebruikersaccount en SYSTEM.

WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! De hostsleutel van de server is een andere dan de vorige keer. Na een herinstallatie is dat te verwachten, anders niet. Verwijder de oude regel gericht met ssh-keygen -R 203.0.113.10, en alleen wanneer u de reden kent.

Buitengesloten: de weg via de console in het klantenpaneel

Zijn beide sessies weg en komt er geen verbinding meer tot stand, dan is dat geen dataverlies maar een omweg. Elke KVM-rootserver en elke dedicated server bij KernelHost heeft in het klantenpaneel een console die op de beeldschermuitvoer van het systeem zit en losstaat van de netwerkstack van de server. U komt er dus ook binnen wanneer SSH helemaal niet meer luistert.

  1. Log in op het klantenpaneel, open de betreffende server en start de console.
  2. Log bij de inlogprompt in als root met het wachtwoord dat bij de oplevering is uitgegeven. Het inloggen op de console loopt niet via SSH en wordt door PermitRootLogin niet beïnvloed.
  3. Draai de wijziging terug: sudo rm /etc/ssh/sshd_config.d/01-hardening.conf
  4. Controleren en herstarten: sudo sshd -t && sudo systemctl try-restart ssh.socket ssh.service
  5. Draait SSH helemaal niet, dan helpen sudo systemctl status ssh.socket ssh.service en een blik in sudo journalctl -u ssh -n 50 --no-pager. De retourwaarde 3 bij status betekent alleen dat een van beide units inactief is, op Debian is dat met de uitgeschakelde ssh.socket het normale geval.

Twee voorzorgsmaatregelen besparen u deze weg bijna altijd. Noteer het rootwachtwoord voordat u de wachtwoordauthenticatie uitschakelt, want de console heeft het nodig. En controleer een actieve firewall voordat u de SSH-poort verplaatst. Een poortwissel zonder bijpassende vrijgave sluit u net zo betrouwbaar buiten als een kapotte sshd_config, maar ziet er anders uit: in plaats van Permission denied krijgt u Connection timed out.

Kort samengevat

  • Laat de tweede sessie open totdat een derde, nieuwe verbinding aantoonbaar werkt.
  • ed25519 met -a 100 en een wachtwoordzin, de publieke sleutel via ssh-copy-id, onder Windows via een pipe.
  • Test het inloggen met sleutel voordat de wachtwoordauthenticatie sneuvelt.
  • Hardening in /etc/ssh/sshd_config.d/01-hardening.conf, niet in sshd_config. De eerst gevonden waarde wint, vandaar het lage nummer.
  • KbdInteractiveAuthentication no niet vergeten, anders blijft de omweg via PAM open.
  • Activeren met sudo sshd -t && sudo systemctl try-restart ssh.socket ssh.service, niet met reload en ook niet met een los restart ssh.socket.
  • Stel vooraf met systemctl is-enabled ssh.socket ssh.service vast welke unit er eigenlijk actief is. Ubuntu 24.04 gebruikt de socket, Debian 13 en Debian 12 de service.
  • Het bewijs levert u met sudo sshd -T en een geforceerde wachtwoordpoging vanuit een nieuwe sessie.
  • De noodweg is de console in het klantenpaneel, houd daarvoor het rootwachtwoord bij de hand.

De voor de hand liggende volgende lagen beschrijven onze artikelen over fail2ban en over de UFW-firewall. Belangrijker dan die twee is wat u zojuist hebt gedaan.

Veelgestelde vragen

Waarom blijft de wachtwoordauthenticatie ondanks PasswordAuthentication no actief?
Bijna altijd door een bestand in /etc/ssh/sshd_config.d/, meestal 50-cloud-init.conf. De Include-regel staat op Debian en Ubuntu aan het begin van sshd_config, en OpenSSH neemt de eerst gevonden waarde over, niet de laatste. Wat in die map ligt, wint dus van het hoofdbestand. Controleer met sudo sshd -T wat er werkelijk geldt en maak uw eigen bestand aan als 01-hardening.conf, zodat het vóór alle automatisch aangemaakte bestanden wordt gelezen.
Moet ik na een wijziging in sshd_config de dienst opnieuw starten?
Op Debian 13, Debian 12 en Ubuntu 22.04 wel, daar is ssh.service standaard ingeschakeld en ssh.socket uitgeschakeld. Op Ubuntu 24.04 luistert systemd standaard via ssh.socket en start het per verbinding een nieuwe sshd, die de configuratie sowieso opnieuw inleest. Alleen Port en ListenAddress betreffen de listener zelf. Welke unit bij u actief is, laat systemctl is-enabled ssh.socket ssh.service zien. Het commando sudo sshd -t && sudo systemctl try-restart ssh.socket ssh.service klopt op alle vier de systemen, een los systemctl restart ssh.socket daarentegen niet: op Debian 13 en Debian 12 mislukt het en wordt de nieuwe configuratie niet actief, op Ubuntu 22.04 zet het de host ongemerkt om op socketactivering.
Waarom kan ik reload beter vermijden?
Op systemen met een actieve ssh.socket, standaard dus op Ubuntu 24.04, breekt systemctl reload ssh af met de melding fatal: Cannot bind any address, komt de dienst in de foutstatus terecht en geeft hij zijn poort vrij. Een herstart heeft dat probleem niet en beëindigt bestaande sessies evenmin, omdat lopende verbindingen door eigen kindprocessen worden bediend.
Hoe krijg ik mijn sleutel vanuit Windows op de server als ssh-copy-id daar ontbreekt?
Via een pipe: type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh gebruiker@server "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys". Let erop dat u de sleutel met -C van commentaar hebt voorzien, anders kan een door PowerShell toegevoegd regelterugloopteken het Base64-blok beschadigen. Op de server ruimt sed -i 's/\r$//' ~/.ssh/authorized_keys dat op.
Hoe toon ik aan dat de wachtwoordauthenticatie werkelijk dicht is?
Met twee stappen. Ten eerste sudo sshd -T, dat de volledig uitgewerkte configuratie toont en waarin passwordauthentication no en kbdinteractiveauthentication no moeten staan. Ten tweede een tegenproef vanuit een nieuwe sessie: ssh -o PubkeyAuthentication=no -o PreferredAuthentications=password,keyboard-interactive gebruiker@server moet onmiddellijk met Permission denied (publickey). worden afgewezen. Staat er tussen de haakjes publickey,password, dan is de toegang nog open.
Wat doe ik als ik mezelf heb buitengesloten?
Log in op het klantenpaneel, open de server en start de console. Die hangt aan de beeldschermuitvoer van het systeem en staat los van SSH. Log daar in als root, verwijder uw eigen bestand met sudo rm /etc/ssh/sshd_config.d/01-hardening.conf, controleer met sudo sshd -t en herstart met sudo systemctl try-restart ssh.socket ssh.service. Houd het rootwachtwoord bij de hand voordat u de wachtwoordauthenticatie uitschakelt.
Is PermitRootLogin no of prohibit-password de betere keuze?
prohibit-password laat root nog altijd via een sleutel toe en sluit alleen wachtwoorden uit, waardoor de toegang bij een foutieve configuratie behouden blijft. no is strenger, maar vereist dat er een tweede gebruiker met sudo bestaat en dat het inloggen met sleutel daarvan al aantoonbaar werkt. Stap pas over wanneer die test is geslaagd.

SSH Serverbeveiliging Linux Debian Ubuntu OpenSSH ed25519 systemd cloud-init Handleiding