SSH ist der einzige Dienst, über den praktisch jede Verwaltungsaufgabe läuft. Wer ihn übernimmt, hat alles. Gleichzeitig ist er der Dienst, bei dem eine falsche Zeile in der Konfiguration dich selbst aussperrt und zwar sofort und vollständig.
Dieser Beitrag geht deshalb in zwei Richtungen: was du abschalten solltest, und wie du sicherstellst, dass du danach noch reinkommst.
Schlüssel: welcher Typ, und warum#
ssh-keygen -t ed25519 -C "mauri@laptop-2026"
Ed25519 ist der Standardfall: kurze Schlüssel, schnelle Prüfung, keine Parameterwahl, bei der man etwas falsch machen kann. RSA brauchst du nur, wenn eine Gegenstelle wirklich nichts anderes kann, dann mit mindestens 4096 Bit.
Drei Gewohnheiten, die sich lohnen:
- Ein Schlüssel pro Gerät, nicht einer für alles. Geht ein Laptop verloren, entfernst du eine Zeile aus
authorized_keysstatt überall neue Schlüssel zu verteilen. - Der Kommentar am Ende ist Dokumentation.
mauri@laptop-2026verrät in zwei Jahren, welche Zeile weg kann.user@hostverrät nichts. - Passphrase setzen. Der Komfortverlust ist dank
ssh-agentgenau einmal pro Sitzung spürbar.
# Agent starten und Schlüssel einmalig entsperren
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519 # unter macOS: ssh-add --apple-use-keychain
Die Client-Konfiguration, die vieles einfacher macht#
Bevor es an den Server geht: ~/.ssh/config auf deinem Rechner spart jeden Tag Tipparbeit und verhindert, dass du bei zehn Maschinen den falschen Schlüssel anbietest.
Host web01
HostName 203.0.113.10
User mauri
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
Host *
ServerAliveInterval 30
ServerAliveCountMax 3
HashKnownHosts yes
IdentitiesOnly yes ist wichtiger, als es aussieht: ohne diese Zeile bietet der Client dem Server der Reihe nach alle geladenen Schlüssel an. Bei MaxAuthTries 3 auf der Gegenseite ist die Verbindung dann abgelehnt, bevor der richtige Schlüssel dran war.
ServerAliveInterval hält die Sitzung offen, wenn die Leitung kurz stockt und ist der Unterschied zwischen „hängt“ und „ist weg“ bei einer eingefrorenen Verbindung.
Die Server-Konfiguration#
Debian und Ubuntu lesen seit einigen Versionen /etc/ssh/sshd_config.d/*.conf mit ein. Eigene Änderungen gehören dorthin, nicht in die Hauptdatei, dann fragt kein Paket-Update, ob du deine Konfiguration behalten willst.
# /etc/ssh/sshd_config.d/10-haertung.conf
# Kein Root-Login, auch nicht mit Schlüssel: alles läuft über sudo,
# damit in den Protokollen steht, wer etwas getan hat.
PermitRootLogin no
# Passwörter aus. Beide Zeilen sind nötig — die zweite deckt den
# Tastatur-interaktiven Weg ab, über den sich sonst doch ein
# Passwortdialog öffnet.
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
AuthenticationMethods publickey
# Nur diese Konten dürfen sich anmelden. Neue Benutzer müssen bewusst
# hinzugefügt werden — das ist der Sinn der Zeile.
AllowUsers mauri deploy
MaxAuthTries 3
LoginGraceTime 20
X11Forwarding no
AllowAgentForwarding no
Prüfen und laden, in dieser Reihenfolge, nie andersherum:
sudo sshd -t # Syntaxprüfung, gibt bei Fehlern die Zeile aus
sudo systemctl reload ssh # bestehende Sitzungen bleiben offen
Halte während der ganzen Änderung eine zweite, bereits angemeldete SSH-Sitzung offen. reload wirft bestehende Verbindungen nicht raus. Teste den neuen Zugang in einem dritten Fenster, erst wenn der funktioniert, schließt du die alte Sitzung. Ohne diesen Ablauf ist eine vertippte AllowUsers-Zeile eine Neuinstallation.
Match-Blöcke: unterschiedliche Regeln für unterschiedliche Konten#
Ein Deploy-Konto braucht andere Rechte als ein Mensch. Match erlaubt das, ohne einen zweiten SSH-Dienst zu betreiben:
Match User deploy
# Deploy-Schlüssel dürfen nur ein Kommando ausführen, kein interaktives Shell-Login
ForceCommand /usr/local/bin/deploy-hook
PermitTTY no
AllowTcpForwarding no
Match-Blöcke stehen immer am Ende der Datei. Alles nach einem Match gilt nur für diesen Fall, bis der nächste Match kommt, eine allgemeine Einstellung, die versehentlich darunter rutscht, wirkt plötzlich nur noch für einen einzigen Benutzer.
Der gleiche Effekt lässt sich auch pro Schlüssel erreichen, direkt in authorized_keys:
restrict,command="/usr/local/bin/backup-pull" ssh-ed25519 AAAAC3Nz... backup@nas
restrict schaltet alle Weiterleitungen ab und ist damit die sinnvolle Grundhaltung für jeden Schlüssel, der nur einen Job hat.
Port ändern: ja oder nein?#
Ehrliche Antwort: Es hilft gegen Statistik, nicht gegen Angreifer.
Ein anderer Port als 22 reduziert die Menge automatisierter Login-Versuche in den Protokollen um Größenordnungen. Das macht die Protokolle lesbar, ein echter Vorteil, wenn du sie tatsächlich liest. Gegen jemanden, der es auf deine Maschine abgesehen hat, hilft er nicht: ein Portscan findet den Dienst in Sekunden.
Wenn du ihn änderst, dann sauber:
Port 2222
sudo ufw allow 2222/tcp comment 'SSH'
sudo sshd -t && sudo systemctl restart ssh
# Erst testen, dann die alte Regel entfernen:
sudo ufw delete allow 22/tcp
Auf Systemen mit SELinux (RHEL, Rocky, Alma) muss der neue Port zusätzlich freigegeben werden: semanage port -a -t ssh_port_t -p tcp 2222. Ohne das startet der Dienst zwar, bindet aber nicht.
Fail2ban: nützlich, aber nicht der Hauptschutz#
Sobald Passwort-Logins aus sind, laufen Brute-Force-Versuche ins Leere, sie kosten nur noch CPU und Protokollzeilen. Fail2ban räumt beides weg:
sudo apt install -y fail2ban
# /etc/fail2ban/jail.d/sshd.local
[sshd]
enabled = true
backend = systemd
maxretry = 4
findtime = 10m
bantime = 1h
# Eskalierend sperren: Wiederholungstäter länger.
bantime.increment = true
bantime.factor = 4
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd
Wichtig ist die Reihenfolge im Kopf: Fail2ban ist Lärmschutz. Der Schutz ist der abgeschaltete Passwort-Login.
Zwei-Faktor, wenn es mehr sein soll#
Für Maschinen, auf denen wirklich etwas liegt, lässt sich ein zweiter Faktor ergänzen, Schlüssel und Einmalcode:
sudo apt install -y libpam-google-authenticator
google-authenticator -t -d -f -r 3 -R 30 -w 3 # als der Benutzer, nicht als root
# /etc/ssh/sshd_config.d/20-mfa.conf
KbdInteractiveAuthentication yes
AuthenticationMethods publickey,keyboard-interactive
# /etc/pam.d/sshd — ganz oben ergänzen
auth required pam_google_authenticator.so nullok
Das nullok erlaubt Konten ohne eingerichteten zweiten Faktor weiterhin die Anmeldung. Das ist während der Einführung praktisch und danach ein Loch, sobald alle eingerichtet sind, gehört es entfernt.
Eine bequemere Alternative für Menschen mit Hardware-Token: ssh-keygen -t ed25519-sk. Der private Schlüssel liegt dann auf dem Stick, und ohne Berührung des Tokens passiert nichts. Voraussetzung ist OpenSSH 8.2 oder neuer auf beiden Seiten, bei aktuellen Distributionen kein Thema mehr.
Wenn es doch schiefgeht#
Der Ablauf, wenn du dich ausgesperrt hast, in der Reihenfolge der Erfolgswahrscheinlichkeit:
- Serielle Konsole oder VNC im Kundenpanel. Fast jeder KVM-Anbieter hat das. Damit kommst du an einen Login, auch wenn das Netz der Maschine dicht ist.
- Rettungssystem (Rescue). Bootet ein Live-Linux, hängt deine Platte ein. Dann
/mnt/etc/ssh/sshd_config.d/aufräumen und neu starten. - Snapshot zurückrollen, falls du vor der Änderung einen gemacht hast. Genau dafür sind Snapshots gut.
Punkt 1 solltest du einmal ausprobiert haben, bevor du ihn brauchst. Die Entdeckung, dass die Konsole ein Java-Applet von 2012 will, macht man besser an einem entspannten Dienstagnachmittag.
Zum Abhaken#
| Prüfung | Erwartetes Ergebnis |
|---|---|
ssh -o PubkeyAuthentication=no user@host | Zugriff verweigert |
ssh root@host | Zugriff verweigert |
sudo sshd -T | grep -E 'permitrootlogin|passwordauth' | beides no |
sudo fail2ban-client status sshd | Jail aktiv |
| Konsole im Kundenpanel | einmal getestet, Zugang bekannt |
Der nächste Baustein ist die Firewall und dort besonders die Richtung, die fast alle vergessen: Firewall auf dem VPS mit nftables.
Geschrieben aus dem laufenden Betrieb: MRMedia betreibt eigene Proxmox- Hosts, einen Backup-Server und Kundendienste in der EU. Fehler in einer Anleitung sind Fehler im eigenen Betrieb. Korrekturen bitte über Discord.