RFC 9308 - Anwendbarkeit des QUIC-Transportprotokolls (Applicability of the QUIC Transport Protocol)
- Status: Informational
- Veröffentlicht: September 2022
- Stream: IETF
- Errata: Keine Errata
Zusammenfassung (Abstract)
Dieses Dokument erörtert die Anwendbarkeit des QUIC-Transportprotokolls und konzentriert sich auf Vorbehalte, die die Entwicklung und den Einsatz von Anwendungsprotokollen über QUIC beeinflussen. Die beabsichtigte Zielgruppe sind Entwerfer von Abbildungen von Anwendungsprotokollen auf QUIC sowie Implementierer dieser Anwendungsprotokolle.
Status dieses Memorandums (Status of This Memo)
Dieses Dokument ist keine Spezifikation des Internet Standards Track; es wird zu Informationszwecken veröffentlicht.
Dieses Dokument ist ein Produkt der Internet Engineering Task Force (IETF). Es repräsentiert den Konsens der IETF-Gemeinschaft. Es hat eine öffentliche Überprüfung erhalten und wurde von der Internet Engineering Steering Group (IESG) zur Veröffentlichung freigegeben. Nicht alle von der IESG freigegebenen Dokumente sind Kandidaten für irgendeine Stufe eines Internet Standard; siehe Abschnitt 2 von RFC 7841.
Informationen über den aktuellen Status dieses Dokuments, etwaige Errata und wie Feedback dazu gegeben werden kann, sind unter https://www.rfc-editor.org/info/rfc9308 erhältlich.
Urheberrechtshinweis (Copyright Notice)
Copyright (c) 2022 IETF Trust and the persons identified as the document authors. All rights reserved.
Dieses Dokument unterliegt BCP 78 und den rechtlichen Bestimmungen des IETF Trust zu IETF-Dokumenten (https://trustee.ietf.org/license-info), die am Veröffentlichungsdatum dieses Dokuments gelten. Bitte prüfen Sie diese Dokumente sorgfältig, da sie Ihre Rechte und Einschränkungen in Bezug auf dieses Dokument beschreiben. Aus diesem Dokument extrahierte Code-Komponenten müssen den Text der Revised BSD License enthalten, wie in Abschnitt 4.e der Trust Legal Provisions beschrieben, und werden ohne Gewährleistung bereitgestellt, wie in der Revised BSD License beschrieben.
Inhaltsverzeichnis (Table of Contents)
- Einleitung
- Die Notwendigkeit eines Fallbacks
- 0-RTT
- Nutzung von Streams
- Paketisierung und Latenz
- Fehlerbehandlung
- Effizienz der Bestätigungen
- Portauswahl und Entdeckung von Anwendungsendpunkten
- Verbindungsmigration
- Verbindungsbeendigung
- Informationsoffenlegung und Connection ID
- QoS und DSCP
- Nutzung von Versionen und kryptografischem Handshake
- Ermöglichung der Bereitstellung neuer Versionen
- Unzuverlässiger Datagrammdienst über QUIC
- IANA-Erwägungen
- Sicherheitserwägungen
- Referenzen
1. Einleitung (Introduction)
QUIC [QUIC] ist ein neues Transportprotokoll, das eine Reihe fortschrittlicher Funktionen bereitstellt. Obwohl es ursprünglich für den HTTP-Anwendungsfall entworfen wurde, bietet es Fähigkeiten, die mit einer viel größeren Vielfalt von Anwendungen genutzt werden können. QUIC wird in UDP gekapselt. QUIC Version 1 integriert TLS 1.3 [TLS13], um alle Nutzdaten und die meisten Steuerinformationen zu verschlüsseln. Die Version von HTTP, die QUIC verwendet, ist als HTTP/3 [QUIC-HTTP] bekannt.
Dieses Dokument bietet Leitlinien für Anwendungsentwickler, die das QUIC-Protokoll nutzen möchten, ohne es selbst zu implementieren. Dazu gehören allgemeine Leitlinien für Anwendungen, die über HTTP/3 oder direkt über QUIC betrieben werden.
In den folgenden Abschnitten erörtern wir spezifische Vorbehalte zur Anwendbarkeit von QUIC und Probleme, die Anwendungsentwickler berücksichtigen müssen, wenn sie QUIC als Transport für ihre Anwendungen verwenden.
2. Die Notwendigkeit eines Fallbacks (The Necessity of Fallback)
QUIC verwendet UDP als Substrat. Dies ermöglicht eine Implementierung im Userspace und erlaubt die Durchquerung von Netzwerk-Middleboxes (einschließlich NAT), ohne Aktualisierungen der bestehenden Netzwerkinfrastruktur zu erfordern.
Messstudien haben gezeigt, dass zwischen 3 % [Trammell16] und 5 % [Swett16] der Netzwerke den gesamten UDP-Verkehr blockieren, obwohl es wenig Hinweise auf andere Formen systematischer Benachteiligung von UDP-Verkehr im Vergleich zu TCP gibt [Edeline16]. Diese Blockierung impliziert, dass alle auf QUIC laufenden Anwendungen entweder darauf vorbereitet sein müssen, Verbindungsfehler in solchen Netzwerken zu akzeptieren, oder so ausgelegt sein müssen, dass sie auf ein anderes Transportprotokoll zurückfallen. Im Fall von HTTP ist dieser Fallback TLS over TCP.
Die IETF-Transport-Services-(TAPS)-Spezifikationen [TAPS-ARCH] beschreiben ein System mit einer gemeinsamen API für mehrere Protokolle. Dies ist besonders relevant für QUIC, da es die Auswirkungen des Fallbacks zwischen mehreren Protokollen behandelt.
Insbesondere muss ein Fallback auf unsichere Protokolle oder auf schwächere Versionen sicherer Protokolle vermieden werden. Im Allgemeinen muss eine Anwendung, die Fallback implementiert, die Sicherheitsfolgen berücksichtigen. Ein Fallback auf TCP und TLS setzt Steuerinformationen der Modifikation und Manipulation im Netzwerk aus. Darüber hinaus können Downgrades auf TLS-Versionen älter als 1.3, die in QUIC Version 1 verwendet wird, zu deutlich schwächerem kryptografischem Schutz führen. Beispielsweise haben die Ergebnisse der Protokollverhandlung [RFC7301] nur dann Vertraulichkeitsschutz, wenn TLS 1.3 verwendet wird.
Diese Anwendungen müssen – möglicherweise mit eingeschränkter Funktionalität – in Abwesenheit von Funktionen arbeiten, die QUIC bereitstellt und die im Fallback-Protokoll nicht vorhanden sind. Für den Fallback auf TLS over TCP ist der offensichtlichste Unterschied, dass TCP kein Stream-Multiplexing bereitstellt und Stream-Multiplexing daher bei Bedarf in der Anwendungsschicht implementiert werden müsste. Weiterhin unterstützen TCP-Implementierungen und Netzwerkpfade oft die TCP-Fast-Open-(TFO)-Option [RFC7413] nicht, die das Senden von Nutzdaten zusammen mit dem ersten Steuerpaket einer neuen Verbindung ermöglicht, wie es auch die 0-RTT-Sitzungswiederaufnahme in QUIC bereitstellt. Es gibt Hinweise darauf, dass Middleboxes SYN-Daten blockieren, selbst wenn TFO erfolgreich ausgehandelt wurde (siehe [PaaschNanog]). Und selbst wenn Fast Open Ende-zu-Ende erfolgreich arbeitet, ist es auf ein einzelnes Paket TLS-Handshake und Anwendungsdaten beschränkt, im Gegensatz zu QUIC 0-RTT.
Darüber hinaus ist die Verschlüsselung (in diesem Fall TLS) untrennbar in QUIC integriert, während die TLS-Aushandlung über TCP blockiert werden kann. Wenn TLS over TCP nicht unterstützt werden kann, sollte die Verbindung abgebrochen werden, und die Anwendung sollte dem Benutzer dann eine geeignete Meldung präsentieren, dass sichere Kommunikation nicht verfügbar ist.
Zusammenfassend wird jeder Fallback-Mechanismus wahrscheinlich eine Leistungsverschlechterung auferlegen und kann die Sicherheit mindern; jedoch darf der Fallback die Erwartung der Anwendung an Vertraulichkeit oder Integrität ihrer Nutzdaten nicht stillschweigend verletzen.
3. 0-RTT
QUIC sieht die 0-RTT-Verbindungsherstellung vor. Obwohl dieselbe Einrichtung in TLS 1.3 mit TCP existiert, bietet 0-RTT für Anwendungen, die QUIC nutzen, sowohl Chancen als auch Herausforderungen.
Ein Transportprotokoll, das die 0-RTT-Verbindungsherstellung bereitstellt, unterscheidet sich aus Sicht der es nutzenden Anwendung qualitativ von einem, das kein 0-RTT bereitstellt. Die relativen Abwägungen zwischen den Kosten des Schließens und Wiederöffnens einer Verbindung und dem Versuch, sie offen zu halten, sind unterschiedlich; siehe Abschnitt 3.2.
Eine Anwendung muss bewusst wählen, 0-RTT zu verwenden, da 0-RTT ein Risiko von Replay-Angriffen birgt. Anwendungsprotokolle, die 0-RTT nutzen, benötigen ein Profil, das die Arten von Informationen beschreibt, die sicher gesendet werden können. Für HTTP wird dieses Profil in [HTTP-REPLAY] beschrieben.
3.1. Replay-Angriffe (Replay Attacks)
Die Neuübertragung oder das bösartige Replay von in 0-RTT-Paketen enthaltenen Daten könnte dazu führen, dass die Serverseite mehrere Kopien derselben Daten empfängt.
Anwendungsdaten, die der Client in 0-RTT-Paketen sendet, könnten mehr als einmal verarbeitet werden, wenn sie wiedergegeben werden. Anwendungen müssen sich bewusst sein, was in 0-RTT sicher zu senden ist. Anwendungsprotokolle, die die Nutzung von 0-RTT ermöglichen wollen, benötigen eine sorgfältige Analyse und eine Beschreibung dessen, was in 0-RTT gesendet werden kann; siehe Abschnitt 5.6 von [QUIC-TLS].
In manchen Fällen kann es ausreichen, in 0-RTT gesendete Anwendungsdaten auf Daten zu beschränken, die keine Aktionen mit dauerhaften Auswirkungen auf einem Server verursachen. Das Initiieren einer Datenabfrage oder das Herstellen einer Konfiguration sind Beispiele für Aktionen, die sicher sein könnten. Idempotente Operationen – solche, bei denen die Wiederholung denselben Nettoeffekt wie eine einzelne Operation hat – könnten sicher sein. Es ist jedoch auch möglich, einzeln idempotente Operationen zu einer nicht-idempotenten Operationsfolge zu kombinieren.
Sobald ein Server 0-RTT-Daten akzeptiert, gibt es kein Mittel, empfangene Daten selektiv zu verwerfen. Protokolle können jedoch Wege definieren, einzelne Aktionen abzulehnen, die bei Replay unsicher sein könnten.
Einige TLS-Implementierungen und -Bereitstellungen könnten in der Lage sein, teilweisen oder sogar vollständigen Replay-Schutz bereitzustellen, der zur Verwaltung des Replay-Risikos genutzt werden könnte.
3.2. Sitzungswiederaufnahme versus Keep-Alive (Session Resumption versus Keep-Alive)
Da QUIC in UDP gekapselt ist, müssen Anwendungen, die QUIC nutzen, mit kurzen Netzwerkleerlauf-Timeouts umgehen. Eingesetzte zustandsbehaftete Middleboxes bauen in der Regel beim ersten gesendeten Paket Zustand für UDP-Flüsse auf und halten Zustand für viel kürzere Leerlaufzeiten als bei TCP. [RFC5382] schlägt eine TCP-Leerlaufzeit von mindestens 124 Minuten vor, obwohl es in der Literatur keine Hinweise auf eine weit verbreitete Umsetzung dieser Richtlinie gibt. Das kurze Netzwerk-Timeout für UDP ist jedoch gut dokumentiert. Laut einer Studie von 2010 ([Hatonen10]) können UDP-Anwendungen annehmen, dass jede NAT-Bindung oder anderer Zustandseintrag bereits nach nur dreißig Sekunden Inaktivität ablaufen kann. Abschnitt 3.5 von [RFC8085] erörtert Keep-Alive-Intervalle für UDP weiter: Es verlangt einen Mindestwert von 15 Sekunden, empfiehlt jedoch größere Werte oder dass Keep-Alive ganz weggelassen wird.
Durch die Verwendung einer Connection ID ist QUIC so ausgelegt, dass es nach einem Timeout robust gegenüber NAT-Rebinding ist. Dies hilft jedoch nur, wenn ein Endpunkt die Verfügbarkeit an der Adresse aufrechterhält, die sein Peer verwendet, und der Peer derjenige ist, der nach dem Timeout sendet.
Einige QUIC-Verbindungen könnten nicht robust gegenüber NAT-Rebinding sein, weil die Routing-Infrastruktur (insbesondere Load Balancer) das Adress-/Port-4-Tupel verwendet, um Verkehr zu leiten. Darüber hinaus könnten Middleboxes mit anderen Funktionen als Adressübersetzung den Pfad weiterhin beeinflussen. Insbesondere lassen einige Firewalls Serververkehr nicht zu, für den die Firewall keinen aktuellen Zustand für ein entsprechendes, vom Client gesendetes Paket hat.
QUIC-Anwendungen können Leerlaufzeiten anpassen, um das Timeout-Risiko zu steuern. Leerlaufzeiten und das Netzwerkleerlauf-Timeout sind vom Verbindungsleerlauf-Timeout zu unterscheiden, das als das Minimum des idle-timeout-Parameters eines der beiden Endpunkte definiert ist; siehe Abschnitt 10.1 von [QUIC]. Es gibt drei Optionen:
- Das Problem ignorieren, wenn das Anwendungsschichtprotokoll nur aus Interaktionen ohne oder mit sehr kurzen Leerlaufzeiten besteht oder wenn die Widerstandsfähigkeit des Protokolls gegen NAT-Rebinding ausreichend ist.
- Sicherstellen, dass es keine langen Leerlaufzeiten gibt.
- Die Sitzung nach einer langen Leerlaufzeit wiederaufnehmen und dabei bei Eignung 0-RTT-Wiederaufnahme verwenden.
Die erste Strategie ist die einfachste, gilt aber nur für bestimmte Anwendungen.
Entweder der Server oder der Client in einer QUIC-Anwendung kann PING-Frames als Keep-Alives senden, um zu verhindern, dass die Verbindung und jeder Zustand auf dem Pfad abläuft. Empfehlungen für die Nutzung von Keep-Alives sind anwendungsspezifisch und hängen hauptsächlich von den Latenzanforderungen und der Nachrichtenhäufigkeit der Anwendung ab. In diesem Fall muss die Anwendungsabbildung spezifizieren, ob der Client oder der Server dafür verantwortlich ist, die Anwendung am Leben zu halten. Während [Hatonen10] nahelegt, dass 30 Sekunden ein geeigneter Wert für das öffentliche Internet sein könnten, wenn ein NAT auf dem Pfad liegt, sind größere Werte vorzuziehen, wenn die Bereitstellung NAT-Rebinding durchgängig überstehen kann oder bekannt ist, dass sie sich in einer kontrollierten Umgebung (z. B. Rechenzentren) befindet, um die Netzwerk- und Rechenlast zu senken.
Das Senden von PING-Frames häufiger als alle 30 Sekunden über lange Leerlaufzeiten kann in manchen Situationen zu übermäßig unproduktivem Verkehr und inakzeptablem Energieverbrauch für energiebegrenzte (mobile) Geräte führen. Darüber hinaus können Timeouts kürzer als 30 Sekunden die Handhabung vorübergehender Netzwerkunterbrechungen erschweren, wie etwa die Migration virtueller Maschinen (VM) oder Abdeckungsverlust während der Mobilität. Siehe [RFC8085], insbesondere Abschnitt 3.5.
Alternativ kann der Client (aber nicht der Server) Sitzungswiederaufnahme statt des Sendens von Keep-Alive-Verkehr verwenden. In diesem Fall kann ein Client, der Daten an einen Server über eine Verbindung senden möchte, die länger als das idle timeout des Servers (aus dem Transportparameter idle_timeout verfügbar) im Leerlauf war, einfach neu verbinden. Wenn möglich, kann diese Neuverbindung 0-RTT-Sitzungswiederaufnahme verwenden und so die mit dem Neustart der Verbindung verbundene Latenz reduzieren. Natürlich ist dieser Ansatz nur in Fällen gültig, in denen es sicher ist, 0-RTT zu verwenden, und wenn der Client der neu startende Peer ist.
Die Abwägungen zwischen Wiederaufnahme und Keep-Alives müssen pro Anwendung bewertet werden. Im Allgemeinen sollten Anwendungen Keep-Alives nur unter Umständen verwenden, in denen fortgesetzte Kommunikation sehr wahrscheinlich ist; [QUIC-HTTP] empfiehlt beispielsweise, Keep-Alives nur zu verwenden, wenn eine Anfrage aussteht.
4. Nutzung von Streams (Use of Streams)
Die Stream-Multiplexing-Funktion von QUIC ermöglicht es Anwendungen, mehrere Streams über eine einzelne Verbindung ohne Head-of-Line-Blocking zwischen Streams auszuführen. Stream-Daten werden in Frames getragen, wobei ein QUIC-Paket auf dem Draht einen oder mehrere Stream-Frames tragen kann.
Streams können unidirektional oder bidirektional sein, und ein Stream kann entweder vom Client oder vom Server initiiert werden. Nur der Initiator eines unidirektionalen Streams kann Daten darauf senden.
Streams und Verbindungen können jeweils maximal 2^62-1 Bytes in jeder Richtung tragen, aufgrund von Kodierungsbeschränkungen bei Stream-Offsets und Verbindungsflusssteuerungslimits. In dem derzeit unwahrscheinlichen Fall, dass diese Grenze von einer Anwendung erreicht wird, müsste eine neue Verbindung hergestellt werden.
Streams können unabhängig geöffnet und geschlossen werden, graceful oder abrupt. Eine Anwendung kann die Ausgangsrichtung eines Streams graceful schließen, indem sie QUIC anweist, ein FIN-Bit in einem STREAM-Frame zu senden. Sie kann die Eingangsrichtung nicht graceful schließen ohne ein vom Peer erzeugtes FIN, ähnlich wie bei TCP. Ein Endpunkt kann jedoch die Ausgangsrichtung abrupt schließen oder seinen Peer auffordern, die Eingangsrichtung abrupt zu schließen; diese Aktionen sind vollständig unabhängig voneinander.
QUIC stellt keine Schnittstelle für die Ausnahmebehandlung eines beliebigen Streams bereit. Wenn ein für eine Anwendung kritischer Stream geschlossen wird, kann die Anwendung Fehlermeldungen auf der Anwendungsschicht erzeugen, um das andere Ende und/oder die höhere Schicht zu informieren, die schließlich die QUIC-Verbindung beenden kann.
Die Abbildung von Anwendungsdaten auf Streams ist anwendungsspezifisch und für HTTP/3 in [QUIC-HTTP] beschrieben. Es gibt einige allgemeine Prinzipien, die bei der Gestaltung der Stream-Nutzung einer Anwendung anzuwenden sind:
- Ein einzelner Stream stellt Ordnung bereit. Wenn die Anwendung verlangt, dass bestimmte Daten in der Reihenfolge empfangen werden, sollten diese Daten auf demselben Stream gesendet werden. Es gibt keine Garantie für Übertragungs-, Empfangs- oder Zustellungsreihenfolge über Streams hinweg.
- Mehrere Streams stellen Parallelität bereit. Daten, die unabhängig verarbeitet werden können und daher unter Head-of-Line-Blocking leiden würden, wenn sie zur geordneten Entgegennahme gezwungen würden, sollten über getrennte Streams übertragen werden.
- Streams können Nachrichtenorientierung bereitstellen und die Stornierung von Nachrichten erlauben. Wenn eine Nachricht auf einen einzelnen Stream abgebildet wird, kann das Zurücksetzen des Streams, um eine unbestätigte Nachricht ablaufen zu lassen, verwendet werden, um teilweise Zuverlässigkeit für diese Nachricht zu emulieren.
Wenn ein QUIC-Empfänger die maximal erlaubte Anzahl gleichzeitiger Streams geöffnet hat und der Sender anzeigt, dass mehr Streams benötigt werden, führt dies nicht automatisch zu einer Erhöhung der maximalen Stream-Anzahl durch den Empfänger. Daher sollte eine Anwendung die maximal erlaubte, derzeit offene und derzeit genutzte Anzahl von Streams berücksichtigen, wenn sie bestimmt, wie Daten auf Streams abgebildet werden.
QUIC weist jedem Stream einen numerischen Bezeichner zu, die Stream ID genannt. Während die Beziehung zwischen diesen Bezeichnern und Stream-Typen in Version 1 von QUIC klar definiert ist, könnten zukünftige Versionen diese Beziehung aus verschiedenen Gründen ändern. QUIC-Implementierungen sollten die Eigenschaften jedes Streams freilegen (welcher Endpunkt den Stream initiiert hat, ob der Stream unidirektional oder bidirektional ist, die für den Stream verwendete Stream ID); Anwendungen sollten diese Eigenschaften abfragen, anstatt zu versuchen, sie aus der Stream ID abzuleiten.
Die Methode der Zuweisung von Stream-Bezeichnern zu von der Anwendung geöffneten Streams kann zwischen Transportimplementierungen variieren. Daher sollte eine Anwendung nicht annehmen, dass eine bestimmte Stream ID einem Stream zugewiesen wird, der noch nicht allokiert wurde. Beispielsweise verwendet HTTP/3 Stream IDs, um auf Streams zu verweisen, die bereits geöffnet wurden, macht aber keine Annahmen über zukünftige Stream IDs oder die Art und Weise, wie sie zugewiesen werden (siehe Abschnitt 6 von [QUIC-HTTP]).
4.1. Stream- versus Flow-Multiplexing (Stream versus Flow Multiplexing)
Streams sind nur für die Anwendung bedeutsam; da Stream-Informationen innerhalb der Verschlüsselungsgrenze von QUIC getragen werden, legt ein gegebenes Paket keine Informationen darüber offen, welche(r) Stream(s) im Paket getragen werden. Daher ist Stream-Multiplexing nicht dazu gedacht, Streams hinsichtlich der Netzwerkbehandlung zu differenzieren. Anwendungsverkehr, der unterschiedliche Netzwerkbehandlung erfordert, sollte daher über unterschiedliche 5-Tupel (d. h. mehrere QUIC-Verbindungen) getragen werden. Angesichts der Fähigkeit von QUIC, Anwendungsdaten im ersten RTT einer Verbindung zu senden (wenn eine vorherige Verbindung zum selben Host erfolgreich hergestellt wurde, um die notwendigen Anmeldeinformationen bereitzustellen), sind die Kosten für die Herstellung einer weiteren Verbindung extrem niedrig.
4.2. Priorisierung (Prioritization)
Stream-Priorisierung wird weder dem Netzwerk noch dem Empfänger offengelegt. Die Priorisierung wird vom Sender verwaltet, und der QUIC-Transport sollte eine Schnittstelle bereitstellen, damit Anwendungen Streams priorisieren können [QUIC]. Anwendungen können ihr eigenes Priorisierungsschema auf QUIC aufsetzen: Ein Anwendungsprotokoll, das auf QUIC läuft, kann explizite Nachrichten zur Signalisierung von Priorität definieren, wie die in [RFC9218] für HTTP definierten. Ein Anwendungsprotokoll kann Regeln definieren, die einem Endpunkt erlauben, die Priorität basierend auf dem Kontext zu bestimmen, oder kann eine Schnittstelle höherer Ebene bereitstellen und die Bestimmung der darüberliegenden Anwendung überlassen.
Die Prioritätsbehandlung von Neuübertragungen kann vom Sender in der Transportschicht implementiert werden. [QUIC] empfiehlt, verlorene Daten vor neuen Daten neu zu übertragen, sofern die Anwendung nichts anderes angibt. Wenn ein QUIC-Endpunkt vollständig zuverlässige Streams zur Übertragung verwendet, ist die Priorisierung von Neuübertragungen in den meisten Fällen vorteilhaft, füllt Lücken und gibt das Flusssteuerungsfenster frei. Für teilweise zuverlässige oder unzuverlässige Streams ist die priorisierte Planung von Neuübertragungen gegenüber Daten höher priorisierter Streams möglicherweise nicht wünschenswert. Für solche Streams könnte QUIC entweder eine explizite Schnittstelle zur Steuerung der Priorisierung bereitstellen oder die Priorisierungsentscheidung aus dem Zuverlässigkeitsniveau des Streams ableiten.
4.3. Geordnete und zuverlässige Zustellung (Ordered and Reliable Delivery)
QUIC-Streams ermöglichen geordnete und zuverlässige Zustellung. Obwohl es möglich ist, dass eine Implementierung Optionen bereitstellt, die Streams für teilweise Zuverlässigkeit oder Out-of-Order-Zustellung nutzen, werden die meisten Implementierungen annehmen, dass Daten zuverlässig und in der Reihenfolge zugestellt werden.
Unter dieser Annahme könnte ein Endpunkt, der Stream-Daten empfängt, keinen Fortschritt machen, bis Daten verfügbar sind, die mit dem Anfang eines Streams zusammenhängend sind. Insbesondere könnte ein Empfänger Flusssteuerungskredit zurückhalten, bis zusammenhängende Daten an die Anwendung geliefert werden; siehe Abschnitt 2.2 von [QUIC]. Um diese Empfangslogik zu unterstützen, sendet ein Endpunkt Stream-Daten, bis sie bestätigt werden, und stellt sicher, dass Daten am Anfang des Streams zuerst gesendet und bestätigt werden.
Ein Endpunkt, der ein anderes Sendeverhalten verwendet und diese Änderung nicht mit seinem Peer aushandelt, könnte Leistungsprobleme oder Deadlocks antreffen.
4.4. Flusssteuerungs-Deadlocks (Flow Control Deadlocks)
Die QUIC-Flusssteuerung (Abschnitt 4 von [QUIC]) stellt ein Mittel bereit, den Zugriff auf die begrenzten Puffer zu verwalten, die Endpunkte für eingehende Daten haben. Dieser Mechanismus begrenzt die Menge an Daten, die sich in Puffern an Endpunkten oder im Transit im Netzwerk befinden können. Es gibt jedoch mehrere Wege, auf denen Limits Bedingungen erzeugen können, die dazu führen können, dass eine Verbindung entweder suboptimal arbeitet oder in einen Deadlock gerät.
Deadlocks in der Flusssteuerung sind für jedes Protokoll möglich, das QUIC verwendet, obwohl ob sie zu einem Problem werden, davon abhängt, wie Implementierungen Daten konsumieren und Flusssteuerungskredit bereitstellen. Das Verständnis, was Deadlocks verursacht, könnte Implementierungen helfen, Deadlocks zu vermeiden.
Die Größe und Rate von Aktualisierungen des Flusssteuerungskredits können die Leistung beeinflussen. Anwendungen, die QUIC nutzen, haben oft einen Datenkonsumenten, der Daten aus Transportpuffern liest. Einige Implementierungen könnten unabhängige Empfangspuffer auf Transport- und Anwendungsschicht haben. Das Konsumieren von Daten impliziert nicht immer, dass sie sofort verarbeitet werden. Eine gängige Implementierungstechnik ist jedoch, den Flusssteuerungskredit an den Sender zu erweitern, indem MAX_DATA- und/oder MAX_STREAM_DATA-Frames ausgegeben werden, während Daten konsumiert werden. Die Zustellung dieser Frames wird durch die Latenz des Rückkanals vom Empfänger zum Datensender beeinflusst. Wenn Kredit nicht rechtzeitig erweitert wird, kann die sendende Anwendung blockiert werden und den Sender effektiv drosseln.
Große Anwendungsnachrichten können Deadlocks erzeugen, wenn der Empfänger Daten nicht schrittweise vom Transport liest. Wenn die Nachricht größer ist als der verfügbare Flusssteuerungskredit und der Empfänger keinen zusätzlichen Flusssteuerungskredit freigibt, bis die gesamte Nachricht empfangen und zugestellt ist, kann ein Deadlock auftreten. Dies ist selbst dann möglich, wenn Stream-Flusssteuerungslimits nicht erreicht sind, weil Verbindungsflusssteuerungslimits von anderen Streams verbraucht werden können.
Ein längengeprägtes Nachrichtenformat erleichtert es einem Datenkonsumenten, Daten ungelesen im Transportpuffer zu belassen und dadurch Flusssteuerungskredit zurückzuhalten. Wenn Flusssteuerungslimits verhindern, dass der Rest einer Nachricht gesendet wird, entsteht ein Deadlock. Ein Längenpräfix könnte auch die Erkennung dieser Art von Deadlock ermöglichen. Wo Anwendungsprotokolle Nachrichten haben, die als einzelne Einheit verarbeitet werden könnten, macht das atomare Reservieren von Flusssteuerungskredit für die gesamte Nachricht diesen Stil von Deadlock unwahrscheinlicher.
Ein Datenkonsument kann alle Daten eifrig lesen, sobald sie verfügbar werden, um den Empfänger zu veranlassen, Flusssteuerungskredit zu erweitern und die Chancen eines Deadlocks zu verringern. Ein solcher Datenkonsument könnte jedoch andere Mittel benötigen, um einen Peer für den zusätzlichen Zustand zur Verantwortung zu ziehen, den er für teilweise verarbeitete Nachrichten hält.
Deadlocks können auch auftreten, wenn Daten auf verschiedenen Streams voneinander abhängen. Angenommen, Daten auf einem Stream treffen vor den Daten auf einem zweiten Stream ein, von dem sie abhängen. Ein Deadlock kann auftreten, wenn der erste Stream ungelesen bleibt und den Empfänger daran hindert, Flusssteuerungskredit für den zweiten Stream zu erweitern. Um die Wahrscheinlichkeit von Deadlocks bei interdependenten Daten zu verringern, sollte der Sender sicherstellen, dass abhängige Daten nicht gesendet werden, bis die Daten, von denen sie abhängen, sowohl im Stream- als auch im Verbindungsebenen-Flusssteuerungskredit berücksichtigt wurden.
Einige Deadlock-Szenarien könnten gelöst werden, indem betroffene Streams mit STOP_SENDING oder RESET_STREAM abgebrochen werden. Das Abbrechen einiger Streams führt bei manchen Protokollen zur Beendigung der Verbindung.
4.5. Stream-Limit-Verpflichtungen (Stream Limit Commitments)
QUIC-Endpunkte sind dafür verantwortlich, das kumulative Limit von Streams zu kommunizieren, die sie ihrem Peer erlauben würden zu öffnen. Anfangslimits werden mit den Transportparametern initial_max_streams_bidi und initial_max_streams_uni beworben. Wenn Streams geöffnet und geschlossen werden, werden sie verbraucht und die kumulative Summe wird erhöht. Limits können mit dem MAX_STREAMS-Frame erhöht werden, aber es gibt keinen Mechanismus, Limits zu reduzieren. Sobald Stream-Limits erreicht sind, können keine weiteren Streams geöffnet werden, was Anwendungen, die QUIC nutzen, daran hindert, weiter fortzuschreiten. In diesem Stadium können Verbindungen über Leerlauf-Timeout oder explizites Schließen beendet werden; siehe Abschnitt 10.
Eine Anwendung, die QUIC nutzt und ein kumulatives Stream-Limit kommuniziert, könnte erfordern, dass die Verbindung geschlossen wird, bevor das Limit erreicht ist, z. B. um den Server für geplante Wartung anzuhalten. Das sofortige Schließen der Verbindung verursacht abruptes Schließen aktiv genutzter Streams. Je nachdem, wie eine Anwendung QUIC-Streams nutzt, könnte dies unerwünscht oder schädlich für Verhalten oder Leistung sein.
Eine gracefulere Schließtechnik besteht darin, das Senden von Erhöhungen der Stream-Limits zu stoppen und der Verbindung zu erlauben, sich natürlich zu beenden, sobald die verbleibenden Streams verbraucht sind. Die Zeitspanne, die dafür benötigt wird, hängt jedoch vom Peer ab, und eine unvorhersehbare Schließperiode könnte nicht zu Anwendungs- oder Betriebsanforderungen passen. Anwendungen, die QUIC nutzen, können mit offenen Stream-Limits konservativ sein, um die Verpflichtung und Unbestimmtheit zu verringern. Übermäßige Konservativität bei Stream-Limits beeinflusst jedoch die Stream-Parallelität. Das Ausbalancieren dieser Aspekte kann anwendungs- und bereitstellungsspezifisch sein.
Anstatt sich auf Stream-Limits zu verlassen, um abruptes Schließen zu vermeiden, kann der graceful-close-Mechanismus einer Anwendungsschicht verwendet werden, um die Absicht zu kommunizieren, die Verbindung zu einem zukünftigen Zeitpunkt explizit zu schließen. HTTP/3 stellt einen solchen Mechanismus mit dem GOAWAY-Frame bereit. In HTTP/3 stoppt ein Client, wenn er den GOAWAY-Frame empfängt, das Öffnen neuer Streams, selbst wenn das kumulative Stream-Limit es erlauben würde. Stattdessen würde der Client eine neue Verbindung erstellen, auf der weitere Streams geöffnet werden. Sobald alle Streams auf der alten Verbindung geschlossen sind, kann sie sicher durch Verbindungsende oder nach Ablauf des Leerlauf-Timeouts beendet werden (siehe Abschnitt 10).
5. Paketisierung und Latenz (Packetization and Latency)
QUIC legt eine Schnittstelle frei, die der Anwendung mehrere Streams bereitstellt; die Anwendung kann jedoch in der Regel nicht steuern, wie über diese Streams übertragene Daten in Frames abgebildet werden oder wie diese Frames zu Paketen gebündelt werden.
Standardmäßig versuchen viele Implementierungen, STREAM-Frames von einem oder mehreren Streams in jedes QUIC-Paket zu packen, um Bandbreitenverbrauch und Rechenkosten zu minimieren (siehe Abschnitt 13 von [QUIC]). Wenn nicht genug Daten verfügbar sind, um ein Paket zu füllen, könnte eine Implementierung kurz warten, um die Bandbreiteneffizienz statt der Latenz zu optimieren. Diese Verzögerung kann entweder vorkonfiguriert oder dynamisch basierend auf dem beobachteten Sendemuster der Anwendung angepasst werden.
Wenn die Anwendung geringe Latenz benötigt und nur kleine Datenblöcke zu senden hat, kann es wertvoll sein, QUIC anzuzeigen, dass alle Daten sofort gesendet werden sollten. Alternativ kann die Anwendung, wenn sie ein bestimmtes Sendemuster erwartet, QUIC auch eine vorgeschlagene Verzögerung dafür bereitstellen, wie lange vor dem Bündeln von Frames in ein Paket gewartet werden soll.
Ebenso hat eine Anwendung in der Regel keine Kontrolle über die Länge eines QUIC-Pakets auf dem Draht. QUIC stellt die Fähigkeit bereit, einen PADDING-Frame hinzuzufügen, um die Paketgröße beliebig zu erhöhen. Padding wird von QUIC verwendet, um sicherzustellen, dass der Pfad während des Handshakes Datagramme mindestens einer bestimmten Größe übertragen kann (siehe Abschnitte 8.1 und 14.1 von [QUIC]) und für die Pfadvalidierung nach Verbindungsmigration (siehe Abschnitt 8.2 von [QUIC]) sowie für Datagram Packetization Layer PMTU Discovery (DPLPMTUD) (siehe Abschnitt 14.3 von [QUIC]).
Padding kann auch von einer Anwendung verwendet werden, um das Auslaufen von Informationen über die gesendeten Daten zu verringern. Eine QUIC-Implementierung kann eine Schnittstelle freilegen, die einer Anwendungsschicht erlaubt, anzugeben, wie Padding angewendet werden soll.
6. Fehlerbehandlung (Error Handling)
QUIC empfiehlt, dass Endpunkte alle erkannten Fehler dem Peer signalisieren. Fehler können auf Transport- und Anwendungsschicht auftreten. Transportfehler, wie eine Protokollverletzung, betreffen die gesamte Verbindung. Anwendungen, die QUIC nutzen, können ihre eigene Fehlererkennung und -signalisierung definieren (siehe z. B. Abschnitt 8 von [QUIC-HTTP]). Anwendungsfehler können eine gesamte Verbindung oder einen einzelnen Stream betreffen.
QUIC definiert einen Fehlercoderaum, der für die Fehlerbehandlung auf der Transportschicht verwendet wird. QUIC ermutigt Endpunkte, den spezifischsten Code zu verwenden, obwohl jeder anwendbare Code erlaubt ist, einschließlich generischer Codes.
Anwendungen, die QUIC nutzen, definieren einen Fehlercoderaum, der von QUIC oder anderen Anwendungen unabhängig ist (siehe z. B. Abschnitt 8.1 von [QUIC-HTTP]). Die Werte in einem Anwendungsfehlercoderaum können über Verbindungs- und Stream-Ebenen-Fehler wiederverwendet werden.
Verbindungsfehler führen zur Verbindungsbeendigung. Sie werden mit einem CONNECTION_CLOSE-Frame signalisiert, der einen Fehlercode und ein reason-Feld enthält, das die Länge null haben kann. Verschiedene Typen von CONNECTION_CLOSE-Frames werden verwendet, um Transport- und Anwendungsfehler zu signalisieren.
Stream-Fehler führen zur Stream-Beendigung. Diese werden mit STOP_SENDING- oder RESET_STREAM-Frames signalisiert, die nur einen Fehlercode enthalten.
7. Effizienz der Bestätigungen (Acknowledgment Efficiency)
QUIC Version 1 ohne Erweiterungen verwendet eine Bestätigungsstrategie, die von TCP übernommen wurde (siehe Abschnitt 13.2 von [QUIC]). Das heißt, es wird empfohlen, dass jedes zweite Paket bestätigt wird. Die Erzeugung und Verarbeitung von QUIC-Bestätigungen verbraucht jedoch Ressourcen bei Sender und Empfänger. Bestätigungen verursachen auch Weiterleitungskosten und tragen zur Link-Auslastung bei, was die Leistung über manche Netztypen beeinträchtigen kann. Anwendungen könnten in der Lage sein, die Gesamtleistung zu verbessern, indem sie alternative Strategien verwenden, die die Bestätigungsrate senken. [QUIC-ACK-FREQUENCY] beschreibt eine Erweiterung zur Signalisierung der gewünschten Verzögerung von Bestätigungen und erörtert Anwendungsfälle sowie Auswirkungen auf Staukontrolle und Wiederherstellung.
8. Portauswahl und Entdeckung von Anwendungsendpunkten (Port Selection and Application Endpoint Discovery)
Im Allgemeinen dienen Portnummern zwei Zwecken: „erstens stellen sie einen Demultiplex-Bezeichner bereit, um Transport-Sitzungen zwischen demselben Endpunktpaar zu unterscheiden, und zweitens können sie auch das Anwendungsprotokoll und den zugehörigen Dienst identifizieren, mit dem Prozesse verbinden“ (Abschnitt 3 von [RFC6335]). Die Annahme, dass eine Anwendung im Netzwerk basierend auf der Portnummer identifiziert werden kann, ist heute weniger wahr aufgrund von Kapselung und Mechanismen für dynamische Portzuweisungen, wie in [RFC6335] angemerkt.
Da QUIC ein Allzweck-Transportprotokoll ist, gibt es keine Anforderungen, dass Server einen bestimmten UDP-Port für QUIC verwenden. Für eine Anwendung mit Fallback auf TCP, die noch keine alternative Abbildung auf UDP hat, ist es in der Regel angemessen, die dem bereits für die Anwendung registrierten TCP-Port entsprechende UDP-Portnummer zu registrieren (falls nötig) und zu verwenden. Beispielsweise ist der Standardport für HTTP/3 [QUIC-HTTP] UDP-Port 443, analog zu HTTP/1.1 oder HTTP/2 over TLS over TCP.
Angesichts der Verbreitung der Annahme in der Netzverwaltungspraxis, dass eine Portnummer eindeutig auf eine Anwendung abbildet, könnte die Nutzung von Ports, die nicht leicht auf einen registrierten Dienstnamen abgebildet werden können, zu Blockierung oder anderen Änderungen des Weiterleitungsverhaltens durch Netzwerkelemente wie Firewalls führen, die die Portnummer zur Anwendungsidentifikation verwenden.
Anwendungen könnten einen alternativen Endpunkt-Entdeckungsmechanismus definieren, um die Nutzung anderer Ports als des Standardports zu erlauben. Beispielsweise spezifiziert HTTP/3 (Abschnitte 3.2 und 3.3 von [QUIC-HTTP]) die Nutzung von HTTP Alternative Services [RFC7838], damit ein HTTP-Origin die Verfügbarkeit eines äquivalenten HTTP/3-Endpunkts auf einem bestimmten UDP-Port ankündigt, indem "h3" als Application-Layer Protocol Negotiation-(ALPN)-[RFC7301]-Token verwendet wird.
ALPN erlaubt Client und Server auszuhandeln, welches von mehreren Protokollen auf einer gegebenen Verbindung verwendet wird. Daher könnten mehrere Anwendungen auf einem einzelnen UDP-Port basierend auf dem angebotenen ALPN-Token unterstützt werden. Anwendungen, die QUIC nutzen, sind verpflichtet, ein ALPN-Token zur Verwendung im TLS-Handshake zu registrieren.
Da QUIC Version 1 die Definition eines vollständigen Versionsverhandlungsmechanismus aufgeschoben hat, verlangt HTTP/3 QUIC Version 1 und definiert das ALPN-Token ("h3") so, dass es nur auf diese Version zutrifft. Bisher wurde weder in HTTP/3 noch allgemein ein einzelner Ansatz zur Verwaltung der Nutzung verschiedener QUIC-Versionen ausgewählt. Anwendungsprotokolle, die QUIC nutzen, müssen berücksichtigen, wie das Protokoll verschiedene QUIC-Versionen verwalten wird. Entscheidungen für diese Protokolle könnten durch von anderen Protokollen wie HTTP/3 getroffene Wahlen informiert werden.
8.1. Quellportauswahl (Source Port Selection)
Einige UDP-Protokolle sind anfällig für Reflection-Angriffe, bei denen ein Angreifer Verkehr als Denial of Service an einen Dritten richten kann. Beispielsweise sind diese Quellports mit Anwendungen verbunden, die bekanntermaßen anfällig für Reflection-Angriffe sind, oft aufgrund von Serverfehlkonfiguration:
- Port 53 - DNS [RFC1034]
- Port 123 - NTP [RFC5905]
- Port 1900 - SSDP [SSDP]
- Port 5353 - mDNS [RFC6762]
- Port 11211 - memcache
Dienste könnten Quellports blockieren, die mit Protokollen verbunden sind, die bekanntermaßen anfällig für Reflection-Angriffe sind, um den Overhead der Verarbeitung großer Paketmengen zu vermeiden. Diese Praxis hat jedoch negative Auswirkungen auf Clients – nicht nur erfordert sie die Herstellung einer neuen Verbindung, sondern in manchen Fällen könnte sie den Client dazu bringen, QUIC für diesen Dienst für eine Zeitspanne zu vermeiden und auf ein Nicht-UDP-Protokoll herabzustufen (siehe Abschnitt 2).
Daher werden Client-Implementierungen ermutigt, die Nutzung von Quellports zu vermeiden, die mit Protokollen verbunden sind, die bekanntermaßen anfällig für Reflection-Angriffe sind. Beachten Sie, dass das Befolgen der allgemeinen Leitlinie für Client-Implementierungen in [RFC6335], ephemere Ports im Bereich 49152-65535 zu verwenden, den Effekt hat, diese Ports zu vermeiden. Beachten Sie, dass auch andere Quellports Reflection-Vektoren sein könnten.
9. Verbindungsmigration (Connection Migration)
QUIC unterstützt Verbindungsmigration durch den Client. Wenn sich die IP-Adresse des Clients ändert, kann ein QUIC-Endpunkt Pakete weiterhin einer bestehenden Transportverbindung zuordnen, indem er das Destination-Connection-ID-Feld (siehe Abschnitt 11) im QUIC-Header verwendet. Dies unterstützt Fälle, in denen sich Adressinformationen ändern, wie NAT-Rebinding, die beabsichtigte Änderung der lokalen Schnittstelle, das Ablaufen einer temporären IPv6-Adresse [RFC8981] oder die Angabe einer bevorzugten Adresse durch den Server (Abschnitt 9.6 von [QUIC]).
Die Verwendung einer Connection ID mit Länge ungleich null für den Server wird dringend empfohlen, wenn Clients hinter einem NAT sind oder sein könnten. Eine Connection ID mit Länge ungleich null wird auch dringend empfohlen, wenn aktive Migration unterstützt wird. Wenn eine Verbindung absichtlich auf einen neuen Pfad migriert wird, wird eine neue Connection ID verwendet, um Linkbarkeit durch Netzwerkbeobachter zu minimieren. Der andere QUIC-Endpunkt verwendet die Connection ID, um verschiedene Adressen mit derselben Verbindung und Entität zu verknüpfen, wenn eine Connection ID mit Länge ungleich null bereitgestellt wird.
Die Basisspezifikation von QUIC Version 1 unterstützt nur die Nutzung eines einzelnen Netzwerkpfads gleichzeitig, was Failover-Anwendungsfälle ermöglicht. Pfadvalidierung ist erforderlich, damit Endpunkte Pfade vor der Nutzung validieren, um Address-Spoofing-Angriffe zu vermeiden. Die Pfadvalidierung dauert mindestens ein RTT, und die Staukontrolle wird nach Pfadmigration ebenfalls zurückgesetzt. Daher hat Migration in der Regel eine Leistungsauswirkung.
QUIC-Probing-Pakete, die gleichzeitig auf mehreren Pfaden gesendet werden können, werden verwendet, um Adressvalidierung durchzuführen sowie Pfadeigenschaften zu messen. Probing-Pakete können keine Anwendungsdaten tragen, enthalten aber wahrscheinlich Padding-Frames. Endpunkte können Informationen über deren Empfang als Eingabe in die Staukontrolle für diesen Pfad verwenden. Anwendungen könnten aus dem Probing gelernte Informationen nutzen, um eine Entscheidung zum Pfadwechsel zu informieren.
Nur der Client kann in Version 1 von QUIC aktiv migrieren. Server können jedoch während des Handshakes anzeigen, dass sie es vorziehen, die Verbindung nach dem Handshake an eine andere Adresse zu übertragen. Dies könnte beispielsweise verwendet werden, um von einer Adresse, die von mehreren Servern geteilt wird, zu einer Adresse zu wechseln, die der Serverinstanz eindeutig ist. Der Server kann eine IPv4- und eine IPv6-Adresse in einem Transportparameter während des TLS-Handshakes bereitstellen, und der Client kann zwischen den beiden wählen, wenn beide bereitgestellt werden. Siehe Abschnitt 9.6 von [QUIC].
10. Verbindungsbeendigung (Connection Termination)
QUIC-Verbindungen werden auf eine von drei Arten beendet: implizites Leerlauf-Timeout, explizites sofortiges Schließen oder explizites zustandsloses Zurücksetzen.
QUIC stellt keinen Mechanismus für graceful Verbindungsbeendigung bereit; Anwendungen, die QUIC nutzen, können ihren eigenen graceful-Beendigungsprozess definieren (siehe z. B. Abschnitt 5.2 von [QUIC-HTTP]).
Das QUIC-Leerlauf-Timeout wird über Transportparameter aktiviert. Client und Server kündigen eine Timeout-Periode an, und der wirksame Wert für die Verbindung ist das Minimum der beiden Werte. Nach Ablauf der Timeout-Periode wird die Verbindung stillschweigend geschlossen. Eine Anwendung sollte daher in der Lage sein, ihren eigenen Maximalwert zu konfigurieren und Zugriff auf den berechneten Minimalwert für diese Verbindung zu haben. Eine Anwendung kann das maximale Leerlauf-Timeout für neue Verbindungen basierend auf der Anzahl offener oder erwarteter Verbindungen anpassen, da kürzere Timeout-Werte Ressourcen schneller freigeben können.
Auf Streams oder in Datagrammen ausgetauschte Anwendungsdaten verschieben das QUIC-Leerlauf-Timeout. Anwendungen, die eigene Keep-Alive-Mechanismen bereitstellen, halten daher eine QUIC-Verbindung am Leben. Anwendungen, die kein eigenes Keep-Alive bereitstellen, können Mechanismen der Transportschicht verwenden (siehe Abschnitt 10.1.2 von [QUIC] und Abschnitt 3.2). Die Schnittstellen von QUIC-Implementierungen zur Steuerung solchen Transportverhaltens können jedoch variieren und die Robustheit solcher Ansätze beeinflussen.
Ein sofortiges Schließen wird durch einen CONNECTION_CLOSE-Frame signalisiert (siehe Abschnitt 6). Sofortiges Schließen führt dazu, dass alle Streams sofort geschlossen werden, was Anwendungen beeinträchtigen kann; siehe Abschnitt 4.5.
Ein zustandsloses Zurücksetzen ist eine Option als letztes Mittel für einen Endpunkt, der keinen Zugriff auf Verbindungszustand hat. Der Empfang eines zustandslosen Zurücksetzens ist ein Hinweis auf einen nicht behebbaren Fehler, der sich von Verbindungsfehlern dadurch unterscheidet, dass keine Informationen der Anwendungsschicht bereitgestellt werden.
11. Informationsoffenlegung und Connection ID (Information Exposure and the Connection ID)
QUIC legt dem Netzwerk einige Informationen im unverschlüsselten Teil des Headers offen, entweder bevor der Verschlüsselungskontext hergestellt ist oder weil die Informationen vom Netzwerk genutzt werden sollen. Weitere Informationen zur Verwaltbarkeit von QUIC finden sich in [QUIC-MANAGEABILITY]. QUIC hat einen langen Header, der einige zusätzliche Informationen freilegt (die Version und die Source Connection ID), während der kurze Header nur die Destination Connection ID freilegt. In QUIC Version 1 wird der lange Header während der Verbindungsherstellung verwendet, während der kurze Header für die Datenübertragung in einer hergestellten Verbindung verwendet wird.
Die Connection ID kann die Länge null haben. Connection IDs der Länge null können an jedem Endpunkt einzeln und auf jedem Paket gewählt werden, außer den ersten Paketen, die Clients während der Verbindungsherstellung senden.
Ein Endpunkt, der eine Connection ID der Länge null wählt, empfängt Pakete mit einer Destination Connection ID der Länge null. Der Endpunkt muss andere Informationen verwenden, wie Quell- und Ziel-IP-Adresse und Portnummer, um zu identifizieren, auf welche Verbindung verwiesen wird. Dies könnte bedeuten, dass der Endpunkt Datagramme nicht erfolgreich Verbindungen zuordnen kann, wenn sich diese Werte ändern, wodurch die Verbindung faktisch unfähig wird, NAT-Rebinding zu überstehen oder auf einen neuen Pfad zu migrieren.
11.1. Servergenerierte Connection ID (Server-Generated Connection ID)
QUIC unterstützt eine servergenerierte Connection ID, die während der Verbindungsherstellung an den Client übertragen wird (siehe Abschnitt 7.2 von [QUIC]). Server hinter Load Balancern müssen möglicherweise die Connection ID während des Handshakes ändern und die Identität des Servers oder Informationen über seinen Load-Balancing-Pool kodieren, um zustandsloses Load Balancing zu unterstützen.
Serverbereitstellungen mit Load Balancern und anderer Routing-Infrastruktur müssen sicherstellen, dass diese Infrastruktur Pakete konsistent an die Serverinstanz mit dem Verbindungszustand weiterleitet, selbst wenn sich Adressen, Ports oder Connection IDs ändern. Dies könnte Koordination zwischen Servern und Infrastruktur erfordern. Eine Methode, dies zu erreichen, besteht darin, Routing-Informationen in die Connection ID zu kodieren. Für ein Beispiel dieser Technik siehe [QUIC-LB].
11.2. Milderung von Timing-Linkbarkeit durch Connection-ID-Migration (Mitigating Timing Linkability with Connection ID Migration)
Wenn QUIC-Endpunkte keine frischen Connection IDs ausgeben, können Clients die Linkbarkeit von Adressmigration nicht durch deren Nutzung reduzieren. Das Wählen von Werten, die für einen externen Beobachter nicht verknüpfbar sind, stellt sicher, dass Aktivität auf verschiedenen Pfaden nicht trivial über die Connection ID korreliert werden kann.
Während hinreichend robuste Connection-ID-Erzeugungsschemata Linkbarkeitsprobleme mildern, bieten sie keinen vollständigen Schutz. Die Analyse der Lebensdauern von 6-Tupeln (Quell- und Zieladressen sowie die migrierte Connection ID) kann diese Verknüpfungen dennoch freilegen.
In dem Fall, dass Verbindungsmigration in einem Serverpool selten ist, ist es trivial für einen Beobachter, zwei Connection IDs zuzuordnen. Umgekehrt kann selbst eine freigelegte Server-Abbildung unzureichende Information sein, wenn jeder Server mehrere gleichzeitige Migrationen handhabt.
Die effizientesten Milderungen für diese Angriffe erfolgen durch Netzwerkdesign und/oder betriebliche Praktiken, indem eine Load-Balancing-Architektur verwendet wird, die mehr Flüsse auf eine einzelne serverseitige Adresse lädt, indem das Timing von Migrationen koordiniert wird, um die Anzahl gleichzeitiger Migrationen zu einem gegebenen Zeitpunkt zu erhöhen, oder durch andere Mittel.
11.3. Nutzung von Server-Retry zur Umleitung (Using Server Retry for Redirection)
QUIC stellt ein Retry-Paket bereit, das von einem Server als Antwort auf das Client-Initial-Paket gesendet werden kann. Der Server kann in diesem Paket eine neue Connection ID wählen, und der Client wird erneut versuchen, indem er ein weiteres Client-Initial-Paket mit der vom Server gewählten Connection ID sendet. Dieser Mechanismus kann verwendet werden, um eine Verbindung an einen anderen Server umzuleiten, z. B. aus Leistungsgründen oder wenn Server in einem Serverpool schrittweise aktualisiert werden und daher verschiedene QUIC-Versionen unterstützen können.
In diesem Fall wird angenommen, dass alle zu einem bestimmten Pool gehörenden Server in Zusammenarbeit mit Load Balancern bedient werden, die den Verkehr basierend auf der Connection ID weiterleiten. Ein Server kann die Connection ID im Retry-Paket so wählen, dass der Load Balancer das nächste Initial-Paket an einen anderen Server in diesem Pool umleitet. Alternativ kann der Load Balancer direkt ein Retry-Offload anbieten, wie weiter in [QUIC-RETRY] beschrieben.
Der in Abschnitt 4 von [RFC5077] beschriebene Ansatz zur Konstruktion von TLS-Wiederaufnahme-Tickets liefert ein Beispiel, das auch auf Validierungstoken angewendet werden kann. Die Verwendung modernerer kryptografischer Algorithmen wird jedoch dringend empfohlen.
12. Quality of Service (QoS) und Diffserv Code Point (DSCP)
QUIC, wie in [QUIC] definiert, hat einen einzelnen Staucontroller und Recovery-Handler. Dieses Design nimmt an, dass alle Pakete einer QUIC-Verbindung – oder zumindest mit demselben 5-Tupel {Zieladresse, Quelladresse, Protokoll, Zielport, Quellport} – die denselben Diffserv Code Point (DSCP) [RFC2475] haben, ähnliche Netzwerkbehandlung erhalten, da Feedback über Verlust oder Verzögerung jedes Pakets als Eingabe in den Staucontroller verwendet wird. Daher sollten zur selben Verbindung gehörende Pakete einen einzelnen DSCP verwenden. Abschnitt 5.1 von [RFC7657] liefert eine Erörterung der Diffserv-Interaktionen mit Datagramm-Transportprotokollen [RFC7657] (in dieser Hinsicht ähneln die Interaktionen mit QUIC denen des Stream Control Transmission Protocol (SCTP)).
Beim Multiplexen mehrerer Flüsse über eine einzelne QUIC-Verbindung sollte der gewählte DSCP-Wert derjenige sein, der mit der höchsten für alle multiplexierten Flüsse angeforderten Priorität verbunden ist.
Wenn differenzierte Netzwerkbehandlung gewünscht wird, z. B. durch die Nutzung verschiedener DSCPs, können mehrere QUIC-Verbindungen zum selben Server verwendet werden. Im Allgemeinen wird empfohlen, die Anzahl der QUIC-Verbindungen zum selben Server zu minimieren, um erhöhten Overhead und – noch wichtiger – konkurrierende Staukontrolle zu vermeiden.
Wie bei anderen Nutzungen von Diffserv könnte, wenn ein Paket in ein Netzwerksegment eintritt, das den DSCP-Wert nicht unterstützt, dies dazu führen, dass die Verbindung nicht die erwartete Netzwerkbehandlung erhält. Der DSCP-Wert in diesem Paket könnte auch neu markiert werden, während das Paket den Netzwerkpfad entlang reist, wodurch die angeforderte Behandlung geändert wird.
13. Nutzung von Versionen und kryptografischem Handshake (Use of Versions and Cryptographic Handshake)
Versionierung in QUIC kann das Verhalten des Protokolls vollständig ändern, außer der Bedeutung einiger Header-Felder, die als invariant erklärt wurden [QUIC-INVARIANTS]. Eine Version von QUIC mit einer höheren Versionsnummer wird nicht notwendigerweise einen besseren Dienst bereitstellen, sondern könnte einfach einen anderen Funktionsumfang bereitstellen. Daher muss eine Anwendung in der Lage sein auszuwählen, welche Versionen von QUIC sie verwenden möchte.
Eine neue Version könnte ein anderes Verschlüsselungsschema als TLS 1.3 oder höher verwenden. [QUIC] spezifiziert Anforderungen an den kryptografischen Handshake, wie er derzeit durch TLS 1.3 realisiert und in einer separaten Spezifikation [QUIC-TLS] beschrieben wird. Diese Aufteilung wird durchgeführt, um leichte Versionierung mit verschiedenen kryptografischen Handshakes zu ermöglichen.
Das in [QUIC] eingerichtete Register „QUIC Versions“ erlaubt vorläufige Registrierungen für Experimente. Die Registrierung, auch experimenteller Versionen, ist wichtig, um Kollisionen zu vermeiden. Experimentelle Versionen sollten nicht langfristig verwendet oder als permanent registriert werden, um das Risiko der Fingerabdruckbildung basierend auf der Versionsnummer zu minimieren.
14. Ermöglichung der Bereitstellung neuer Versionen (Enabling Deployment of New Versions)
QUIC Version 1 spezifiziert in der Basisspezifikation keinen Versionsverhandlungsmechanismus, aber [QUIC-VERSION-NEGOTIATION] schlägt eine Erweiterung vor, die kompatible Versionsverhandlung bereitstellt.
Dieser Ansatz verwendet einen dreistufigen Bereitstellungsmechanismus, der progressive Einführung und Experimente mit mehreren Versionen über eine große Serverbereitstellung hinweg ermöglicht. Bei diesem Ansatz müssen alle Server in der Bereitstellung Verbindungen mit einer neuen Version akzeptieren (Stufe 1), bevor irgendein Server sie bewirbt (Stufe 2), und die Authentifizierung der neuen Version (Stufe 3) erfolgt erst, nachdem die Bewerbung dieser Version vollständig bereitgestellt ist.
Siehe Abschnitt 5 von [QUIC-VERSION-NEGOTIATION] für Details.
15. Unzuverlässiger Datagrammdienst über QUIC (Unreliable Datagram Service over QUIC)
[RFC9221] spezifiziert eine QUIC-Erweiterung, um das Senden und Empfangen unzuverlässiger Datagramme über QUIC zu ermöglichen. Im Gegensatz zum direkten Betrieb über UDP müssen Anwendungen, die den QUIC-Datagrammdienst nutzen, keine eigene Staukontrolle implementieren, gemäß [RFC8085], da QUIC-Datagramme staugesteuert sind.
QUIC-Datagramme sind nicht flussgesteuert, und daher können Datenblöcke verworfen werden, wenn der Empfänger überlastet ist. Während der zuverlässige Übertragungsdienst von QUIC eine stream-basierte Schnittstelle bereitstellt, um Daten geordnet über mehrere QUIC-Streams zu senden und zu empfangen, hat der Datagrammdienst eine ungeordnete nachrichtenbasierte Schnittstelle. Bei Bedarf kann ein Framing der Anwendungsschicht darüber verwendet werden, um getrennte Flüsse unzuverlässiger Datagramme auf einer QUIC-Verbindung zu multiplexen.
16. IANA-Erwägungen (IANA Considerations)
Dieses Dokument hat keine Aktionen für IANA; beachten Sie jedoch, dass Abschnitt 8 empfiehlt, dass eine Anwendung, die bereits einen TCP-Port registriert hat, aber QUIC als Transport spezifizieren möchte, einen UDP-Port analog zu ihrer bestehenden TCP-Registrierung registrieren sollte.
17. Sicherheitserwägungen (Security Considerations)
Siehe die Sicherheitserwägungen in [QUIC] und [QUIC-TLS]; die Sicherheitserwägungen für das zugrunde liegende Transportprotokoll sind für Anwendungen relevant, die QUIC nutzen. Erwägungen zu Linkbarkeit, Replay-Angriffen und Zufälligkeit, die in [QUIC-TLS] erörtert werden, sollten beim Bereitstellen und Nutzen von QUIC berücksichtigt werden.
Weiterhin legt die Migration zu einer neuen Adresse eine Verknüpfung zwischen Client-Adressen dem Server offen und kann diese Verknüpfung auch dem Pfad offenlegen, wenn die Connection ID nicht geändert werden kann oder Flüsse anderweitig korreliert werden können. Wenn Migration unterstützt wird, muss dies im Hinblick auf die Privatsphäre der Benutzer berücksichtigt werden.
Anwendungsentwickler sollten beachten, dass jeder Fallback, den sie verwenden, wenn QUIC aufgrund von Netzwerkblockierung von UDP nicht genutzt werden kann, dieselben Sicherheitseigenschaften wie QUIC garantieren sollte. Wenn dies nicht möglich ist, sollte die Verbindung fehlschlagen, damit die Anwendung den Fallback auf eine weniger sichere Alternative explizit handhaben kann. Siehe Abschnitt 2.
Weiterhin stellt [QUIC-HTTP] HTTP-spezifische Sicherheitserwägungen bereit. Erörterungen wie zu Cross-Protocol-Angriffen, Verkehrsanalyse und Padding oder Migration könnten jedoch auch für andere Anwendungen relevant sein, die QUIC nutzen.
18. Referenzen (References)
18.1. Normative Referenzen (Normative References)
[QUIC] Iyengar, J., Ed. and M. Thomson, Ed., "QUIC: A UDP-Based Multiplexed and Secure Transport", RFC 9000, DOI 10.17487/RFC9000, May 2021, https://www.rfc-editor.org/info/rfc9000.
[QUIC-INVARIANTS] Thomson, M., "Version-Independent Properties of QUIC", RFC 8999, DOI 10.17487/RFC8999, May 2021, https://www.rfc-editor.org/info/rfc8999.
[QUIC-TLS] Thomson, M., Ed. and S. Turner, Ed., "Using TLS to Secure QUIC", RFC 9001, DOI 10.17487/RFC9001, May 2021, https://www.rfc-editor.org/info/rfc9001.
18.2. Informative Referenzen (Informative References)
[Edeline16] Edeline, K., Kühlewind, M., Trammell, B., Aben, E., and B. Donnet, "Using UDP for Internet Transport Evolution", DOI 10.48550/arXiv.1612.07816, 22 December 2016, https://arxiv.org/abs/1612.07816.
[Hatonen10] Hätönen, S., Nyrhinen, A., Eggert, L., Strowes, S., Sarolahti, P., and M. Kojo, "An Experimental Study of Home Gateway Characteristics", Proc. ACM IMC 2010, November 2010, <https://conferences.sigcomm.org/imc/2010/papers/ p260.pdf>.
[HTTP-REPLAY] Thomson, M., Nottingham, M., and W. Tarreau, "Using Early Data in HTTP", RFC 8470, DOI 10.17487/RFC8470, September 2018, https://www.rfc-editor.org/info/rfc8470.
[PaaschNanog] Paasch, C., "Network support for TCP Fast Open", NANOG 67 Presentation, 13 June 2016, <https://www.nanog.org/sites/default/files/ Paasch_Network_Support.pdf>.
[QUIC-ACK-FREQUENCY] Iyengar, J. and I. Swett, "QUIC Acknowledgement Frequency", Work in Progress, Internet-Draft, draft-ietf- quic-ack-frequency-02, 11 July 2022, <https://datatracker.ietf.org/doc/html/draft-ietf-quic- ack-frequency-02>.
[QUIC-HTTP] Bishop, M., Ed., "HTTP/3", RFC 9114, DOI 10.17487/RFC9114, June 2022, https://www.rfc-editor.org/info/rfc9114.
[QUIC-LB] Duke, M., Banks, N., and C. Huitema, "QUIC-LB: Generating Routable QUIC Connection IDs", Work in Progress, Internet- Draft, draft-ietf-quic-load-balancers-14, 11 July 2022, <https://datatracker.ietf.org/doc/html/draft-ietf-quic- load-balancers-14>.
[QUIC-MANAGEABILITY] Kühlewind, M. and B. Trammell, "Manageability of the QUIC Transport Protocol", RFC 9312, DOI 10.17487/RFC9312, September 2022, https://www.rfc-editor.org/info/rfc9312.
[QUIC-RETRY] Duke, M. and N. Banks, "QUIC Retry Offload", Work in Progress, Internet-Draft, draft-ietf-quic-retry-offload- 00, 25 May 2022, <https://datatracker.ietf.org/doc/html/ draft-ietf-quic-retry-offload-00>.
[QUIC-VERSION-NEGOTIATION] Schinazi, D. and E. Rescorla, "Compatible Version Negotiation for QUIC", Work in Progress, Internet-Draft, draft-ietf-quic-version-negotiation-10, 27 September 2022, <https://datatracker.ietf.org/doc/html/draft-ietf-quic- version-negotiation-10>.
[RFC1034] Mockapetris, P., "Domain names - concepts and facilities", STD 13, RFC 1034, DOI 10.17487/RFC1034, November 1987, https://www.rfc-editor.org/info/rfc1034.
[RFC2475] Blake, S., Black, D., Carlson, M., Davies, E., Wang, Z., and W. Weiss, "An Architecture for Differentiated Services", RFC 2475, DOI 10.17487/RFC2475, December 1998, https://www.rfc-editor.org/info/rfc2475.
[RFC5077] Salowey, J., Zhou, H., Eronen, P., and H. Tschofenig, "Transport Layer Security (TLS) Session Resumption without Server-Side State", RFC 5077, DOI 10.17487/RFC5077, January 2008, https://www.rfc-editor.org/info/rfc5077.
[RFC5382] Guha, S., Ed., Biswas, K., Ford, B., Sivakumar, S., and P. Srisuresh, "NAT Behavioral Requirements for TCP", BCP 142, RFC 5382, DOI 10.17487/RFC5382, October 2008, https://www.rfc-editor.org/info/rfc5382.
[RFC5905] Mills, D., Martin, J., Ed., Burbank, J., and W. Kasch, "Network Time Protocol Version 4: Protocol and Algorithms Specification", RFC 5905, DOI 10.17487/RFC5905, June 2010, https://www.rfc-editor.org/info/rfc5905.
[RFC6335] Cotton, M., Eggert, L., Touch, J., Westerlund, M., and S. Cheshire, "Internet Assigned Numbers Authority (IANA) Procedures for the Management of the Service Name and Transport Protocol Port Number Registry", BCP 165, RFC 6335, DOI 10.17487/RFC6335, August 2011, https://www.rfc-editor.org/info/rfc6335.
[RFC6762] Cheshire, S. and M. Krochmal, "Multicast DNS", RFC 6762, DOI 10.17487/RFC6762, February 2013, https://www.rfc-editor.org/info/rfc6762.
[RFC7301] Friedl, S., Popov, A., Langley, A., and E. Stephan, "Transport Layer Security (TLS) Application-Layer Protocol Negotiation Extension", RFC 7301, DOI 10.17487/RFC7301, July 2014, https://www.rfc-editor.org/info/rfc7301.
[RFC7413] Cheng, Y., Chu, J., Radhakrishnan, S., and A. Jain, "TCP Fast Open", RFC 7413, DOI 10.17487/RFC7413, December 2014, https://www.rfc-editor.org/info/rfc7413.
[RFC7657] Black, D., Ed. and P. Jones, "Differentiated Services (Diffserv) and Real-Time Communication", RFC 7657, DOI 10.17487/RFC7657, November 2015, https://www.rfc-editor.org/info/rfc7657.
[RFC7838] Nottingham, M., McManus, P., and J. Reschke, "HTTP Alternative Services", RFC 7838, DOI 10.17487/RFC7838, April 2016, https://www.rfc-editor.org/info/rfc7838.
[RFC8085] Eggert, L., Fairhurst, G., and G. Shepherd, "UDP Usage Guidelines", BCP 145, RFC 8085, DOI 10.17487/RFC8085, March 2017, https://www.rfc-editor.org/info/rfc8085.
[RFC8981] Gont, F., Krishnan, S., Narten, T., and R. Draves, "Temporary Address Extensions for Stateless Address Autoconfiguration in IPv6", RFC 8981, DOI 10.17487/RFC8981, February 2021, https://www.rfc-editor.org/info/rfc8981.
[RFC9218] Oku, K. and L. Pardue, "Extensible Prioritization Scheme for HTTP", RFC 9218, DOI 10.17487/RFC9218, June 2022, https://www.rfc-editor.org/info/rfc9218.
[RFC9221] Pauly, T., Kinnear, E., and D. Schinazi, "An Unreliable Datagram Extension to QUIC", RFC 9221, DOI 10.17487/RFC9221, March 2022, https://www.rfc-editor.org/info/rfc9221.
[SSDP] Donoho, A., Roe, B., Bodlaender, M., Gildred, J., Messer, A., Kim, Y., Fairman, B., and J. Tourzan, "UPnP Device Architecture 2.0", 17 April 2020, <https://openconnectivity.org/upnp-specs/UPnP-arch- DeviceArchitecture-v2.0-20200417.pdf>.
[Swett16] Swett, I., "QUIC Deployment Experience @Google", IETF96 QUIC BoF Presentation, 20 July 2016, <https://www.ietf.org/proceedings/96/slides/slides-96- quic-3.pdf>.
[TAPS-ARCH] Pauly, T., Trammell, B., Brunstrom, A., Fairhurst, G., and C. Perkins, "An Architecture for Transport Services", Work in Progress, Internet-Draft, draft-ietf-taps-arch-14, 27 September 2022, <https://datatracker.ietf.org/doc/html/ draft-ietf-taps-arch-14>.
[TLS13] Rescorla, E., "The Transport Layer Security (TLS) Protocol Version 1.3", RFC 8446, DOI 10.17487/RFC8446, August 2018, https://www.rfc-editor.org/info/rfc8446.
[Trammell16] Trammell, B. and M. Kühlewind, "Internet Path Transparency Measurements using RIPE Atlas", RIPE 72 MAT Presentation, 25 May 2016, <https://ripe72.ripe.net/wp-content/uploads/ presentations/86-atlas-udpdiff.pdf>.
Danksagungen (Acknowledgments)
Besonderer Dank gilt den Last-Call-Gutachtern Chris Lonvick und Ines Robles.
Diese Arbeit wurde teilweise von der Europäischen Kommission im Rahmen der Horizon-2020-Fördervereinbarung Nr. 688421 Measurement and Architecture for a Middleboxed Internet (MAMI) und vom Schweizerischen Staatssekretariat für Bildung, Forschung und Innovation unter Vertrag Nr. 15.0268 unterstützt. Diese Unterstützung impliziert keine Billigung.
Mitwirkende (Contributors)
Die folgenden Personen haben wesentlichen Text oder Feedback zu diesem Dokument beigetragen:
Gorry Fairhurst, Ian Swett, Igor Lubashev, Lucas Pardue, Mike Bishop, Mark Nottingham, Martin Duke, Martin Thomson, Sean Turner, Tommy Pauly
Adressen der Autoren (Authors' Addresses)
Mirja Kühlewind
Ericsson
Email: [email protected]
Brian Trammell
Google Switzerland GmbH
Gustav-Gull-Platz 1
CH-8004 Zurich
Switzerland
Email: [email protected]