SSD Nodes Learn Hosting plans →
Guides Matt ConnorPar Matt Connor

Tailscale lent : relais DERP ou connexion directe ?

Tailscale est lent via un relais DERP, mais presque aussi rapide que votre ligne en direct. Deux commandes identifient le cas et les correctifs UDP pour un VPS.

Pourquoi Tailscale est lent : connexion relayée au lieu d’une connexion directe

Tailscale est lent lorsque la connexion passe par l’un de ses serveurs DERP partagés. Les performances sont proches du débit de la ligne lorsque la connexion est directe. Une connexion directe transmet les paquets WireGuard chiffrés directement d’une machine à l’autre. Elle utilise donc le débit disponible sur les deux liens Internet. Une connexion relayée envoie d’abord chaque paquet par une troisième machine. Elle dépend donc de la latence de cette machine et de la part de sa bande passante qui vous est attribuée. Le coût dépend du relais utilisé. Tailscale indique que ses serveurs DERP sont « généralement plus lents que les connexions directes ». Un relais entre pairs que vous exploitez vous-même est « généralement plus rapide que DERP » et, lors des premiers tests de Tailscale, son débit « approchait celui d’une connexion directe ». La page de performances de Tailscale résume la règle générale en une phrase : « Les connexions directes offrent presque toujours une latence plus faible et un débit plus élevé. »

Rien dans votre application n’indique la différence. La copie de fichiers est simplement lente et la session SSH présente simplement un délai. La première étape consiste donc à déterminer le type de connexion utilisé. Deux commandes suffisent en moins d’une minute. Le reste consiste à corriger la cause. Il est utile de comprendre 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 status

La 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-b

Une 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 35ms

L’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 established

La 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 established

Lisez 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=40000

Le 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 sortant qui bloque l’UDP

Tailscale documente deux raisons pour lesquelles une connexion reste relayée. La première est le blocage de l’UDP. Interrogez directement la machine :

tailscale netcheck

Le 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: Dallas

UDP: false est l’indice le plus important. Cela signifie que la machine n’a pas pu envoyer de paquet UDP aux serveurs de test de Tailscale. La documentation de référence de l’interface en ligne de commande de Tailscale indique que, dans ce cas, « il est peu probable que Tailscale puisse établir des connexions directes entre pairs ». Le trafic passe alors par DERP sur le port TCP 443. Ce mécanisme de repli explique pourquoi la machine semble parfaitement saine : elle est connectée, elle est accessible et chaque octet est relayé. netcheck décrit le réseau, et non une connexion particulière. Vérifiez donc le chemin réellement utilisé par un pair avec tailscale status ou tailscale ping avant de modifier les règles.

Deux règles sortantes sont documentées. « Autoriser vos appareils internes à démarrer des connexions UDP de :41641 vers *:* », ce qui correspond au trafic WireGuard lui-même, et « Autoriser vos appareils internes à démarrer des connexions UDP vers *:3478 », ce qui correspond à STUN (outils de traversée de session pour 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. Une liste d’adresses écrite manuellement sera donc obsolète en moins d’un an.

Sur un serveur loué, le coupable habituel est une politique sortante stricte. Elle peut provenir d’une image renforcée que vous avez héritée, ou être appliquée en amont par votre fournisseur. Examinez d’abord la politique sortante par défaut :

sudo ufw status verbose
sudo nft list ruleset

Default: deny (incoming), allow (outgoing) est correct et ne pose pas problème. Une politique sortante 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 la présence d’iptables ou de nftables sous-jacent, et modifier le mauvais pare-feu est une manière fréquente 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 facile de la connexion. Si son pare-feu accepte 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. Trouvez le port réellement utilisé :

sudo ss -lunp | grep tailscaled
sudo ufw allow 41641/udp

41641 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 affiché sur 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 du serveur, et une règle ajoutée avec ufw ne modifie pas ce pare-feu externe.

Cause 2 : NAT strict d’un côté ou des deux

La deuxième cause documentée est un NAT strict. Le NAT (traduction d’adresses réseau) est effectué par un routeur lorsqu’il remplace votre adresse privée par votre 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 de terminaison. Un NAT strict attribue un port public différent selon la 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 avec la valeur MappingVariesByDestIP: true.

Un seul NAT strict reste gérable. Si l’autre côté possède un point de terminaison public stable, la machine derrière le NAT strict peut quand 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 normalement afficher false. Une adresse publique ne signifie pas toujours qu’aucune traduction n’est effectuée. AWS indique par exemple que sa passerelle Internet réalise un NAT biunivoque entre l’adresse IPv4 publique d’une instance et son adresse privée. Un mappage statique biunivoque de ce type conserve le même port quel que soit l’interlocuteur. Il ne s’agit donc pas d’un NAT strict et le champ affiche toujours false. S’il affiche true sur un serveur que vous louez, un équipement du réseau du fournisseur attribue un port différent selon la destination. Aucune règle de pare-feu configurée dans la machine ne pourra modifier ce comportement. Vous pouvez placer un relais de pairs sur une machine qui possède un point de terminaison public fonctionnel, 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 bon chemin vers le réseau, et non d’un bon chemin vers chacun de ses appareils.

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 -s

Exé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 -r

Une 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 off

Vé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-tailscale

Exé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.conf

Quelle MTU votre interface tailscale0 utilise-t-elle ?

Ne devinez pas cette valeur. Lisez-la directement sur la machine :

ip link show tailscale0

La 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 classiques, 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 au 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. S’il affiche UDP: false, le trafic UDP sortant ne passe pas, le plus souvent à cause d’un firewall egress, et Tailscale indique qu’une connexion point à point est alors peu probable. Vérifiez avec tailscale status ou tailscale ping que le pair utilise DERP, qui fonctionne sur TCP 443 et explique pourquoi la machine semble toujours 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 firewall réseau de votre fournisseur ainsi que celui du serveur, car ces contrôles sont distincts et une règle ufw ne modifie pas celle 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 coûte en latence et en débit, pas en confidentialité. Le serveur de coordination contrôle en revanche les appareils qui apprennent l’existence les uns des autres, et 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 quelle partie vous souhaitez auto-héberger.

Le paramètre rx-udp-gro-forwarding aide-t-il toutes les machines ?

Non. Sa documentation le destine aux machines Linux qui transfèrent 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. Il nécessite également Tailscale 1.54 ou une version ultérieure et le noyau Linux 6.2 ou une version ultérieure. Vérifiez donc d’abord tailscale version et uname -r, et rappelez-vous que ethtool -K est réinitialisé au redémarrage si vous ne le rendez pas persistant.

Tailscale est-il plus lent que WireGuard classique ?

Les deux utilisent WireGuard pour chiffrer votre trafic. Tailscale ajoute la configuration de la connexion que WireGuard classique vous laisse effectuer manuellement, et c’est cette configuration qui vous place parfois sur un relais. WireGuard classique ne dispose d’aucun relais : il se connecte directement ou échoue complètement à se connecter. Comparez donc des configurations équivalentes, et ne mesurez Tailscale que lorsque tailscale status indique direct. Si vous souhaitez la version configurée manuellement pour comparaison, un serveur WireGuard que vous configurez vous-même nécessite environ quarante lignes de configuration, et le compromis correspondant est expliqué dans la comparaison des deux approches.