SSH ist der Standard für Fernzugriff auf Linux-Systeme. Die Standardkonfiguration ist funktionsfähig, aber nicht für exponierte Systeme gedacht. Wer einen SSH-Port ins Internet stellt, sieht binnen Stunden Zugriffsversuche – Härtung ist keine Kür.
\nDie Grundkonfiguration
\n# /etc/ssh/sshd_config.d/10-haertung.conf\n# (Auf neueren Systemen liegt eine solche Datei im Verzeichnis\n# sshd_config.d und wird von sshd_config eingebunden. Die\n# erste passende Anweisung in der Gesamtreihenfolge gewinnt!)\n\n# ---- Anmeldung ------------------------------------------------\nPermitRootLogin no # NIEMALS root direkt per SSH\nPasswordAuthentication no # nur Schluessel!\nKbdInteractiveAuthentication no\nPermitEmptyPasswords no\nMaxAuthTries 3\nLoginGraceTime 20\nMaxSessions 10\n\n# ---- Benutzer -------------------------------------------------\nAllowUsers devon deploy@10.0.0.0/24\nAllowGroups ssh-users\nDenyUsers backup\n# Ohne AllowUsers/AllowGroups darf JEDES Konto anmelden -\n# auch solche, die nie dafuer gedacht waren.\n\n# ---- Schluessel -----------------------------------------------\nPubkeyAuthentication yes\nAuthorizedKeysFile .ssh/authorized_keys\n# In der richtigen Datei liegt bei ausgeschaltetem Passwort\n# die GESAMTE Zugangskontrolle.\n\n# ---- Weiterleitungen ------------------------------------------\n# Ein Tunnel ist ein vollstaendiger Zugang zum internen Netz.\nAllowTcpForwarding no # nur wenn wirklich gebraucht\nX11Forwarding no\nAllowAgentForwarding no\nPermitTunnel no # tun-Geraete (VPN!) verbieten\nGatewayPorts no # keine Weiterleitung an 0.0.0.0\n\n# ---- Sitzung --------------------------------------------------\nClientAliveInterval 300\nClientAliveCountMax 2 # tote Sitzungen nach 10 min schliessen\nLogLevel VERBOSE # Fingerabdruecke der Schluessel protokollieren\n\n# ---- Protokolle -----------------------------------------------\n# Wer wann mit welchem Schluessel verbunden war, steht\n# im Systemjournal. Bei einem Vorfall ist das Gold wert.\nSchlüssel: der ganze Zugang hängt daran
\n# Schluesselpaar erzeugen - ED25519 ist Standard, RSA als Ausweich\nssh-keygen -t ed25519 -a 100 -C "devon@arbeitsplatz" -f ~/.ssh/id_ed25519\n# -a 100: 100 Runden Schluesselableitung (schuetzt bei\n# schwacher Passphrase)\n# Die Passphrase auf dem Schluessel ist PFLICHT (schuetzt\n# bei Verlust des Arbeitsplatzes), auch wenn sie unbequem ist.\n\nssh-keygen -t rsa -b 4096 -o -a 100 -f ~/.ssh/id_rsa # Alternative\n\n# Oeffentlichen Schluessel auf den Server bringen\nssh-copy-id -i ~/.ssh/id_ed25519.pub devon@server\n\n# Fingerabdruecke pruefen - VOR dem ersten Verbinden!\nssh-keygen -lf ~/.ssh/id_ed25519.pub\n# Den Server-Fingerabdruck beim Anbieter/Administrator\n# abgleichen und in known_hosts bestaetigen.\n# Ein ungepruefter Fingerabdruck ist eine offene Einfahrt.\n\n# Der Server erzeugt seinen Gastgeberschluessel selbst:\nssh-keyscan -t ed25519 server > /tmp/scanbuch\n# ACHTUNG: keyscan beweist nichts - nur der Anbieter kann\n# den echten Fingerabdruck bestaetigen.\n\n# Agent fuer die Passphrase (bequem und sicher)\neval "$(ssh-agent -s)"\nssh-add -t 8h ~/.ssh/id_ed25519\nssh-add -l # welche Schluessel geladen?\n\n# WICHTIG: Agent-Weiterleitung ist gefaehrlich\n# Wer Zugriff auf den Zielrechner hat, kann ueber den Agent\n# ueberall dorthin, wo der Schluessel passt. Besser:\n# ssh -J sprung@bastion ziel # ProxyJump\n# ProxyJump braucht keine Agent-Weiterleitung.\nZwei-Faktor: der große Gewinn
\n# Ein gestohlener Schluessel ist nutzlos ohne zweiten Faktor.\n# Das ist die wirksamste Massnahme ueberhaupt.\n\n# /etc/ssh/sshd_config.d/20-mfa.conf\nKbdInteractiveAuthentication yes\nAuthenticationMethods publickey,keyboard-interactive\n\n# /etc/pam.d/sshd - TOTP pruefen (google-authenticator oder oathtool)\nauth required pam_google_authenticator.so nullok\n\n# Einrichtung je Benutzer (erzeugt ~/.google_authenticator)\ngoogle-authenticator --time-based --disallow-reuse \\\n --rate-limit=3 --rate-time=30 --window-size=3\n# Notfallcodes sicher verwahren - ohne sie ist der Zugang\n# bei Verlust des Telefons verloren.\n\n# Fuer Skripte und Automatisierung: eigene Konten mit\n# publickey allein und eingeschraenktem Befehl\n# (siehe Befehlsbeschraenkung unten)\nZugang einschränken – nicht nur die Anmeldung
\n# Ein Schluessel darf nur EINEN Befehl ausfuehren (z. B. Sicherung)\n# In ~/.ssh/authorized_keys (eine lange Zeile!):\n# command="/usr/local/bin/sicherung.sh",no-port-forwarding,\n# no-agent-forwarding,no-pty,no-X11-forwarding ssh-ed25519 AAAA...\n#\n# Damit ist der Schluessel auch bei Verlust nur so gefaehrlich\n# wie der eine Befehl. Das Muster ist bei Sicherungen und\n# Automatisierung deutlich besser als ein voller Zugang.\n\n# Chroot: Ein Benutzer sieht nur sein Verzeichnis\nMatch User uebertragung\n ChrootDirectory /srv/uebertragung\n ForceCommand internal-sftp\n AllowTcpForwarding no\n PasswordAuthentication no\n\n# Unterschiedliche Regeln je Konto/Netz (Reihenfolge beachten!)\nMatch Address 10.0.0.0/8\n PasswordAuthentication no\n PermitRootLogin no\n\n# Fuer Konten, die nur Tunnel brauchen\nMatch User tunneluser\n PermitTTY no\n ForceCommand /bin/false\n AllowTcpForwarding yes\n PermitOpen db.intern:5432 # NUR dieser eine Zielpunkt!\n\n# Automatisierung ohne Benutzerkonten (moderne Variante):\n# SSH-Zertifikate mit der eigenen Zertifizierungsstelle.\n# - Kurze Gueltigkeit (Stunden statt Jahre)\n# - Zentraler Widerruf\n# - Keine authorized_keys-Pflege auf jedem Server\nFail2ban: Brute-Force begrenzen
\n# /etc/fail2ban/jail.d/sshd.local\n[sshd]\nenabled = true\nport = ssh\nmode = aggressive # strengere Mustererkennung\nmaxretry = 3\nfindtime = 10m\nbantime = 1h\nbantime.increment = true # Wiederholungstaster verlaengern\nbantime.factor = 2\nbantime.maxtime = 1w\nignoreip = 127.0.0.1/8 10.0.0.0/8 # eigene Netze ausnehmen!\n# ACHTUNG: Bei ignoreip versehentlich 0.0.0.0/0 eintragen\n# deaktiviert den Schutz vollstaendig.\n\n# Umstellung auf nftables (statt iptables)\nbanaction = nftables-multiport\nbanaction_allports = nftables-allports\n\nfail2ban-client status sshd\nfail2ban-client status sshd | grep -E 'Banned|Total'\nfail2ban-client set sshd unbanip 203.0.113.5\nfail2ban-client banned # alle Sperren\nPrüfen und überwachen
\n# Konfiguration pruefen\nsshd -t\nsshd -T | grep -Ei 'permitrootlogin|passwordauth|allowusers|maxauth'\n\n# Effektive Konfiguration anzeigen (alle Quellen zusammengefuehrt)\nsshd -T | head -50\n\n# Wer ist angemeldet?\nwho\nw\nlast -n 20\nlastb -n 20 # fehlgeschlagene Anmeldungen\n\n# Fehlgeschlagene Versuche zaehlen\njournalctl -u ssh --since "24 hours ago" | grep -c "Failed password"\njournalctl -u ssh --since "1 hour ago" | grep -E "Invalid user|Failed" | tail -20\n\n# Welche Schluessel wurden benutzt?\njournalctl -u ssh | grep -i "Accepted publickey" | tail -20\n\n# Von wo kommen die Versuche?\njournalctl -u ssh | grep "Failed password" | \\\n awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head\n\n# Test NACH jeder Aenderung - in einer ZWEITEN Sitzung!\n# 1. Aenderung speichern\n# 2. sshd -t (Syntax)\n# 3. systemctl reload ssh\n# 4. In einer NEUEN Sitzung anmelden und pruefen\n# 5. Erst dann die ALTE Sitzung schliessen\n# Wer das nicht macht, sperrt sich aus.\nPrüfliste
\n- \n
- Ist
PermitRootLogin nogesetzt? \n - Ist die Passwortanmeldung abgeschaltet (nur Schlüssel)? \n
- Ist
AllowUsersoderAllowGroupsgesetzt? \n - Haben alle Schlüssel eine Passphrase? \n
- Sind die Server-Fingerabdrücke abgeglichen und in
known_hosts? \n - Ist ein zweiter Faktor für exponierte Systeme aktiv? \n
- Sind Agent-Weiterleitung und X11-Weiterleitung abgeschaltet, wenn sie nicht gebraucht werden? \n
- Ist Fail2ban aktiv UND die eigenen Netze ausgenommen (ohne Sperre gegen sich selbst)? \n
- Ist der Zugang über einen Sprungserver (Bastion) statt direkt möglich? \n
- Ist ein Notfallweg dokumentiert (Konsole, ausfallsicherer Nachbarzugang)? \n
- Wird
sshd -Tnach Änderungen geprüft? \n - Werden Anmeldungen protokolliert und ausgewertet? \n
Häufige Fehler
\n- \n
- PasswordAuthentication nicht abgeschaltet. Damit ist der Schlüssel wertlos und das System offen für Erraten. \n
- Ausgesperrt nach Änderung. Immer in zweiter Sitzung testen, bevor die erste geschlossen wird. Bei Providern mit Konsole: dort prüfen, wie man wieder hineinkommt. \n
- Schlüssel ohne Passphrase. Bei Verlust des Arbeitsplatzes ist der Zugang verloren. Die Passphrase mit Agent bequem machen, nicht weglassen. \n
- Agent-Weiterleitung aktiviert. Der Zielrechner erhält damit Zugang überall dorthin, wo der Schlüssel passt. ProxyJump nutzen. \n
- Kein
AllowUsers. Jedes vorhandene Konto ist erreichbar, auch vergessene Dienstkonten. \n - Fail2ban sperrt die eigenen Verbindungen. Nach Passwortwechsel oder fehlerhafter Automatisierung sperrt man sich selbst.
ignoreipist Teil der Konfiguration, nicht optional. \n - Port ändern als Ersatz für Härtung. Ein anderer Port reduziert nur die Protokollzeilen, nicht die Angriffsfläche. Kein Ersatz für die Maßnahmen oben. \n
- Konfiguration in mehreren Dateien. Auf Systemen mit
sshd_config.dgewinnt die erste passende Anweisung. Wer eine Regel imMatch-Block vergeblich sucht, nimmtsshd -T. \n - Sicherung der Zugänge fehlt. Wer Aussperrrisiken eingeht, braucht einen dokumentierten Ausweg. \n
Verwandte Grundlagen: SSH, SSH-Befehle, Fail2ban, Zero Trust.