SSH Hardening: Linux-Server Schritt für Schritt absichern
Ein frisch aufgesetzter Server mit SSH auf Port 22 und Standard-Konfiguration ist innerhalb von Minuten das Ziel von automatisierten Brute-Force-Scans. Die gute Nachricht: Mit den richtigen Maßnahmen lässt sich die Angriffsfläche drastisch reduzieren – ohne den Komfort zu verlieren.
Dieser Guide geht systematisch vor: von der Grundkonfiguration bis zu 2FA und automatisiertem Audit.
Wichtig: Behalte während aller Änderungen eine aktive SSH-Session offen und teste in einer zweiten Session. So sperrst du dich nicht aus.
Voraussetzungen und Vorsichtsmaßnahmen
Bevor du beginnst:
# 1. SSH-Schlüssel eingerichtet? (Pflicht vor Passwort-Deaktivierung)
ssh-add -l
ls ~/.ssh/authorized_keys # auf dem Server
# 2. Aktuelle sshd_config sichern
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup
# 3. Root-Zugang sichern (Notfall-Konsole kennen)
# Cloud-Provider: Hetzner, DigitalOcean, AWS → Web-Konsole notieren
# 4. Syntax-Check vor jedem Neustart
sudo sshd -t # 0 = keine Syntaxfehler
Arbeitsweise: Nie live testen ohne Backup-Session
# Session 1 (bleibt offen):
ssh user@server # diese Session läuft weiter
# Session 2 (zum Testen nach Änderungen):
ssh user@server # neue Verbindung zum Testen öffnen
SSH-Schlüssel: Grundlage des Hardenings
Ohne SSH-Schlüssel kannst du Passwort-Auth nicht sicher deaktivieren.
# Auf dem Client: Ed25519-Schlüssel erstellen (falls noch nicht vorhanden)
ssh-keygen -t ed25519 -C "server-name-$(date +%Y)" -f ~/.ssh/id_server
# Auf den Server kopieren
ssh-copy-id -i ~/.ssh/id_server.pub user@server
# Testen: Login mit Schlüssel
ssh -i ~/.ssh/id_server user@server
# Erst jetzt Passwort-Auth deaktivieren!
sshd_config: Die wichtigsten Einstellungen
sudo nano /etc/ssh/sshd_config
Essentielle Einstellungen
# === Authentifizierung ===
# Passwort-Login deaktivieren (NUR wenn Schlüssel funktionieren!)
PasswordAuthentication no
# Leere Passwörter verbieten
PermitEmptyPasswords no
# Root-Login deaktivieren
PermitRootLogin no
# Maximale Auth-Versuche pro Verbindung
MaxAuthTries 3
# Zeit bis Login abgeschlossen sein muss
LoginGraceTime 30s
# Challenge-Response deaktivieren (kein PAM-Passwort-Fallback)
ChallengeResponseAuthentication no
KbdInteractiveAuthentication no # OpenSSH 8.7+
# PAM-Modul (für 2FA benötigt, sonst kann es auf no)
UsePAM yes # Für 2FA: yes; ohne 2FA: no
# === Zugriff einschränken ===
# Nur erlaubte Benutzer (Trennzeichen: Leerzeichen)
AllowUsers deploy andre
# Oder: Nur bestimmte Gruppen
# AllowGroups sshusers sudo
# === Verbindungsoptimierung ===
# Keep-Alive: Verbindungen sauber halten
ClientAliveInterval 120
ClientAliveCountMax 2
# Maximale gleichzeitige unauth. Verbindungen begrenzen
MaxStartups 10:30:60
# Format: start:rate:full
# start: ab welcher Anzahl zu droppen beginnen
# rate: Wahrscheinlichkeit in Prozent
# full: ab wann alle neuen blockieren
# === Features deaktivieren ===
# X11-Forwarding (GUI-Anwendungen über SSH)
X11Forwarding no # nur aktivieren wenn benötigt
# TCP-Forwarding (Port-Tunneling)
AllowTcpForwarding no # nur aktivieren wenn benötigt
# Agent-Forwarding
AllowAgentForwarding no
# SFTP statt SCP (sicherer)
# Subsystem sftp /usr/lib/openssh/sftp-server # bleibt aktiv
# === Protokoll und Verschlüsselung ===
# Nur SSH Protokoll 2 (ist Standard, zur Sicherheit explizit)
Protocol 2
# Moderne Algorithmen (OpenSSH >=8.2 verwendet diese standardmäßig)
# Diese Zeilen sind optional wenn du aktuelles OpenSSH nutzt:
# KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org
# Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com
# MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
Änderungen übernehmen
# Syntax-Check IMMER vor Reload!
sudo sshd -t
# (keine Ausgabe = alles ok)
# Reload (laufende Verbindungen bleiben)
sudo systemctl reload sshd
# In zweiter Session verbinden und testen!
Fail2ban: Brute-Force-Schutz
Fail2ban überwacht Logs und sperrt IPs nach zu vielen Fehlversuchen automatisch.
# Installieren
sudo apt install fail2ban # Ubuntu/Debian
sudo dnf install fail2ban # Fedora
# Konfiguration: IMMER .local-Dateien anlegen (nicht .conf bearbeiten!)
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.local
Grundkonfiguration
[DEFAULT]
# Eigene IP nicht sperren (kommagetrennte Liste, CIDR erlaubt)
ignoreip = 127.0.0.1/8 ::1 192.168.1.0/24
# Zeitfenster für Fehlversuche (10 Minuten)
findtime = 600
# Maximale Fehlversuche in findtime
maxretry = 5
# Sperrzeit (1 Stunde)
# -1 = dauerhaft
bantime = 3600
# Progressiver Anstieg: jeder weitere Ban verdoppelt die Zeit
bantime.increment = true
bantime.factor = 24 # 24h nach mehrfachem Ban
bantime.maxtime = 604800 # max. 7 Tage
# Gesperrte IPs per UFW oder iptables
banaction = ufw
# Alternative: iptables-multiport
[sshd]
enabled = true
port = 22 # anpassen wenn anderer Port!
filter = sshd
logpath = /var/log/auth.log # Ubuntu/Debian
# Fedora: logpath = /var/log/secure
maxretry = 3 # SSH: strengerer Wert
# Starten und aktivieren
sudo systemctl enable --now fail2ban
# Status prüfen
sudo systemctl status fail2ban
# Gesperrte IPs anzeigen
sudo fail2ban-client status sshd
# Status for the jail: sshd
# |- Filter
# | |- Currently failed: 2
# | |- Total failed: 47
# `- Actions
# |- Currently banned: 1
# |- Total banned: 5
# `- Banned IP list: 203.0.113.99
# IP manuell sperren
sudo fail2ban-client set sshd banip 203.0.113.99
# IP entsperren
sudo fail2ban-client set sshd unbanip 203.0.113.99
# Jail-Status aller aktiven Jails
sudo fail2ban-client status
Fail2ban-Logs
sudo journalctl -u fail2ban -f
sudo tail -f /var/log/fail2ban.log
Port-Änderung: Weniger Scan-Lärm
Das Ändern des SSH-Ports ist kein echter Sicherheitsgewinn gegen gezielte Angriffe, aber es reduziert automatisierte Port-22-Scans drastisch.
# In /etc/ssh/sshd_config:
Port 2222
# oder einen anderen Port > 1024
# ZUERST: Firewall-Regel für neuen Port setzen!
sudo ufw allow 2222/tcp # Ubuntu/Debian
sudo firewall-cmd --permanent --add-port=2222/tcp # Fedora
sudo firewall-cmd --reload
# DANN: sshd neu starten
sudo sshd -t && sudo systemctl restart sshd
# In zweiter Session mit neuem Port testen
ssh -p 2222 user@server
# ERST DANN: Port 22 in der Firewall schließen
sudo ufw delete allow OpenSSH
sudo ufw delete allow 22/tcp
# Fedora:
sudo firewall-cmd --permanent --remove-service=ssh
sudo firewall-cmd --reload
# SELinux: neuen Port erlauben (Fedora/RHEL)
sudo semanage port -a -t ssh_port_t -p tcp 2222
~/.ssh/config anpassen
Host mein-server
HostName server-ip
User deploy
Port 2222
IdentityFile ~/.ssh/id_server
AllowUsers/AllowGroups: Zugang einschränken
# In /etc/ssh/sshd_config:
# Nur bestimmte Benutzer (sicherste Methode)
AllowUsers deploy andre backup-bot
# Nur Mitglieder der Gruppe "sshusers"
AllowGroups sshusers
# Kombination: Benutzer aus bestimmter IP
AllowUsers deploy@192.168.1.0/24 # deploy nur aus internem Netz
AllowUsers andre # andre von überall
# Service-Accounts von SSH ausschließen
DenyUsers www-data mysql redis postgres
# Gruppe erstellen und User hinzufügen
sudo groupadd sshusers
sudo usermod -aG sshusers deploy
sudo usermod -aG sshusers andre
# Prüfen
getent group sshusers
2FA mit TOTP (optional, empfohlen)
Zwei-Faktor-Authentifizierung mit TOTP (Time-based One-Time Password) – kompatibel mit Google Authenticator, Authy, Bitwarden.
# Google Authenticator PAM installieren
sudo apt install libpam-google-authenticator # Ubuntu/Debian
sudo dnf install google-authenticator # Fedora
# Als der Benutzer (nicht root!) konfigurieren
google-authenticator
Do you want authentication tokens to be time-based? y
# QR-Code erscheint → mit Authenticator-App scannen
# Backup-Codes notieren!
Do you want me to update your "~/.google_authenticator" file? y
Do you want to disallow multiple uses of the same authentication
token? y
By default, a new token is generated every 30 seconds... do you want to
extend the window? n
Do you want to enable rate-limiting? y
PAM konfigurieren
sudo nano /etc/pam.d/sshd
Am Anfang der Datei (vor @include common-auth):
# 2FA: TOTP-Code erforderlich
auth required pam_google_authenticator.so
sshd_config für 2FA anpassen
sudo nano /etc/ssh/sshd_config
# Schlüssel + TOTP (empfohlen)
AuthenticationMethods publickey,keyboard-interactive
# Keyboard-Interactive aktivieren (für TOTP-Abfrage)
KbdInteractiveAuthentication yes
UsePAM yes
sudo sshd -t && sudo systemctl restart sshd
# Testen: Login sollte Schlüssel + TOTP-Code verlangen
ssh -o PreferredAuthentications=publickey,keyboard-interactive user@server
Backup-Plan: Wenn du 2FA vergisst oder die App verlierst → Cloud-Konsole nutzen und
~/.google_authenticatorlöschen.
Firewall-Integration
# UFW (Ubuntu/Debian)
# SSH erlauben (wenn Port 22)
sudo ufw allow OpenSSH
# SSH auf eigenem Port
sudo ufw allow 2222/tcp
# SSH nur aus bestimmtem Netz (sicherste Option für Server)
sudo ufw allow from 192.168.1.0/24 to any port 22 proto tcp
# Rate-Limiting gegen Brute-Force (zusätzlich zu Fail2ban)
sudo ufw limit 22/tcp
# firewalld (Fedora)
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" service name="ssh" accept'
sudo firewall-cmd --reload
SSH-Audit durchführen
ssh-audit (Tool)
# Installieren
sudo apt install ssh-audit # Ubuntu 22.04+
# oder:
pip3 install ssh-audit
# Server auditieren
ssh-audit localhost
ssh-audit server-ip
# Ausgabe:
# (gen) banner: SSH-2.0-OpenSSH_9.8p1 Ubuntu-3ubuntu0.7
# (kex) curve25519-sha256 -- [info] available since OpenSSH 7.4, Dropbear SSH 2018.76
# (kex) ...
# [WARNING] ...
# [CRITICAL] ...
Manueller Konfigurations-Check
# OpenSSH-Version prüfen (sollte aktuell sein)
sshd -V
ssh -V
# Aktive Konfiguration anzeigen
sudo sshd -T | grep -E "permitrootlogin|passwordauthentication|pubkeyauthentication|maxauthtries|logingracetime|allowusers|x11forwarding"
# Alle lauschenden Ports
sudo ss -tlnp | grep sshd
# Aktive SSH-Verbindungen
sudo ss -tnp | grep :22
who # eingeloggte User
w # eingeloggte User + Aktivität
last # Login-History
Regelmäßige Überprüfung
# Fehlgeschlagene Login-Versuche (letzte 24h)
sudo journalctl _COMM=sshd --since "24 hours ago" | grep "Failed\|Invalid" | \
awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -10
# Erfolgreiche Logins
sudo journalctl _COMM=sshd --since "7 days ago" | grep "Accepted"
# Login-Zeiten pro User
last | grep -v "wtmp\|reboot" | head -20
Hardening-Checkliste
SSH Hardening Checkliste – Stand: 2026-02-18
============================================
Basis-Sicherheit:
[ ] SSH-Schlüssel (Ed25519) eingerichtet und getestet
[ ] PasswordAuthentication no
[ ] PermitRootLogin no
[ ] PermitEmptyPasswords no
[ ] MaxAuthTries 3
[ ] LoginGraceTime 30s
Zugriffskontrolle:
[ ] AllowUsers oder AllowGroups gesetzt
[ ] X11Forwarding no (wenn nicht benötigt)
[ ] AllowTcpForwarding no (wenn nicht benötigt)
Brute-Force-Schutz:
[ ] Fail2ban installiert und aktiv
[ ] maxretry ≤ 5
[ ] bantime ≥ 3600
[ ] bantime.increment aktiviert
[ ] Eigene IP in ignoreip
Optional (empfohlen):
[ ] Port geändert (nicht 22)
[ ] 2FA (TOTP) aktiviert
[ ] ssh-audit durchgeführt
[ ] Firewall: SSH nur aus bekannten IPs (wenn möglich)
Monitoring:
[ ] Fail2ban-Logs aktiv
[ ] journalctl -u sshd regelmäßig prüfen
[ ] last und w regelmäßig prüfen
Fazit
SSH-Hardening ist keine einmalige Aufgabe, sondern ein kontinuierlicher Prozess. Die drei wichtigsten Maßnahmen mit dem größten Sicherheitsgewinn:
- Passwort-Auth deaktivieren → eliminiert Passwort-Brute-Force
- Fail2ban → stoppt automatisierte Scan-Angriffe
- AllowUsers → begrenzt potenzielle Angriffspunkte
Für sensible Server: 2FA als zusätzliche Schicht – selbst bei kompromittiertem Schlüssel ist der Angriff gescheitert.