Fünf Tage. So lange hat es gedauert, bis ein frischer Ubuntu-Server mit offenem SSH-Port von knapp 19.000 Login-Versuchen pro Tag getroffen wurde. Nicht weil jemand gezielt mein Portfolio angreifen wollte — sondern weil automatisierte Scanner das gesamte IPv4-Internet kontinuierlich nach offenen SSH-Ports absuchen.

Dass es passiert, war erwartbar. Wie schnell es eskaliert und welche konkreten Auswirkungen es hat, war trotzdem aufschlussreich. Dieser Artikel dokumentiert den Verlauf anhand realer Logs — und die drei Maßnahmen, die das Problem gelöst haben.

Der Auslöser

Eine GitHub Actions Pipeline, die seit Tagen zuverlässig lief, schlug plötzlich fehl:

kex_exchange_identification: read: Connection reset by peer
Connection reset by 10.0.0.2 port 22

SSH war erreichbar, der Server lief, keine Firewall-Regel blockierte. Trotzdem wurden Verbindungen abgelehnt. Ein Blick in die sshd-Logs zeigte die Ursache:

error: beginning MaxStartups throttling
drop connection #10 from [167.99.38.221]:53320 past MaxStartups

sshd hat das Default-Limit von 10 gleichzeitigen unauthentifizierten Verbindungen erreicht — und danach wahllos neue Verbindungen gedropt. Darunter die von GitHub Actions.

Die Eskalation

Ein Blick in die Journal-Logs der ersten Woche zeigt, wie schnell das eskaliert:

TagFehlgeschlagene VersucheAnmerkung
26.02.1.367Server geht ans Netz, Scanning beginnt
27.02.10.341IP in Scan-Listen aufgenommen
28.02.13.449Anstieg
01.03.18.948Peak — fast 19.000 Versuche an einem Tag
02.03.9.193fail2ban ab 10:36 aktiv, danach stark reduziert

Innerhalb von zwei Tagen nach dem ersten öffentlichen SSH-Port war die IP in den Scan-Listen. Am vierten Tag knapp 19.000 Versuche. Das ist kein Ausnahmefall — das ist der Normalzustand für jeden Server mit offenem Port 22 im Internet.

Die Angreifer

Am Tag des fehlgeschlagenen Deployments habe ich die Logs im Detail analysiert:

  • 20+ verschiedene Angreifer-IPs aktiv
  • 213 MaxStartups-Throttling Events — so oft wurden legitime Verbindungen gedropt
  • Peaks von 40 Versuchen pro Minute in der Nacht

Herkunft

IPVersucheHerkunft
134.199.157.1482.332DigitalOcean
46.225.10.1601.833Hetzner Cloud
165.245.137.1421.360DigitalOcean
134.199.156.126855DigitalOcean
209.97.130.120715DigitalOcean

Fast ausschließlich Cloud-VMs von DigitalOcean und Hetzner. Kompromittierte oder eigens für Scanning gemietete Instanzen. Eine IP kam sogar aus demselben Hetzner-Rechenzentrum wie mein Server.

Versuchte Usernamen

3.531  root        (38%)
  792  admin
  410  postgres
  408  test
  369  oracle
  308  ubuntu
  230  hadoop
  216  git
  200  mysql

Klassisches Wörterbuch-Scanning gegen Standard-Dienste-User. root, admin, postgres, mysql, jenkins, docker, elasticsearch — die Bots probieren jeden Usernamen, der bei einer typischen Serverinstallation existieren könnte. Kein gezielter Angriff, reines Spray-and-Pray. Aber in der Masse reicht das, um einen ungeschützten sshd lahmzulegen.

Die Gegenmaßnahmen

1. Password-Authentifizierung deaktiviert

PasswordAuthentication no

Die offensichtlichste Maßnahme: Brute-Force-Angriffe mit Passwörtern laufen ins Leere. Nur Public-Key-Authentifizierung ist erlaubt. Die Angreifer verschwenden ihre Zeit — aber sie belasten trotzdem den sshd-Prozess mit der Verbindungsaufnahme. Deshalb reicht diese Maßnahme allein nicht.

2. fail2ban

fail2ban überwacht die sshd-Logs und bannt IPs nach wiederholten fehlgeschlagenen Versuchen per Firewall-Regel:

[sshd]
enabled   = true
backend   = systemd
maxretry  = 3
findtime  = 600
bantime   = 86400

3 fehlgeschlagene Versuche innerhalb von 10 Minuten → IP wird für 24 Stunden komplett blockiert. Nicht nur für SSH, sondern auf Firewall-Ebene — die Pakete werden gedropt, bevor sie sshd erreichen.

Die Wirkung war sofort messbar: Von ~30 fehlgeschlagenen Versuchen pro Minute auf unter 5. Innerhalb der ersten Minuten wurden 15 IPs gebannt. Nach einer Stunde war der SSH-Traffic auf ein Zehntel des vorherigen Niveaus gefallen.

3. MaxStartups erhöht

MaxStartups 30:50:100

Das Format bedeutet: Ab 30 unauthentifizierten Verbindungen beginnt sshd mit einer Wahrscheinlichkeit von 50%, neue Verbindungen abzulehnen. Ab 100 wird jede neue Verbindung abgelehnt. Der Default von 10:30:100 war zu niedrig — selbst ein moderater Scan hat das Limit erreicht.

In Kombination mit fail2ban wird dieses Limit in der Praxis nicht mehr erreicht. Die Angreifer werden gebannt, bevor sie genug gleichzeitige Verbindungen aufbauen können.

Die Wirkung

Nach der Aktivierung aller drei Maßnahmen:

  • Fehlgeschlagene Versuche: Von ~30/Minute auf unter 5/Minute
  • MaxStartups-Throttling: Null Events seit Aktivierung
  • Gebannte IPs: Steigt kontinuierlich, aktuell über 15 pro Server
  • Legitime Verbindungen: Kein einziger Drop mehr

Die CI/CD-Pipeline läuft seitdem zuverlässig. Das eigentliche Problem — der fehlgeschlagene Deploy — war innerhalb von Minuten gelöst.

Fazit

Ein Server mit offenem Port 22 wird angegriffen. Nicht vielleicht, nicht irgendwann — sofort und permanent. Die Frage ist nicht ob, sondern wie schnell die Scan-Bots die IP finden. In meinem Fall: zwei Tage.

Die drei Maßnahmen — Password-Auth deaktivieren, fail2ban, MaxStartups erhärten — kosten zusammen weniger als fünf Minuten Einrichtungszeit. Ohne sie wäre mein Deploy-Workflow weiterhin unzuverlässig, und sshd würde einen relevanten Teil seiner Ressourcen für die Verarbeitung von Bot-Traffic verschwenden.

SSH-Hardening gehört nicht auf die “Mach ich irgendwann”-Liste. Es gehört in die erste Stunde nach der Serverinstallation.

Glossar

fail2ban
Ein Intrusion-Prevention-Tool, das Log-Dateien überwacht und IP-Adressen nach wiederholten fehlgeschlagenen Anmeldeversuchen automatisch per Firewall-Regel sperrt. Schützt vor Brute-Force-Angriffen auf SSH, Webserver und andere Dienste.
Rate Limiting
Ein Schutzmechanismus, der die Anzahl der Anfragen pro Zeiteinheit begrenzt. Verhindert Brute-Force-Angriffe und Token-Enumeration durch automatisierte Abfragen.