Eigen-DoS 🙄

Ich habe mich heute selbst ge-DoS-ed, und dabei wieder 1-2 wichtige Lektionen gelernt, die ich euch nicht vorenthalten möchte. Gut, technisch gesehen war es kein DoS, da der Service nicht in die Knie ging. Andrerseits musste das System heute ein vielfaches (d.h. 190000-fache dessen, was es sonst so im Schnitt macht) leisten, und da's auch irgendwie lustig war gibt's jetzt einen Blogpost dazu.

Damit man das Ausmaß versteht ein paar Hintergrundinfos: Seit geraumer Zeit bastle ich auf Basis des ZigBee-Protokolls an meinem SmartHome. Ich persönlich bin absolut kein Fan von Cloud-basierten Diensten, daher übernimmt die Steuerung des Systems mein Homeserver, auf welchem wiederum diverse Dienste abgeschottet laufen.

Die Kommunikation mit den ZigBee-Geräten übernimmt dabei ein ConBee II USB-Stick, einfache Steuerungsaufgaben (Ein/Aus von Lampen bspw.) werden über die vom Hersteller verfügbare Software erledigt.

Komplexere Aufgaben übernimmt eine Node-RED-Instanz. Node-RED ist eine Browser-basierte Entwicklungs- und Laufzeitumgebung, mit der man so gut wie alles machen kann. Im Prinzip läuft da ein NodeJS-Server mit Weboberfläche, auf der Flows (d.h. Abläufe) definiert und ausgeführt werden können. Es gibt ein paar vorgefertigte Nodes die viele Dinge erleichtern, dann eine gefühlte Million Drittanbieternodes, als auch die Möglichkeit Code direkt in JavaScript zu schreiben. Ich bin kein Fan von JavaScript, aber Node-RED macht die Entwicklung und das Deployment schon sehr einfach. Nutzen wir unter anderem aus diesem Grund auch in der Firma bei Industrieanlagen. Man kommt damit sehr schnell an Ergebnisse, und ich muss zugeben, dass ich auch privat einfach keine Lust mehr habe riesen Projekte aufzusetzen wenn man einfach nur ein paar Sachen automatisiert haben will. Und dafür ist Node-RED echt genial.

Das hat mir aber noch nicht gereicht, nein, ich wollte auch die Möglichkeit haben über gewisse Dinge auch unterwegs benachrichtigt werden zu können (bspw. wenn ein Paket ankommt). Und da mir Sicherheit schon so halbwegs wichtig ist, laufen Benachrichtigungen von Node-RED an mein Smartphone über den Signal Messenger.

Und da fängt der Spaß jetzt an. Damit nicht jeder über Signal mit meiner Node-RED-Instanz kommunizieren kann, habe ich eine Allowlist implementiert. Da ist aktuell nur meine Mobilfunknummer hinterlegt, und wenn ich eine Anfrage via Signal schicke, bekomme ich auch eine Antwort. Das habe ich gestern Abend noch getestet, war glücklich damit, und ging guten Gewissens ins Bett.

Heute Morgen dann, als ich bereits außer Haus war, kam mir die wunderbare Idee auch mal zu sehen ob der Filter auch für Geräte funktioniert, die nicht in der Allowlist hinterlegt sind. Also das Zweithandy gezückt, Die Nachricht „Test“ getippt, auf Senden gedrückt, und die Antwort abgewartet. Relativ genau 1,6 Sekunden später kam dann ein „You're not allowed to use this service.“ zurück, und für weitere 1,6 Sekunden hatte ich auch ein Lächeln im Gesicht. Und dann kam die gleiche Meldung nochmal, und weitere 1,6 Sekunden später nochmal.

Kein Stress dachte ich mir, Signal hat ja ein Rate Limit eingebaut, das geht vielleicht 100 Nachrichten oder so gut, und dann werd ich eh blockiert. Denkste.

Nach 150 Nachrichten habe ich dann langsam mal das Smartphone stummgeschaltet, und nach den ersten 500 Nachrichten kam ich ins Zweifeln, ob es tatsächlich ein Rate Limit gibt. Nach 1000 Nachrichten war klar: Es gibt keines.

2021-06-22-Eigen-DoS

Exakt 19056 Nachrichten später hatte ich dann auch den Fehler gefunden: Wenn man in Signal eine Nachricht sendet, bekommt man standardmäßig auch eine Nachricht ohne Inhalt zurück. Ich konnte nicht herausfinden, wofür genau (ist das die Benachrichtigung dass die Nachricht zugestellt wurde, oder die Benachrichtigung, dass die Nachricht gelesen wurde?), aber das war die Ursache.

Nachdem ich mein „Test“ abgesendet hatte, hat Node-RED die Nachricht empfangen, und mit einem „You're not allowed to use this service.“ quittiert. Das hat wiederum mein Smartphone mit einer Inhaltslosen Nachricht quittiert, was Node-RED wiederum zum Anlass nahm, mir den gleichen Text nochmal zu schicken. Und das eben den ganzen Tag. Die Fehlerbehebung bestand entsprechend darin innerhalb meines Node-RED-Flows zu schauen ob die via Signal übertragene Nachricht überhaupt einen Inhalt hat, und falls nicht kann die Nachricht direkt verworfen werden.

Gelernt habe ich also:

  • Dass Signal entgegen der üblichen Meinungen (und ich habe echt viele Threads dazu gefunden) zumindest bei mir absolut kein Rate Limit anwendet. Ich kann anscheinend den ganzen Tag senden was ich will ohne dass das irgendeine Auswirkung hätte. Und wenn es SPAM ist, ist es halt so
  • Unterwegs nicht testen, ob der Code, den man am Abend zuvor geschrieben hat, auch wirklich funktioniert, das macht man zu Hause
  • Code spätestens dann testen, wenn man den Spaß live schaltet
  • Akkus in Smartphones enorme Sprünge gemacht haben, ebenso wie die verbauten CPUs. Nachdem Signal verhindert hat, dass sich Android in den Deep Sleep begibt, habe ich nach 9 Stunden gerade mal 57% Akku verbraten. Finde ich, dafür dass das Gerät den ganzen Tag aktiv war, in Ordnung
  • Signal relativ problemlos mit mehreren tausend Nachrichten zurechtkommt. Allerdings auch nur so lange, wie man nicht den ganzen Thread dazu öffnet
  • Es gut ist, dass mein Node-RED-Service eine Ablaufzeit für verschwindende Nachrichten bei Signal erzwingt. Die Nachrichten, die ich von meinem SmartHome bekomme, sind immer nur kurze Zeit relevant (Paket angekommen, Licht noch an, Bewegung erkannt, whatever), und werden in der Regel nach einem Tag automatisch gelöscht. Das war übrigens der ausschlaggebende Punkt in diesem Anwendungsfall auf Signal anstelle von Matrix zu setzen
  • Der Spaß deutlich weniger Datenvolumen verbraucht hat als erwartet. Der komplette bisherige Monat wird mir mit 5MB angezeigt, was bei über 19000 Nachrichten deutlich weniger ist, als ich erwartet habe, zumal da auch noch ein paar Mediendateien mit drin sind.