Voraussetzungen
- nginx ab 1.25.0 mit dem Modul
http_v3_module. Die Pakete von nginx.org enthalten es. Ob deine Version es hat, zeigtnginx -V 2>&1 | grep -o http_v3_module. - TLS 1.3 muss aktiv sein, QUIC baut darauf auf.
- UDP-Port 443 muss von außen erreichbar sein, zusätzlich zu TCP 443.
Mit dem normalen OpenSSL nutzt nginx eine Kompatibilitätsschicht für QUIC. Sie funktioniert, kann aber kein 0-RTT (Early Data). Für die meisten Websites spielt das keine Rolle.
Die Konfiguration
server {
listen 443 ssl;
listen [::]:443 ssl;
listen 443 quic reuseport;
listen [::]:443 quic reuseport;
http2 on;
http3 on;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
# Browsern mitteilen, dass es HTTP/3 gibt
add_header Alt-Svc 'h3=":443"; ma=86400' always;
}
Wichtig: reuseport darf pro Adresse und Port nur einmal vorkommen. Hast du mehrere server-Blöcke, bekommt nur der erste listen 443 quic reuseport;, alle anderen nur listen 443 quic;. Sonst startet nginx nicht und meldet „duplicate listen options“.
Danach nginx -t und systemctl reload nginx. Eine vollständige, sichere Konfiguration samt HSTS erzeugt dir der TLS-Konfigurationsgenerator (Option „HTTP/3“).
UDP 443 freigeben
Der häufigste Grund, warum HTTP/3 „nicht geht“: Die Firewall lässt nur TCP durch. Browser fallen dann still auf HTTP/2 zurück, es gibt keine Fehlermeldung.
# ufw sudo ufw allow 443/udp # firewalld sudo firewall-cmd --permanent --add-port=443/udp && sudo firewall-cmd --reload # nftables (Beispiel) nft add rule inet filter input udp dport 443 accept
Denk auch an Firewalls außerhalb des Servers: Security Groups in der Cloud, die Hoster-Firewall oder ein vorgeschalteter Load Balancer. Viele Load Balancer reichen QUIC nicht durch.
Wie der Browser zu HTTP/3 wechselt
Ein Browser verbindet sich beim ersten Besuch per TCP (HTTP/2). Im Header Alt-Svc erfährt er, dass HTTP/3 auf Port 443 verfügbar ist, und nutzt es ab der nächsten Anfrage. ma=86400 heißt: Diese Info gilt einen Tag.
Schneller geht es mit einem HTTPS-Eintrag im DNS. Damit kennt der Browser HTTP/3 schon vor der ersten Verbindung:
example.com. 3600 IN HTTPS 1 . alpn="h3,h2"
Eine typische Falle: add_header wird nicht vererbt, sobald ein location-Block eigene add_header-Zeilen hat. Dann fehlt Alt-Svc genau dort. Lösung: Header in eine Datei auslagern und per include in jedem betroffenen Block einbinden.
Testen
# Header vorhanden? curl -sI https://example.com | grep -i alt-svc # Echte HTTP/3-Verbindung (curl mit HTTP/3-Unterstützung nötig) curl -sI --http3-only https://example.com # Lauscht nginx auf UDP? sudo ss -ulpn | grep ':443'
Im Browser zeigen die Entwicklertools in der Netzwerkansicht die Spalte „Protokoll“: h3 heißt HTTP/3. Beim allerersten Aufruf steht dort noch h2, erst nach einem Neuladen wechselt es.
Der HTTP/2- & HTTP/3-Check prüft ALPN, Alt-Svc und den HTTPS-Eintrag und schickt ein QUIC-Paket an den Server.
FAQ
Bringt HTTP/3 wirklich etwas?
Vor allem in Mobilfunk- und WLAN-Netzen mit Paketverlust: Ein verlorenes Paket blockiert nicht mehr alle Anfragen, und der Verbindungsaufbau ist schneller. Im schnellen Kabelnetz ist der Unterschied oft kaum messbar.
Muss ich HTTP/2 weiter anbieten?
Ja. Jeder Browser startet per TCP, und manche Netze blockieren UDP. HTTP/3 ergänzt HTTP/2, es ersetzt es nicht.
Warum zeigt der Browser trotz Alt-Svc nur h2?
Meist kommt UDP 443 nicht an (Firewall, Load Balancer, Firmennetz) oder der Browser hat die Info noch nicht. Neu laden, sonst mit curl --http3-only von außen testen.
Geht HTTP/3 auch mit Apache?
Nein, Apache unterstützt HTTP/3 bisher nicht. Üblich ist ein vorgeschalteter Proxy wie nginx, Caddy oder ein CDN.