Warum SSH bei jedem Tastendruck 100 Pakete sendet
(eieio.games)- In einer SSH-Sitzung wurde beobachtet, dass bei einem einzelnen Tastendruck Hunderte von Paketen übertragen werden; der Fall wurde bis zur Ursache zurückverfolgt
- Die Analyse mit
tcpdumpzeigte, dass die meisten Pakete aus sich wiederholenden 36-Byte-Nachrichten bestanden und in Abständen von etwa 20 ms auftraten - Ursache war die 2023 zu SSH hinzugefügte Funktion zur Verschleierung des Tastenanschlag-Timings (keystroke timing obfuscation), die zur Verbergung des Eingabe-Timings des Nutzers zahlreiche „chaff“-Pakete (SSH2_MSG_PING) sendet
- Wird diese Funktion deaktiviert oder der Server so geändert, dass er die Erweiterung
[email protected]nicht bewirbt, sinken CPU-Auslastung und Bandbreitenverbrauch auf weniger als die Hälfte - Der Fall zeigt, dass eine Sicherheitsfunktion von SSH bei Anwendungen mit kritischer Echtzeit-Performance (z. B. Spiele) zu erheblicher Last führen kann
Problem entdeckt
- Beim Testen der TUI eines Hochleistungsspiels, das über SSH ausgeführt wird, wurde festgestellt, dass bereits ein einzelner Tastendruck 270 Pakete auslöste
- Laut
tcpdumpwaren 66 % davon 36-Byte-Nachrichten, 33 % TCP-ACKs und der Rest kleine Mengen sonstiger Daten - Im Durchschnitt wurden 90 Pakete/Sekunde mit einem Abstand von etwa 11 ms übertragen
- Laut
- Während der Tests war der Server fälschlich so konfiguriert, dass er nur die Meldung „your screen is too small“ sendete; dabei halbierten sich CPU- und Bandbreitennutzung
- Obwohl keine Spieldaten übertragen werden sollten und die CPU-Auslastung nahe 0 % liegen müsste, blieb sie dennoch bei etwa 50 %
- Dadurch entstand der Verdacht, dass SSH selbst Kommunikations-Overhead verursacht
Untersuchungsverlauf
- Mit
tcpdumpwurde der SSH-Verkehr im Normalbetrieb und im Fehlerzustand verglichen- Auch im Fehlerzustand traten die 36-Byte-Pakete weiterhin alle 20 ms auf
- Dasselbe Muster wurde auch mit dem standardmäßigen SSH-Client von macOS bestätigt
- Die Analyse der pcap-Dateien mit Claude Code ergab
- Von insgesamt 413.703 Paketen waren 66 % 36 Byte groß, 34 % waren 0-Byte-ACKs
- Der SSH-Client erzeugte die Pakete aktiv
Grundursache
- Im SSH-Debug-Log (
ssh -vvv) erschien folgende Meldungobfuscate_keystroke_timing: starting: interval ~20ms obfuscate_keystroke_timing: stopping: chaff time expired (101 chaff packets sent)- Das 20-ms-Intervall und die Dutzenden bis über hundert chaff-Pakete entsprachen genau dem beobachteten Muster
- Verursacher war die 2023 in SSH eingeführte Funktion zur Verschleierung des Tastenanschlag-Timings
- Um zu verhindern, dass Muster in der Tippgeschwindigkeit des Nutzers offengelegt werden, sendet sie zufällige „chaff“-Pakete
- Das ist sicherheitstechnisch nützlich, erzeugt aber in Umgebungen, in denen Latenz entscheidend ist, übermäßige Last
Lösungsansätze
- Auf Client-Seite kann die Funktion mit der Option
ObscureKeystrokeTiming=nodeaktiviert werden- Danach sanken CPU-Auslastung und Bandbreitenverbrauch deutlich, während die Datenübertragung normal erhalten blieb
- Als serverseitige Maßnahme wurde in Gos SSH-Bibliothek die Bewerbung der Erweiterung
[email protected]entfernt- Nach dem Rückgängigmachen des entsprechenden Commits ergaben Tests
- CPU-Auslastung 29,9 % → 11,6 %,
Systemaufrufe 3,10 s → 0,66 s,
Kryptoberechnungen 1,6 s → 0,11 s,
Bandbreite 6,5 Mbit/s → 3 Mbit/s
- CPU-Auslastung 29,9 % → 11,6 %,
- Die Performance verbesserte sich um mehr als 50 %
- Nach dem Rückgängigmachen des entsprechenden Commits ergaben Tests
Debugging-Erfahrungen mit LLMs
- Mit Claude Code wurde die Analyse von
tcpdumpundtsharkautomatisiert, wodurch sich die Ursache schnell eingrenzen ließ- Durch das Echtzeit-Beobachten der Befehlsausführung ließ sich ein mentales Modell des Problems aufrechterhalten
- Mit ChatGPT wurde auch ein Unterschied zwischen den Modellen erlebt, etwa als das Verhalten von SSH fälschlich als „normal“ eingestuft wurde
- LLMs ersetzen zwar nicht den gesamten Problemlösungsprozess, zeigen aber als unterstützende Analysewerkzeuge eine hohe Effizienz
- Ein Beispiel dafür, wie sich menschliches Schlussfolgern und LLM-Analyse kombinieren lassen, um komplexe Netzwerk-Performance-Probleme zu lösen
1 Kommentare
Hacker-News-Kommentare
Einen Fork der crypto-Bibliothek von Go zu pflegen, fühlt sich etwas beängstigend an
Ich überlege, wie ich meinen kleinen Patch sicher halten kann
Eigentlich sollte so eine Funktion als Option in die SSH-Bibliothek upstream gehen
In nicht vertrauenswürdigen Umgebungen sind Chaff-Pakete standardmäßig sinnvoll, aber oft möchte man auch Bandbreite sparen
Die richtige Lösung wäre, eine Option hinzuzufügen, mit der der Server dem Client signalisieren kann: „nicht nötig“, und der Client kann das dann akzeptieren oder eine Warnung ausgeben
Es gilt nur für TTY-Sitzungen, und der Client kann es deaktivieren
Dieser Fall ist nur eine Ausnahme, weil der Server im Voraus weiß, dass die Verbindung nicht wichtig ist
In den meisten Fällen erwartet der Client, dass die Einstellung ObscureKeystrokeTiming eingehalten wird
Die crypto-Bibliothek ist eine Codebasis mit sehr starken Meinungen, dort kann man nicht einmal die Reihenfolge der TLS cipher suites ändern
Das scheint ein sehr spezieller Anwendungsfall für SSH zu sein
Wenn man das zu breit freigibt, endet es womöglich in „einmal konfigurieren und dann vergessen“, was die Sicherheit eher schwächt
Es gab auch die Zeit mit 1200-bps-Modems, und 56K-Modems waren in Wahrheit ziemlich übertrieben
Um 1994 arbeitete ich an einer britischen Militärhochschule und kam zum ersten Mal mit dem WWW in Kontakt, damals dachte ich nur: „eher meh“
Wenn ich heute darüber nachdenke, ist dieser Wandel der Zeiten schon erstaunlich
Von dieser Obfuskationsfunktion hatte ich noch nie gehört, fand sie aber interessant
Wenn man das Verhalten von SSH debuggen will, ist es auch eine gute Methode, den Cipher
Nonezu patchen und sich den Paketinhalt direkt anzusehenWenn Sicherheit nicht wichtig ist und es auf Performance ankommt, etwa bei einem Terminal-Spiel, könnte man auch einfach Telnet in Betracht ziehen
Ich wusste nicht, dass SSH so etwas macht
Ich verstehe, warum es standardmäßig aktiviert ist, aber in meiner Umgebung scheint es sinnvoll, es auszuschalten
Deshalb will ich
ObscureKeystrokeTiming=nosetzen. Gibt es einen Grund, warum ich das nicht tun sollte?(1) Man kann nicht immer unterscheiden, wann jemand ein Geheimnis eingibt, und die gesamte Aktivität kann einer Musteranalyse unterzogen werden
(2) Das ist schon auf dem Niveau eines Universitätslabors ein möglicher Angriff — siehe das USENIX-Paper und dieses Forschungsbeispiel
(3) In einem Internet, das von Video-Traffic dominiert wird, ergibt es wenig Sinn, für ein paar gesparte Bytes bei Tastenanschlägen Sicherheit aufzugeben
Wenn ein Angreifer das Timing der Tastenanschläge analysiert, kann er möglicherweise Befehle und Muster des verschlüsselten Passworts abschätzen
Natürlich ist eine Entschlüsselung schwierig, weil der Sitzungsschlüssel jedes Mal anders ist, aber die Möglichkeit besteht
Ich kopiere die meisten Passwörter ohnehin aus einem Passwort-Manager und füge sie ein
Die meisten Leute haben das Gefühl, dass es kein Problem ist, Sicherheitsfunktionen von SSH abzuschalten, aber das liegt oft nur daran, dass sie bisher Glück hatten
Wenn man wirklich Performance braucht, ist Telnet besser, und wenn man wirklich Sicherheit braucht, ist eine Kombination aus ContainerSSH + OAuth2 sinnvoll
2004 habe ich einmal zur Analyse der Verzögerungen zwischen Tastenanschlägen in SSH-Sitzungen geforscht, um Befehle abzuleiten
Siehe die damaligen Analyseunterlagen
Der Patch von 2023 hat dieses Problem damit endlich gelöst
Vortragsunterlagen
Die Zeit vergeht wirklich schnell
Ich bin mir nicht sicher, ob Claude beim Debuggen wirklich praktisch geholfen hat
Der Autor kannte die Richtung bereits, und Claude wirkte eher so, als hätte es einfach zugestimmt
Dass Claude Dinge wie „Holy Cow!“ sagt, finde ich etwas nervig
Wenn ich mit Claude das Verhalten eines Systems debugge, bekomme ich zwar nicht immer direkte Antworten, aber es hilft mir, mein Verständnis zu strukturieren und motiviert zu bleiben
Rubber-Duck-Debugging-Wiki
Wenn man sieht, dass der Autor die Reaktion „holy cow“ mochte und in den Blog übernommen hat, scheint Claude die Stimmung gut gelesen zu haben
Mit TCP_CORK kann man die Paketanzahl verringern, ohne zusätzliche Latenz zu erzeugen
TCP_NODELAY abzuschalten ist auch eine Möglichkeit, hat aber den Preis höherer Latenz
Wenn man einen Socket corkt, puffert der Kernel Daten und sendet sie erst beim Uncorken oder wenn die MSS erreicht ist
Das heißt, Pakete werden gebündelt übertragen
Referenz
Ping würde ich weiterhin empfangen, aber vermutlich könnte ich die Zahl der gesendeten Pongs reduzieren
TCP_NODELAY habe ich schon ausprobiert, aber die Latenz wurde zu hoch, daher passt das nicht zu meinem Spiel
Früherer HN-Beitrag
Für den Zweck der Obfuskation scheint Coalescing wohl nicht möglich zu sein
Der Ausdruck „The smoking gun!“ war lustig
Ich bin kein englischer Muttersprachler, habe ihn aber zuerst durch Claude oft gehört
Inzwischen verbreitet er sich wirklich wie ein geflügeltes Wort
Diese Abhängigkeit von LLMs finde ich bedauerlich
Das hätte sich wahrscheinlich schneller einfach durch einen Blick auf einen Paketmitschnitt in Wireshark klären lassen
Der SSH-Dissector ist ziemlich ausgereift
Schon wenn man mit tcpdump nur einen einzigen Tastenanschlag mitschneidet, bekommt man Hunderte verschlüsselte Pakete
Letztlich hat der Autor dank des LLM etwas Interessantes gelernt und geteilt, also hatte es durchaus einen Wert
Nach der Nachricht NEWKEYS wird nichts mehr geparst, und selbst mit einem Patch auf
none-Verschlüsselung lässt sich der Ablauf nicht vollständig interpretierenDa gibt es noch Raum für Verbesserungen
Mit Werkzeugen zu lernen, ist für sich genommen schon wertvoll
Mit einem einfachen Paketmitschnitt bekommt man nur schwer sinnvolle Informationen
Ich verstehe nicht, warum das etwas Bedauerliches sein soll
2023 hat SSH eine Funktion zur Obfuskation des Tastenanschlag-Timings hinzugefügt
Da man anhand der Tippgeschwindigkeit Zeichen erraten kann, mischt SSH Chaff-Pakete ein, damit Angreifer sie nicht unterscheiden können
Aber das scheint mir der falsche Ansatz zu sein
Wenn man das wirklich will, könnte man einfach alle Tastenanschläge in 50-ms-Intervallen senden
Die aktuelle Implementierung bündelt in 20-ms-Einheiten und hört nach einer gewissen Zeit ohne Eingabe auf, Chaff zu senden
Der Kern von SSH ist zwar Sicherheit, aber wenn Sicherheit nicht nötig ist, warum dann überhaupt SSH verwenden?
Zum Beispiel ist netcat (nc) auf den meisten Plattformen standardmäßig installiert
Bei SSH gibt es auch andere Aspekte wie Performance und Komfort
Der Autor hat nur gesagt, dass die Funktion zur Obfuskation von Tastenanschlägen (Privacy) unnötig ist
Möglicherweise möchte er Verschlüsselung und Integritätsschutz weiterhin behalten
Es ist also eine Entscheidung, den Großteil der Sicherheitsfunktionen von SSH beizubehalten und nur einen Teil zu deaktivieren