SSD Nodes Learn Hosting plans →
Guides Matt ConnorPar Matt Connor

Tailscale : qu’est-ce que c’est et comment ça marche ?

Découvrez Tailscale : tunnels WireGuard entre serveurs, serveur de coordination pour les clés et ACL, traversée du NAT, relais DERP et modèle de menace.

Qu’est-ce que Tailscale ?

Tailscale est un VPN qui connecte directement vos machines entre elles, au lieu d’acheminer tout le trafic par une passerelle que vous gérez. Chaque nœud exécute WireGuard. Les paquets circulent donc de manière chiffrée d’un serveur à l’autre, et aucun élément situé sur le chemin ne peut les lire. Un serveur de coordination hébergé gère les mises en relation. Il stocke et distribue les clés publiques, puis indique à chaque nœud où se trouvent les autres. Il transmet également les règles d’accès que vous avez définies.

Cette séparation constitue l’ensemble de l’architecture. Le plan de données est pair à pair et chiffré entre les nœuds. Le plan de contrôle est un service que Tailscale exécute pour vous. Toutes les questions importantes concernant Tailscale, y compris celles qui portent sur la confiance, découlent de ces deux faits. Si vous avez déjà configuré un VPN WireGuard manuellement sur un VPS, Tailscale fournit le même tunnel, avec la distribution des clés et la traversée des pare-feu prises en charge pour vous.

Comment fonctionne Tailscale ?

Votre réseau privé de nœuds s’appelle un tailnet. Quatre opérations se produisent lorsqu’une machine le rejoint.

  1. Le daemon tailscaled démarre, génère une paire de clés WireGuard et conserve son état dans /var/lib/tailscale/tailscaled.state. La clé privée reste sur cette machine. Tailscale le formule clairement : « la clé privée ne quitte jamais son nœud, absolument jamais ».
  2. Le nœud se connecte au serveur de coordination et lui envoie sa clé publique, ainsi que les adresses auxquelles il pense pouvoir être joint. Tailscale décrit ce serveur comme « une boîte de dépôt partagée pour les clés publiques ».
  3. Le serveur de coordination renvoie une network map : la clé publique, l’adresse du tailnet, le nom de la machine et les endpoints candidats de chaque nœud que celui-ci est autorisé à joindre.
  4. Chaque paire de nœuds essaie ensuite d’établir directement un tunnel WireGuard entre eux. En cas d’échec, les paquets passent par un relais.

Chaque nœud reçoit une adresse stable dans 100.64.0.0/10, la plage de carrier-grade NAT qui va de 100.64.0.0 à 100.127.255.255. Tailscale utilise cette plage parce qu’elle est réservée à l’infrastructure des fournisseurs et entre donc rarement en conflit avec les adresses privées déjà utilisées par vos serveurs. Sous Linux, le tunnel apparaît comme une interface nommée tailscale0.

L’implémentation WireGuard s’exécute dans tailscaled en userspace, et non dans le module du kernel. C’est pourquoi Tailscale démarre avec la virtualisation de conteneurs lorsque sudo modprobe wireguard échoue avec Operation not supported. Cela signifie également que le débit maximal sur une machine donnée est inférieur à celui de WireGuard dans le kernel. C’est l’un des compromis abordés dans la comparaison entre Tailscale et WireGuard classique.

Deux commandes indiquent votre situation.

tailscale ip -4
tailscale status

tailscale status affiche une ligne par nœud, et la dernière colonne est celle qui compte.

100.101.102.103  web-1      you@  linux  -
100.101.102.104  db-1       you@  linux  active; direct 198.51.100.24:41641
100.101.102.105  ci-runner  you@  linux  active; relay "fra"

direct suivi d’une adresse et d’un port signifie que les deux machines ont trouvé un chemin direct et que le trafic passe de pair à pair. relay "fra" signifie que le trafic passe par un relais Tailscale à Francfort. Un - signifie qu’aucune session active n’est établie avec ce nœud pour le moment, ce qui est normal.

Ce que le serveur de coordination peut voir et ne peut pas voir

Le serveur de coordination conserve les clés publiques et les métadonnées. Il connaît les noms de vos machines, l’utilisateur ou le tag associé à chaque nœud, l’adresse tailnet de chaque nœud, les adresses publiques auxquelles vos nœuds sont joignables, la date de leur dernière connexion et le fichier de règles que vous avez écrit. Il dispose ainsi d’une cartographie complète de votre parc.

Il ne détient aucune clé privée. Il ne peut donc pas déchiffrer le trafic entre deux nœuds. Le chiffrement est de bout en bout entre les pairs WireGuard, et le serveur de coordination n’est pas un pair.

En revanche, il peut distribuer des clés. Tout serveur de coordination, hébergé ou auto-administré, est autorisé à indiquer à vos nœuds quelles clés publiques appartiennent au tailnet. C’est le point central du modèle de menace présenté plus loin, et la raison d’être de Headscale, un serveur de coordination open source que vous hébergez vous-même.

Comment deux serveurs situés derrière des pare-feu différents communiquent directement

Le NAT (traduction d’adresses réseau) permet à plusieurs machines de partager une même adresse publique. Votre VPS possède généralement sa propre adresse publique, mais ce n’est souvent pas le cas des autres machines que vous voulez ajouter au tailnet : serveur à domicile, build runner sur le réseau d’un bureau ou machine située derrière le pare-feu d’un fournisseur que vous ne pouvez pas modifier.

Tailscale trouve un chemin à l’aide de techniques fondées sur les standards STUN (session traversal utilities for NAT) et ICE. Chaque nœud envoie un petit paquet UDP à un serveur STUN et apprend l’adresse et le port publics que son routeur a attribués à cette socket. Les deux nœuds transmettent ces candidats au serveur de coordination, qui les communique à l’autre extrémité. Les deux nœuds commencent ensuite à s’envoyer des paquets en même temps. Chaque routeur voit d’abord un paquet sortant : il crée donc un mapping et accepte la réponse provenant de cette même adresse. Aucune des deux extrémités n’a besoin d’une règle de pare-feu entrante.

Les ports sont précis. Les tunnels WireGuard directs utilisent UDP avec un port source par défaut fixé à 41641. STUN utilise UDP 3478 vers les serveurs relais de Tailscale. La connexion de contrôle privilégie HTTP sur TCP 80, encapsulé dans le transport chiffré de Tailscale, puis utilise HTTPS sur TCP 443 si le port 80 ne répond pas. Les données relayées par les serveurs DERP de Tailscale utilisent HTTPS sur TCP 443, tandis qu’un relais pair que vous exécutez dans votre propre tailnet les transporte via UDP. La plupart du temps, vous n’avez rien à ouvrir en entrée. Toutefois, sur un réseau avec un NAT difficile, autoriser UDP 41641 en entrée augmente les chances d’établir une connexion directe.

tailscale netcheck

Lisez deux lignes de ce rapport. UDP: true signifie que cette machine peut envoyer des paquets UDP vers Internet, tandis que UDP: false signifie qu’elle ne le peut pas ; toutes les connexions depuis ce nœud seront donc relayées. MappingVariesByDestIP: true signifie que le routeur attribue un port public différent selon la destination. La prédiction d’adresse ci-dessus ne peut donc pas fonctionner, et ces nœuds restent généralement relayés.

Quand Tailscale utilise un relais DERP

DERP (designated encrypted relay for packets) est le mécanisme de secours. Tailscale exploite des relais dans de nombreuses régions, accessibles via TCP 443. Un nœud qui ne peut pas établir de chemin direct envoie ses paquets WireGuard par l’intermédiaire de l’un d’eux. L’exception concerne un tailnet dans lequel vous avez désigné des relais pairs : ce sont vos propres appareils, qui transmettent le trafic via UDP. Tailscale essaie d’abord ces relais et utilise DERP uniquement lorsqu’aucun n’est disponible. Dans ce cas, tailscale status affiche la connexion comme peer-relay.

Les paquets restent chiffrés. Tailscale l’indique clairement : « un serveur DERP ne peut jamais déchiffrer votre trafic. Il se contente de transmettre aveuglément le trafic déjà chiffré d’un nœud à un autre ». Un relais voit le texte chiffré. Il voit également quel nœud communique avec quel autre.

Les relais transportent aussi les premiers paquets de la plupart des connexions. L’établissement d’un chemin direct prend un moment. Une session commence donc souvent via un relais, puis passe directement dès que les deux nœuds se trouvent. Vous pouvez observer ce changement.

tailscale ping db-1

Les premières réponses reviennent via via DERP(fra). Une ligne ultérieure indique ensuite quelque chose comme via 198.51.100.24:41641. Ce changement correspond au passage à un tunnel direct. S’il ne se produit jamais, exécutez tailscale netcheck aux deux extrémités. Un chemin relayé fonctionne malgré tout. Il augmente la latence, car chaque paquet passe par une troisième machine. Si vous avez constaté des transferts lents plutôt qu’une connexion interrompue, pourquoi une connexion Tailscale relayée est beaucoup plus lente qu’une connexion directe mesure l’écart et explique comment faire passer un VPS sur un chemin direct.

Ajouter un VPS à votre tailnet

Le script d’installation prend en charge Ubuntu et Debian.

curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up

sudo tailscale up affiche une URL. Ouvrez-la, authentifiez-vous, puis le nœud apparaît dans votre console d’administration. Vérifiez ensuite que le daemon redémarre après un reboot, car cette étape est souvent oubliée.

sudo systemctl is-enabled tailscaled
tailscale status

is-enabled doit afficher enabled, et tailscale status doit lister le nouveau nœud avec son adresse 100.x. Pour un serveur construit à partir d’un script, une URL interactive ne sert à rien. Générez une auth key dans la console d’administration et transmettez-la avec un tag indiquant le type de machine.

sudo tailscale up --auth-key=tskey-auth-REPLACE-ME --advertise-tags=tag:server

Un nœud associé à un tag appartient au tag, et non à la personne qui a exécuté la commande. Il continue donc de fonctionner même si le compte de cette personne est supprimé. Le tag doit d’abord être déclaré dans votre fichier de règles sous tagOwners, sinon la commande est refusée. L’utilisation d’un tag modifie également le calcul de votre forfait : une ressource taguée est facturée séparément des appareils personnels d’un utilisateur. Ce que couvre réellement l’offre gratuite précise les limites applicables.

Deux paramètres sont importants pour un parc de machines. Les node keys expirent par défaut après 180 jours (en octobre 2026), et lorsque cette clé expire, « les connexions vers et depuis le endpoint concerné cessent de fonctionner » jusqu’à la nouvelle authentification de l’appareil. Un administrateur peut sélectionner Temporarily extend key sur une machine dont la clé a expiré dans la console d’administration. Cela accorde 30 minutes pour se reconnecter ou désactiver l’expiration. Pour un nœud authentifié avec un tag, comme celui présenté ci-dessus, l’expiration de la clé est désactivée par défaut. Pour tout autre serveur sans supervision, ouvrez la ligne de la machine dans la console d’administration et sélectionnez Disable Key Expiry. MagicDNS, activé par défaut pour les tailnets créés le 20 octobre 2022 ou après cette date, attribue à chaque nœud un nom tel que db-1.yak-bebop.ts.net, résolu par un stub resolver à 100.100.100.100. Utilisez les noms plutôt que les adresses, car un nœud reconstruit reçoit une nouvelle adresse mais conserve son nom.

Si l’installation échoue avec apt ou au niveau du repository, les erreurs courantes d’installation de Tailscale sur Ubuntu présente les correctifs.

Accéder à un service lié à localhost

C’est ici qu’un tailnet devient utile, et que les difficultés commencent souvent. Rejoindre le tailnet ne rend pas un service lié à la loopback accessible.

ss -tlnp | grep 3000

Si cette commande affiche 127.0.0.1:3000, le socket n’accepte que les paquets dont la destination est 127.0.0.1. Une requête provenant d’un autre nœud arrive avec l’adresse 100.x de ce nœud comme destination. Le kernel ne trouve donc aucun processus à l’écoute et répond par un TCP reset. Le client affiche Connection refused. Le tunnel fonctionne. Le problème vient du listener.

Deux solutions correctes sont possibles. Liez le service à l’adresse tailnet du nœud. Il restera ainsi inaccessible depuis l’interface publique, sans proxy intermédiaire. Passez --bind 100.101.102.104 ou l’option équivalente dans votre configuration. Pour un conteneur, publiez le port avec -p 100.101.102.104:3000:3000. Vous pouvez aussi laisser le service sur la loopback et placer Tailscale devant lui.

tailscale serve 3000

Cette commande proxyfie les requêtes vers http://127.0.0.1:3000 et les rend accessibles dans votre tailnet avec un nom ts.net en HTTPS, une fois les certificats HTTPS activés pour le tailnet. Le service reste privé et accessible uniquement à vos nœuds. La version publique du même principe s’appelle Funnel. La page Tailscale serve et Funnel explique lequel utiliser.

Deux tâches associées disposent de leur propre page. Pour accéder à tout un réseau privé sur lequel Tailscale n’est pas installé, utilisez un subnet router sur un VPS. Pour faire passer le trafic Internet sortant d’un nœud par un autre nœud, utilisez un exit node.

Fermer les ports dont vous n’avez plus besoin

Une fois que tous les administrateurs accèdent au serveur via le tailnet, le port public 22 ne sert plus. C’est le bénéfice concret : un port fermé ne peut pas être soumis à des attaques par force brute, et vos journaux ne se remplissent plus de tentatives.

L’ordre des opérations est important. Ajoutez l’accès via le tailnet, vérifiez que vous pouvez vous connecter par ce moyen depuis une deuxième session, puis seulement supprimez la règle publique.

sudo ufw allow in on tailscale0
sudo ufw status verbose

Supprimez ensuite la règle SSH publique et reconnectez-vous en utilisant le nom MagicDNS. Notez ce que fait réellement ufw allow in on tailscale0 : il fait confiance à tout ce qui arrive par le tunnel. Votre fichier de règles Tailscale devient donc le mécanisme de contrôle d’accès à la place de ufw. Rédigez la règle en conséquence.

Attention si vous utilisez des conteneurs. Un port publié par Docker installe ses propres règles NAT et contourne ufw ; un ufw deny ne le ferme donc pas. Les ports publiés par Docker contournent ufw explique ce mécanisme. Publier le port sur l’adresse du tailnet, comme ci-dessus, permet d’éviter ce problème. Si l’application s’exécute avec Docker Compose, un sidecar Tailscale dans la stack Compose va plus loin et supprime complètement le port publié. Le conteneur reste alors accessible uniquement via son nom sur le tailnet.

Ce que Tailscale protège et ce qu’il ne protège pas

Il est utile de l’énoncer clairement, car la présentation marketing brouille cette distinction.

Protégé : le trafic entre deux nœuds est chiffré de bout en bout avec WireGuard, et aucun relais intermédiaire ne peut le lire. Les clés privées ne quittent jamais la machine qui les a générées. Les nœuds n’ont besoin d’aucun port public entrant : Internet ne peut donc rien analyser sur 22 ou 5432. Les communications entre les nœuds sont contrôlées par un fichier de stratégie, et non par toute personne qui connaît une adresse.

Non protégé : le serveur de coordination voit la topologie de vos appareils. Ces métadonnées sont sensibles en elles-mêmes, car les noms des machines, leurs propriétaires, leurs adresses et leurs heures de connexion décrivent votre infrastructure. Le serveur distribue également les clés, ce qui constitue le risque le plus important. Tailscale l’indique directement : « Si Tailscale était malveillant et ajoutait discrètement de nouveaux nœuds à votre réseau, Tailscale pourrait envoyer du trafic vers vos nœuds existants ou en recevoir en clair. » Votre fournisseur de single sign-on se trouve dans le même chemin de confiance, car toute personne capable d’y créer une identité peut ajouter un nœud. Un nœud compromis est par ailleurs un pair du tailnet : ce qu’il peut atteindre ensuite dépend de ce que votre stratégie autorise. Le caractère acceptable de ce risque dépend de la personne ou de l’organisation contre laquelle vous vous protégez. Le modèle de confiance complet examine chacun de ces cas, notamment ce qu’un compte d’identité dérobé permet réellement de faire.

Il existe deux réponses au risque lié à la distribution des clés. La première est tailnet lock. Cette fonctionnalité exige que des nœuds de confiance existants signent cryptographiquement un nouveau nœud avant que vos autres nœuds l’acceptent. Un control plane qui ajoute un nœud sans signature valide est ignoré. La console d’administration génère la ligne tailscale lock init exacte pour vos nœuds de signature, et chaque nœud peut vérifier ce qu’il reçoit.

tailscale lock status

Tous les nœuds doivent déclarer le même ensemble de clés de signature approuvées. La seconde réponse consiste à exécuter vous-même le control plane. Un serveur de coordination Headscale auto-hébergé utilise le même protocole avec les mêmes clients, ce qui déplace la topologie des appareils et la distribution des clés vers du matériel que vous contrôlez. Vous êtes alors également responsable de la disponibilité de ce serveur. Si vous comparez encore les control planes auto-hébergés au lieu de retenir celui-ci, NetBird est un VPN mesh distinct dont vous exécutez le serveur de bout en bout sur un seul VPS.

Un réglage doit être corrigé dès le premier jour. Un nouveau tailnet est permissif par défaut : « le fichier de stratégie par défaut du tailnet autorise les communications entre tous les appareils du tailnet ». Dès que vous ajoutez une section acls, le modèle passe à un refus par défaut et seules vos règles autorisent les communications.

{
  "tagOwners": {
    "tag:server": ["autogroup:admin"]
  },
  "acls": [
    {"action": "accept", "src": ["autogroup:member"], "dst": ["tag:server:22"]}
  ]
}

Cette stratégie permet aux membres du tailnet d’accéder à SSH sur les serveurs marqués, et à rien d’autre. Ajoutez une règle par service au lieu de conserver le caractère générique, car celui-ci permet à une seule clé d’ordinateur portable dérobée d’atteindre votre base de données.

Modes de défaillance et messages affichés

tailscale status indique toujours relay. Les deux nœuds n’ont jamais établi de chemin direct. Exécutez tailscale netcheck aux deux extrémités. UDP: false signifie que le trafic UDP sortant est bloqué ; seul un relais peut donc fonctionner. MappingVariesByDestIP: true signifie qu’un NAT strict est présent. Autoriser le trafic UDP entrant sur le port 41641 du côté que vous contrôlez règle souvent le problème.

Un nœud qui fonctionnait depuis des mois a disparu. Une cause fréquente est l’expiration de la clé du nœud après les 180 jours par défaut. Vérifiez donc d’abord la machine dans la console d’administration. Si elle est indiquée comme expirée, sudo tailscale up sur la machine la réactive. Désactiver l’expiration des clés sur les serveurs évite que le problème se reproduise. Si la clé n’est pas expirée, vérifiez le fichier de stratégie. Tailscale recommande, lorsqu’un appareil est absent de tailscale status, de rechercher les règles d’accès qui empêchent la connexion.

Les pairs sont répertoriés, mais les connexions expirent. Si tailscale ping reçoit des réponses, la connectivité fonctionne. La cause probable est donc que la stratégie refuse le trafic. Vérifiez la section acls et recherchez une règle couvrant cette source, cette destination et ce port. Un paquet refusé est supprimé au lieu de recevoir une réponse. C’est pourquoi vous obtenez un délai d’expiration plutôt que Connection refused.

Les noms MagicDNS ne sont pas résolus. ping db-1 échoue alors que ping 100.101.102.104 fonctionne. Vérifiez d’abord que le client accepte les paramètres DNS de Tailscale. Un nœud démarré avec --accept-dns=false n’envoie jamais ses requêtes au résolveur stub situé à 100.100.100.100. Examinez ensuite cat /etc/resolv.conf ainsi que les autres composants de la machine qui écrivent dans ce fichier. Sur un système utilisant systemd-resolved, ce fichier est normalement un lien symbolique vers /run/systemd/resolve/stub-resolv.conf. Il est donc normal que 100.100.100.100 n’y soit pas listé. Lorsque tailscaled écrit directement dans le fichier, un client DHCP ou un autre outil qui l’écrase interrompt MagicDNS. Si aucune de ces vérifications n’explique le problème, l’erreur peut également se trouver dans la configuration DNS locale ou réseau. Il s’agit du même type de problème que DNS qui ne fonctionne plus dans un tunnel WireGuard.

tailscale up refuse votre tag. Le tag n’est pas déclaré sous tagOwners dans le fichier de stratégie. Ajoutez-le à cet endroit, puis exécutez à nouveau la commande.

FAQ

Tailscale est-il un VPN ou un réseau mesh ?

Les deux termes sont corrects, mais ils décrivent des couches différentes. Les tunnels utilisent WireGuard, ce qui en fait un VPN. La topologie est un mesh, car chaque nœud établit un tunnel directement avec chaque nœud auquel il parle, au lieu d’envoyer chaque paquet via un serveur central. Le serveur de coordination intervient dans le plan de contrôle, pas dans le plan de données. S’il devient inaccessible, vos tunnels existants continuent donc de transporter le trafic. En cas de panne, seuls l’ajout de nouveaux nœuds et l’application des changements de clés ou de stratégie sont interrompus.

Tailscale peut-il lire mon trafic ?

Pas son contenu. Le trafic est chiffré de bout en bout entre les nœuds avec WireGuard, les clés privées ne quittent jamais les nœuds et un relais DERP transmet des paquets qu’il ne peut pas déchiffrer. Tailscale voit toutefois les métadonnées : noms des machines, propriétaires, clés publiques, adresses des endpoints et état en ligne de chaque nœud. Il distribue également les clés. Un serveur de coordination compromis pourrait donc tenter d’insérer un nœud auquel votre parc ferait ensuite confiance. Tailnet lock bloque ce scénario en exigeant des signatures de vos propres nœuds de confiance. Headscale retire par ailleurs le plan de contrôle hébergé de l’architecture.

Dois-je ouvrir des ports du firewall pour Tailscale ?

Presque jamais en entrée. Tailscale indique que « la plupart du temps, vous n’avez pas besoin d’ouvrir de ports du firewall ». En sortie, un nœud a besoin de TCP 443 vers le serveur de coordination et les relais, ainsi que d’UDP 3478 pour STUN. Les tunnels directs utilisent UDP avec un port source qui vaut 41641 par défaut. Autoriser UDP 41641 en entrée est facultatif. Cela aide uniquement les connexions directes à fonctionner sur les réseaux difficiles.

Pourquoi les autres nœuds ne peuvent-ils pas atteindre mon service sur le port 3000 ?

Vérifiez d’abord l’adresse d’écoute avec ss -tlnp. Un listener sur 127.0.0.1:3000 refuse les connexions destinées à l’adresse tailnet 100.x du nœud, car ce socket n’accepte que la destination loopback. Le client reçoit alors Connection refused. Faites écouter le service sur l’adresse tailnet, ou exécutez tailscale serve 3000 pour servir de proxy. Si le listener écoute déjà sur 0.0.0.0 et que la connexion expire au lieu d’être refusée, l’adresse d’écoute n’est pas en cause. Examinez d’abord les règles de stratégie et les firewalls de l’hôte, puis les firewalls réseau et vérifiez si l’authentification de l’un des deux appareils a expiré.

Dois-je utiliser Headscale à la place du serveur de coordination de Tailscale ?

Utilisez Headscale lorsque le graphe des appareils ou la distribution des clés doit rester sur une infrastructure que vous contrôlez, ou lorsque le tailnet doit fonctionner sans dépendre d’un service externe. Les clients et le protocole sont identiques. En contrepartie, vous devez exploiter le serveur de coordination. En cas de panne, l’ajout de nouveaux nœuds et l’application des changements de stratégie sont interrompus. Pour un petit parc, le plan de contrôle hébergé avec tailnet lock activé offre généralement le meilleur compromis.