SSH-Verbindungen absichern: Keys, Config, Härtung
$
/etc
Linux · SSH · Server-Sicherheit · OpenSSH
SSH-Verbindungen absichern
Keys, Config und Härtung für produktive Linux-Server

Server, die SSH ausschließlich mit Passwort-Login und offenem Root-Zugang betreiben, sind ein bevorzugtes Ziel automatisierter Brute-Force-Angriffe aus dem gesamten Internet. Dieser Artikel zeigt praxisnah, wie Key-basierte Authentifizierung, eine konsequent gehärtete sshd_config, saubere Client-Konfiguration über host-spezifische Einträge und fail2ban als ergänzende Schutzschicht SSH-Zugänge auf produktiven Linux-Servern zuverlässig und dauerhaft absichern, ganz ohne exotische Zusatztools.

14 Min. Lesezeit SSH-Keys · sshd_config · fail2ban OpenSSH · Linux-Administration

1. Warum SSH die wichtigste Angriffsfläche ist

Auf praktisch jedem produktiven Linux-Server ist SSH der einzige offene Verwaltungszugang nach außen, und genau deshalb ist er das bevorzugte Ziel automatisierter Angriffe. Wer die Logs eines frisch aufgesetzten Servers mit offenem Port 22 beobachtet, sieht innerhalb weniger Minuten die ersten Brute-Force-Versuche aus Botnetzen, die systematisch Standardbenutzernamen wie root, admin oder ubuntu gegen gängige Passwörter durchprobieren. Diese Scans sind kein Einzelfall, sondern permanenter Hintergrundlärm im Internet.

Die gute Nachricht: Die wirksamsten Gegenmaßnahmen sind keine exotischen Zusatztools, sondern eine Handvoll gut dokumentierter Konfigurationsänderungen an sshd_config und der konsequente Wechsel von Passwort- zu Key-basierter Authentifizierung. Ein Server, der ausschließlich Public-Key-Auth erlaubt, keinen Root-Login über SSH zulässt und nur moderne Verschlüsselungsverfahren anbietet, reduziert die realistische Angriffsfläche auf nahezu null, selbst wenn Port 22 offen und öffentlich erreichbar bleibt. Die folgenden Abschnitte zeigen die konkrete Umsetzung, vom Schlüsselpaar bis zur produktionsreifen sshd_config.

2. Key-basierte Authentifizierung statt Passwörter

Ein SSH-Schlüsselpaar besteht aus einem privaten Schlüssel, der niemals den eigenen Rechner verlässt, und einem öffentlichen Schlüssel, der auf dem Zielserver in ~/.ssh/authorized_keys hinterlegt wird. Für neue Schlüssel ist der Algorithmus Ed25519 die richtige Wahl: kürzere Schlüssel als bei RSA, schnellere Signaturberechnung und keine bekannten praktischen Schwächen. RSA mit mindestens 4096 Bit bleibt als Fallback sinnvoll, wenn Zielsysteme sehr alt sind und Ed25519 nicht unterstützen.

Der Schlüssel sollte immer mit einer Passphrase geschützt werden, damit ein gestohlener privater Schlüssel allein nicht ausreicht. ssh-copy-id überträgt den öffentlichen Schlüssel sauber, ohne bestehende Berechtigungen zu verändern, und ist dem manuellen Anhängen per cat vorzuziehen, weil es Duplikate vermeidet. Wichtig sind korrekte Dateiberechtigungen: Das Verzeichnis ~/.ssh braucht 700, die Datei authorized_keys 600. Weichen diese Berechtigungen ab, verweigert sshd in der Standardkonfiguration die Schlüssel-Authentifizierung stillschweigend, ohne dass dies im Client sichtbar wird.


#!/usr/bin/env bash
# Generate a modern Ed25519 keypair (recommended over RSA for new keys)
ssh-keygen -t ed25519 -a 100 -C "deploy@mironsoft.de" -f ~/.ssh/id_ed25519_mironsoft

# Copy the public key to the target server (appends to authorized_keys)
ssh-copy-id -i ~/.ssh/id_ed25519_mironsoft.pub deploy@server.mironsoft.de

# Enforce strict permissions manually if the key was copied by other means
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chmod 600 ~/.ssh/id_ed25519_mironsoft
chmod 644 ~/.ssh/id_ed25519_mironsoft.pub

# Verify which key the client actually offers during the handshake
ssh -vv deploy@server.mironsoft.de 2>&1 | grep "Offering public key"

3. sshd_config härten: PermitRootLogin und PasswordAuthentication

Die zentrale Konfigurationsdatei /etc/ssh/sshd_config steuert das Verhalten des SSH-Servers, und zwei Direktiven haben den größten Sicherheitseffekt. PermitRootLogin no unterbindet jede direkte Root-Anmeldung über SSH, sodass Angreifer selbst mit einem korrekten Root-Passwort keinen Zugriff bekommen; administrative Aufgaben laufen stattdessen über einen normalen Benutzer mit sudo. PasswordAuthentication no deaktiviert Passwort-Logins vollständig und lässt ausschließlich Public-Key-Authentifizierung zu, womit klassische Brute-Force-Angriffe gegen SSH ins Leere laufen, weil kein Passwort mehr existiert, das erraten werden könnte.

Vor der Aktivierung dieser Einstellungen muss sichergestellt sein, dass mindestens ein funktionsfähiger Schlüssel für einen sudo-fähigen Benutzer hinterlegt ist, denn ein Fehler an dieser Stelle sperrt den einzigen Zugang zum Server aus. Bewährte Praxis: Änderungen in einer zweiten SSH-Sitzung testen, während die erste Sitzung geöffnet bleibt, und erst nach erfolgreichem Login mit dem neuen Schlüssel die alte Sitzung schließen. sshd -t prüft die Syntax der Konfigurationsdatei, bevor der Dienst neu geladen wird, und verhindert so, dass ein Tippfehler den SSH-Dienst komplett lahmlegt.


# /etc/ssh/sshd_config - core hardening directives
# Disable direct root login entirely, use sudo instead
PermitRootLogin no

# Disable password authentication, allow public key auth only
PasswordAuthentication no
PubkeyAuthentication yes
KbdInteractiveAuthentication no
ChallengeResponseAuthentication no

# Reject empty passwords outright (defense in depth)
PermitEmptyPasswords no

# Limit authentication attempts and time per connection
MaxAuthTries 3
LoginGraceTime 20

# Restrict SSH access to specific users or groups
AllowUsers deploy admin
# AllowGroups ssh-users

# Validate syntax before reloading the service:
#   sshd -t && systemctl reload sshd

4. Protokoll- und Verschlüsselungsrestriktionen

Neben der Authentifizierungsmethode entscheidet die Auswahl der erlaubten Verschlüsselungs-, Schlüsselaustausch- und MAC-Algorithmen darüber, wie widerstandsfähig eine SSH-Verbindung gegen kryptografische Angriffe ist. Ältere OpenSSH-Versionen aktivieren aus Kompatibilitätsgründen standardmäßig auch schwächere Algorithmen wie diffie-hellman-group1-sha1 oder arcfour, die längst als unsicher gelten. Mit den Direktiven Ciphers, KexAlgorithms und MACs lässt sich die erlaubte Liste explizit auf moderne Verfahren wie chacha20-poly1305@openssh.com und aes256-gcm@openssh.com einschränken.

Der Befehl ssh -Q cipher, ssh -Q kex und ssh -Q mac listet auf dem lokalen System alle unterstützten Algorithmen auf und ist der schnellste Weg, eine Whitelist zusammenzustellen, ohne veraltete Dokumentation zu Rate ziehen zu müssen. Ein oft übersehener Punkt: Das Verschieben von Port 22 auf einen anderen Port reduziert zwar das Volumen an automatisiertem Scan-Rauschen in den Logs erheblich, ist aber keine echte Sicherheitsmaßnahme im kryptografischen Sinn, sondern reine Security-through-Obscurity und sollte nie als Ersatz für die eigentliche Härtung verstanden werden.


# /etc/ssh/sshd_config - restrict to modern, audited algorithms
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com

KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group16-sha512

MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com

# Only protocol 2 has been supported since OpenSSH 7.6, listed here for clarity
Protocol 2

# Optional: move off the default port to cut down automated scan noise
# Port 2222

# Disable features rarely needed on a hardened server
X11Forwarding no
AllowTcpForwarding no
AllowAgentForwarding no

5. Client-Konfiguration mit ~/.ssh/config

Auf der Client-Seite spart eine gepflegte ~/.ssh/config nicht nur Tipparbeit, sondern reduziert auch Fehlerquellen: Statt bei jedem Verbindungsaufbau Benutzername, Port und Schlüsseldatei manuell anzugeben, definiert man pro Host einen Alias mit allen nötigen Parametern. IdentityFile legt fest, welcher private Schlüssel für einen Host verwendet wird, und IdentitiesOnly yes verhindert, dass der SSH-Client zusätzlich alle im Agenten geladenen Schlüssel anbietet, was auf Servern mit begrenztem MaxAuthTries sonst schnell zur Aussperrung führen kann.

Für Server, die nur über einen Bastion- oder Jump-Host erreichbar sind, übernimmt ProxyJump die Weiterleitung automatisch und ersetzt die früher übliche, deutlich fehleranfälligere ProxyCommand-Syntax mit manuellem nc-Aufruf. HashKnownHosts yes speichert Host-Einträge in ~/.ssh/known_hosts gehasht statt im Klartext, sodass ein gestohlenes Known-Hosts-File keine Liste erreichbarer Server preisgibt. Mit Include lassen sich größere Konfigurationen zusätzlich in team- und projektspezifische Dateien aufteilen und versionieren.


# ~/.ssh/config - per-host client configuration
Host prod-shop
    HostName server.mironsoft.de
    User deploy
    Port 2222
    IdentityFile ~/.ssh/id_ed25519_mironsoft
    IdentitiesOnly yes
    AddKeysToAgent yes

Host db-internal
    HostName 10.0.4.12
    User dbadmin
    ProxyJump prod-shop
    IdentityFile ~/.ssh/id_ed25519_internal
    IdentitiesOnly yes

# Global defaults applied to hosts without an explicit block
Host *
    HashKnownHosts yes
    ServerAliveInterval 30
    ServerAliveCountMax 3
    IdentitiesOnly yes

6. SSH-Agent und Key-Management

ssh-agent hält entschlüsselte private Schlüssel im Speicher, damit die Passphrase nicht bei jeder Verbindung erneut eingegeben werden muss. Das ist komfortabel, hat aber eine wichtige Kehrseite: AddKeysToAgent yes in der Client-Config und ssh-add -t 3600 mit einem Zeitlimit sorgen dafür, dass Schlüssel nicht dauerhaft, sondern nur für eine begrenzte Session im Speicher bleiben. Auf gemeinsam genutzten Systemen oder Jump-Hosts sollte Agent-Forwarding (ForwardAgent yes) nur gezielt für einzelne, vertrauenswürdige Hosts aktiviert werden, niemals global, da ein kompromittierter Zwischenserver sonst jeden weitergeleiteten Schlüssel missbrauchen kann.

Für Deployment-Pipelines gilt dieselbe Vorsicht: Deploy-Keys sollten pro Repository oder Zielsystem einzeln erstellt werden, statt einen persönlichen Schlüssel in CI/CD-Umgebungen zu hinterlegen. Rotiert man Schlüssel regelmäßig und entfernt alte Einträge konsequent aus authorized_keys, bleibt die Angriffsfläche auch bei wechselnden Teammitgliedern klein. Der Befehl ssh-keygen -y -f key prüft dabei, ob ein privater Schlüssel tatsächlich zum hinterlegten öffentlichen Schlüssel passt, bevor ein alter Eintrag gelöscht wird.


# .github/workflows/deploy.yml - load a dedicated deploy-only key via ssh-agent
name: Deploy
on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Start ssh-agent and load the deploy key
        run: |
          eval "$(ssh-agent -s)"
          ssh-add - <<< "${{ secrets.DEPLOY_KEY_ED25519 }}"
          echo "SSH_AUTH_SOCK=$SSH_AUTH_SOCK" >> "$GITHUB_ENV"

      - name: Deploy over SSH
        run: ssh -o StrictHostKeyChecking=yes deploy@server.mironsoft.de "bin/deploy.sh"

7. Ergänzender Schutz: fail2ban gegen Brute-Force

Auch mit deaktivierter Passwort-Authentifizierung lohnt sich eine zusätzliche Schutzschicht gegen die schiere Menge automatisierter Verbindungsversuche: fail2ban wertet /var/log/auth.log beziehungsweise journalctl -u ssh aus, erkennt wiederholte fehlgeschlagene Anmeldeversuche von derselben IP-Adresse und sperrt diese für eine konfigurierbare Zeit über iptables oder nftables. Das reduziert Log-Rauschen erheblich und entlastet den SSH-Daemon selbst, weil Verbindungsversuche gesperrter IP-Adressen den TCP-Handshake gar nicht erst erreichen.

Für SSH genügt in den meisten Fällen die mitgelieferte Jail-Vorlage, aktiviert über /etc/fail2ban/jail.local mit angepasstem maxretry und bantime. Wichtig: fail2ban ersetzt keine der vorherigen Maßnahmen, sondern ergänzt sie, denn ohne funktionierende Key-Authentifizierung wäre ein einzelner cleverer Angreifer mit niedriger Versuchsfrequenz weiterhin ein Risiko. Die vollständige Konfiguration von fail2ban mit eigenen Filtern und mehreren Jails ist ein eigenes Thema und würde den Rahmen dieses Artikels sprengen.

8. Monitoring und Logging von SSH-Zugriffen

Gehärtete Konfiguration allein reicht nicht, wenn niemand bemerkt, wenn sich das Zugriffsmuster ändert. journalctl -u ssh --since "1 hour ago" zeigt aktuelle Anmeldeversuche direkt aus dem systemd-Journal, während grep "Failed password" /var/log/auth.log | wc -l einen schnellen Überblick über die Zahl fehlgeschlagener Versuche liefert. Erfolgreiche Root-Logins, sofern sie überhaupt noch möglich sind, sollten in jedem Monitoring-System einen sofortigen Alarm auslösen, da sie fast immer entweder eine Fehlkonfiguration oder einen erfolgreichen Angriff bedeuten.

Für zentrales Logging über mehrere Server hinweg empfiehlt sich das Weiterleiten der Auth-Logs an einen zentralen Syslog-Server oder in einen Log-Aggregator wie Loki oder die ELK-Stack-Familie, damit Muster über die gesamte Infrastruktur hinweg sichtbar werden, statt in isolierten Einzel-Logs unterzugehen. last und lastlog liefern zusätzlich einen schnellen Überblick über erfolgreiche Logins der letzten Zeit und helfen, unerwartete Zugriffszeiten oder unbekannte Quell-IPs frühzeitig zu erkennen, bevor daraus ein größerer Vorfall wird.

9. SSH-Härtung im direkten Vergleich

Die folgende Übersicht fasst die wichtigsten Einstellungen zusammen, bei denen der Unterschied zwischen Standardkonfiguration und gehärtetem Setup besonders groß ausfällt.

Einstellung Standard / Unsicher Empfohlene Härtung Vorteil
Root-Login PermitRootLogin yes PermitRootLogin no Kein direkter Root-Zugriff über SSH möglich
Authentifizierung PasswordAuthentication yes PasswordAuthentication no Brute-Force gegen Passwörter läuft ins Leere
Login-Versuche MaxAuthTries unbegrenzt MaxAuthTries 3 Automatisierte Versuchsketten brechen früh ab
Verschlüsselung Default-Ciphers inkl. veralteter Verfahren Ciphers chacha20-poly1305,aes256-gcm Keine bekannt schwachen Algorithmen aktiv
Brute-Force-Schutz Kein aktives Rate-Limiting fail2ban mit sshd-Jail aktiv Auffällige IP-Adressen werden automatisch gesperrt

Wer alle fünf Zeilen konsequent umsetzt, hat die realistischen Angriffsvektoren gegen SSH bereits auf ein Minimum reduziert. Der verbleibende Rest, etwa Zero-Day-Schwachstellen in OpenSSH selbst, lässt sich nur durch zeitnahes Patchen und einen aktuellen Paketstand abdecken, nicht durch Konfiguration allein.

Mironsoft

Server-Härtung, SSH-Sicherheit und Infrastruktur-Automatisierung für euren Linux-Stack

SSH-Zugänge professionell absichern?

Wir prüfen eure bestehende SSH-Konfiguration, schließen Lücken in sshd_config und Client-Setup und richten fail2ban sowie Monitoring ein, damit eure Linux-Server dauerhaft gegen automatisierte Angriffe abgesichert bleiben.

Security-Audit

Bestehende sshd_config und Key-Bestand systematisch prüfen

Config-Härtung

Key-Auth, Protokoll-Restriktionen und Client-Setup einrichten

Monitoring-Setup

fail2ban, zentrales Logging und Alerting für Anmeldeversuche

10. Zusammenfassung

Die wichtigsten Maßnahmen, um SSH-Verbindungen abzusichern, greifen ineinander: Key-basierte Authentifizierung mit Ed25519-Schlüsseln ersetzt Passwörter vollständig und macht klassische Brute-Force-Angriffe wirkungslos. PermitRootLogin no und PasswordAuthentication no in sshd_config schließen die beiden größten Einfallstore direkt an der Quelle. Eingeschränkte Ciphers, KexAlgorithms und MACs verhindern, dass veraltete, unsichere Verschlüsselungsverfahren überhaupt zur Wahl stehen. Eine gepflegte ~/.ssh/config macht die tägliche Arbeit sicherer und komfortabler zugleich.

fail2ban ergänzt diese Maßnahmen als zusätzliche Schutzschicht gegen die schiere Masse automatisierter Scans, ersetzt aber keine der vorherigen Schritte. Kontinuierliches Monitoring über journalctl, zentrale Logs und Alerts bei erfolgreichen Root-Logins stellt sicher, dass Abweichungen vom normalen Zugriffsmuster nicht erst Wochen später auffallen. Wer alle Bausteine konsequent umsetzt, reduziert die realistische Angriffsfläche eines Linux-Servers über SSH auf ein Minimum, unabhängig davon, ob der Standardport offen bleibt oder nicht.

SSH-Verbindungen absichern - Das Wichtigste auf einen Blick

Key-Authentifizierung

Ed25519-Schlüsselpaar mit Passphrase, ssh-copy-id und korrekte Berechtigungen (700/600) statt Passwort-Login.

sshd_config-Härtung

PermitRootLogin no, PasswordAuthentication no, MaxAuthTries 3 und eingeschränkte Ciphers/KexAlgorithms.

Client-Config

~/.ssh/config mit IdentityFile, ProxyJump und IdentitiesOnly yes pro Host.

Ergänzung & Monitoring

fail2ban gegen Brute-Force-Massen, journalctl und zentrales Logging für kontinuierliche Überwachung.

11. FAQ: SSH-Verbindungen absichern

1Warum sind SSH-Keys sicherer als Passwörter?
Ein kryptografisches Schlüsselpaar kann nicht erraten werden. Der private Schlüssel verlässt nie den Client und ist zusätzlich per Passphrase geschützt, anders als reine Passwörter.
2Wie erstelle ich ein sicheres SSH-Keypair?
ssh-keygen -t ed25519 -a 100 erzeugt ein modernes Schlüsselpaar. Starke Passphrase setzen, dann den öffentlichen Schlüssel per ssh-copy-id übertragen.
3Was bewirkt PermitRootLogin no genau?
Unterbindet jede direkte Root-Anmeldung über SSH, auch mit korrektem Passwort oder Schlüssel. Administration läuft über einen normalen Benutzer mit sudo.
4Soll ich den SSH-Standardport 22 ändern?
Reduziert Scan-Rauschen, ist aber keine echte Sicherheitsmaßnahme. Key-Auth, gehärtete sshd_config und fail2ban wirken deutlich stärker.
5Unterschied zwischen ~/.ssh/config und sshd_config?
~/.ssh/config ist clientseitig und regelt die Verbindung zu Hosts. sshd_config liegt auf dem Server und steuert, welche Verbindungen der SSH-Daemon zulässt.
6Wie funktioniert ProxyJump?
Leitet eine Verbindung automatisch über einen Bastion-Host weiter, ohne manuelle ProxyCommand-Syntax mit nc. Ersetzt die alte, fehleranfällige Tunnel-Konfiguration.
7Ist SSH-Agent-Forwarding sicher?
Nur gezielt für einzelne, vertrauenswürdige Hosts, niemals global. Ein kompromittierter Zwischenserver kann sonst weitergeleitete Schlüssel missbrauchen.
8Was bringt fail2ban zusätzlich?
Sperrt IP-Adressen mit wiederholten Fehlversuchen automatisch. Reduziert Log-Rauschen und Last, ersetzt aber keine der grundlegenden Härtungsmaßnahmen.
9Wie überwache ich SSH-Zugriffe?
journalctl -u ssh und /var/log/auth.log für Einzelserver. Zentrales Logging und Alerts bei erfolgreichen Root-Logins für größere Infrastrukturen.
10Was, wenn ich mich mit falscher sshd_config aussperre?
Vor jedem Neuladen sshd -t ausführen und Änderungen in einer zweiten, offenen Sitzung testen. Erst nach erfolgreichem Login die alte Sitzung schließen.