All pages
Powered by GitBook
1 of 8

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Verbindungen verwenden TLS

Unmittelbar nach dem ersten Aufbau einer Verbindung sendet der Initiator einen Krypto-Frame, der mit dem Einrichten des Handshakes der Sicherheitsschicht beginnt. Die Sicherheitsschicht verwendet TLS 1.3.

Es gibt keine Möglichkeit, TLS bei eine QUIC-Verbindung zu deaktivieren oder zu vermeiden. Das Protokoll ist so konzipiert, dass es für Middleboxen schwer zu manipulieren ist, um eine Ossifikation des Protokolls zu verhindern.

Wie QUIC funktioniert

In diesem Abschnitt wird beschrieben, wie die grundlegenden Bausteine des QUIC-Transportprotokolls funktionieren, ohne dabei auf alle Bits und Bytes einzugehen. Wenn du deinen eigenen QUIC-Stack implementieren möchtest, sollte dir diese Beschreibung ein allgemeines Verständnis vermitteln. Alle Details findest du in den aktuellen IETF Internet-Entwürfen und RFCs.

  1. Eine Verbindung aufbauen

  2. ... die TLS inkludiert

  3. und dann verwendet

Streams

QUIC Streams bieten eine einfache, geordnete Byte-Stream-Abstraktion.

In QUIC gibt es zwei grundlegende Arten von Streams:

  • Unidirektionale Streams übertragen Daten in eine Richtung: vom Initiator des Streams zu seinem Peer.

  • Bidirektionale Streams ermöglichen das Senden von Daten in beide Richtungen.

Jeder Stream-Typ kann von jedem Endpunkt erstellt werden, gleichzeitig mit anderen Streams verschachtelte Daten senden und abgebrochen werden.

Um Daten über eine QUIC-Verbindung zu senden, werden ein oder mehrere Streams verwendet.

Ablaufsteuerung

Streams werden individuell ablaufgesteuert, sodass ein Endpunkt die Speicherbindung begrenzen und Gegendruck ausüben kann. Die Erstellung von Streams wird ebenfalls ablaufgesteuert, wobei jeder Peer die maximale Stream-ID angibt, die er zu einem bestimmten Zeitpunkt akzeptieren möchte.

Stream Identifikatoren

Streams werden durch eine vorzeichenlose 62-Bit-Ganzzahl identifiziert, die als Stream-ID bezeichnet wird. Die niedrigstwertigen zwei Bits der Stream-ID werden verwendet, um den Stream-Typ (unidirektional oder bidirektional) und den Initiator des Streams zu identifizieren.

Das niedrigstwertige Bit (0x1) der Stream-ID identifiziert den Initiator des Streams. Clients initiieren geradzahlige Streams (solche mit dem niedrigstwertigen Bit auf 0); Server initiieren ungeradzahlige Streams (wobei das Bit auf 1 gesetzt ist).

Das zweitniedrigste Bit (0x2) der Stream-ID unterscheidet zwischen unidirektionalen und bidirektionalen Streams. Bei unidirektionalen Streams ist dieses Bit immer auf 1 gesetzt, und bei bidirektionalen Streams ist dieses Bit auf 0 gesetzt.

Gleichzeitigkeit von Streams

Mit QUIC kann eine beliebige Anzahl von Streams gleichzeitig betrieben werden. Ein Endpunkt begrenzt die Anzahl der gleichzeitig aktiven eingehenden Streams, indem die maximale Stream-ID begrenzt wird.

Die maximale Stream-ID ist für jeden Endpunkt spezifisch und gilt nur für den Peer, der die Einstellung erhält.

Daten senden und empfangen

Endpunkte verwenden Streams zum Senden und Empfangen von Daten - das ist immerhin ihr letztendlicher Zweck. Streams sind eine geordnete Byte-Stream-Abstraktion. Separate Streams werden jedoch nicht unbedingt in der ursprünglichen Reihung ausgeliefert.

Stream Priorisierung

Stream-Multiplexing hat erhebliche Auswirkungen auf die Anwendungsleistung, wenn den Streams zugewiesene Ressourcen korrekt priorisiert werden. Die Erfahrung mit anderen Multiplex-Protokollen - wie HTTP/2 - zeigt, dass effektive Priorisierungsstrategien einen signifikanten positiven Einfluss auf die Leistung haben.

QUIC selbst bietet keine Frames für den Austausch von Priorisierungsinformationen. Stattdessen müssen Prioritätsinformationen von der Anwendung empfangen werden, die QUIC verwendet. Protokolle, die QUIC verwenden, können jedes Priorisierungsschema definieren, das ihrer Anwendungssemantik entspricht.

Wenn HTTP/3 über QUIC verwendet wird, erfolgt die Priorisierung in der HTTP-Schicht.

Streams

Verbindungen

Eine QUIC-Verbindung ist eine einzelne Konversation zwischen zwei QUIC-Endpunkten. Der Verbindungsaufbau von QUIC kombiniert die Versionsaushandlung mit den kryptografischen und Transport-Handshakes, um die Latenz beim Verbindungsaufbau zu verringern.

Um tatsächlich Daten über eine solche Verbindung zu senden, müssen ein oder mehrere Streams erstellt und verwendet werden.

Verbindungs-ID

Jede Verbindung verfügt über eine Reihe von Verbindungskennungen oder Verbindungs-IDs, von denen jede zur Identifizierung der Verbindung verwendet werden kann. Verbindungs-IDs werden unabhängig von den Endpunkten ausgewählt; jeder Endpunkt wählt die Verbindungs-IDs aus, die sein Peer verwendet.

Die Hauptfunktion dieser Verbindungs-IDs besteht darin, sicherzustellen, dass Änderungen in der Adressierung auf niedrigeren Protokollschichten (UDP, IP und darunter) nicht dazu führen, dass Pakete einer QUIC-Verbindung an den falschen Endpunkt gesendet werden.

Durch die Nutzung der Verbindungs-ID können Verbindungen auf eine Weise zwischen IP-Adressen und Netzwerkschnittstellen migrieren, wie dies TCP niemals könnte. Durch die Migration kann beispielsweise ein laufender Download von einer Mobilfunkverbindung zu einer schnelleren WLAN-Verbindung geändert werden, wenn der Benutzer sein Gerät an einen Standort mit WLAN-Verbindung bringt. Ebenso kann der Download über die Mobilfunkverbindung erfolgen, wenn das WLAN nicht mehr verfügbar ist.

Portnummern

QUIC ist auf UDP aufgebaut, daher wird ein 16-Bit-Portnummernfeld verwendet, um eingehende Verbindungen zu unterscheiden.

Versionsaushandlung

Eine von einem Client stammende QUIC-Verbindungsanforderung teilt dem Server mit, welche QUIC-Protokollversion er sprechen möchte. Der Server antwortet mit einer Liste der unterstützten Versionen, aus denen der Client auswählen kann.

API

Einer der Erfolgsfaktoren von regulärem TCP und Programmen, die dieses verwenden, ist die standardisierte Socket-API. Sie verfügt über gut definierte Funktionen und ermöglicht ein Verschieben von Programmen zwischen vielen verschiedenen Betriebssystemen, da TCP überall gleich funktioniert.

QUIC ist nicht so weit. Es gibt keine Standard-API für QUIC.

Bei QUIC muss eine der vorhandenen Implementierungen ausgewählt werden, bei deren API man bleiben muss. Dadurch werden Anwendungen bis zu einem gewissen Grad an eine einzelne Bibliothek "gebunden". Das Wechseln zu einer anderen Bibliothek bedeutet eine andere API und kann viel Arbeit erfordern.

Da QUIC normalerweise im User-space implementiert wird, kann es die Socket-API nicht einfach erweitern oder der vorhandenen TCP- und UDP-Funktionalität ähneln. Die Verwendung von QUIC bedeutet die Verwendung einer anderen API als der Socket-API.

0-RTT

Um die zum Herstellen einer neuen Verbindung erforderliche Zeit zu verkürzen, kann ein Client, der zuvor eine Verbindung zu einem Server hergestellt hat, bestimmte Parameter dieser Verbindung zwischenspeichern und anschließend eine 0-RTT-Verbindung mit dem Server herstellen. Auf diese Weise kann der Client Daten sofort senden, ohne auf den Abschluss eines Handshakes warten zu müssen.

Spin Bit

Eine der vielleicht längsten Designdiskussionen innerhalb der QUIC-Arbeitsgruppe - Gegenstand von mehreren hundert Mails und stundenlangen Diskussionen - betrifft ein einziges Bit: das Spin Bit.

Die Befürworter dieses Bits bestehen darauf, dass Operatoren und Personen zwischen zwei QUIC-Endpunkten die Latenz messen können.

Die Gegner dieser Funktion mögen das potenzielle Informationsleck nicht.

Ein Bit drehen

Beide Endpunkte, der Client und der Server, behalten für jede QUIC-Verbindung den Spin-Wert 0 oder 1 bei und setzen das Spin Bit für Pakete, die für diese Verbindung gesendet werden, auf den entsprechenden Wert.

Beide Seiten senden dann Pakete aus, bei denen das Spin Bit auf den gleichen Wert gesetzt ist solange ein Roundtrip dauert, und schalten dann den Wert um. Der Effekt ist dann ein Impuls von Einsen und Nullen in dem Bitfeld, das Beobachter überwachen können.

Diese Messung funktioniert nur, wenn der Absender weder auf die Anwendung noch auf die Flusskontrolle beschränkt ist. Die Neuordnung von Paketen über das Netzwerk kann auch zu unscharfen Daten führen.

User-space

Die Implementierung eines Transportprotokolls im User-space ermöglicht eine schnelle Iteration des Protokolls, da das Protokoll vergleichsweise einfach weiterentwickelt werden kann, ohne dass Clients und Server ihren Betriebssystemkern aktualisieren müssen, um neue Versionen bereitzustellen.

QUIC gibt nichts vor, dass eine zukünftige Implementierung in Betriebssystemkernen verhindern könnte - sollte jemand dies für eine gute Idee halten.

Viele Implementierungen

Ein offensichtlicher Effekt der Implementierung eines neuen Transportprotokolls im User-space besteht darin, dass wir viele unabhängige Implementierungen erwarten können.

Verschiedene Anwendungen werden wahrscheinlich auf absehbare Zeit unterschiedliche HTTP/3- und QUIC-Implementierungen inkludieren, oder auf solchen aufbauen.