Tailscale lent : connexion relayée ou directe ?
Une connexion Tailscale relayée ralentit les transferts. Utilisez deux commandes pour l’identifier, puis corrigez UDP bloqué et NAT strict sur un VPS.
Pourquoi Tailscale est lent : connexion relayée au lieu d’une connexion directe
Tailscale est lent lorsque la connexion est relayée, et son débit est proche de celui de la ligne lorsque la connexion est directe. Une connexion directe achemine les paquets WireGuard chiffrés directement d’une machine à l’autre. Elle atteint donc le débit que les deux connexions Internet peuvent fournir. Une connexion relayée fait d’abord passer chaque paquet par une troisième machine. Elle hérite donc de la latence de cette machine et de la part de bande passante qui vous est attribuée. La page consacrée aux performances de Tailscale le résume ainsi : « Les connexions directes offrent presque toujours une latence plus faible et un débit plus élevé. »
Rien dans votre application ne permet de voir la différence. La copie de fichiers est simplement lente et la session SSH présente simplement des délais. La première étape consiste donc à déterminer le type de connexion utilisé. Deux commandes suffisent pour le savoir en moins d’une minute. Tout le reste consiste à corriger la cause. Il est utile de connaître le fonctionnement de la configuration avant de commencer, car le serveur de coordination et le data plane WireGuard sont deux systèmes distincts et seul le data plane transporte vos données.
Les deux commandes qui distinguent une connexion directe d’une connexion relayée
Envoyez du trafic au pair avant toute mesure. Tailscale établit un chemin à la demande. Un pair avec lequel vous n’avez pas échangé aujourd’hui n’en a peut-être pas encore négocié un. Vous liriez alors une information obsolète. Un ping ou un curl vers l’adresse tailnet du pair suffit.
tailscale statusLa réponse se trouve à la fin de la ligne de chaque pair.
100.113.160.82 device-a tagged-devices linux active; offers exit node; direct 203.0.113.9:41641
100.104.93.78 device-b you@ android active; relay "tor"direct suivi d’une adresse et d’un port signifie que les paquets vont directement à cette adresse. relay "tor" désigne un serveur DERP (designated encrypted relay for packets), l’un des serveurs relais de Tailscale. Tous les paquets destinés à ce pair passent par ce serveur. Une troisième valeur, peer-relay, est expliquée dans la section suivante.
tailscale ping device-bUne connexion saine commence par être relayée, puis devient directe. Les premiers paquets passent par le serveur DERP le plus proche pendant que les deux machines négocient. Le chemin change ensuite :
pong from device-b (100.113.160.82) via DERP(tor) in 51ms
pong from device-b (100.113.160.82) via DERP(tor) in 48ms
pong from device-b (100.113.160.82) via 203.0.113.9:41641 in 35msL’exécution s’arrête à ce stade, car --until-direct vaut true par défaut. Une connexion qui ne devient pas directe ressemble plutôt à ceci. Elle se termine par une phrase et non par un pong :
pong from device-b (100.104.93.78) via DERP(tor) in 53ms
pong from device-b (100.104.93.78) via DERP(tor) in 60ms
direct connection not establishedLa dernière ligne donne le résultat. Tailscale a envoyé toutes les sondes prévues et n’a jamais obtenu de chemin direct. Pour continuer à surveiller un chemin relayé au lieu de vous arrêter au premier chemin direct, exécutez tailscale ping --until-direct=false -c 20 device-b et examinez la dispersion de la latence. Un chemin relayé affiche généralement des valeurs plus élevées et plus variables, car il combine deux chemins Internet au niveau d’une machine que vous ne contrôlez pas.
Que signifie peer-relay dans l’état de Tailscale ?
Un peer relay est une machine de votre propre tailnet qui relaie le trafic d’autres membres lorsqu’une connexion directe est impossible. Il écoute sur un port UDP de votre choix, et le daemon l’utilise en priorité par rapport à DERP. tailscale status indique une telle connexion peer-relay, et tailscale ping affiche le endpoint du relay :
pong from device-b (100.97.143.93) via peer-relay(203.0.113.42:40000:vni:1) in 4ms
direct connection not establishedLisez ce résultat attentivement. Il ne s’agit toujours pas d’une connexion directe, donc l’exécution se termine encore par direct connection not established. Ce qui change, c’est la machine qui relaie le trafic. Un VPS doté d’une adresse IP publique et d’une bande passante généreuse constitue un bien meilleur relay pour votre propre trafic qu’un nœud DERP partagé. C’est pourquoi cette fonctionnalité est importante pour toute personne qui loue un serveur. Activez-la sur la machine qui dispose du endpoint public approprié :
sudo tailscale set --relay-server-port=40000Le port 0 sélectionne un port inutilisé au hasard, et une chaîne vide désactive le relay server. Autorisez ensuite les appareils clients à l’utiliser avec la capability tailscale.com/cap/relay dans le fichier de policy de votre tailnet :
{
"grants": [
{
"src": ["tag:us-east-vpc"],
"dst": ["tag:us-east-relays"],
"app": {
"tailscale.com/cap/relay": []
}
}
]
}L’appareil relay et les appareils clients doivent tous utiliser Tailscale 1.86 ou une version ultérieure. Vérifiez donc avec tailscale version sur chacun d’eux avant de passer une heure sur le fichier de policy. Il est utile de mémoriser l’ordre des tentatives du daemon. Il essaie d’abord d’établir une connexion directe. En cas d’échec, il recherche un peer relay qu’il est autorisé à utiliser. S’il n’en trouve aucun, il utilise DERP. DERP n’est jamais totalement écarté, car il sert également de canal de négociation initiale entre les deux machines.
Cause 1 : un pare-feu de sortie qui bloque UDP
Tailscale documente deux raisons pour lesquelles une connexion reste relayée. La première est le blocage d’UDP. Interrogez directement la machine :
tailscale netcheckLe rapport est tronqué ici. Le premier champ est celui qui détermine tout :
Report:
* UDP: true
* IPv4: yes, 203.0.113.9:41641
* IPv6: no
* MappingVariesByDestIP: false
* PortMapping:
* Nearest DERP: DallasUDP: false constitue toute la réponse lorsque cette valeur apparaît. La machine ne peut pas envoyer de paquet UDP aux serveurs de test de Tailscale. Aucun chemin direct ne peut donc être établi, et le daemon utilise DERP sur TCP port 443. Ce repli explique pourquoi la machine semble parfaitement opérationnelle : elle est connectée, elle est accessible et chaque octet est relayé.
Deux règles de sortie sont documentées. « Autoriser vos appareils internes à démarrer une connexion UDP de :41641 vers *:* » concerne le trafic WireGuard lui-même. « Autoriser vos appareils internes à démarrer une connexion UDP vers *:3478 » concerne STUN (session traversal utilities for NAT), le protocole utilisé par la machine pour connaître sa propre adresse et son propre port publics. Utilisez des jokers pour les destinations. Tailscale ajoute régulièrement des serveurs relais, et une liste d’adresses saisie manuellement sera obsolète en moins d’un an.
Sur un serveur loué, la cause habituelle est une politique de sortie stricte, héritée d’une image renforcée ou appliquée en amont par le fournisseur. Commencez par examiner la politique de sortie par défaut :
sudo ufw status verbose
sudo nft list rulesetDefault: deny (incoming), allow (outgoing) est correct et n’est pas à l’origine du problème. Une politique de sortie par défaut définie sur deny, avec une courte liste d’autorisations limitée à TCP 443 et au DNS, maintient précisément un serveur sur un relais indéfiniment : le chemin DERP sur TCP 443 passe par cette ouverture, contrairement au chemin direct. L’emplacement réel de ces règles dépend de l’utilisation d’iptables ou de nftables par le système, et modifier le mauvais pare-feu est un moyen courant de ne rien changer.
Le trafic entrant compte également, car un VPS possède une adresse IP publique et peut donc constituer la moitié la plus simple de la connexion. Si son pare-feu autorise les connexions UDP entrantes sur le port utilisé par tailscaled, les pairs situés derrière des routeurs domestiques difficiles à traverser peuvent le joindre sans configuration particulière. Recherchez le port réellement utilisé :
sudo ss -lunp | grep tailscaled
sudo ufw allow 41641/udp41641 est le port statique par défaut. Dans un tailnet où le paramètre randomizeClientPort est activé, les clients choisissent plutôt un port aléatoire. Dans ce cas, utilisez le numéro réel indiqué par la sortie de ss, et non celui de cette page. Vérifiez ensuite le panneau de contrôle de votre fournisseur. La plupart des hébergeurs utilisent un pare-feu réseau distinct de celui qui s’exécute sur le serveur, et une règle ajoutée avec ufw ne modifie pas ce pare-feu externe.
Cause 2 : NAT strict des deux côtés ou d’un seul
La deuxième cause documentée est un NAT strict. Le NAT (traduction d’adresses réseau) est l’opération par laquelle un routeur remplace votre adresse privée par son adresse publique. Un routeur compatible conserve le même port public pour un socket interne donné, quel que soit l’interlocuteur. On parle alors de mappage indépendant du point d’extrémité. Un NAT strict attribue un port public différent pour chaque destination. L’adresse apprise par la machine auprès d’un serveur STUN n’est donc pas celle qu’un pair pourra utiliser. Tailscale l’indique dans netcheck sous la forme MappingVariesByDestIP: true.
Un seul NAT strict reste gérable. Si l’autre côté possède un point de terminaison public stable, la machine située derrière le NAT strict peut tout de même établir la connexion, et le chemin se forme. Deux NAT stricts simultanés provoquent l’échec, car aucun des deux côtés ne peut prévoir le port sur lequel l’autre apparaîtra.
Sur un VPS doté d’une adresse IPv4 publique, ce champ doit afficher false, puisque rien ne traduit cette adresse. S’il affiche true sur un serveur que vous louez, l’adresse est traduite quelque part dans le réseau du fournisseur. Aucune règle de pare-feu appliquée sur la machine ne pourra modifier cela. Vous pouvez placer un relais entre pairs sur une machine qui possède un point de terminaison public directement accessible, ou déplacer la charge de travail. C’est également le cas où annoncer vos plages privées depuis un subnet router est utile, car vous avez alors besoin d’un seul chemin fonctionnel vers le réseau, et non d’un chemin fonctionnel vers chaque appareil qui s’y trouve.
Pourquoi un exit node donne l’impression que Tailscale est plus lent qu’il ne l’est
Un exit node ajoute un second saut, que les lecteurs attribuent souvent au tunnel. Lorsqu’un exit node est sélectionné, une requête quitte votre ordinateur portable, traverse le tunnel jusqu’au VPS, quitte le VPS vers Internet, puis la réponse revient par le même chemin. Même une connexion parfaitement directe vers ce VPS ne peut pas rendre l’ensemble plus rapide que la liaison montante du VPS. La distance supplémentaire se ressent lors du chargement de chaque page.
Mesurez séparément les deux segments. Désactivez l’exit node, puis testez uniquement le tunnel vers l’adresse tailnet du VPS :
sudo tailscale set --exit-node=
sudo apt install -y iperf3
iperf3 -sExécutez iperf3 -c 100.113.160.82 depuis le client vers cette adresse tailnet. Cette valeur mesure votre tunnel. Réactivez ensuite l’exit node avec sudo tailscale set --exit-node=100.113.160.82 et lancez un speed test normal vers Internet. Cette valeur mesure le tunnel et la liaison montante du VPS. Si la première valeur est bonne et la seconde mauvaise, Tailscale n’est pas en cause. Il faut alors examiner le réseau et le dimensionnement de l’exit node. tailscale exit-node list affiche les ressources disponibles si vous ne savez plus quel nœud vous avez sélectionné.
Le CPU constitue l’autre limite d’un exit node. Tailscale recommande de privilégier une génération récente de CPU avec une fréquence d’horloge élevée plutôt qu’un nombre de cœurs plus important. Un plan avec davantage de vCPU n’est donc pas automatiquement plus rapide dans ce cas. Sur un hôte partagé chargé, le CPU qui vous a été attribué n’est pas toujours celui dont vous disposez réellement. La steal time due à un voisin bruyant se traduit par un débit qui varie selon l’heure, sans aucun changement de votre côté.
Le seul paramètre à ajuster : rx-udp-gro-forwarding
Tailscale documente un seul paramètre Linux. Il s’applique aux machines qui transmettent du trafic, c’est-à-dire aux exit nodes et aux subnet routers. Un simple client n’en tire aucun bénéfice. Cette fonctionnalité nécessite Tailscale 1.54 ou une version ultérieure, ainsi qu’un noyau Linux 6.2 ou ultérieur. Vérifiez donc ces deux versions avant toute modification :
tailscale version
uname -rUne fois ces conditions réunies, activez le forwarding UDP GRO (generic receive offload) sur l’interface connectée à Internet :
NETDEV=$(ip -o route get 8.8.8.8 | cut -f 5 -d " ")
sudo ethtool -K $NETDEV rx-udp-gro-forwarding on rx-gro-list offVérifiez que la modification a bien été prise en compte :
ethtool -k $NETDEV | grep -E 'rx-udp-gro-forwarding|rx-gro-list'Vous devriez voir rx-udp-gro-forwarding: on et rx-gro-list: off. Cette optimisation est utile parce que le trafic de Tailscale utilise UDP. Le fait de conserver les petits paquets UDP regroupés tout au long du chemin de forwarding permet au daemon de traiter moins de segments, mais plus volumineux, pour un même nombre d’octets. ethtool -K ne résiste pas à un redémarrage. Rendez donc le paramètre persistant. Sur un système utilisant networkd-dispatcher :
printf '#!/bin/sh\n\nethtool -K %s rx-udp-gro-forwarding on rx-gro-list off \n' "$(ip -o route get 8.8.8.8 | cut -f 5 -d " ")" | sudo tee /etc/networkd-dispatcher/routable.d/50-tailscale
sudo chmod 755 /etc/networkd-dispatcher/routable.d/50-tailscaleExécutez le script manuellement une fois et vérifiez que son code de sortie est 0. Un nœud qui transmet du trafic doit également avoir l’IP forwarding activé. Il s’agit d’un paramètre distinct et d’une cause de panne distincte :
echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
sudo sysctl -p /etc/sysctl.d/99-tailscale.confQuelle MTU votre interface tailscale0 utilise-t-elle ?
Ne devinez pas cette valeur. Lisez-la directement sur la machine :
ip link show tailscale0La valeur mtu dans cette sortie correspond à la valeur réellement utilisée par votre tunnel. Elle est inférieure à 1500, la valeur indiquée par votre interface Ethernet. C’est volontaire, ce n’est pas un bug. Chaque paquet envoyé dans le tunnel est encapsulé : un en-tête IP externe de 20 octets en IPv4 ou de 40 octets en IPv6, un en-tête UDP de 8 octets, ainsi que l’encapsulation WireGuard et son tag d’authentification de 32 octets. L’ensemble doit tenir dans ce que le chemin réseau réel peut transporter. Tailscale choisit donc une valeur suffisamment basse pour fonctionner sur les liaisons qui transportent moins qu’un paquet complet de 1500 octets, notamment les connexions PPPoE, certains réseaux mobiles et les tunnels IPv6.
Le symptôme d’un problème de MTU est caractéristique. Ne le diagnostiquez pas uniquement à partir d’un ralentissement. SSH reste réactif, ping fonctionne, puis les transferts volumineux ou les grandes pages HTTPS se bloquent complètement au lieu de ralentir. Cela signifie que des paquets trop volumineux sont abandonnés quelque part, sans qu’aucun message ICMP ne revienne en informer l’émetteur. Augmenter la MTU tailscale0 vers 1500 aggrave le problème, car les paquets qui ne passent déjà pas deviennent encore plus volumineux. La véritable correction consiste à trouver la MTU fonctionnelle du chemin par dichotomie et à limiter le TCP MSS sur le routeur qui achemine le trafic. Le type de connexion ne change rien à ce comportement : un chemin relayé et un chemin direct utilisent la même MTU d’interface.
FAQ
Comment savoir si ma connexion Tailscale est directe ou relayée ?
Exécutez tailscale status et lisez la fin de la ligne du pair. direct 203.0.113.9:41641 indique une connexion directe, relay "tor" signifie que chaque paquet passe par ce serveur DERP et peer-relay signifie que les paquets passent par une machine de votre propre tailnet. Pour obtenir un second avis, exécutez tailscale ping <peer> : un chemin sain commence sur DERP, puis affiche un pong avec une adresse et un port en clair, tandis qu’un chemin relayé affiche des pongs DERP jusqu’à la fin de l’exécution avec direct connection not established. Envoyez d’abord du trafic vers le pair, car Tailscale ne construit un chemin qu’à la demande.
Pourquoi mon VPS n’établit-il jamais de connexion directe ?
Exécutez tailscale netcheck sur le VPS. Si la commande affiche UDP: false, un pare-feu de sortie bloque l’UDP sortant et le daemon a basculé vers DERP sur TCP 443, ce qui explique que la machine reste connectée. Autorisez l’UDP sortant depuis le port 41641 vers n’importe quelle destination, ainsi que l’UDP sortant vers n’importe quelle destination sur le port 3478. Vérifiez le pare-feu réseau de votre fournisseur et celui du serveur, car il s’agit de deux contrôles distincts et une règle ufw n’agit pas sur le pare-feu du fournisseur.
Une connexion Tailscale relayée est-elle moins sécurisée qu’une connexion directe ?
Non. Un serveur DERP relaie les paquets WireGuard qu’il ne peut pas déchiffrer, car les clés de chiffrement sont générées sur vos appareils et ne les quittent jamais. Le relais entraîne une latence et une baisse du débit, mais pas une perte de confidentialité. Le serveur de coordination contrôle en revanche les appareils qui peuvent se découvrir mutuellement. La séparation entre le matériel de clé et les métadonnées de connexion mérite d’être comprise avant de décider dans quelle mesure vous souhaitez auto-héberger ces composants.
Le paramètre rx-udp-gro-forwarding est-il utile sur toutes les machines ?
Non. Sa documentation le destine aux machines Linux qui transmettent du trafic pour d’autres machines, c’est-à-dire aux exit nodes et aux subnet routers. Un ordinateur portable ou un serveur qui communique uniquement avec ses propres pairs n’en tire aucun bénéfice. Ce paramètre nécessite également Tailscale 1.54 ou une version ultérieure et un noyau Linux 6.2 ou une version ultérieure. Vérifiez donc d’abord tailscale version et uname -r, et n’oubliez pas que ethtool -K est réinitialisé au redémarrage si vous ne le rendez pas persistant.
Tailscale est-il plus lent que WireGuard utilisé directement ?
Les deux utilisent WireGuard pour chiffrer votre trafic. Tailscale ajoute la configuration de la connexion que WireGuard utilisé directement vous laisse effectuer manuellement. C’est cette configuration qui peut parfois vous faire passer par un relais. WireGuard utilisé directement ne dispose d’aucun relais : il se connecte directement ou échoue complètement à établir la connexion. Comparez donc des configurations équivalentes et ne mesurez Tailscale que lorsque tailscale status indique direct. Si vous souhaitez utiliser la version configurée manuellement pour la comparaison, un serveur WireGuard que vous construisez vous-même nécessite environ quarante lignes de configuration. Le compromis correspondant est expliqué dans la comparaison des deux approches.