Auf deiner Firewall gibt es eine Funktion, die in deine Pakete hineinliest, dort eine IP-Adresse und eine Portnummer im Text findet und ein eingehendes Loch dafür öffnet. Keine Regel. Kein Change Request. Kein Logeintrag, den du je anschauen würdest. Auf den meisten Geräten, die sie haben, ist sie standardmäßig an, das ist seit gut fünfundzwanzig Jahren so, und die Branche, die sie dort hingebaut hat, ist in den letzten zwanzig davon still zu dem Schluss gekommen, dass sie abgeschaltet gehört — in Standarddokumenten, in Kernel-Defaults und in vier getrennten Runden von Notfall-Patches für Browser.
Sie heißt Protokoll-Helper, oder Application Level Gateway, ALG, Session-Helper, Fixup, Inspection Engine, conntrack-Helper. Dasselbe Ding. Es gibt sie, weil NAT eine Handvoll Protokolle kaputt gemacht hat, die Adressen in ihre eigene Nutzlast schreiben, und weil jemand entschieden hat, die am wenigsten schlechte Lösung sei, dem Übersetzer beizubringen, diese Nutzlast im Vorbeigehen zu lesen und umzuschreiben.
Hier kommt der Teil, der dich stutzig machen sollte.
Der Helper kann nicht erkennen, wer den Text geschrieben hat. Er liest Bytes von einer Verbindung und handelt danach, sofort, ohne irgendwen oder irgendwas zu fragen. Er hat keine Möglichkeit zu wissen, ob die Zeichenkette PORT 192,168,1,29,4,0 von einem echten FTP-Client bei einer echten Übertragung stammt oder von einem versteckten Formular auf einer Webseite, die dein Nutzer aus Versehen geöffnet hat. Beides sieht auf der Leitung identisch aus, weil es auf der Leitung identisch ist. Ein Fremder im Internet, der irgendetwas in deinem Netz dazu bringt, die richtigen Bytes zu senden — einen Browser, einen Chat-Client, alles, was schickt, was man ihm sagt — darf sich also aussuchen, welchen eingehenden Port deine Firewall öffnet und wohin.
Das ist kein Bug im Parser eines Herstellers. Das ist, was die Funktion tut. Die Bugreports und die CVEs sind das interessante Detail obendrauf; die Form darunter ist, dass ein Sicherheitsgerät Konfigurationsanweisungen aus nicht vertrauenswürdigen Daten entgegennimmt und sie sofort umsetzt.
Samy Kamkar hat die Browser-Variante im Januar 2010 vorgeführt1, eine deutlich bessere im Oktober 20202, und drei Monate später hat Armis sie so erweitert, dass der geöffnete Port nicht einmal auf dem Rechner liegen muss, der geklickt hat — er kann auf deinem Drucker sein, deiner Kamera oder einer speicherprogrammierbaren Steuerung zwei VLANs weiter3. Dazwischen hat die IETF festgehalten, dass diese Dinger standardmäßig aus sein sollten4, Linux hat sie im Kernel abgeschaltet5, und die Browser-Hersteller haben eine Liste gesperrter Ports ausgeliefert, die sich fast Zeile für Zeile liest wie ein Verzeichnis der Linux-conntrack-Module6. Jede einzelne dieser Korrekturen wurde woanders angebracht, weil das, was tatsächlich repariert gehört, in einer Kiste sitzt, die niemand patchen wird.
Ich bin zu dem Schluss gekommen, dass Protokoll-Helper überall standardmäßig aus gehören und in jedem Netz, für das du verantwortlich bist, tatsächlich aus sein sollten. Nicht getunt. Nicht als erste Maßnahme auf vertrauenswürdige Subnetze eingeschränkt. Aus, mit den zwei oder drei echten Ausnahmen aufgeschrieben und datiert, genau so, wie du jede andere eingehende Regel dokumentieren würdest — denn genau das sind sie.
Was folgt, ist der Mechanismus, dann die Angriffe in der Reihenfolge ihrer Entdeckung, dann die Compliance-Lage, denn im Vereinigten Königreich ist das nicht bloß unklug, sondern ein glattes Versagen einer Zertifizierungsanforderung, die du womöglich schon hältst, und schließlich die Befehle, um es in Ordnung zu bringen.
Was ein Fremder davon hat
Fang beim Ergebnis an, denn der Mechanismus interessiert einen leichter, wenn man die Rechnung gesehen hat. Jemand öffnet einen Link. Das ist sein ganzer Beitrag. Die Seite führt JavaScript aus, das mit dem Server des Angreifers spricht, und dieser Server formt das Gespräch — füllt es auf, misst es aus, bestätigt Teile davon und andere nicht — bis ein Segment bei deiner Firewall ankommt, das exakt aussieht wie die Eröffnungsnachricht eines VoIP-Anrufs. Deine Firewall glaubt es, denn das Glauben ist die Funktion. Sie legt ein eingehendes Mapping an, und der Angreifer verbindet sich direkt hindurch zurück.
In der Fassung von 2020 öffnet sich der Port auf dem Rechner, der geklickt hat, also jeder Dienst, der auf diesem Host lauscht, erreichbar aus dem Internet, solange das Mapping lebt2. Dateifreigabe. Der Remote-Desktop, den niemand lauschen lassen wollte. Zum Fisher-Price OS (Windows) hat Armis das Naheliegende angemerkt: Erreiche den Port der Dateifreigabe, und du bist einen ungepatchten Host von dem Weg entfernt, den WannaCry genommen hat3.
Die Fassung von 2021 ist schlimmer, und das ist der Teil, der es für dich entscheiden sollte. Weil der H.323-Helper Rufumleitung beherrscht, kann eine einzige Nachricht eine dritte Adresse benennen statt eines der beiden Enden der Verbindung. Der Angreifer ist damit nicht mehr auf den Rechner beschränkt, der geklickt hat, sondern kann deinen internen Adressbereich durchgehen, auf jeder Adresse einen Port öffnen und zurücklesen, was antwortet. Armis hat genau das vorgeführt: Port 80 über einen ganzen Bereich, Banner eingesammelt, ein Ziel ausgesucht, dann den Rohdruck-Port des Druckers geöffnet und einen Druckauftrag geschickt. Ihre zweite Vorführung erreichte eine Steuerung über deren unauthentifizierten Management-Port und änderte ihr Programm3.
Auf keinem dieser Geräte wurde eine Schwachstelle ausgenutzt. Der Drucker war ein funktionierender Drucker, die Kamera eine funktionierende Kamera, die Steuerung eine funktionierende Steuerung, und das Einzige, was versagt hat, war die Grenze — und die hat versagt, indem sie genau das tat, wozu sie konfiguriert war. Überleg auch, wer sich innerhalb dieser Grenze befindet. Nicht nur deine Belegschaft: ein Besucher im Gästenetz, das Notebook eines Dienstleisters, jeder mit einem Browser. Der Angriff braucht keine Zugangsdaten, keinen Fuß in der Tür und keine Schadsoftware, denn der Browser ist das Transportmittel, und der ist bereits installiert und bereits vertrauenswürdig.
Halte das jetzt gegen das, wofür eine Firewall da ist: sicherzustellen, dass von außen niemand ein Gespräch mit irgendetwas drinnen anfängt, außer du hast es erlaubt. Der Helper ist die Ausnahme, und die Ausnahme wird auf Basis einer Zeichenkette in einem Paket gewährt.
Was ein Protokoll-Helper tatsächlich ist
Ein reines NAT ist ein dummes, ehrliches Ding. Ein Paket kommt an, es schreibt Quelladresse und Port im Header um, notiert eine Zeile, damit die Antwort wieder zurückgedreht werden kann, und leitet weiter. Es schaut nie unter den Transport-Header, und es weiß nicht und kümmert sich nicht darum, ob die Bytes darin eine Webanfrage, eine Datenbankabfrage oder das Foto eines Hundes sind.
Das funktioniert, bis ein Protokoll eine Adresse in seine eigene Nutzlast schreibt. FTP tut das, im Klartext im Kommandostrom: verbinde dich zurück zu mir, an diese Adresse, auf diesen Port. SIP tut es in den Feldern Via, Contact und SDP, H.323 tut es, und IRC tut es für Direktübertragungen. Alle wurden entworfen, als die Adresse eines Hosts die Adresse dieses Hosts war und jede Maschine jede andere erreichen konnte, und unter dieser Annahme ist es eine völlig vernünftige Sache. Stell einen Übersetzer in den Pfad, und die Adresse in der Nutzlast wird zur Lüge.
Also wurde der Helper erfunden. Er liest die Nutzlast, findet die Adresse, schreibt sie auf die öffentliche um und tut dann das, worüber alle hinweglesen: Er legt eine Regel an, die genau die eingehende Verbindung erlaubt, die die Nutzlast eben beschrieben hat. Netfilter nennt diese Regel Expectation. Cisco nennt sie Pinhole oder NAT-Tür7. Palo Alto nennt sie dynamisches NAT-Pinhole8. Juniper nennt sie Gate. Anderes Wort, identisches Objekt: ein Loch in der Grenze, geschlagen auf Basis von etwas, das aus einem Paket gelesen wurde.
Die IETF hat das Muster benannt, bevor die meisten dieser Produkte existierten. Ein ALG, sagt RFC 2663, ist ein „application specific translation agent“, der „may interact with NAT to set up state, use NAT state information, modify application specific payload and perform whatever else is necessary to get the application running across disparate address realms“9. Lies das noch einmal mit einem Angreifer im Kopf: whatever else is necessary, gesteuert von application specific payload. Und im Februar 2002 nannte die Middlebox-Taxonomie der IETF den Mechanismus schon beim Namen und merkte an, dass manche ALGs Fragmentierungsprobleme erzeugen, „although in this case the problem is arguably the result of a deliberate layer violation (e.g., mucking with the application data stream of an FTP control connection by twiddling TCP segments on the fly)“10.
Ein absichtlicher Schichtbruch. An TCP-Segmenten im Flug herumfummeln. Das ist der Mechanismus, beschrieben von den Leuten, die ihn vor vierundzwanzig Jahren katalogisiert haben, und es ist derselbe Mechanismus, durch den jeder Angriff in diesem Beitrag geradewegs hindurchmarschiert.
Die Expectation ist das ganze Problem
Alles Weitere in diesem Beitrag folgt aus einem einzigen Objekt, also lohnt es sich, das richtig zu verstehen.
Eine Expectation ist eine vorab genehmigte Verbindung: ein Tupel aus Quelladresse, Quellport, Zieladresse, Zielport und Protokoll, einige Felder gefüllt, andere als Platzhalter offen gelassen, dazu ein Timer. Kommt ein passendes Paket an, behandelt die Firewall es als verwandt mit einem bestehenden erlaubten Fluss statt als neue eingehende Verbindung, lässt es durch und verbraucht die Expectation. Unter Linux liest du sie direkt aus /proc/net/nf_conntrack_expect oder mit conntrack -L expect. Auf einem gesunden System ist diese Liste leer, und genau das ist der Punkt — Expectations sollen selten sein, kurzlebig und von etwas ausgelöst, das ein Host von innen wirklich angefordert hat.
Zwei dieser Antworten sind schlechter, als man erwartet. Die Werte kommen aus der Nutzlast statt von der Firewall, also von demjenigen Ende des Gesprächs, das der Helper gerade gelesen hat. Und beim IRC-Helper ist die Quelladresse konstruktionsbedingt ein Platzhalter, weil das Protokoll nicht wissen kann, wer sich verbinden wird: er „creates expectations whose destination address is the client address and source address is any address“11.
Hier ist der Satz zum Mitnehmen. Eine Expectation ist eine eingehende Firewall-Regel, angelegt in Leitungsgeschwindigkeit, von einer nicht vertrauenswürdigen Partei, ohne jeden Nachweis, wer sie angefordert hat oder warum. Behalte ihn bis zum Abschnitt über Cyber Essentials, denn dort ist er das ganze Argument.
Wie vorgesehen: FTP sagt PORT, und die Firewall glaubt es
Nimm den einfachsten Helper und sieh ihm beim korrekten Arbeiten zu, denn der Angriff ist dieselbe Abfolge mit einem ausgetauschten Beteiligten. Aktives FTP benutzt zwei Verbindungen. Der Client öffnet eine Steuerverbindung zum Server auf Port 21 und gibt ihm Befehle in reinem ASCII, und wenn eine Übertragung ansteht, öffnet er einen lauschenden Socket und schickt ein PORT-Kommando, das Adresse und Port für den Rückruf nennt, woraufhin der Server sich eingehend verbindet. Das ist das Protokoll wie spezifiziert, und so läuft es seit 1985. Auf der Leitung sind es sechs Zahlen, vier für die Adresse und zwei für den Port, höherwertiges Byte zuerst:
PORT 192,168,1,29,4,0
Das ist 192.168.1.29, Port 1024, denn 4 × 256 + 0 = 1024.
Der Helper beobachtet diesen Strom, erkennt PORT, schreibt die Adresse von der privaten auf die öffentliche um und passt dabei die Sequenznummern an, weil die Zeichenkette ihre Länge geändert hat, und legt eine Expectation an, die die eingehende Verbindung des Servers auf dem genannten Port erlaubt. Wirklich nützlich, unter den Zwängen von 1994 völlig vernünftig und in jedem Schritt korrekt.
Sieh genau hin, was geprüft wurde, bevor sich das Loch öffnete. Die Bytes lagen auf einer Verbindung zu Port 21. Sie begannen mit PORT. Das war es. Sonst nichts, weil es sonst nichts zu prüfen gibt — FTP hat keine Signatur anzubieten, keinen Sitzungsschlüssel und keinerlei Authentifizierung, und der Helper liest einen Strom, an dem er nicht beteiligt ist.
Noch eine Sache steckt in diesem Code, und sie ist eine Warnung, die sich die Autoren selbst hineingeschrieben haben. Ist die Adresse im PORT-Kommando nicht die eigene des Clients — bittet der Client den Server also, sich ganz woanders hin zu verbinden — verweigert der Linux-Helper das standardmäßig, und der Kommentar im Quelltext sagt warum: „DMZ machines opening holes to internal networks, or the packet filter itself“12. Setz den Modulparameter loose, und diese Verweigerung ist weg. Die Leute, die den Helper geschrieben haben, wussten genau, wozu man ihn bringen kann. Sie lieferten den sicheren Standard und einen Schalter aus, und fünfundzwanzig Jahre später ist der Schalter immer noch da.
Nicht wie vorgesehen: dieselben Bytes, von einer Webseite
Ein Helper liest einen Bytestrom und gleicht ein Muster ab. Er prüft nicht — und kann konstruktionsbedingt nicht prüfen — ob das Ding am anderen Ende der Client ist, für den es sich ausgibt. Samy Kamkar hat die Konsequenz im Januar 2010 veröffentlicht und sie NAT Pinning genannt1. Der Trick ist peinlich klein: Leg ein Formular auf eine Webseite, richte es auf den Server des Angreifers auf Port 6667, und ordne den Rumpf so an, dass er eine Direktchat-Anfrage enthält.
PRIVMSG samy :^ADCC CHAT samy 3325256705 22^A
Der Browser schickt es ab, in der Annahme, ein HTTP-POST zu machen. Der IRC-Helper des Routers, der eine Verbindung auf Port 6667 beobachtet, sieht DCC CHAT mit einer Adresse und einem Port vorbeiziehen und tut, wozu er gebaut ist. Die Adresse dort ist 198.51.100.1, geschrieben als eine einzelne Dezimalzahl, denn so kodiert das Protokoll sie, und der Port ist 22; nichts in dieser Zeichenkette hat das Opfer gewählt. Die FTP-Variante ist dieselbe Idee auf Port 21, mit einer Antwortzeile im Passiv-Modus statt dessen1.
Kein Cross-Site-Scripting. Keine Request Forgery im üblichen Sinn. Keine Schwachstelle im Browser. Der Browser tat, was Browser tun, die Firewall tat, wozu sie konfiguriert war, und das Ergebnis ist eine Portweiterleitung zum Angreifer.
Das war 2010. Vor sechzehn Jahren. Die Browser-Hersteller haben die IRC-Ports auf ihre Sperrliste gesetzt, was genau diese Tür schloss und den Raum dahinter ließ, wie er war.
Sag den Punkt deutlich, denn er geht zwischen Herstellernamen und CVE-Nummern verloren. Die Angriffe nutzen keinen Fehler in den Helpern aus. Sie benutzen die Helper korrekt. Jedes Paket ist wohlgeformt, und jede Prüfung besteht ehrlich. Die Funktion tut ihren Job, und ihr Job ist das Problem.
Die Bytes dorthin schieben, wo der Helper liest
Zwischen NAT Pinning und etwas sehr viel Schlimmerem lag ein echtes Hindernis, und der Weg darum herum ist das Cleverste am ganzen Thema. Die meisten Helper gleichen ein Muster nicht irgendwo im Strom ab: Sie prüfen, dass das Schlüsselwort am Anfang des Datenteils eines Pakets steht, was bei einer echten Protokollnachricht so ist und bei einem HTTP-Rumpf nie, weil ein Rumpf nach einem Stapel Header ankommt, den der Angreifer nicht kontrolliert. Samy zitiert das Verhalten des Kernels selbst — der Handler bricht ab, wenn die Methode nicht am Anfang der Daten steht2.
Der Angreifer braucht also einen Browser, der ein TCP-Segment ausgibt, dessen allererstes Byte das Schlüsselwort ist. Die Header kann er nicht schreiben, aber den Rumpf schon, und den so lang machen, wie er will — womit das Problem zur Rechenaufgabe wird.
Der Browser schickt eine große Anfrage mit einem erkennbaren Trennzeichen im Rumpf; der Server des Angreifers schnüffelt sie mit, misst, wie viele Header-Bytes davor kamen, und kennt damit den Offset. Dann kündigt er entweder eine Segmentgröße an, die das gewünschte Byte auf eine Grenze legt, oder er bestätigt den Strom nur teilweise, sodass das Opfer genau ab dort erneut sendet — und Armis ergänzt, dass sich auch das TCP-Fenster in diesen Bestätigungen präparieren lässt, „in order to fully control how the TCP stream is to be segmented“3. Das ist der ganze Trick, und er benutzt nichts weiter als das ferne Ende einer Verbindung, die der Browser des Opfers selbst geöffnet hat.
Hat man das, ist der Browser ein Allzweck-Paketgenerator, der auf das Innere deiner Firewall zeigt. Kein perfekter, denn er kann keine beliebigen Header setzen und keine beliebigen Protokolle wählen, aber das musste er nie sein. Er muss nur die richtigen dreißig Bytes an den Anfang eines Segments legen.
Die Arbeit von 2021 hat sich die Rechnerei größtenteils gespart. Eine Browser-Relay-Verbindung über TCP trägt ein vom Angreifer kontrolliertes Benutzernamenfeld, früh gesendet, das Zeilenumbrüche und Nullbytes akzeptiert, solange das Ergebnis gültiger Text ist — Armis zeigte einen Mitschnitt, in dem dieses Feld die Zeichenkette \r\nPORT 192,168,1,29,4,0\r\n ist, mit einer Teilbestätigung, die das Opfer genau ab dem PORT erneut senden lässt3. Schlimmer noch: Dieser Weg fragte die Sperrliste des Browsers überhaupt nicht ab, womit die eine Gegenmaßnahme, die die Branche zweimal ausgeliefert hatte, schlicht umgangen war.
NAT Slipstreaming, von Anfang bis Ende
Setz die Teile zusammen, und das ist der ganze Angriff, der Reihe nach.
Verstrichene Zeit insgesamt: Sekunden. Nutzerinteraktion insgesamt: ein Klick. Auf dem Rechner des Opfers ausgenutzte Schwachstellen insgesamt: keine.
Der Ablauf der Offenlegung ist für sich genommen ein Beweisstück. Samy veröffentlichte am 31. Oktober 2020, Armis meldete sich drei Tage später, und die koordinierte Offenlegung bei den Browser-Herstellern begann am 11. November. Chrome lieferte am 6. Januar 2021 eine Gegenmaßnahme aus, Edge am Tag darauf, Safari am 14. als Beta und am 1. Februar stabil, Firefox am 26.3 — geführt als CVE-2020-16043, CVE-2021-23961 und CVE-2021-1799.
Vier Browser-Hersteller lieferten Notfall-Patches für eine Firewall-Funktion aus. Armis erklärt in eigenen Worten, warum: „While the underlying issue of this attack is the way NATs are implemented (in various ways in routers and firewalls, throughout numerous vendors and applications), the easiest and fastest way to mitigate was through a patch to browsers“3.
Das ist keine Lösung. Das sind vier fremde Branchen, die Sandsäcke vor die Haustür von jemand anderem stapeln, weil die Tür selbst nie ersetzt werden würde.
H.323-Rufumleitung zeigt auf alles in deinem Netz
Die meisten Helper begrenzen den Schaden, ohne es zu wollen. Der FTP-Helper heftet das Ziel der Expectation an den Client, der sie erzeugt hat, sodass ein Angreifer schlimmstenfalls einen Port auf dem Rechner bekommt, der geklickt hat — schlimm, aber überlebbar.
H.323 ist katastrophal, und der Grund ist eine Telefoniefunktion.
Eine Telefonanlage muss Rufumleitung beherrschen, und ein umgeleiteter Anruf ist per Definition ein Anruf bei jemandem, der nicht in der Leitung ist. Die Signalisierung muss also einen dritten Endpunkt benennen, und der Helper muss einen Pfad dorthin öffnen, sonst funktioniert Umleitung durch NAT überhaupt nicht. Jede ernsthafte Implementierung kann das, und der netfilter-Helper dokumentiert das Verhalten ausdrücklich, mit Diagramm, auf der netfilter-Seite13. Armis hat den Code gelesen und die Konsequenz in einem Satz festgehalten: „a single H.323 packet sent over TCP port 1720 that initiates call forwarding can open a pinhole (named an expectation in the conntrack subsystem) to any TCP port of any internal IP on the network“3.
Jeder TCP-Port. Jede interne Adresse. Aus einem Paket, das der Angreifer einen Browser hat senden lassen.
Der Angriff geht damit nicht mehr um den Rechner des Opfers, sondern wird zu einem Portscan deines internen Netzes, durchgeführt aus dem Internet, mit Ergebnissen, die über Verbindungen zurückgelesen werden, die deine eigene Firewall genehmigt. Die Geräte, die er findet, sind der Punkt, denn sie sind nicht gepatcht, oft gar nicht patchbar, und das ganze Sicherheitsmodell der meisten lautet es steht ja drinnen. Armis hat diese Annahme mit einer Zahl versehen: Ein Jahr nach Veröffentlichung waren 97 % der für eine Serie kritischer Lücken anfälligen Industriesteuerungen noch ungepatcht3. Niemand behauptet, diese Zahl sei gut. Sie ist die Wirklichkeit, die „es steht ja drinnen“ trägt.
Also ist H.323 auf jeder Plattform das Erste, worum du dich kümmerst, weil es das Einzige ist, das über das Opfer hinausreicht — und weil es zugleich das ist, das fast niemand mehr benutzt, ist es die billigste Sicherheitsverbesserung in diesem Beitrag. Schalte es ab. Es wird dich niemand deswegen anrufen.
Der Helper lässt sich von einer Nachricht auslösen, die du nie geschickt hast
Eine Variante verdient einen eigenen Abschnitt, weil sie die Annahme kippt, nach der Leute greifen, wenn sie einen Grund zum Nichtstun suchen: Gut, aber der Auslöser muss ja von innen kommen, also kontrolliere die Browser und du kontrollierst das Problem.
Nein.
Im Juli 2022 fand David Leadbeater zwei Fehler im Linux-IRC-Helper14. Das Modul sucht die Zeichenkette \1DCC irgendwo im Strom, statt zu prüfen, ob sie an der richtigen Stelle in einer korrekt gerahmten Nachricht steht, und seine Adressprüfung vergleicht mit der Adresse des Chat-Servers statt mit der des Hosts hinter dem Übersetzer, sodass die öffentlich bekannte Adresse eines öffentlichen Servers genügt. Zusammen bedeutet das: Ein Angreifer schickt dem Client des Opfers einen Client-zu-Client-Ping — etwas völlig Normales, das man von jedem anderen Nutzer bekommt — mit einer Direktübertragungsanfrage darin:
PRIVMSG ExampleUser :^APING ^ADCC CHAT x 3325256705 22^A
Nach den Regeln des Protokolls beantwortet der Client einen Ping, indem er die Nutzlast zurückspiegelt, also schickt der Client des Opfers diese Zeichenkette pflichtschuldig nach außen, und der Helper, der den ausgehenden Strom beobachtet, findet DCC darin und öffnet den Port.
Niemand drinnen hat etwas falsch gemacht, und niemand hat geklickt. Der Client folgte der Spezifikation, und Spezifikation und Helper zusammen erzeugten ein eingehendes Loch auf Port 22 zu einer Maschine im Netz. Daraus wurde CVE-2022-2663, und die Beschreibung in der nationalen Schwachstellendatenbank ist erfreulich klar: „A firewall may be able to be bypassed when users are using unencrypted IRC with nf_conntrack_irc configured“15.
Achte auf das Wort unencrypted. Merk dir auch das.
Die Empfehlung des Autors ist genau das, wo der Rest dieses Beitrags aus einer anderen Richtung ankommt: „Potentially entirely deprecate and remove nf_conntrack_irc, it’s unclear it has much use anymore“14.
Die Parser sind die andere Hälfte
Bisher ging es darum, dass Helper korrekt arbeiten. Es gibt ein zweites, davon getrenntes Problem: Sie sind Protokoll-Parser in C, die im schnellen Pfad eines Sicherheitsgeräts laufen, auf Daten, die Fremde liefern — mit der Fehlerquote, die man nach dieser Beschreibung erwarten würde. Und das ist kein Linux-Problem und kein Billigrouter-Problem, es taucht bei jedem Hersteller auf, im Code, für den sie am meisten verlangen.
| CVE | Komponente | Was ein präpariertes Paket bewirkt |
|---|---|---|
| CVE-2018-0051 | Junos SIP ALG | Bringt den Flow-Daemon auf SRX und MX zum Absturz; hält außerdem fest, dass SIP ALG außer auf High-End-Modellen standardmäßig an ist |
| CVE-2018-15454 | Cisco ASA / FTD SIP-Inspection | Startet das Gerät neu oder nagelt die CPU fest |
| CVE-2022-2663 | Linux nf_conntrack_irc | Öffnet Ports durch die Firewall, wie oben |
| CVE-2023-22412 | Junos SIP ALG | „Specific SIP messages“ bringen den Flow-Daemon reproduzierbar zum Absturz |
| CVE-2023-22415 | Junos H.323 ALG | Schreibzugriff außerhalb der Grenzen durch „specific H.323 packets“ |
| CVE-2024-21616 | Junos SIP ALG | Ein SIP-Paket erschöpft den NAT-Pool, echter Verkehr wird nicht mehr übersetzt |
| CVE-2024-26851 | Linux nf_conntrack_h323 | Bitverschiebung außerhalb des gültigen Bereichs beim Dekodieren der H.323-Bitmap |
| CVE-2024-39551 | Junos H.323 ALG | Speicher wird durch „specific packets“ erschöpft, bis der Verkehr steht |
Jede davon ist ohne Authentifizierung aus dem Netz erreichbar, von jedem, der ein Paket an die Außenschnittstelle bekommt, also von allen. Und lies die Formulierungen: specific SIP messages, specific H.323 packets, a specific SIP packet. Das ist kein Protokoll, das unter Last versagt. Das ist jemand, der absichtlich ein Paket baut.
Bleib einen Moment beim Cisco-Fall. CVE-2018-15454 wurde am 31. Oktober 2018 mit Schweregrad 8.6 veröffentlicht, wurde aktiv ausgenutzt, und das Advisory sagte, das Software-Update sei noch nicht verfügbar16. Ciscos Gegenmaßnahme lautet im eigenen Advisory no inspect sip. Die Antwort des Herstellers auf eine aktiv ausgenutzte Lücke in der Funktion war also, die Funktion abzuschalten — womit die Frage auf dem Tisch liegt, auf der der Rest dieses Beitrags aufbaut. Wenn Abschalten während eines Vorfalls eine akzeptable Antwort ist, mit welcher Begründung ist es die restliche Zeit an?
Ein Helper funktioniert nur, wenn du nicht verschlüsselst
Das ist der Teil, der die Diskussion allein beenden sollte, und es ist der Teil, der am wenigsten Beachtung bekommt. Ein Protokoll-Helper liest deine Nutzlast und kann eine verschlüsselte nicht lesen. Ein Helper tut also überhaupt nur etwas auf Verkehr, den du im Klartext gelassen hast, und den Helper funktionsfähig zu halten heißt, diesen Verkehr im Klartext zu halten.
Jedes Protokoll auf dieser Liste hat seit weit über einem Jahrzehnt einen verschlüsselten Modus. FTP hat TLS seit 200517; schalte es ein, und die PORT- und PASV-Wechsel sind unsichtbar, der Helper tut nichts. SIP hat TLS seit der Basisspezifikation, samt verschlüsselter Medien. H.323 hat seinen eigenen Sicherheitsanhang. Chat hat seit sehr langer Zeit TLS, und die offizielle Empfehlung zu CVE-2022-2663 lautete mit genau diesen Worten, es zu benutzen, damit der Helper deine Übertragungsanfragen nicht sehen kann15.
Die ehrliche Fassung von „wir brauchen das SIP ALG“ lautet also: wir brauchen unsere Anrufsignalisierung im Klartext über nicht vertrauenswürdige Netze, damit eine Middlebox, die wir nicht kontrollieren, sie umschreiben kann. Sag es so in einem Design-Review und schau, wie weit du kommst.
Es gibt eine schärfere Fassung, und deshalb ist das kein knapper Fall. Einen Helper aktiv zu lassen, ist ein dauerhafter Anreiz gegen Verschlüsselung: An dem Tag, an dem jemand SIP über TLS einschaltet, brechen die Gespräche, und der Helper ist der Grund, also wird die Änderung zurückgenommen und der Klartext bleibt noch ein Jahr. Frag jemanden, der das hinter einer Consumer-Firewall versucht hat, wie es gelaufen ist.
Jedes andere Protokoll im Internet ist den umgekehrten Weg gegangen: Webverkehr standardmäßig verschlüsselt, DNS verschlüsselt, Mailtransport verschlüsselt, QUIC verschlüsselt sogar den Transport-Header selbst, genau damit Middleboxen ihn weder lesen noch verändern können. Die Middlebox-Ära ist im offenen Internet vor Jahren zu Ende gegangen, und die letzten Stellen, die sich noch auf ein Gerät im Pfad verlassen, das die Nutzlast liest, sind die, an denen jemand einen Helper angelassen hat.
IPsec ist der Fall, in dem der Helper gar nichts lesen kann
Damit stellt sich die naheliegende Frage nach dem Protokoll, das nichts als Verschlüsselung ist. Die Antwort ist schlimmer, als du vermuten würdest.
ESP hat keine Portnummern, weil es ein eigenständiges IP-Protokoll ist und nicht etwas, das über UDP läuft, und ein Übersetzer demultiplext Rückverkehr über Ports. Bei zwei Clients hinter einer öffentlichen Adresse, die zum selben Gateway wollen, gibt es also nichts, woran man ihre eingehenden Pakete unterscheiden könnte. RFC 3715 hat das im März 2004 festgehalten: Ein NAT kann die Zuordnung nicht durch Hinsehen lernen, und „it is possible that the NAT will deliver the incoming IPsec packets to the wrong destination“18.
Also bauten die Hersteller einen Helper. Er beobachtet den IKE-Austausch auf UDP 500, dessen erste Pakete im Klartext liegen, sammelt die Cookies und den Security Parameter Index ein und öffnet ein Gate, damit eingehendes ESP mit diesem Wert beim richtigen Host drinnen ankommt. Juniper beschreibt es am klarsten: „When ESP traffic hits the IKE ALG gates, sessions are created to capture subsequent ESP traffic“19. Ciscos inspect ipsec-pass-thru macht dasselbe für ESP und AH „associated with an IKE UDP port 500 connection“, mit einer Vorgabe-Map, die überhaupt kein Limit für ESP-Verbindungen pro Client setzt20.
Dasselbe Objekt, dieselbe Autorität, nur passt der Helper hier nicht einmal ein Schlüsselwort ab. Er kann ESP nicht parsen, denn ESP ist der verschlüsselte Teil; er steuert Pakete anhand einer 32-Bit-Zahl, die er im Klartext vorbeiziehen sah. Der Abschnitt von RFC 3715, der das behandelt, heißt ohne jede Ironie „Helper Incompatibilities“ und hält fest, dass Cookie-Demultiplexing „results in problems with re-keying“ und dass Geräte, die ISAKMP-Payloads parsen, „may not handle all payload ordering combinations“18. Eine Vermutung anstelle einer Regel, und ein selbstgebauter Parser im Paketpfad, aufgeschrieben vor zweiundzwanzig Jahren.
Die Lösung kam zehn Monate später, im Protokoll, wo sie hingehört: RFC 3947 lässt die beiden Enden während des Schlüsselaustauschs einen Übersetzer erkennen, und RFC 3948 verpackt ESP in UDP auf Port 4500, damit es wieder Ports gibt21. Juniper spricht es dann offen aus: „IKE NAT-T traffic on floating port 4500 is not processed in an IKE ALG“19. Macht man es richtig, wird der Helper komplett umgangen — derselbe Satz wie beim passiven FTP und bei ICE.
Der Mainline-Linux-Kernel hat diesen hier nie übernommen. Unter den Conntrack-Protokollen gibt es kein ESP-Modul, und ein Patch von 2021, der SPI-basiertes Tracking hinzufügen sollte, durchlief das Review auf der Netfilter-Liste und wurde nie gemergt22. Die Hersteller, die ihn ausliefern, liefern ihn out of tree aus, auf den Geräten, die am wenigsten wahrscheinlich je aktualisiert werden.
Es reißt Cyber Essentials, Zeile für Zeile
Bis hierher war das ein Sicherheitsargument. Für jeden, der im Vereinigten Königreich zertifiziert, ist es auch ein Compliance-Argument, und dabei ist keinerlei kluge Auslegung im Spiel — es sind drei Stichpunkte gegen drei Stichpunkte. Cyber Essentials ist das von der britischen Regierung getragene Programm, umgesetzt über IASME, seine erste technische Anforderung sind Firewalls, und das aktuelle Anforderungsdokument ist Version 3.3 vom April 2026. Das hier verlangt es von dir, wörtlich23:
- block unauthenticated inbound connections by default
- ensure inbound firewall rules are approved and documented by an authorised person, and include the business need in the documentation
- remove or disable unnecessary firewall rules, when they are no longer needed
Jetzt stell einen Protokoll-Helper daneben.
Eine Expectation existiert genau dazu, eine eingehende Verbindung zu erlauben, die sonst blockiert würde, und die Partei, deren Daten sie ausgelöst haben, hat sich gegenüber nichts authentifiziert — der erste Stichpunkt fällt also glatt durch. Die Regel wurde in Leitungsgeschwindigkeit von einem Kernelmodul geschrieben, es gibt also kein Dokument, keinen erfassten geschäftlichen Bedarf und keine autorisierte Person irgendwo in der Kette — frag einen Prüfer nach dem Genehmigungsnachweis für die Regel, die eine Verbindung an Port 9100 deines Druckers durchgelassen hat, und du hast keinen und kannst keinen anfertigen, weil sie vor achtzehn Monaten neunzig Sekunden lang bestand. Und die Regeln eines Helpers werden von einem Timer entfernt, und ein Timer ist keine Überprüfung.
Drei Anforderungen, drei Fehlschläge, bei der ersten Kontrolle von fünf, die in den Worten des Programms für „boundary firewalls, desktop computers, laptops, routers, servers“23 gilt, also für alles, was du besitzt.
Sei fair damit, denn ich bin nicht die Zertifizierungsstelle. Ein Prüfer arbeitet mit dem Fragenkatalog und den Nachweisen, die du ihm gibst, und dieser Katalog fragt, ob du unauthentifizierte eingehende Verbindungen standardmäßig blockierst und ob deine eingehenden Regeln dokumentiert und genehmigt sind. Antworte mit Ja, während auf deiner Grenze ein Helper läuft, und die Antwort stimmt nicht. Bestehen wirst du wahrscheinlich trotzdem. Bestehen und Einhalten sind nicht dasselbe, und die Lücke dazwischen zeigt sich nach einem Vorfall statt davor.
Cyber Essentials ist mit dem, was es verlangt, auch nicht ungewöhnlich, nur ungewöhnlich klar formuliert. Ein Kartenbranchen-Standard, ein staatliches Prüfprogramm, der Fragebogen eines Kunden und das Antragsformular deines Versicherers fragen in anderer Sprache dasselbe: Weißt du, was deine Firewall eingehend erlaubt, und hat das jemand entschieden? Das ist also der Abschnitt für die Person, die das Zertifikat unterschreibt. Nicht die Angriffe und nicht die CVEs. Drei Stichpunkte und die ehrliche Antwort auf jeden.
Die Branche hat das vor zwanzig Jahren entschieden
Nichts davon ist neu, und nichts davon ist umstritten. Bemerkenswert ist, wie lange die Entscheidung schon steht, während die Standardeinstellungen unbeirrt weiterliefen.
RFC 3027 hat im Januar 2001 jedes Protokoll katalogisiert, das NAT kaputt macht24. RFC 3234 hat ALGs ein Jahr später in die Middlebox-Taxonomie eingeordnet, den Mechanismus „a deliberate layer violation“ genannt und die Kosten zusätzlicher Kisten im Pfad klar benannt: das „creates extra points of attack, reduces or eliminates the ability to perform end to end encryption, and complicates trust models“10. Dann legte im Januar 2007 RFC 4787 — eine Best Current Practice, kein Vorschlag — fest, wie NAT sich zu verhalten hat, und Anforderung zehn sagte dies:
REQ-10: To eliminate interference with UNSAF NAT traversal mechanisms and allow integrity protection of UDP communications, NAT ALGs for UDP-based protocols SHOULD be turned off.4
Aus. Vor neunzehn Jahren, mit Begründung: Helper stehen den Mechanismen im Weg, die tatsächlich funktionieren, und sie hindern dich daran, die Integrität deines eigenen Verkehrs zu schützen. Derselbe Abschnitt hält resigniert fest, dass manche Produkte ALGs „turned on permanently“ haben4.
Drei Jahre später zeigte NAT Pinning eine Webseite, die einen Port öffnet1. Netfilter antwortete 2012 mit einem Mechanismus, das absichtlich statt automatisch zu tun — dem CT-Ziel, das einen Helper per ausdrücklicher Regel an einen benannten Fluss hängt, und einem Schalter, der die automatische Zuweisung ganz abstellt11. Dann änderte der Kernel am 25. April 2016 seinen Standard, in einer Commit-Nachricht, die man ganz lesen sollte, so müde klingt sie:
Four years ago we introduced a new sysctl knob to disable automatic helper assignment […] This knob kept this behaviour enabled by default to remain conservative. This measure was introduced to provide a secure way to configure iptables and connection tracking helpers through explicit rules. Give the time we have waited for this, let’s turn off this by default now, worse case users still have a chance to recover the former behaviour by explicitly enabling this back through sysctl.5
Das kam mit Linux 4.7, und seither tut eine Kiste mit geladenen Modulen nichts damit, bis du eine Regel schreibst, die einen an einen Fluss hängt — mit einer Logzeile, die es dir sagt. Alles danach steht im Diagramm oben: Slipstreaming und seine Variante für jedes Gerät, vier Browser-Hersteller mit Gegenmaßnahmen, während der Web-Plattform-Standard selbst die Portliste bekam25, der IRC-Helper, der auf eine Nachricht anspringt, die niemand verfasst hat, und vier weitere ALG-Lücken in der Flaggschiff-Firewall-Linie eines Herstellers.
Schau jetzt auf die Liste und sieh, was fehlt. In fünfundzwanzig Jahren ist keine einzige Zeile davon ein Firewall-Hersteller, der ein Firmware-Update ausrollt, das diese Dinger auf bereits ausgeliefertem Gerät abschaltet. Das Standardisierungsgremium hat es verlangt. Der Kernel hat es upstream getan. Die Forscher haben es viermal getrennt bewiesen. Die Browser haben dafür bezahlt. Die Kisten liefen weiter.
Und die Sperrliste der Ports ist das Indiz. Die Ports 69, 137, 161, 554, 1719, 1720, 1723, 5060, 5061, 6566 und 10080 stehen alle darauf6 — TFTP, NetBIOS, SNMP, RTSP, H.323 zweimal, PPTP, SIP zweimal, das Scanner-Protokoll und das Amanda-Backup-Protokoll. Lass dir die Helper-Module in einem Linux-Kernelbaum auflisten, und du wirst merken, dass du dieselbe Liste zweimal gelesen hast. Kein Zufall, und keine Sicherheitsmaßnahme. Es ist eine Branche, die dauerhaft eine wachsende Sperrliste von Ports pflegt, weil eine andere Branche einen Standardwert nicht ändern will.
Unter den meisten Abzeichen steckt Linux
Das netfilter-Detail ist der wichtige Teil und kein Linux-förmiger Exkurs, und es lohnt sich, vor der Herstellerliste zu sagen, warum. Ein sehr großer Anteil der Kisten, die auf diesem Planeten NAT machen, ist Linux mit netfilter unter einer Herstelleroberfläche: jede OpenWrt-Ableitung, also der Großteil des Consumer- und Kleinunternehmens-Routermarkts, die meisten vom Provider gestellten Heimrouter, ein guter Teil der Carrier-Grade-NAT-Technik und reichlich kommerzielle Appliances, deren Weboberfläche nicht andeutet, was darunter liegt. Der Helper, der dein SIP parst, ist in sehr vielen Fällen dasselbe nf_conntrack_sip.c, das im Mainline-Kernel ausgeliefert wird, von jemand anderem übersetzt und über ein Menü gesteuert.
Der Beleg steckt in der Forschung selbst. Als Samy in einem Netgear-Router nach dem SIP ALG suchte, extrahierte er die Firmware und fand ein Kernelmodul mit ftp_decode und sip_decode2. Die Testliste von Armis enthielt OpenWrt und VyOS sowie eine Kategorie, die sie schlicht „various consumer grade Linux routers, with likely older kernel versions“ nannten, und die H.323-Analyse, aus der der Befund „jeder interne Host“ stammt, entstand beim Lesen des netfilter-Quelltexts und wurde danach an kommerziellen Firewalls von drei Herstellern bestätigt3.
Daraus folgen zwei praktische Konsequenzen.
Der Kernel-Standard erreicht dich nicht. Linux 4.7 hat die automatische Helper-Zuweisung 2016 abgeschaltet, aber nur, wenn der Kernel neu genug ist und niemand sie wieder eingeschaltet hat. Armis fand VyOS, das nf_conntrack_helper ausdrücklich wieder auf 1 setzt, und hielt fest, dass reichlich Linux-basierte Produkte sie wieder aktivieren, „as it is still useful for many users“3. Ein Kernel von 2014 in einem Produkt von 2026 bekommt das Verhalten von 2014, und ein aktueller Kernel mit umgelegtem Schalter bekommt dasselbe. Keines von beidem steht auf einem Datenblatt.
Wer das netfilter-Modell kennt, weiß, was er jede andere Kiste fragen muss. Die drei Fragen aus dem Abschnitt über Expectations sind keine Linux-Fragen. Es sind die Fragen. Jeder Hersteller hat dasselbe Objekt unter anderem Namen, die Dokumentation liefert die Antworten fast nie, und zu wissen, was die Referenzimplementierung tut, ist der Weg herauszufinden, was du testen musst.
Mach die Linux-Arbeit ordentlich, und lies dann jeden anderen Hersteller dagegen.
Die Linux-Helper, richtig gemacht
Fang damit an, was tatsächlich geladen ist:
lsmod | grep -E 'nf_conntrack|nf_nat'
Die Helper-Module sind die nach Protokollen benannten — nf_conntrack_ftp, _sip, _h323, _irc, _tftp, _pptp, _snmp, _amanda, _sane, _netbios_ns und _talk — jeweils mit einem passenden nf_nat_*, wo Adressen umgeschrieben werden. Dann prüfe, ob die automatische Zuweisung an ist, denn das ist der Schalter, der entscheidet, ob ein geladenes Modul von sich aus etwas tut:
sysctl net.netfilter.nf_conntrack_helper
Null ist, was du willst, und Null ist der Standard ab Linux 4.75. Eins heißt, dass jeder geladene Helper auf jedem Fluss aktiv ist, der zu seinem Port passt, von jeder Adresse — das Verhalten von 2015 und das Verhalten, das die Angriffe in diesem Beitrag voraussetzen.
Beobachte dann conntrack -L expect auf einer laufenden Firewall. Mit abgeschalteten Helpern bleibt es leer; mit eingeschalteten stell einen Mitschnitt daneben und sieh zu, wie Zeilen auftauchen, während Leute das Netz benutzen. Diese Übung lohnt sich einmal im Leben, denn nichts macht den Punkt schneller, als eine eingehende Erlaubnis, die du nicht geschrieben hast, vor deinen Augen auftauchen und verschwinden zu sehen.
Ist die automatische Zuweisung aus und du willst trotzdem einen bestimmten Helper auf einem bestimmten Fluss, ist der vorgesehene Weg eine ausdrückliche Regel, die ihn wenigstens auf ein Ziel und einen Port begrenzt:
iptables -t raw -A PREROUTING -p tcp --dport 21 -d 192.0.2.10 -j CT --helper ftp
Das nftables-Gegenstück deklariert ein ct helper-Objekt und hängt es in der Prerouting-Kette mit ct helper set an, dieselbe Disziplin mit besserer Syntax.
Und jetzt schau, was diese Regel ist: eine dokumentierte, genehmigte, geschäftlich begründete eingehende Ausnahme, von einem Menschen geschrieben, im Regelwerk, wo ein Prüfer sie lesen kann. Also genau das, was die automatische Variante nie sein konnte.
Wenn du sie ganz los sein willst statt nur schlafend — und auf einer Firewall solltest du das — verhindere das Laden der Module überhaupt:
for m in ftp sip h323 irc tftp pptp snmp amanda sane netbios_ns talk; do
echo "install nf_conntrack_$m /bin/false"
done > /etc/modprobe.d/no-conntrack-helpers.conf
install ... /bin/false statt blacklist ist Absicht: blacklist verhindert nur das automatische Laden über Aliase, und wer das Modul beim Namen anfordert, bekommt es trotzdem. Und wenn die Firewall-Schicht deiner Distribution sie für dich lädt — firewalld tut das, wenn eine Zone den FTP- oder TFTP-Dienst aktiviert hat — dann ist das die Schicht, die du anfassen musst, denn sie legt sie hilfsbereit wieder hin.
Jedes andere Abzeichen und wie man es abschaltet
Prüfe deine eigene Version, statt irgendetwas im Internet zu glauben, meins eingeschlossen, denn diese Standardwerte verschieben sich zwischen Releases und zwischen Modellen derselben Reihe.
pfSense und OPNsense sind der Beweis, dass die Diskussion vorbei ist. Es gibt kein SIP ALG zum Abschalten, weil es nie eines zum Einschalten gab. Sie gehören zu den am weitesten verbreiteten Firewall-Distributionen überhaupt, sie betreiben Telefonie für sehr viele Organisationen, und wäre ein Helper wirklich nötig, damit modernes VoIP funktioniert, wäre das nicht möglich. Es ist offensichtlich möglich. Dem FTP-Proxy erging es genauso: Netgate hat ihn im Januar 2015 aus dem Basissystem genommen und zu einem Zusatzpaket degradiert, das die meisten nie installiert haben.
OpenBSDs Entwurf ist der, den alle anderen hätten kopieren sollen. pf schreibt im Weiterleitungspfad überhaupt keine Nutzlast um. Willst du FTP geholfen haben, startest du ftp-proxy, einen eigenen Userspace-Dienst, und schreibst eine ausdrückliche divert-to-Regel, die die Steuerverbindung dorthin schickt; der Proxy verbindet sich dann im Auftrag des Clients zum Server26. Daraus fallen sofort drei Eigenschaften: Er ist aus, außer du schaltest ihn absichtlich ein, er sieht nur Verkehr, den du in einer Regel benannt hast, und ein Fehler darin bringt einen Userspace-Prozess zum Absturz statt den Paketpfad. So sieht Opt-in aus, wenn jemand es entwirft statt nachträglich anzuflanschen.
OpenWrt liefert die ALG-Module nicht mit, und die automatische Zuweisung bleibt aus, selbst wenn du sie nachinstallierst.
Cisco ASA und FTD tragen Inspection Engines in der Standard-Global-Policy, und no inspect sip ist Ciscos eigener Rat im Ernstfall:
policy-map global_policy
class inspection_default
no inspect sip
no inspect h323 h225
no inspect h323 ras
no inspect skinny
Auf FTD lautet es configure inspection sip disable auf der Geräte-CLI16. IPsec-Pass-through ist das eine, das Cisco richtig gemacht hat: inspect ipsec-pass-thru steht gar nicht erst in der Standardrichtlinie, es gibt also nichts zu entfernen, sofern es niemand absichtlich hinzugefügt hat20.
Cisco IOS und IOS XE haben es ebenfalls standardmäßig an — „NAT support for SIP is enabled by default on port 5060“, in Ciscos eigenen Worten7, und dasselbe für H.323:
no ip nat service sip tcp port 5060
no ip nat service sip udp port 5060
no ip nat service h225
Juniper SRX aktiviert SIP und H.323 auf den Branch-Modellen und nicht auf den High-End-Geräten, was für sich genommen schon verrät, was Junipers Entwickler davon halten. Finde mit show security alg status heraus, wo du stehst, dann:
set security alg h323 disable
set security alg sip disable
set security alg ftp disable
set security alg ike-esp-nat disable
FortiGate inspiziert VoIP standardmäßig über das VoIP-Profil, mit einem Kernel-Session-Helper darunter. Fortinets dokumentierte Reihenfolge entfernt zuerst den Helper27:
config system session-helper
show
delete <der SIP-Eintrag>
end
config system settings
set default-voip-alg-mode kernel-helper-based
end
Lies die Eintragsnummer aus deiner eigenen show-Ausgabe, statt eine abzuschreiben, denn sie verschiebt sich zwischen Modellen und Releases. Fortinet weist darauf hin, dass oft ein Neustart nötig ist.
Check Point ist der unangenehme Fall für ein Audit, weil es keinen einzelnen Schalter gibt. Der Helper ist eine Eigenschaft des Service-Objekts in der Regel, der vordefinierte SIP-Dienst bringt dir also den Protokoll-Handler und alles, was er tut. Ihn zu vermeiden heißt, einen eigenen einfachen UDP- oder TCP-Dienst auf Port 5060 zu definieren, den Protokolltyp auf „none“ zu setzen, das Matching zu aktivieren und diese Regel über alles zu legen, was noch die eingebauten benutzt. „Ist das ALG an?“ ist also keine Frage, die eine Einstellungsseite beantworten kann. Sei daher vorsichtig, bevor du jemandes Wort akzeptierst, es sei abgeschaltet.
Palo Alto gibt dir einen Schalter je Anwendung, und die eigene Dokumentation sagt, das SIP ALG „creates dynamic NAT pinholes“8. Objects, Applications, sip suchen, die ALG-Option anpassen, Disable ALG anhaken, committen.
MikroTik liefert zehn Helper unter /ip firewall service-port aus — SIP, H.323, FTP, IRC, TFTP, PPTP, RTSP und mehr — jeweils in einer Zeile dokumentiert, ohne irgendeinen Sicherheitshinweis auf der Seite. Erst auflisten, dann abschalten, was du findest:
/ip firewall service-port print
/ip firewall service-port set [find name=sip] disabled=yes
/ip firewall service-port set [find name=h323] disabled=yes
/ip firewall service-port set [find name=ftp] disabled=yes
Consumer- und Provider-Router. Such nach „SIP ALG“, „SIP Helper“, „VoIP Passthrough“ oder „Application Layer Gateway“, meist unter einer Seite für erweitertes NAT. Bei vielen, besonders bei Providergeräten, gibt es gar keine Einstellung — was dir sagt, ob diese Kiste in ein Netz gehört, für das du verantwortlich bist.
Egal auf welcher Plattform, beende es gleich: Beweise es. Setz einen Mitschnitt auf die Außenschnittstelle, schick von außen eine präparierte PORT- oder REGISTER-Zeile an den passenden Port und stelle sicher, dass sich nichts öffnet. Eine Einstellung, die du nicht getestet hast, ist ein Glaube.
Das meiste, was kaputtgeht, ist ohnehin tot
Ehrlich über die Kosten zu sein, ist die ganze Grundlage dafür, das von jemandem zu verlangen, also hier sind sie. Den SIP-Helper in einem Netz mit schlecht konfigurierten Telefonen abzuschalten, kann Gespräche zerschießen, meist einseitiges Audio oder abreißende Registrierungen. Den FTP-Helper abzuschalten, zerschießt aktives FTP nach außen. Den H.323-Helper abzuschalten, zerschießt H.323, falls du noch welches hast. Das ist real, und du solltest mit mindestens einem davon rechnen, wenn du das in einem einzigen Change auf einem Netz machst, das seit Jahren niemand angeschaut hat.
Lies dir jetzt die Liste noch einmal durch und merke, dass fast jedes Protokoll, dem ein Helper dient, eines ist, das der Rest der Branche längst begraben hat. H.323 hat vor zwanzig Jahren gegen SIP verloren. PPTP ist seit 1998 nicht mehr zu verteidigen, und diesen Fall habe ich in IPsec war eine gute Idee ausführlich gemacht. IRC-Direktübertragungen gehören in ein Jahrzehnt, dem niemand nachtrauert. NetBIOS-Namensdienst, die Community-String-Versionen von SNMP, das Scanner-Erkennungsprotokoll und das alte Backup-Protokoll sind Relikte für lokale Netze, die nie eine Grenze überschreiten sollten. Reines FTP ist aus den Browsern ganz verschwunden — Firefox hat es in Version 88 deaktiviert und in 90 im Juli 2021 entfernt, Chrome hat den Code im Oktober darauf in Version 95 gelöscht, beide mit der Begründung, die Nutzung sei vernachlässigbar und die Sicherheit den Pflegeaufwand nicht wert28.
„Wir können den Helper nicht abschalten, sonst geht etwas kaputt“ ist also meist ein Argument dafür, ein totes Protokoll am Leben zu erhalten, um eine Funktion zu rechtfertigen, die Fremden Ports öffnet. Abschalten macht dein Netz nicht kaputt. Es legt das eine Ding darin offen, das vor Jahren hätte ausgemustert gehört — eine Information, die du ohnehin haben wolltest.
SIP ist die echte Ausnahme, und es ist die einzige. Alles andere auf dieser Liste ist ein Argument, das zu verlieren du froh sein solltest — und nichts davon ist unlösbar, denn jedes beteiligte Protokoll hat sein Übersetzungsproblem vor Jahren selbst gelöst, im Protokoll, wo es hingehört.
Was du stattdessen tun solltest
FTP. Passiv-Modus, seit 1985 in der Spezifikation und seit zwanzig Jahren Standard in jedem Client: Beide Verbindungen gehen nach außen, und für einen Helper bleibt nichts zu tun. Und wenn du 2026 Dateien zwischen Organisationen bewegst, ist FTP nicht das Protokoll dafür — SFTP und FTPS sind verschlüsselt, und ein Helper kommt an keines von beiden heran.
SIP und alles andere in Echtzeit. Der Endpunkt fragt einen Server im Internet, wie seine öffentliche Adresse und sein Port von außen aussehen, bietet jeden Pfad an, den er hat, und die beiden Enden testen die Pfade gegeneinander und behalten einen, der funktioniert — mit einem Relay, wo kein direkter Pfad existiert. Das ist STUN, TURN und ICE, und genau das tut jeder Browser der Welt bei jedem Videoanruf, durch jede Art von Übersetzer, ohne ein einziges ALG im Pfad. Wenn deine Telefonanlage das 2026 nicht kann, liegt das Problem bei der Telefonanlage.
IPsec. NAT-Traversal, also RFC 3947 und RFC 3948: Die beiden Enden bemerken den Übersetzer während des Schlüsselaustauschs und verpacken ESP für den Rest der Sitzung in UDP 450021, ohne Gate auf irgendeiner Box dazwischen.
H.323. Ausmustern. SIP hat diese Diskussion um 2005 gewonnen, es gibt also keine Migration zu planen, nur ein Löschen. Direktübertragungen, TFTP, SNMP, NetBIOS, Scanner-Erkennung und das Backup-Protokoll gehen denselben Weg: Keines davon hat an einer Grenze etwas verloren.
IPv6. Dort existiert nichts davon, denn es gibt keine Übersetzung und damit nichts, was ein Helper umschreiben könnte. Ein Host hat seine eigene Adresse, die Adresse in der Nutzlast stimmt, und eine zustandsbehaftete Firewall erlaubt, was du ihr gesagt hast, und sonst nichts. Jedes Problem in diesem Beitrag stammt von Adressübersetzung ab, und Adressübersetzung stammt davon ab, IPv6 nicht ausgerollt zu haben — ein Argument, das ich an anderer Stelle ausführlich gemacht habe und hier nicht wiederhole.
Jetzt der Teil, bei dem ich nicht diplomatisch sein werde.
Wenn dir jemand sagt, du sollst die einschalten — ein Lieferant, ein Telefonie-Installateur, ein Managed-Service, ein Integrator auf einem Rahmenvertrag — dann ist das kein Netzwerkingenieur und kein Sicherheitsspezialist. Er mag sehr gut in dem sein, was er tatsächlich tut, und das hier wird es nicht sein. Die richtige Antwort auf eine Telefonanlage, die eine Firewall braucht, um ihre Signalisierung umzuschreiben, ist, die Telefonanlage zu reparieren, und wer dir stattdessen sagt, du sollst deine Grenze einem Textmuster-Parser öffnen, sagt dir damit, dass er entweder nicht weiß, was eine Expectation ist, oder dass es ihm egal ist. Wir sind hier nicht bei den Amateuren. Seit 2007 steht in Standards-Track-Dokumenten, wie man es richtig macht, und „schalt halt den SIP-Helper ein“ ist das Geräusch von jemandem, der nach dem greift, was das Ticket heute schließt.
Frag ihn im Raum, worauf der Platzhalter für die Quelladresse der Expectation gesetzt ist. Wenn die Frage überrascht, hast du deine Antwort, und um das Protokoll ging es nie.
Wenn du sie noch betreibst — kannst du dich Profi nennen?
Das ist eine ernst gemeinte Frage, und sie verdient eine ernst gemeinte Antwort, also hier sind drei, denn es gibt drei Fälle. Es hängt davon ab, ob du es weißt — und Wissen ist nichts, was einem passiert. Dafür zu sorgen, dass man es weiß, ist die Arbeit.
Wenn auf einer Grenze, für die du verantwortlich bist, ein SIP-, H.323- oder FTP-Helper aktiv ist und du nicht ohne Nachschlagen sagen kannst, was eine Expectation ist, welche ihrer Felder Platzhalter sind, wer die Werte liefert und was deine Zertifizierungsangabe über eingehende Regeln behauptet — dann nein. Hierbei nicht. Du hast keine Konfiguration gewählt, du hast einen Standardwert geerbt und nie nachgelesen. Das Versäumnis ist nicht die Lücke; Lücken hat jeder, und diese hatte ich auch. Es ist, eine Grenze über eine Lücke zu bauen, die du nie geschlossen hast, und dann etwas zu unterschreiben, das sagt, die Grenze sei dicht.
Wenn du genau weißt, was es tut, und es an ist, weil ein Regulierer das Protokoll benennt, weil die Technik eines Partners nichts anderes terminiert oder weil die Telefonanlage im März ersetzt wird und das bis dahin laufen muss — dann ja, offensichtlich, und du machst deine Arbeit richtig. Das sind echte Zwänge, und ich habe mich um Schlimmeres herumgearbeitet. Professionell statt fahrlässig wird es dadurch, dass du aufgeschrieben hast, welcher Helper, auf welcher Schnittstelle, für welchen Fluss, warum, und zu welchem Datum er wieder abgeht. Also genau die Papierarbeit, nach der die Firewall-Anforderung ohnehin gefragt hat.
Der unhaltbare Fall ist der mittlere. Genug zu wissen, um unruhig zu sein, und es trotzdem laufen zu lassen, weil dich nie jemand zur Rechtfertigung gezwungen hat. Das ist keine Ingenieursarbeit. Das ist Gewohnheit mit einer Change-Nummer daran, und so ist eine Funktion, die dir eine Best Current Practice im Januar 2007 abzuschalten geheißen hat, 2026 noch an.
Am meisten zählt das, wenn du jemanden für sein Urteilsvermögen bezahlst, denn Urteilsvermögen lässt sich bei der Lieferung nicht prüfen. Prüfe es also vorher. Frag, was ihr Standardaufbau mit Protokoll-Helpern macht und warum, frag, was passiert, wenn jemand im Gästenetz einen Link öffnet, und frag, welche internen Geräte mit aktivem H.323-Helper erreichbar wären — und achte darauf, ob sie „nur der Rechner, der geklickt hat“ sagen, denn das ist falsch, und es ist die falsche Antwort, die eine kompetent klingende Person gibt. Du weißt innerhalb von zwei Minuten, ob dir etwas erzählt oder etwas vorgelesen wird, und zwei Minuten sind ein viel billigerer Test als ein Vorfall.
Kommt als Antwort ein Schulterzucken und du unterschreibst trotzdem, ist auch das eine Entscheidung. Sie hat nur aufgehört, ihre zu sein, und ist deine geworden.
Niemand musste es je rechtfertigen
Ich möchte den Leuten gegenüber fair sein, die diese Dinge gebaut haben, denn das haben sie verdient.
1994 war der Helper eine vernünftige Antwort auf ein echtes Problem. Adressen wurden knapp, NAT war die pragmatische Lösung, eine Handvoll wichtiger Protokolle überlebte sie nicht, und die Wahl bestand darin, jeden FTP-Client der Welt zu ändern oder der Kiste das Lesen beizubringen. Sie brachten der Kiste das Lesen bei, lieferten die sichersten Standardwerte aus, die ihnen einfielen, und schrieben Warnungen in den Quelltext, wozu man das Ding bringen kann. Diese Warnungen stehen immer noch da. Eine davon habe ich zitiert.
Was danach schieflief, ist kein technisches Versagen. Es ist, dass in dieser Branche nie irgendjemand gezwungen war, es noch einmal anzuschauen. Die IETF sagte, schaltet sie ab, und hatte keine Macht, irgendjemanden dazu zu bringen. Der Kernel änderte seinen Standard und konnte die bereits ausgelieferten Geräte nicht erreichen. Forscher haben es in sechzehn Jahren viermal bewiesen, und jedes Mal landete die Korrektur woanders als in der Firewall.
Währenddessen blieb der Standardwert an. Nicht, weil ihn jemand verteidigt hätte. Sondern weil ein Standardwert, über den niemand streitet, unbegrenzt überlebt, und weil es nirgends eine Abteilung gibt, deren Aufgabe es wäre, Dinge zu beenden.
Das ist das Muster, und es ist größer als eine Firewall-Funktion. Dieses Gewerbe ist hervorragend im Erhalten und hoffnungslos im Aufhören. Wartung ist budgetiert, besetzt, abrechenbar und sicher, während Stilllegung eine Person braucht, die ihren Namen unter eine Änderung setzt, die keinen Vorteil bringt, wenn sie gutgeht, und überall ihren Namen trägt, wenn nicht. Also bleibt das Ding, und es bleibt, und eines Tages stellt jemand fest, dass es Ports zu deinem Drucker öffnet.
Das Indiz ist für mich diese Formulierung in Ciscos eigener Dokumentation: Das ALG erzeugt eine NAT-Tür. Kein Filter. Keine Kontrolle. Eine Tür, in der Wand, für die du bezahlt hast, geöffnet von jedem, der ein Paket mit den richtigen Wörtern vorne dran hindurchbekommt — und die eingespielte Antwort der Branche war, die Vorbeigehenden zu bitten, bitte nicht an der Klinke zu ziehen.
Du kannst deine heute Nachmittag schließen, und das ist der Teil, auf dem es sich zu enden lohnt. Nicht die Angriffe; die Angriffe sind nur das, was passiert, wenn es niemand tut. Geh nachsehen, was deine Grenze eingehend erlaubt, das du nie aufgeschrieben hast, entscheide, ob du es so wolltest, und nimm die heraus, die du nicht wolltest — mit einem Datum neben dem, was du behältst.
Mehr war eine Grenze nie: eine Liste von Dingen, die jemand zu erlauben gewählt hat und begründen konnte. Was darauf steht, ohne dass es jemand gewählt hat, ist keine Sicherheit. Das ist Mobiliar.
Samy Kamkar — NAT Pinning, 5. Januar 2010. Der ursprüngliche Angriff vom Browser auf das ALG, mit einem versteckten Formular, das einen Browser ein IRC-
DCC CHAToder eine FTP-227-Antwortzeile senden lässt, sodass der Helper des Routers einen eingehenden Port öffnet. „No XSS or CSRF required.“ ↩︎ ↩︎ ↩︎ ↩︎Samy Kamkar — NAT Slipstreaming, 31. Oktober 2020, aktualisiert im Januar 2021. Vom Autor zusammengefasst als „an attacker to remotely access any TCP/UDP service bound to a victim machine, bypassing the victim’s NAT/firewall (arbitrary firewall pinhole control), just by the victim visiting a website“. Enthält die Technik mit den Segmentgrenzen, den Hinweis, dass der SIP-Handler „will bail unless the method (eg, REGISTER) occurs at the start of the data portion of the packet“, und die Firmware-Analyse eines Netgear-Geräts, die
ftp_decodeundsip_decodein einem Kernelmodul fand. ↩︎ ↩︎ ↩︎ ↩︎Ben Seri und Gregory Vishnepolsky, Armis — NAT Slipstreaming v2.0, 26. Januar 2021. Das H.323-Rufumleitungs-Primitiv, die Umgehung der Browser-Sperrliste über das Relay, die Liste der getesteten Produkte (OpenWrt, VyOS, Consumer-Linux-Router, FortiGate, Cisco ASAv und csr1000v, HPE vsr1000, SonicWall TZ300), der Ablauf der Offenlegung und der Schluss, dass „resolving the issue will require a fundamental change of their implementations by various router/firewall vendors“. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
RFC 4787 — Network Address Translation (NAT) Behavioral Requirements for Unicast UDP, Januar 2007, BCP 127. Abschnitt 7 trägt REQ-10 und die Beobachtung, dass „Certain NATs have these ALGs turned on permanently, others have them turned on by default but allow them to be turned off“. ↩︎ ↩︎ ↩︎
Pablo Neira Ayuso — netfilter: nf_ct_helper: disable automatic helper assignment, Commit
3bb398d9, 25. April 2016, ausgeliefert mit Linux 4.7. Ändert den Standard vonnf_conntrack_helpervon aktiviert auf deaktiviert. ↩︎ ↩︎ ↩︎Chromium-Quelltext —
net/base/port_util.cc, dessenkRestrictedPorts-Array 69, 137, 139, 161, 554, 1719, 1720, 1723, 5060, 5061, 6566 und 10080 enthält. Adam Rices Ankündigung der SIP-Ports, 5. November 2020: „a carefully-crafted HTTP request to port 5060 on an attacker’s server can fool some NAT devices into treating it as a SIP packet and setting up port forwarding to an attacker-controlled port number.“ ↩︎ ↩︎Cisco — SIP ALG Hardening for NAT and Firewall, IP Addressing Configuration Guide, Cisco IOS XE 17.x. „SIP ALG creates a firewall pinhole or a Network Address Translation (NAT) door based on the first value in the Via header field for each SIP request received.“ NAT-Unterstützung für SIP ist „enabled by default on port 5060“. Siehe auch Using Application-Level Gateways with NAT, wo steht, dass SIP und H.323 standardmäßig aktiviert sind. ↩︎ ↩︎
Palo Alto Networks — Disable the SIP Application-level Gateway (ALG). „SIP ALG creates dynamic NAT pinholes but may interfere with VoIP applications that have NAT traversal capabilities, causing communication failures.“ ↩︎ ↩︎
RFC 2663 — IP Network Address Translator (NAT) Terminology and Considerations, August 1999. In Abschnitt 2.9 wird das Application Level Gateway definiert. ↩︎
RFC 3234 — Middleboxes: Taxonomy and Issues, Februar 2002. Die Zeile zum Schichtbruch steht in Abschnitt 2.11; die Kosten zusätzlicher Kisten im Pfad in Abschnitt 5, der ergänzt, das „creates extra points of attack, reduces or eliminates the ability to perform end to end encryption, and complicates trust models and key distribution models“. ↩︎ ↩︎
Eric Leblond, Pablo Neira Ayuso, Patrick McHardy, Jan Engelhardt und Mr Dash Four — Secure use of iptables and connection tracking helpers. „This system relies on parsing of data coming either from the user or the server. It is therefore vulnerable to attack and great care must be taken when using connection tracking helpers.“ Quelle des Zitats zum IRC-Platzhalter, und Dokumentation des
nf_conntrack_helper-sysctl und desCT --helper-Ziels. ↩︎ ↩︎Linux-Kernelquelltext —
net/netfilter/nf_conntrack_ftp.c. Der Modulparameterloosesteht standardmäßig auf false und schützt den Fall, in dem die Adresse imPORT-Kommando nicht die des Clients ist; der Kommentar benennt das Risiko als „DMZ machines opening holes to internal networks, or the packet filter itself“. ↩︎netfilter — H.323 conntrack/NAT helper, vom Autor des Moduls. Enthält das Rufumleitungsszenario, in dem eine Sitzung auf eine dritte Adresse verweisen darf. ↩︎
David Leadbeater — NAT-Again: IRC NAT helper flaws, August 2022. Zeigt den Auslöser über das Ping-Echo, merkt an, dass sich damit auch scannen, die echten Adressen verschleierter Nutzer aufdecken und Nutzer durch Angabe von Port 0 trennen lassen, und empfiehlt: „Potentially entirely deprecate and remove nf_conntrack_irc, it’s unclear it has much use anymore.“ ↩︎ ↩︎
CVE-2022-2663 — „An issue was found in the Linux kernel in nf_conntrack_irc where the message handling can be confused and incorrectly matches the message. A firewall may be able to be bypassed when users are using unencrypted IRC with nf_conntrack_irc configured.“ ↩︎ ↩︎
Cisco — Advisory zu CVE-2018-15454, erstveröffentlicht am 31. Oktober 2018. Als Gegenmaßnahme wird
no inspect sipauf der ASA undconfigure inspection sip disableauf FTD genannt; der NVD-Eintrag hält fest, dass zum Zeitpunkt der Veröffentlichung galt: „Software updates that address this vulnerability are not yet available.“ ↩︎ ↩︎RFC 3715 — IPsec-Network Address Translation (NAT) Compatibility Requirements, März 2004. Abschnitt 2.1 Punkt (f) behandelt die SPI-Wahl gegenüber NAT; Abschnitt 2.3 trägt den Titel Helper Incompatibilities und enthält die zitierten Zeilen zum IKE-Cookie-Demultiplexing und zum Parsen von ISAKMP-Payloads. ↩︎ ↩︎
Juniper — IKE and ESP ALG, Application Layer Gateways User Guide. Quelle der Gate-Beschreibung, des Hinweises, dass NAT-T-Verkehr auf Port 4500 vom ALG nicht verarbeitet wird, und der Warnung, dass das Gerät bei zwei Clients hinter derselben übersetzten Adresse „will be unable to distinguish and route return traffic properly“. ↩︎ ↩︎
Cisco — IPsec Pass Through Inspection, ASA Firewall CLI Configuration Guide 9.20. „IPsec Pass Through application inspection provides convenient traversal of ESP (IP protocol 50) and AH (IP protocol 51) traffic associated with an IKE UDP port 500 connection.“ Nicht in der Standardrichtlinie; die mitgelieferte
_default_ipsec_passthru_map„sets no maximum limit on ESP connections per client“. ↩︎ ↩︎RFC 3947 — Negotiation of NAT-Traversal in the IKE, und RFC 3948 — UDP Encapsulation of IPsec ESP Packets, beide Januar 2005. ↩︎ ↩︎
Cole Dishington — netfilter: nf_conntrack: Add conntrack helper for ESP/IPsec, Mai 2021, dritte Fassung. Auf netfilter-devel reviewt und nicht gemergt;
net/netfilterim Mainline-Kernel enthält weiterhin keinenf_conntrack_proto_esp.c. ↩︎NCSC und IASME — Cyber Essentials: Requirements for IT Infrastructure v3.3, April 2026. Kontrolle 1, Firewalls, gilt für „boundary firewalls, desktop computers, laptops, routers, servers, IaaS, PaaS, SaaS“, und die drei im Text zitierten Anforderungen sind ihre eigenen Worte. ↩︎ ↩︎
RFC 3027 — Protocol Complications with the IP Network Address Translator, Januar 2001. „The purpose of this document is to identify the protocols and applications that break with NAT enroute.“ ↩︎
WHATWG Fetch — Pull Request 1109, die Standardänderung, die die Bad-Port-Einträge über alle Browser hinweg ergänzt hat. ↩︎
OpenBSD —
ftp-proxy(8). „ftp-proxy is a proxy for the Internet File Transfer Protocol.“ Steuerverbindungen erreichen ihn nur, weil du sie dorthin schickst: „FTP control connections should be redirected into the proxy using the pf(4) divert-to command, after which the proxy connects to the server on behalf of the client.“ ↩︎Fortinet — Technical Tip: Disabling VoIP Inspection. Dokumentiert das Entfernen des SIP-Eintrags aus
config system session-helper,set default-voip-alg-mode kernel-helper-based, und den Hinweis, dass ein erneutes Aktivieren einen Neustart erfordert. ↩︎Mozilla — Stopping FTP support in Firefox 90, 20. Juli 2021, und Google — Deprecations and removals in Chrome 95, Oktober 2021: „Use of FTP in the browser is sufficiently low that it is no longer viable to invest in improving the existing FTP client.“ ↩︎