Post-Mortem SSH Probleme 02.04.2025
Wie einige von euch vielleicht mitbekommen haben, gab es am Mittwoch bei uns ein paar unerwartete Probleme. Dafür möchten wir euch um Entschuldigung bitten.
Die Auswirkungen
Zwischen 15:30 Uhr bis spätestens 21 Uhr war der Login per SSH auf unseren Uberspace Hosts nicht mehr möglich. Ab etwa 17 Uhr konnten wir den Login dann schrittweise wiederherstellen. Leider mussten wir dafür alle VMs herunterfahren um Arbeiten direkt am Dateisystem durchzuführen. Dadurch waren auch eure Dienste, meist für einige Minuten, nicht erreichbar. Bedauerlicherweise sind einige VMs nicht sauber wieder hochgefahren, wodurch auf 14 Hosts teilweise eine Downtime von bis zu 2h entstanden ist.
Der Vorfall
Um etwa 15 Uhr am 02.04.2025 gab es einen Hinweis darauf, dass ein SSH Key von einer Person aus unserem Team möglicherweise kompromittiert wurde (dazu folgt bald ein eigener Artikel). Daraufhin haben wir sofort Maßnahmen ergriffen, um diesen Key auf allen betroffenen Systemen zu entfernen, vor allem auf den U7 Hosts.
Dazu haben wir um ca 15:20 nach ein paar Tests per Ansible einen Hotfix ausgerollt, der den entsprechenden Key entfernen sollte. Zusätzlich sollte der Key dann auch noch in eine revoked-keys
Datei geschrieben werden für eine weitere Absicherung. In diesem Schritt passierten dann aber 2 Fehler: Diese zweite Änderung wurde versehentlich sofort über alle U7 Hosts ausgerollt ohne nochmal durch die Überprüfung von check-diffs und Test-hosts zu gehen. Das wäre an sich noch kein Schaden gewesen, aber ausgerechnet an dieser Stelle gab es noch einen Copy-Paste Fehler: der Schlüssel war (visuell unauffällig) zum Teil abgeschnitten. Der SSH Daemon konnte die Datei deswegen nicht mehr parsen und verwehrte daraufhin den kompletten Zugriff, nicht nur uns, sondern auch allen Usern auf dem Host, bzw. gleich allen 250 U7 Hosts.
Der Fix
Zuerst einmal mussten wir in diesem Moment verstehen, was überhaupt vorgefallen war. Gar nicht so einfach, ohne Zugriff. Nachdem wir eine Weile überlegt haben, wie wir an entsprechende Informationen kommen, ist uns quasi gleichzeitig aufgefallen, dass wir zentrale Logs in unserem noch relativ neuen Loki haben, aber auch dass eine Person aus unserem Team noch eine aktive SSH-Session auf einem Host hatte. Dort haben wir dann in den Logs rasch sehen können, dass das Problem am fehlerhaften Key in der /etc/ssh/not_authorized_keys
lag. Eine entsprechende Anpassung hat dann auch sofort den Zugang auf diesem U7 Host wiederhergestellt.
Jetzt mussten wir das nur noch auf ca. 250 weiteren U7 Hosts umsetzen, auf die wir keinen Zugriff mehr hatten. Denn einen Root Login per Passwort haben wir über die Konfiguration ausgeschlossen, also war uns der Weg über die serielle Konsole verwehrt. Ganz davon abgesehen, dass dieser Weg sehr langwierig und mit viel manuellem Aufwand verbunden gewesen wäre.
Also haben wir einen anderen Weg gesucht. Von unseren Migrationen, damals von einer KVM Kette auf Proxmox, hatten wir schon einige Erfahrung wie wir einfach eine virtuelle Disk aus dem Ceph in einen beliebigen Host mounten können. Gesagt, getan, haben wir das mit unserem Test Hosts Fairydust gemacht. Also VM (das heißt, den U7 Host) herunterfahren, mount der Disk, dabei anpassen, unmount der Disk und die VM wieder starten. Leider ohne Erfolg. Jetzt hatten wir aber eine neue Fehlermeldung, nämlich permission denied
. Also neue Runde und die Berechtigungen mit dem Host, der funktionierte, abgeglichen. Die sahen auf den ersten Blick aber eigentlich gut aus.
Allerdings wussten wir schon aus Erfahrung: Berechtigungsprobleme, die nicht mit Dateirechten erklärbar sind, lassen sich oft auf SELinux zurückführen, das wir unseren Systemen im enforcing-Mode betreiben. Also zunächst überprüft und in der Tat, vor der Änderung der Datei auf dem VM-Node mit Debian waren die SELinux Flags noch korrekt, danach aber nicht mehr das korrekte system_u:object_r:etc_t:s0
, sondern system_u:object_r:etc_runtime_t:s0
. Die Flags mit einem einfachen restorecon
zu fixen, funktioniert zwar in der laufenden VM, aber nicht in einem chroot eines ganz anderen Kernels. Eine chroot-Umgebung ist, vereinfacht gesagt, die Möglichkeit, das aktuelle root-Verzeichnis temporär zu ändern und so Befehle innerhalb des nicht laufenden und nur gemounteten Systems auszuführen.
Mit dem Befehl chcon system_u:object_r:etc_t:s0 /etc/ssh/not_authorized_keys
konnten wir dann den SELinux-Kontext der Datei korrigieren. Und siehe da, nach einem weiteren Versuch der Änderung und einem Reboot war der Login dann möglich.
Also haben wir ein Script gebaut, das mit den passenden Werten für den entsprechenden Ceph Pool und dem zugehörigen “Rados Block Device” (RBD) die Änderungen automatisiert durchführt. Wir hätten an dieser Stelle natürlich auch noch diese beiden Parameter genau wie das Herunterfahren der VMs automatisieren können, hier wäre aber die Automatisierungsarbeit langwieriger gewesen als diese paar Schritte manuell durchzuführen. Und da wir die Hosts schnell wieder zugänglich machen wollten, haben wir darauf verzichtet.
Damit wir schneller vorankommen, haben wir uns die beiden Standorte aufgeteilt und angefangen immer einen ganzen Host herunterzufahren und dann alle VMs mit dem Script anzupassen. Das haben wir dann schrittweise für alle etwa 250 U7 Hosts gemacht. Das hat etwa 3,5h gedauert. Dabei haben alle Hosts wegen der externen Änderung im Anschluss beim Booten einen Quota-Check durchgeführt. Da der bisweilen eine Weile dauert, und wir nicht warten wollten, bis alle Hosts immer wieder gebootet waren um weiterzumachen, haben wir dann auf einigen Hosts übersehen, dass diese nach dem Check nicht sauber weiter gebootet sind. Das waren dann die 14 Hosts, die wir leider erst gegen 21 Uhr wieder am Laufen hatten.
Was haben wir daraus gelernt?
Zum einen natürlich, dass auch unter Zeitdruck immer darauf geachtet werden muss, eine Änderung vor dem Deployment auf allen Hosts zu testen, als auch dem Mehr-Augen-Prinzip zu folgen, wie wir es schon für alle anderen regulären Änderungen haben. Ebenso wollen wir unsere Dokumentation für den hoffentlich nicht eintretenden Wiederholungsfall verbessern, damit auch in solch einer stressigen Situation weniger Fehler passieren. Außerdem haben wir gemerkt, dass wir unsere Kommunikation auf der Statusseite noch verbessern müssen. Wir bitten dafür um Entschuldigung. Aufgrund der vielen Maßnahmen und auch einer gewissen Überlastung ist hier die Kommunikation nicht den Ansprüchen entsprechend gelaufen, die wir an uns selbst stellen.
So viel erst einmal zu diesem Vorfall. Für alles Weitere werden wir nächste Woche noch einen zweiten Post-Mortem veröffentlichen. Hier ist noch ein wenig mehr Recherchearbeit notwendig, um alle nötigen Informationen zusammenzutragen.