Stranger Than Usual

HTTP 3

HTTP 3. Eigentlich ist die Schreibweise „HTTP/3“, aber mich irritiert das immer. Wie soll man das denn aussprechen? „HTTP geteilt durch drei“? Oder „HTTP oder drei“? Warum ist da ein Schrägstrich?

Ist ja auch egal. Zu HTTP 3 gibt es unterschiedliche Meinungen. Auf der einen Seite gibt es Leute, die meinen, HTTP 3 sei zu komplex (und damit ein Sicherheitsrisiko), würde nur dann etwas bringen, wenn man ganz bestimmte Anforderungen hat oder sei sowieso doof, weil Google zu sehr seine Finger im Spiel hatte. Auf der anderen Seite gibt es Leute, die sagen, man müsse es unbedingt nutzen, weil es alles so viel schneller macht und ja sowieso das Neueste und Beste ist, und wer sich dagegen ausspricht sei ein zurückgebliebener Maschinenstürmer (wen überhaupt die Möglichkeit in Betracht gezogen wird, dass sich jemand dagegen aussprechen könnte). Dazwischen gibt es eine ganze Menge nuancierter Meinungen.

Ich selbst spiele schon seit einer Weile mit dem Gedanken, es für mein Blog einfach mal auszuprobieren. Es scheiterte immer wieder daran, dass die nginx-Version auf meinem Server das Feature nicht aktiviert hatte und ich definitiv keine nginx-Version installieren wollte, die nicht aus dem Paketmanager stammt (wegen des Wartungsaufwands). So ähnlich ging es mir ja auch mit Brotli, wobei ich Brotli wirklich dringend nutzen wollte, während HTTP 3 nur ein „probieren wir es mal“ ist.

Zwischenspiel: HTTP 2 und nginx

Ich nutze nginx als HTTP-Server. Um sicherzustellen, dass meine nginx-Konfiguration gültig ist, habe ich /usr/sbin/nginx -t ausgeführt. Ergebnis, ohne dass ich irgendwas geändert hätte:

the "listen ... http2" directive is deprecated, use the "http2" directive instead in [REDACTED]

Ok, kurz nachgeschaut und diese Zeilen hier

listen 443 ssl http2;
listen [::]:443 ssl http2;

Durch diese ersetzt:

listen 443 ssl;
listen [::]:443 ssl;
http2 on;

Selbst wenn das mit dem HTTP 3 also nichts werden sollte habe ich immerhin meine nginx-Config auf den aktuellen Stand gebracht.

HTTP 3 mit nginx

Ich habe nach der offiziellen nginx-Dokumentation zu HTTP 3 gearbeitet. Der wichtigste Teil ist, hinter diesen Zeilen, die für HTTP 1 und 2 zuständig sind:

listen 443 ssl;
listen [::]:443 ssl;

Diese beiden Zeilen einzufügen:

listen 443 quic reuseport;
listen [::]:443 quic reuseport;

WICHTIG: Hier habe ich ein bisschen kämpfen müssen. Ohne reuseport funktionierte es bei mir überhaupt nicht. Es wird allerdings überall davor gewarnt, reuseport mehr als ein Mal zu verwenden. Ich habe in meiner nginx-config aber mehrere virtuelle Server. Kann ich dann nicht alle mit HTTP 3 betreiben? Doch, natürlich kann ich das. Aber es muss genau einer davon reuseport definiert haben (pro port + IP-Version).

Dann kann man noch ein paar weitere Optionen setzen, zum Beispiel diese hier:

quic_retry on; 
ssl_early_data on; 
quic_gso on; 
add_header Alt-Svc 'h3=":443"; ma=86400';

Die ersten drei sind optional und sollten die Performance verbessern oder so. Speziell die dritte funktioniert nur unter Linux. Die vierte Option, der Alt-Svc header hingegen ist recht wichtig. Denn ohne den erkennen User-Agents (z.B. Browser) nicht, dass es neben der HTTP 1 bzw. 2-Verbindung auch noch eine HTTP 3-Option gibt. HTTP 3 läuft über ein komplett anderes Transport-Layer-Protokoll (UDP statt TCP). Während bei HTTP 1 also ein Update zu HTTP 2 über das Protokoll selber sehr einfach möglich ist ohne auch nur die TCP-Verbindung neu zu verhandeln, geht das bei HTTP 3 nicht. Ohne diesen Header wird also vermutlich kaum ein Browser probieren, HTTP 3 zu verwenden. ma=86400 bedeutet, dass sich der User-Agent das für 86400 Sekunden (also 24 Stunden) merken soll. Vielleicht drehe ich das später mal höher, wenn HTTP 3 bei mir über längere Zeit stabil läuft.

Testen mit curl

Bevor ich diesen Alt-Svc-Header aber gesetzt habe, wollte ich wissen, ob HTTP 3 auch stabil läuft (was gut war, denn zunächst lief es wegen der reuseport-Sachen nicht stabil). Dazu wollte ich curl verwenden. Bei meinem Ubuntu 25.10 ist curl aber leider noch ohne HTTP 3-Unterstützung gebaut. Das kann man mit curl --version herausfinden. Wenn da unter features nirgendwo HTTP 3 gelistet ist, kann dieses curl kein HTTP 3.

Ironischerweise hat ausgerechnet mein Server selber eine curl-Version mit HTTP 3-Unterstützung. Ironischerweise, weil der Server mit Debian läuft und Debian eigentlich notorisch dafür ist, alte („stable“) Versionen zu benutzen. Die curl-Version ist übrigens die gleiche wie auf Ubuntu, aber halt mit HTTP 3-Support gebaut.

So konnte ich dann mit diesen beiden Befehlen (jeweils für IPv4 bzw. IPv6) testen, ob es geht:

curl -4 --http3-only -v https://blog.strangerthanusual.de/
curl -6 --http3-only -v https://blog.strangerthanusual.de/

Bei Erfolg bekam ich eine ganz normale HTTP-Antwort. Ohne reuseport kam nur

Failed to connect to blog.strangerthanusual.de port 443 after 30055 ms: Could not connect to server

Wie geht es weiter?

Ich lasse das jetzt erst einmal eine Weile so laufen und schaue mir an, wie gut es läuft. Ich werde das allerdings nicht rigoros monitoren oder methodisch korrekt untersuchen. Wenn es gut läuft, werde ich vielleicht noch einen HTTP Resource Record in meine DNS-Config packen, so dass User-Agents schon bei der Adressaufösung mitbekommen, dass hier HTTP 3 angeboten wird.

Nicht verschweigen möchte ich, dass ich bei meinen Recherchen auf Berichte zu einem Bug gestoßen bin, der in Kombination mit reuseport und soft-reload der nginx-Konfiguration Probleme bereitet. Also sollte ich hier ein bisschen vorsichtig sein.

Aber immerhin. Firefox nutzt gerade schon mit Freude die HTTP 3-Verbindung. Wie viel mir das jetzt tatsächlich bringt sei mal dahingestellt.