QUIC ist der UDP-basierte, mit TLS 1.3 verschlüsselte, multiplexte Transport, der in RFC 9000 definiert ist, und der Transport, auf dem HTTP/3 läuft.
QUIC ist ein Allzweck-Transportprotokoll, das in drei Kerndokumenten spezifiziert ist:
| RFC | Title | Was es definiert |
|---|---|---|
| RFC 9000 | QUIC: A UDP-Based Multiplexed and Secure Transport | Der Transport selbst: Pakete, Frames, Streams, Connection-IDs, Flusssteuerung, Verbindungslebenszyklus und Migration. |
| RFC 9001 | TLS zur Absicherung von QUIC verwenden | Wie TLS 1.3 in den Handshake eingebettet ist, der Key Schedule, der Paketschutz und der Header-Schutz. |
| RFC 9002 | QUIC-Verlusterkennung und Überlastungssteuerung | Bestätigungen, RTT-Schätzung, Verlusterkennung, Probe-Timeouts und der Congestion-Controller. |
QUIC wurde entworfen, um Probleme zu beheben, die in TCP plus TLS struktureller Natur sind und die sich nicht beheben lassen, ohne den Transport selbst zu ändern.
Diese Bibliothek enthält zwei QUIC-Engines. Sie werden durch die Aufzählung TsgcQUICMode dargestellt, die in sgcSSL_QUIC.pas deklariert ist:
TsgcQUICMode = (qmCustom, qmBuiltin);
Die Engine wird nicht direkt gesetzt. Sie folgt dem TLS-IOHandler der QUIC-Optionen (SSLQUICOptions beim QUIC-Client, TLSOptions beim HTTP/3-Client, QUICOptions.SSLOptions bei den Servern):
iohOpenSSL, der Standard: Die Engine wird erkannt, wenn OpenSSL geladen wird. Wenn OpenSSL den integrierten QUIC-Stack exportiert (OSSL_QUIC_client_method, OpenSSL 3.5 oder neuer), wird qmBuiltin verwendet. Andernfalls wird, wenn es die OpenSSL-3.5-QUIC-TLS-API exportiert (SSL_set_quic_tls_cbs), die sgc-Engine qmCustom als Fallback verwendet. IsOpenSSL_QUIC_Available und IsOpenSSL_QUIC_TLS_Available, deklariert in sgcIdSSLOpenSSLHeaders, melden diese beiden APIs. Ist keine von beiden verfügbar, etwa bei einem quictls-Build, löst die Komponente eine Ausnahme aus, die besagt, dass QUIC nicht verfügbar ist.iohNativeTLS: Es wird immer qmCustom verwendet, und der TLS-1.3-Handshake läuft auf der nativen TLS-Engine des sgcCrypto-Packs. Session-Tickets, Wiederaufnahme und 0-RTT funktionieren wie bei OpenSSL.Mit den mit der Bibliothek ausgelieferten OpenSSL-Binärdateien erhalten Sie qmBuiltin. Die Server melden die Engine, mit der sie gestartet wurden, in der schreibgeschützten Eigenschaft QUICMode.
Mit iohNativeTLS schützt die sgc-Engine Pakete nativ, ohne jedes Define: Paket- und Header-Schutz (AES-128-GCM, AES-256-GCM, ChaCha20-Poly1305), Schlüsselableitung, Schlüsselaktualisierung und das Retry-Integritätstag laufen auf sgcCrypto statt auf OpenSSL, pro Verbindung. Zusammen mit dem nativen TLS-1.3-Handshake laufen QUIC und HTTP/3 vollständig ohne OpenSSL, siehe SSL ohne OpenSSL. Mit iohOpenSSL folgt der Paketschutz sgcCryptoBackend (oder dem Define SGC_NATIVE_CRYPTO).
Die folgende Tabelle spiegelt wider, was der Code tatsächlich tut, nicht wozu QUIC prinzipiell in der Lage ist.
qmBuiltin | qmCustom | |
|---|---|---|
| Transport-Implementierung | Natives QUIC von OpenSSL 3.5+. Die Bibliothek steuert es über OSSL_QUIC_client_method, OSSL_QUIC_server_method, SSL_new_listener und SSL_accept_connection. | Pascal-QUIC-Stack innerhalb der Bibliothek (die sgcQUIC_*-Units: Pakete, Frames, Überlastkontrolle, Flusssteuerung), wobei der TLS 1.3-Handshake über die OpenSSL-3.5-QUIC-TLS-API oder die native TLS-Engine abgewickelt wird. |
| Ausgewählt, wenn | IOHandler = iohOpenSSL und OpenSSL exportiert den integrierten QUIC-Stack. Das ist der Standard bei mainline OpenSSL 3.5+. | IOHandler = iohNativeTLS, oder OpenSSL exportiert die QUIC-TLS-API, aber nicht den integrierten QUIC-Stack. |
| Verwendet von TsgcQUICClient und TsgcHTTP3Client | Ja | Ja |
| Verwendet von TsgcQUICServer und TsgcHTTP3Server | Ja | Ja. Ein leeres Host lauscht dual-stack, auf IPv4 und IPv6, wie bei der integrierten Engine. |
| Mehrere Streams pro Verbindung über die Komponenten-API | Ja. OpenStream wird auf SSL_new_stream abgebildet, und vom Peer geöffnete Streams können eingesammelt werden. | Ja. OpenStream, WriteStreamData und ConcludeStream funktionieren mit Flusssteuerung und erneuter Übertragung je Stream. Der HTTP/3-Client öffnet seine Control- und QPACK-Streams und verwendet für spätere Anfragen dieselbe QUIC-Verbindung erneut. |
| WebTransport | Ja. WebTransport benötigt mehrere Streams pro Verbindung, daher benötigt es diese Engine. | Nein. |
Kurz gesagt: qmBuiltin ist die Standard-Engine bei mainline OpenSSL 3.5+. qmCustom ist der Fallback, wenn der integrierte Stack nicht verfügbar ist, und die Engine, die bei iohNativeTLS verwendet wird.
Eine QUIC-Verbindung ist ein Container für Streams. Ein Stream ist eine geordnete, flussgesteuerte Folge von Bytes, und Streams sind voneinander unabhängig, was das Head-of-Line-Blocking auf Transportebene beseitigt. Streams gibt es in zwei Ausprägungen:
Jeder Stream hat eine 62-Bit-Stream-ID. Die beiden niedrigstwertigen Bits der ID kodieren, wer den Stream geöffnet hat und ob er bidirektional ist, und genau dieses Layout bildet die Bibliothek in TsgcQUICStreamTypes (sgcQUIC_Types.pas) ab:
| Untere 2 Bits | Aufzählungswert | Bedeutung |
|---|---|---|
0x00 | qcstClientBidirectional | Client-initiiert, bidirektional |
0x01 | qcstServerBidirectional | Server-initiiert, bidirektional |
0x02 | qcstClientUnidirectional | Client-initiiert, unidirektional |
0x03 | qcstServerUnidirectional | Vom Server initiiert, unidirektional |
Stream-IDs werden innerhalb jeder dieser vier Kategorien in aufsteigender Reihenfolge vergeben, und wie viele Streams ein Peer öffnen darf, wird durch die während des Handshakes ausgetauschten Transportparameter begrenzt. Die QUIC-Komponenten stellen von Haus aus einen einzigen Standard-Stream bereit. Zusätzliche Streams müssen über EnableMultiStream und OpenStream aktiviert werden, und wie oben erwähnt erfordern sie die builtin-Engine.
| Komponente | Beschreibung |
|---|---|
| TsgcQUICClient | Low-Level-QUIC-Client. Öffnet eine QUIC-Verbindung zu einem Server und tauscht rohe Anwendungsbytes über QUIC-Streams aus. Verwenden Sie ihn, wenn Sie QUIC als Transport ohne HTTP-Semantik nutzen möchten. |
| TsgcQUICServer | Low-Level-QUIC-Server. Lauscht auf QUIC-Verbindungen und tauscht rohe Anwendungsbytes über QUIC-Streams aus. |
Die HTTP/3-Komponenten bauen auf dieser Schicht auf. TsgcHTTP3Server leitet sich direkt von TsgcQUICServer ab und ergänzt das HTTP/3-Framing, die Einstellungen und die Anfrageverarbeitung auf den QUIC-Verbindungen, die sein Vorfahr annimmt. TsgcHTTP3Client ist eine eigenständige Komponente und kein Nachfahre von TsgcQUICClient, steuert aber denselben zugrunde liegenden QUIC-Transport. Siehe HTTP/3.
Der Client verbindet sich mit einem Host und einem Port und schreibt dann Anwendungsbytes auf den Standard-Stream. Die vollständige Dokumentation zu Eigenschaften, Methoden und Ereignissen finden Sie auf den Komponentenseiten.
oClient := TsgcQUICClient.Create(nil);
oClient.Host := 'localhost';
oClient.Port := 4433;
oClient.OnQUICConnect := OnQUICConnectHandler;
if oClient.Connect(10000) then
oClient.WriteData('hello over QUIC');
Der Server bindet einen UDP-Port, lädt ein Zertifikat und einen Schlüssel und löst dann für jeden empfangenen Puffer ein Ereignis aus.
oServer := TsgcQUICServer.Create(nil);
oServer.Port := 4433;
oServer.QUICOptions.SSLOptions.CertFile := 'cert.pem';
oServer.QUICOptions.SSLOptions.KeyFile := 'key.pem';
oServer.OnQUICData := OnQUICDataHandler;
oServer.Start;
QUIC läuft immer über UDP, stellen Sie daher sicher, dass der UDP-Port auf jeder Firewall im Pfad geöffnet ist. Ein Port, der für TCP funktioniert, ist nicht automatisch über UDP erreichbar.
Der Listener bindet die Adresse in Host. Ein Wert, der einen Doppelpunkt enthält, ist ein IPv6-Literal, und jeder andere Wert, ein IPv4-Literal oder ein Hostname, wird über beide Adressfamilien aufgelöst. Ein leeres Host bindet den Dual-Stack-Platzhalter, sodass ein einziger Listener IPv4- und IPv6-Gegenstellen auf demselben Port bedient.
| Voraussetzung | Detail |
|---|---|
| Edition | All-Access. Das Paket SGC_PACK_HTTP3, das QUIC aktiviert, befindet sich im Block SGC_EDT_ALL von sgcVer.inc. |
| Pack-Define | SGC_PACK_HTTP3. Es wird in sgcVer.inc auskommentiert ausgeliefert und muss daher ausdrücklich aktiviert werden, bevor QUIC einkompiliert wird. |
| Feature-Defines | Wenn SGC_PACK_HTTP3 und SGC_INDY_LIB beide aktiviert sind, definiert sgcVer.inc die Symbole SGC_QUIC, SGC_HTTP3 und SGC_WEBTRANSPORT. Die QUIC-Komponenten werden unter SGC_QUIC kompiliert. |
| Indy | SGC_INDY_LIB ist erforderlich. Die QUIC-Defines sind in einen SGC_INDY_LIB-Guard eingebettet, sodass QUIC in einem Indy-freien Build nicht verfügbar ist. |
| OpenSSL | OpenSSL 3.5 oder neuer. Die Serverkomponenten benötigen den nativen QUIC-Listener (SSL_new_listener, SSL_accept_connection), der in 3.5 eingeführt wurde, und lösen bei älteren Versionen eine Ausnahme aus. |
| Units | sgcHTTP.pas deklariert die Komponenten. Der Transport befindet sich in den sgcQUIC_*-Units und die OpenSSL-Anbindung in sgcSSL_QUIC.pas. |
Um QUIC zu aktivieren, bearbeiten Sie sgcVer.inc und entfernen Sie die Kommentarzeichen des Pack-Defines im All-Access-Block:
{$IFDEF SGC_EDT_ALL} { ALL-ACCESS }
{$DEFINE SGC_PACK_HTML}
{$DEFINE SGC_PACK_HTTP3}
{.$DEFINE SGC_PACK_WEBRTC}
{$ENDIF}