Prérequis
- nginx 1.25.0 ou plus récent avec
http_v3_module. Les paquets de nginx.org l’incluent.nginx -V 2>&1 | grep -o http_v3_moduleindique si ta version l’a. - TLS 1.3 doit être actif ; QUIC repose dessus.
- Le port UDP 443 doit être joignable de l’extérieur, en plus du TCP 443.
Avec l’OpenSSL standard, nginx utilise une couche de compatibilité pour QUIC. Elle fonctionne mais ne gère pas le 0-RTT (early data). Pour la plupart des sites, cela n’a pas d’importance.
La configuration
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;
# indiquer aux navigateurs que HTTP/3 est disponible
add_header Alt-Svc 'h3=":443"; ma=86400' always;
}
Important : reuseport ne peut apparaître qu’une seule fois par adresse et port. Avec plusieurs blocs server, seul le premier reçoit listen 443 quic reuseport;, les autres seulement listen 443 quic;. Sinon nginx refuse de démarrer avec « duplicate listen options ».
Ensuite nginx -t et systemctl reload nginx. Le générateur de configuration TLS crée une configuration complète et sûre avec HSTS (option « HTTP/3 »).
Ouvrir l’UDP 443
La raison la plus fréquente pour laquelle HTTP/3 « ne marche pas » : le pare-feu ne laisse passer que le TCP. Les navigateurs reviennent alors silencieusement à HTTP/2, sans message d’erreur.
# ufw sudo ufw allow 443/udp # firewalld sudo firewall-cmd --permanent --add-port=443/udp && sudo firewall-cmd --reload # nftables (exemple) nft add rule inet filter input udp dport 443 accept
Pense aussi aux pare-feu en dehors du serveur : groupes de sécurité dans le cloud, pare-feu de l’hébergeur ou répartiteur de charge en amont. Beaucoup de répartiteurs ne laissent pas passer QUIC.
Comment le navigateur passe à HTTP/3
À la première visite, le navigateur se connecte en TCP (HTTP/2). L’en-tête Alt-Svc lui apprend que HTTP/3 est disponible sur le port 443, et il l’utilise dès la requête suivante. ma=86400 signifie que l’information vaut un jour.
Un enregistrement HTTPS dans le DNS va plus vite : le navigateur connaît HTTP/3 avant même la première connexion.
example.com. 3600 IN HTTPS 1 . alpn="h3,h2"
Un piège classique : add_header n’est plus hérité dès qu’un bloc location a ses propres lignes add_header. Alt-Svc manque alors précisément là. Solution : mettre les en-têtes dans un fichier et l’inclure avec include dans chaque bloc concerné.
Tester
# en-tête présent ? curl -sI https://example.com | grep -i alt-svc # vraie connexion HTTP/3 (curl avec support HTTP/3 requis) curl -sI --http3-only https://example.com # nginx écoute-t-il en UDP ? sudo ss -ulpn | grep ':443'
Dans les outils de développement du navigateur, la vue réseau a une colonne « Protocole » : h3 signifie HTTP/3. À la toute première requête, elle indique encore h2 ; cela change après un rechargement.
Le test HTTP/2 & HTTP/3 vérifie ALPN, Alt-Svc et l’enregistrement HTTPS et envoie un paquet QUIC au serveur.
FAQ
HTTP/3 apporte-t-il vraiment quelque chose ?
Surtout sur les réseaux mobiles et Wi-Fi avec perte de paquets : un paquet perdu ne bloque plus toutes les requêtes et l’établissement de la connexion est plus rapide. Sur un réseau filaire rapide, la différence est souvent à peine mesurable.
Dois-je continuer à proposer HTTP/2 ?
Oui. Tout navigateur commence en TCP, et certains réseaux bloquent l’UDP. HTTP/3 complète HTTP/2, il ne le remplace pas.
Pourquoi le navigateur n’affiche-t-il que h2 malgré Alt-Svc ?
En général l’UDP 443 n’arrive pas (pare-feu, répartiteur de charge, réseau d’entreprise) ou le navigateur n’a pas encore l’information. Recharger, sinon tester de l’extérieur avec curl --http3-only.
HTTP/3 fonctionne-t-il avec Apache ?
Non, Apache ne gère pas HTTP/3 à ce jour. On place généralement devant un proxy comme nginx, Caddy ou un CDN.