Pourquoi quitter WireGuard ?
L'itinéraire complet : WireGuard, un détour par Iroh, puis un fork de Quinn.
Pourquoi WarrenGuard ne repose pas sur WireGuard, ce que QUIC apporte au transport, et les trois correctifs de notre fork de Quinn qui valent bien au-delà du VPN.
Sommaire
Pour coder un VPN, la première chose que l'on fait, c'est ouvrir la page de WireGuard. C'est petit, c'est audité, c'est rapide, c'est dans le noyau Linux. Nous avons donc commencé par là. Mais nous avons pris une autre route, avec quelques erreurs en chemin, surtout une en fait ; nous avons fini par forker Quinn.
Voilà l'itinéraire complet, avec quelques chiffres clairs. Nous le livrons ici à toute fin utile : même si vous n'utilisez pas Warren, vous devriez pouvoir repartir avec un meilleur bagage. Il est par exemple possible que vous embarquiez un bug BBR en production, sans le savoir.
Le livre blanc est bien plus détaillé et complet. Cet article est fait pour le rendre plus accessible, tout en s'adressant à des profils techniques. Nous partageons tout cela sans retenue pour que vous puissiez mettre à l'épreuve, tester et continuer de consolider les choix effectués.
#Trois raisons pour servir nos objectifs
Nous avons pris cette décision, non pas du fait de bugs majeurs de WireGuard ; mais ce que nous voulions construire nous a naturellement mené ailleurs.
La signature. Un tunnel WireGuard « nu » se fait bloquer ou brider sur les réseaux qui filtrent l'UDP, ou bien lorsque le DPI reconnaît sa signature. Le rendre furtif signifie alors empiler une couche d'obfuscation par-dessus ; par conséquent maintenir cette couche à vie, séparément du transport. Et devoir activer un mode furtif implique qu'on puisse oublier de l'activer.
Les fonctions manquantes. Le multi-hop chiffré de bout en bout, le port forwarding en bande, la défense contre l'analyse de trafic (DAITA). WireGuard n'offre ni négociation de capacités, ni canal de contrôle in-band, ni extensibilité du handshake. Chacune de ces trois fonctions devrait donc être greffée par-dessus, avec son propre canal de contrôle et sa propre maintenance. Trois greffes, trois surfaces d'attaque, trois choses à faire vieillir ensemble.
La double identité. L'identité d'un tunnel WireGuard repose sur une clé propre au tunnel, distincte de l'identité cryptographique de l'utilisateur. Deux identités à synchroniser, donc deux surfaces de corrélation. Nous n'en voulions qu'une seule.
Les trois convergent vers une même conclusion, qui a déterminé nos choix et nos développements : les propriétés requises ne doivent pas se greffer sur le transport, elles doivent être portées par le transport.
#Une erreur initiale : Iroh
Le raisonnement précédent mène naturellement à QUIC.
Notre première approche fut de prendre Iroh, une stack P2P bâtie sur QUIC. Sur le papier c'est parfait : une identité de nœud déjà alignée sur une clé publique, intégration native du NAT traversal et du multipath.
À l'usage, Iroh embarquait surtout du poids. Des milliers de lignes inutilisées pour notre cas. Une API qui bouge chaque semaine. Une classe de bugs du NAT traversal que nous n'avons pas su résoudre. Et une longue traîne de dépendances transitives.
Le point que nous avons mis un moment à identifier : dans la topologie de Warren, un client s'adresse à un serveur de sortie connu. Le NAT traversal et le multipath, les deux fonctions phares d'Iroh, ne servaient donc strictement à rien. C'était payer le prix fort pour des fonctionnalités que l'appli n'appelait jamais.
#Le pivot, mai 2026
Abandon d'Iroh, passage à Quinn, l'implémentation Rust de référence de QUIC, sans la surcouche P2P. La migration a pris quelques jours.
Les résultats :
- variabilité du débit fortement réduite
- binaires réduits de plus de moitié
- arbre de dépendances ramené de quatre-vingts crates à environ vingt-cinq
La règle que nous avons retenue, et qui s'applique bien au-delà d'un VPN : préférer une fondation modeste et comprise à une fondation ambitieuse et brumeuse. Une dépendance non totalement maîtrisée est à la fois une dette de sécurité et une dette technique.
#Ce que QUIC nous donne
Cinq propriétés structurelles ; aucune n'est une option qu'il faut penser à activer.
La furtivité native. Le trafic se confond avec HTTP/3 sur le port 443. L'obfuscation, c'est le protocole lui-même.
Un canal de contrôle in-band. Streams fiables, négociation de capacités, handshake extensible. Le multi-hop et le port forwarding vivent au sein du protocole au lieu d'être greffés à côté.
Une identité unique. TLS 1.3 est intégré au transport, l'authentification mutuelle se fait en Raw Public Keys (RFC 7250), en Ed25519, vérifiées directement sans CA.
Les datagrammes IP. Les paquets IP voyagent en 1:1 dans des frames DATAGRAM (RFC 9221).
La connection migration. Un passage du Wi-Fi vers l'Ethernet ou vers le cellulaire est détecté et encaissé.
Côté performances, sur un bare-metal 10 GbE en AMD EPYC Zen4, entre deux machines du même datacenter, un tunnel unique tient de 5,5 à 7 Gbit/s, de manière stable. Un serveur tient plus de cinq mille sessions simultanées à moins de dix pour cent de charge CPU. Et avec 2 % de perte injectée sur un flux, là où un contrôleur de congestion classique s'effondre à quelques mégabits par seconde, BBR en maintient plusieurs centaines.
#Notre fork de Quinn
Le fork est là : github.com/WarrenBrowse/warren-quinn
Il est publié sous MIT OR Apache-2.0, comme l'upstream, avec des crates renommées (warren-quinn, warren-quinn-proto, warren-quinn-udp) pour que personne n'ait besoin d'un [patch.crates-io]. Chaque divergence est isolée en un patch documenté, et le fork est resynchronisé quand l'upstream avance.
Trois deltas valent le détour même en dehors d'un VPN.
Le bug BBR. Deux défauts où une connexion app-limited reste coincée en STARTUP et voit sa cwnd croître sans borne. En production, nous avons observé des fenêtres d'un demi-gigaoctet. Faire tourner Quinn avec BBR sur du trafic app-limited permet de le constater. Le patch est conforme à la spec et destiné à l'upstream.
Si vous faites tourner Quinn avec BBR sur du trafic app-limited, un tunnel au repos par exemple, allez regarder votre cwnd avant de nous croire sur parole. Le symptôme est silencieux : rien ne casse, la fenêtre gonfle.
L'AQM sur la file de datagrammes. FQ-CoDel (RFC 8289 et RFC 8290), queues per-flow, scheduling DRR, flow isolation. Les têtes de queue dont le sojourn time maintient la file au-dessus du target pendant un intervalle complet subissent un head-drop. Sans cela, un seul flux glouton ruine la latence de tous les autres dans le tunnel.
Le send buffer adaptatif au BDP. clamp(4 × EWMA(bw × min_rtt), 1 MiB, configuré). Sur les last miles lents, cela fait tomber la queue depth de 16 MiB à environ 1 MiB. C'est du bufferbloat en moins, gratuitement.
Il y a aussi du sizing GSO (MAX_TRANSMIT_DATAGRAMS de 20 à 80, MAX_TRANSMIT_SEGMENTS de 10 à 40), l'auto-sizing des socket buffers sous Unix et Windows, et un fast datapath Apple.
#Le MTU
Faire passer des paquets IP dans des frames DATAGRAM QUIC, c'est facile. Les faire passer sans casser la moitié d'Internet, beaucoup moins.
Nos solutions :
- Nous partons d'un floor prudent de 1280 octets, nous sondons à la hausse quand le chemin natif le permet, et nous ne descendons jamais sous 1200 octets, le minimum que QUIC garantit de bout en bout.
- Pour les flux TCP, MSS clamping sur les SYN, des deux côtés du tunnel. Les deux extrémités se dimensionnent d'elles-mêmes sans dépendre d'ICMP, ce qui règle le cas des chemins où ICMP est filtré et où la PMTUD part dans le mur.
- Pour les autres flux, un paquet trop grand est droppé et son émetteur reçoit un vrai ICMP Fragmentation Needed en IPv4, ou ICMPv6 Packet Too Big en IPv6, avec la bonne taille.
- Sur le fallback TCP, où la stack peut fragmenter d'elle-même, la PMTUD est désactivée et le budget interne plafonné à 1100 octets, la taille qui traverse ce transport sans tomber dans un blackhole.
#Le handshake
Le SNI et le début du ClientHello sont fragmentés sur au moins deux datagrammes UDP paddés, avec un padding floor sur le paquet Initial et un cap sur la taille du premier fragment CRYPTO.
C'est une défense précise contre un extracteur de SNI documenté du GFW, et contre une attaque d'extraction passive publiée en 2025. Elle est active par défaut, sur toutes les connexions, sans rien à configurer.
#Les liens
- Le moteur, sous AGPL-3.0 : github.com/WarrenBrowse/warrenguard
- Le fork de Quinn, sous MIT OR Apache-2.0 : github.com/WarrenBrowse/warren-quinn
- Le livre blanc, 33 sections, détaille entre autres tous les points de cet article
