Eine interaktive Shell über den Tunnel friert für mehrere Sekunden ein, während eine Dateikopie läuft, und setzt dann fort, als wäre nichts passiert. Der Download ist das Einzige mit einem Problem, doch die Shell wartet ebenfalls, und beide erholen sich im selben Moment. Dieses Muster ist die Signatur eines zuverlässigen Stroms, der viele Gespräche trägt, und es übersteht fast jede Abstimmungsänderung, die Leute zuerst versuchen.

Das Symptom lohnt genaues Lesen, weil es auf einen Mechanismus statt auf eine Einstellung zeigt: Die Pause ist geteilt, also ist die Ursache geteilt, und das geteilte Objekt ist die äußere Verbindung. Alles andere im Protokoll sieht währenddessen normal aus.

Das Symptom: alles pausiert gleichzeitig

Zwei innere Verbindungen, die zusammen stocken, sind der Hinweis. Ein langsamer Download und eine langsame Shell sind getrennte TCP-Gespräche mit getrennten Sequenznummern und getrenntem Überlastzustand, also sollte ein Fehler in einem den anderen nicht berühren. Wenn sie im Gleichschritt pausieren, ordnet etwas über ihnen ihre Bytes.

Dieses Etwas ist der Transport des Tunnels. Im TCP-Modus schreibt OpenVPN die gekapselten Pakete in eine einzige TCP-Verbindung zum Peer, und der Vertrag von TCP ist die Auslieferung eines einzelnen Bytestroms in Reihenfolge. Spätere Bytes werden der Anwendung nicht vor den fehlenden übergeben, egal zu welchem inneren Gespräch sie gehören.

Beachten Sie, was das Symptom nicht sagt. Es sagt nicht, dass der Pfad defekt ist, dass der Server überlastet ist oder dass die Verschlüsselung langsam ist. Diese erzeugen andere Formen: gleichmäßig niedrigen Durchsatz, Zeitüberschreitungen oder Fehler, die eine Richtung betreffen. Eine geteilte Pause, die endet, wenn ein verlorenes Segment erneut übertragen wird, ist speziell ein Reihenfolgeeffekt.

Ein äußerer Bytestrom, viele innere Gespräche

Stellen Sie sich vor, der Tunnel trägt gleichzeitig einen Download und eine Shell. Ein Segment der äußeren Verbindung geht verloren. Die folgenden Segmente können beim empfangenden Host ankommen, und der empfangende TCP-Stack wird sie bestätigen, aber er kann sie nicht nach oben ausliefern, bis die Lücke gefüllt ist. OpenVPN hat daher nichts für die Shell zu lesen, obwohl die Bytes der Shell selbst längst angekommen sind.

Das ist Head-of-Line-Blocking innerhalb einer Verbindung, und es verlangt nicht, dass die beiden Anwendungen eine innere Verbindung teilen. Sie teilen die äußere, und das reicht.

Der Effekt zweiter Ordnung macht es schlimmer. Ein innerer Sender, der keine Bestätigung sieht, überträgt möglicherweise Daten erneut, die die äußere Schicht bereits auszuliefern versucht. Diese erneute Übertragung wird zusätzlicher Tunnelverkehr auf einem Pfad, der gerade bewiesen hat, dass er Segmente verlieren kann, sodass die Wiederherstellungsarbeit mit der Wiederherstellung konkurriert, auf die es ankommt.

Nichts davon garantiert einen Zusammenbruch. Auf einem sauberen Pfad mit kurzen Umlaufzeiten und großzügigen Warteschlangen kann die Anordnung jahrelang vollkommen brauchbar sein. Der Fehler zeigt sich, wenn Verlust, Verzögerung und Warteschlangentiefe zusammenkommen; deshalb häufen sich die Berichte bei überlasteten Uplinks und Mobilfunkstrecken und nicht bei gut ausgestatteten Büros.

Warum ein längerer innerer Timer nicht helfen kann

Das Anheben der minimalen Wiederholungszeit auf einer Route mit rto_min verschiebt die zeitgeberbasierte erneute Übertragung für lokal erzeugten TCP-Verkehr, der diese Route nutzt. Es ist ein echter Regler mit echter Wirkung, und er adressiert das Problem zweiter Ordnung statt das erste.

ip route show
ip route show cache 2>/dev/null | head
ss -tin dst 10.70.0.1

Was er nicht kann: äußere Bytes außer der Reihenfolge freigeben, das fehlende Segment schneller wiederherstellen oder den entfernten Anwendungsserver dazu bringen, denselben Timer zu übernehmen. Der empfangende Stack liefert weiterhin in Reihenfolge aus, und der Sender am anderen Ende nutzt weiterhin seine eigenen Umlaufzeitmessungen.

Er deaktiviert auch nicht jeden anderen Mechanismus zur Verlustbehebung. Wo echter Verlust eine zeitgeberbasierte Wiederherstellung erfordert, lässt ein größeres Minimum die Anwendung länger warten, bevor sie handelt, was das Gegenteil dessen ist, was eine latenzempfindliche Sitzung braucht.

Ein fester Mindestwert von zwölf Sekunden erscheint in Ratschlägen zu diesem Thema, als ob die Existenz eines TCP-Tunnels ihn implizierte. Der in RFC 6298 beschriebene Wiederholungs-Timer leitet sich aus gemessener Umlaufzeit mit exponentiellem Backoff ab, sodass ein konstanter Mindestwert eine Richtlinienwahl für einen bestimmten Pfad und keine Protokollanforderung ist. Breit angewandt verbirgt er das Symptom, während er die Wiederherstellung für jeden Fluss ändert, den diese Route abdeckt.

Was tcp-nodelay leistet und was nicht

Die Tunneloption, die Nagle-artige Pufferung auf dem Transport-Socket deaktiviert, hat einen engen Zweck: Sie hindert kleine Schreibvorgänge daran, auf weitere Daten zu warten, bevor sie gesendet werden. Das hilft interaktivem Verkehr, eine zusätzliche Verzögerung auf einem ansonsten gesunden Pfad zu vermeiden.

Sie macht den Transport nicht ungeordnet und verkürzt auch nicht die Wiederherstellung nach einem verlorenen Segment. Eine Shell, die auf eine Zeitüberschreitung bei der erneuten Übertragung pausiert, pausiert auch mit aktivierter Option, weil die Option die Reihenfolgeregel nie berührt hat.

Die beiden zu verwechseln ist leicht, weil beide als Latenzkorrekturen beschrieben werden. Eine beseitigt eine künstliche Wartezeit durch Pufferung; die andere würde erfordern zu ändern, was der Transport garantiert, und das tut keine Socket-Option.

Wie man Transporte fair vergleicht

Wenn der Betreiber es erlaubt und beide Dienste existieren, vergleichen Sie einen UDP-Dienst und einen TCP-Dienst mit derselben Arbeitslast über denselben Zugangspfad zum selben Server. Land, Anbieter oder Servergeneration zwischen den beiden Tests zu ändern, führt eine Variable ein, die das Ergebnis dominieren wird.

Achten Sie auf die geteilte Pause statt auf eine Durchsatzzahl. Mehrere innere Anwendungen, die während äußeren Verlusts zusammen stocken, sind die Beobachtung, die Head-of-Line-Blocking identifiziert; eine einzelne niedrigere Speedtest-Zahl tut das nicht.

Autorisierte Mitschnitte auf der Tunnelschnittstelle und auf der physischen Schnittstelle trennen die beiden Schichten sauber, weil innere und äußere erneute Übertragungen zu verschiedenen Verbindungen mit verschiedenen Sequenzräumen gehören. Innere erneute Übertragungen zu sehen, während der äußere Strom eine Lücke zeigt, ist der direkte Beleg.

Der Wechsel zu UDP entfernt den zusätzlichen zuverlässigen Strom und überlässt dem inneren TCP seine eigene Wiederherstellung. Er verspricht weder Nulldverlust noch niedrige Latenz, und ein gesättigter Uplink, überdimensionierte Warteschlangen oder ein MTU-Problem müssen weiterhin behoben werden. Verkehr außerhalb des Tunnels wird nie hinter der Sequenzlücke des Tunnels zurückgehalten, obwohl er noch leiden kann, wenn beide Pfade eine überlastete Strecke teilen, und dieser gemeinsame Engpass verdient eine eigene Untersuchung, statt in diese hineingefaltet zu werden.

Ähnliche Artikel