Das Internet hat sich seit seiner Entstehung rasant weiterentwickelt und ist heute ein zentraler Bestandteil unseres täglichen Lebens. Mit dieser Entwicklung sind auch die Anforderungen an die Technologien, die das Internet unterstützen, gestiegen. In diesem Blogbeitrag werden wir uns mit QUIC (Quick UDP Internet Connections), genauer gesagt mit der Funktionsweise und dem Ablauf von QUIC befassen, einem modernen Protokoll, das entwickelt wurde, um die Leistung von Webanwendungen zu verbessern.
Was ist das Quick UDP Internet Connections Protocol (QUIC)?
QUIC ist ein Transportprotokoll, das von Google entwickelt und als Open-Source-Projekt veröffentlicht wurde, um die Latenzzeit von Verbindungen zu reduzieren und die Leistung von Webanwendungen zu verbessern. QUIC verwendet das User Datagram Protocol (UDP) anstelle des Transmission Control Protocol (TCP), um eine schnellere und effizientere Kommunikation zu ermöglichen. Primär findet das QUIC seinen Einsatz bei der Verwendung von HTTP/3.
Wie funktioniert QUIC?
Quick UDP Internet Connections (kurz QUIC) ist ein von Google entwickeltes, und von der IETF standardisiertes Protokoll, welches auf Basis von UDP implementiert wurde. QUIC hat als Ziel, die Probleme von TCP zu beheben und gleichzeitig ein hohes Maß an Sicherheit zu gewährleisten. QUIC implementiert als Transportprotokoll eine zwingende Verschlüsselung auf Protokollebene, welche typischerweise erst von höheren Protokollen (z.B. TLS) implementiert wird. Um eine bessere Sicherheit und eine zuverlässige Datenübertragung zu gewährleisten, kombiniert QUIC sozusagen den TCP Verbindungsaufbau mit der TLS Kommunikation.
QUIC Verbindungsaufbau
Der Verbindungsaufbau des Quick UDP Internet Connections Protocol ist eine der zentralen Veränderungen im Vergleich zum Transmission Control Protocol (TCP). QUIC nutzt zwei Verfahren zum Verbindungsaufbau, abhängig davon, ob die Verbindungsdaten (z.B. Serverzertifikat) bereits vorliegen, also eine erneute Verbindung hergestellt wird oder eine Verbindung zum ersten Mal aufgebaut wird.
1-RTT Verbindungsaufbau
Wenn ein Client zum ersten Mal eine Verbindung zu einem Server herstellt, findet der sogenannte 1-RTT (Round-Trip Time) Verbindungsaufbau statt. Der Client sendet zunächst ein Initial-Paket (Verbindungswunsch), das die jeweilige QUIC-Version und eine zufällig generierte Verbindungs-ID enthält. Dieses Paket enthält auch eine „Client Hello“-Nachricht (Verschlüsselungswunsch), die Teil des TLS-Handshakes ist.
Der Server antwortet ebenfalls mit einem Initial-Paket (Verbindungswunsch), das eine „Server Hello“-Nachricht (Verschlüsselungswunsch) und andere TLS-Handshake-Nachrichten enthält. Zusätzlich wird ein Sitzungsschlüssel übertragen, den der Client in allen zukünftigen Kommunikationen verwenden muss.
Nachdem der Client das Initial-Paket des Servers erhalten hat, sendet er ein weiteres Paket, das die restlichen TLS-Handshake-Nachrichten enthält. Sobald der Server dieses Paket erhält, ist der Verbindungsaufbau abgeschlossen und die Datenübertragung kann beginnen. Dieser gesamte Prozess erfordert nur einen Round-Trip, daher der Name 1-RTT Verbindungsaufbau.
Nach erfolgreichem Verbindungsaufbau kann die Datenübertragung beginnen.
0-RTT Verbindungsaufbau
QUIC bietet eine Möglichkeit, den Verbindungsaufbau weiter zu beschleunigen, wenn ein Client zuvor bereits eine Verbindung zum jeweiligen Server hergestellt hat. Dies wird als 0-RTT (Round-Trip Time) Verbindungsaufbau bezeichnet.
Während des ersten Verbindungsaufbaus sendet der Server dem Client einen individuellen Sitzungsschlüssel, der die verschlüsselte Informationen über die aktuelle Sitzung enthält. Wenn der Client später eine erneute Verbindung zum Server herstellt, kann er den Sitzungsschlüssel in seinem ersten Initial-Paket (Verbindungs- und Verschlüsselungswunsch) einschließen. Direkt auf das Initial-Paket folgt bei einem erneuten Verbindungsaufbau ein Paket, dass die gewünschten Daten vom Server anfordert (z.B. HTTP Request).
Der Server kann den Sitzungsschlüssel entschlüsseln und die Sitzungsinformationen verwenden, um den Zustand der vorherigen Verbindung wiederherzustellen. Dies ermöglicht es dem Server, sofort auf die Datenanfrage zu antworten und zusätzlich dein Verbindungs- und Verschlüsselungswunsch seinerseits zu senden.
QUIC Datenübertragung
Nachdem die Verbindung zwischen Client und Server hergestellt wurde, beginnt die Datenübertragung. QUIC verwendet sogenannte „Streams“ für die Datenübertragung, wobei ein Stream in QUIC eine unabhängige, bidirektionale Sequenz von Bytes darstellt. Es können mehrere Streams gleichzeitig innerhalb einer einzigen QUIC-Verbindung, unabhängig voneinander übertragen werden, sodass der Verlust eines Pakets die Übertragung der anderen Streams nicht beeinträchtigt (dazu später mehr).
Jedes Datenpaket, das über QUIC gesendet wird, enthält eine Sequenznummer bzw. Paketnummer, die verwendet wird, um die Reihenfolge der Pakete zu bestimmen und zu erkennen, ob ein Paket verloren gegangen ist. Wenn der Empfänger ein Paket erhält, sendet dieser eine Bestätigung (ACK) an den Sender, worin die Paketnummer des empfangenen Pakets enthalten ist. Kommt die Empfangsbestätigung nicht beim Sender an, geht dieser davon aus, dass das Paket verloren gegangen ist und sendet es erneut.
QUIC Verbindungsabbau
Der Verbindungsabbau in QUIC ist relativ einfach. Entweder Client oder Server können eine Verbindung beenden, indem sie ein spezielles Paket (CONNECTION_CLOSE) an den anderen sendet. Dieses Paket enthält einen Grund für den Verbindungsabbau und eine finale Paketnummer.
Fehlerbehandlung in QUIC
Nicht immer werden alle Pakete korrekt übertragen oder gehen auf dem Weg zum Empfänger verloren. QUIC nutzt denselben einfachen Mechanismus, um fehlende Pakete zu identifizieren wie TCP. Auf jedes empfangene Paket sendet der Empfänger eine Empfangsbestätigung (ACK). Die gesendete Empfangsbestätigung erhält der Absender und verifiziert diese anhand der mitgesendeten Paketnummer.
Für jedes übertragene Paket, startet der Sender einen Timer, der beim Erhalt der Empfangsbestätigung verworfen wird. Sollte dieser Timer nach einer festgelegten Zeit nicht zurückgesetzt werden, kommt es zu einem sogenannten Timeout. Beim Eintreten eines Timeouts, nimmt der Sender an, dass das Paket nicht empfangen wurde und wiederholt den Sendevorgang des Pakets.
Multiplexing ohne Head-of-Line-Blocking (HOL)
Das QUIC Protokoll bietet die Möglichkeit, mehrere Streams gleichzeitig zu übertragen, um eine bessere Übertragungsrate zu gewährleisten. Dadurch kommt es bei anderen Protokollen wie SPDY, einem auf TCP basierenden Protokoll, was in HTTP/2 genutzt wird, jedoch oft zum sog. Head-of-Line-Blocking (HOL). Head-of-Line-Blocking tritt auf, wenn das erste Datenpaket einer Warteschlange einen Fehler aufweist und sich deshalb alle nachfolgenden Pakete stauen. QUIC umgeht das Problem des Head-of-Line-Blocking indem nur voneinander abhängige Streams verzögert werden.
Beispiel: Angenommen, das QUIC Paket 2 (siehe Abb. 5) geht verloren und die übrigen Pakete kommen bei dem Empfänger an. Das QUIC Paket 1 kann ohne Probleme verarbeitet werden sowie der Stream mit der ID 1 aus dem QUIC Paket 3, da die Byte Range des Streams (450-999) auf die Byte Range des zuvor verarbeiteten Streams (QUIC Paket 1) mit derselben ID (Stream ID 1) folgt. Nun versucht die Anwendung den Stream, mit der ID 2 aus Paket 3, den zuvor übermittelten Streams zuzuordnen, dies gelingt jedoch nicht, da die Byte Range (300-599) nicht bei 0 beginnt und der zuvor benötigte Stream, mit der ID 2 aus Paket 2, mit der Byte Range (0-299) noch nicht eingetroffen ist. Jetzt wird der Stream mit der ID 2 aus Paket 3 so lange zurückgehalten, bis das Paket 2 mit dem Stream und der Stream ID 2 eintrifft.
Migrating Flows in QUIC
Um zu verhindern, dass eine QUIC Verbindung abbricht, wenn sich die Quell-IP-Adresse, Ziel IP-Adresse, Quell Port Nummer, Ziel Port Nummer oder das verwendete Protokoll ändert, generiert QUIC eine sogenannte Connection ID. Auch wenn sich einer der fünf Parameter ändert, bleibt die Connection ID gleich und die Verbindung bestehen.
So wird zum Beispiel verhindert, dass beim Verbindungsverlust innerhalb eines Bezahlvorgangs das Geld vom Konto des Käufers abgebucht, jedoch nicht als Zahlung bei dem Verkäufer registriert wird.
Flusskontrolle in QUIC
Die Flusskontrolle ist ein Mechanismus, der in Netzwerkprotokollen wie QUIC verwendet wird, um sicherzustellen, dass nicht mehr Daten gesendet werden, als der Empfänger verarbeiten kann.
In QUIC wird die Flusskontrolle sowohl auf Verbindungsebene als auch auf Stream-Ebene durchgeführt. Jeder Stream und die gesamte Verbindung haben ein zugeordnetes Flusskontrollfenster, das die maximale Anzahl von Bytes darstellt, die übersendet werden dürfen, bevor eine Empfangsbestätigung vom Empfänger empfangen werden muss. Wenn der Empfänger Daten empfängt und verarbeitet, sendet er eine Flusskontroll-Bestätigung an den Sender, die angibt, wie viele zusätzliche Bytes der Sender senden darf.
Die Flusskontrolle in QUIC ist bidirektional. Das bedeutet, dass sowohl der Client als auch der Server Flusskontrollfenster haben.
Staukontrolle in QUIC
Während die Flusskontrolle sicherstellt, dass der Sender die Anwendung des Empfängers nicht überlastet, dient die Staukontrolle dazu, eine Überlastung des Netzwerks zu verhindern. Bei der Staukontrolle passt der Sender seine Datenübertragungsrate an die Netzwerkkapazität an.
Wenn der Sender feststellt, dass Pakete verloren gehen, geht dieser davon aus, dass eine Netzwerküberlastung vorliegt und verringert die Datenübertragungsrate. Werden alle Pakete jedoch erfolgreich bestätigt, wird angenommen, dass das Netzwerk eine höhere Kapazität hat und die Datenübertragungsrate erhöht.
Sicherheit von QUIC
QUIC verwendet TLS 1.3 für die Verschlüsselung auf Protokollebene, um eine sichere Datenübertragung zu gewährleisten. Es unterstützt sowohl die Verschlüsselung des Payload als auch des Header, was es schwieriger macht, QUIC-Verkehr zu analysieren und zu manipulieren. Darüber hinaus ermöglicht die Integration von TLS in QUIC einen schnelleren Verbindungsaufbau im Vergleich zu TCP+TLS.
Abschließender Gedanke zu QUIC
QUIC ist ein vielversprechendes Protokoll, das die Leistung von Webanwendungen erheblich verbessern kann. Durch die Kombination der besten Eigenschaften von TCP und UDP bietet QUIC eine effiziente und zuverlässige Lösung für die Datenübertragung im Internet.
Jedoch, wird QUIC von vielen Webhostern und Serviceanbietern noch nicht unterstützt. IIS, LiteSpeed und Nginx unterstützen in ihren neusten Versionen zwar bereits HTTP/3 unter der Verwendung von QUIC, der aber immer noch gern genutzte Apache Webserver, lässt mit der Implementierung von HTTP/3 und damit QUIC jedoch auf sich warten. Ein gern genutztes Mittel, um HTTP/3 trotz fehlender Unterstützung des Webservers HTTP/3 auf Ihrer Webseite zu implementieren, ist der Umweg über ein CDN (Content Delivery Network) wie KeyCDN. Sollten Sie bei der Umsetzung von HTTP/3 in Ihrer App, klassischen oder WordPress Webseite Hilfe benötigen, wenden Sie sich gern an mich.