SSD Nodes Learn Hosting plans →
Guides Matt ConnorPar Matt Connor · Mis à jour le 2026-08-26

Configurer un subnet router Tailscale sur un VPS

Rendez un réseau privé accessible depuis votre tailnet avec un VPS : approbation de la route, IP forwarding persistant après redémarrage et --accept-routes sous Linux.

Ce que fait un subnet router Tailscale

Un subnet router Tailscale est une machine qui annonce une plage complète d’adresses IP privées à votre tailnet. Tous les appareils du tailnet peuvent ainsi atteindre les adresses de cette plage, même si aucun appareil de cette plage n’exécute Tailscale. Votre tailnet est votre réseau Tailscale privé : l’ensemble des appareils connectés au même compte ou à la même organisation. Un exit node est la fonctionnalité avec laquelle on le confond souvent, mais il remplit la fonction inverse. Il achemine tout le trafic d’un appareil via le VPS, qui devient alors la route de cet appareil vers Internet public.

Une phrase pour chacun. Un subnet router rend un réseau privé accessible depuis le tailnet. Un exit node modifie le point de sortie de votre trafic public. Si c’est ce second fonctionnement que vous recherchez, consultez plutôt comment exécuter un exit node Tailscale sur un VPS. Ce sont des flags distincts. Un même VPS peut utiliser les deux en même temps, mais ils répondent à des problèmes différents et ne rencontrent pas les mêmes pannes.

Quand un VPS doit servir de subnet router

Le cas le plus courant concerne un réseau privé déjà fourni par votre hébergeur. Votre VPS possède une adresse publique et une seconde interface sur un segment privé. Les autres serveurs de ce segment n’ont aucune adresse publique : une base de données à 10.0.0.20 et une cible de sauvegarde à 10.0.0.30. Installez Tailscale sur un VPS et annoncez 10.0.0.0/24. Votre ordinateur portable pourra alors joindre directement ces adresses privées. Rien d’autre ne change sur le segment, et la base de données ne possède toujours aucune adresse publique. Si ce segment ne vous sert qu’à accéder à une seule application web sur un seul port, annoncer toute la plage dépasse le besoin réel. Dans ce cas, Tailscale serve active plutôt HTTPS sur ce seul port. Le même raisonnement s’applique à un daemon qui se lie volontairement à localhost uniquement, comme dsh exécuté sans interface sous systemd. Une adresse du tailnet sur ce VPS remplace alors le tunnel SSH que vous devriez autrement maintenir ouvert pour accéder à son interface.

L’autre cas concerne un réseau situé de l’autre côté du VPS. Il peut s’agir d’un LAN (local area network) domestique ou professionnel derrière son propre routeur, ou d’un ensemble d’équipements qui ne peuvent pas exécuter Tailscale, comme un switch administrable ou un ancien NAS doté d’un firmware verrouillé. Une machine Linux de ce réseau devient le subnet router pour tous les autres équipements. À domicile, cette machine est souvent une petite VM sur un hyperviseur que vous exploitez déjà. Le calcul du coût d’un hôte Proxmox à domicile par rapport à un VPS loué doit alors être fait avant de décider de quel côté du tunnel vos services doivent fonctionner.

Les deux cas ont une exigence commune. Le subnet router doit déjà pouvoir atteindre la plage qu’il annonce, avec sa propre table de routage et son propre firewall. Tailscale ne crée pas cette connexion. Il achemine le trafic jusqu’au routeur, puis le remet au kernel afin qu’il le transmette.

Installer Tailscale et vérifier d’abord la route locale

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

Le script détecte la distribution, ajoute le dépôt de paquets de Tailscale, installe la commande tailscale et le daemon tailscaled, puis active le service. Vérifiez-le avec systemctl is-active tailscaled, qui doit afficher active.

Avant toute autre étape, vérifiez que le VPS peut atteindre le réseau que vous prévoyez d’annoncer.

ip route show
ping -c3 10.0.0.20

ip route show doit lister la plage privée sur une interface réelle, par exemple 10.0.0.0/24 dev enp7s0 proto kernel scope link src 10.0.0.5. Si le ping échoue ici, directement vers le routeur, aucun flag Tailscale ne pourra résoudre le problème. Le problème vient de la configuration réseau du VPS ou d’un firewall sur l’hôte cible. Corrigez-le d’abord, car tous les tests suivants en dépendent.

Activer le routage IP et le conserver après un redémarrage

Une machine Linux abandonne tout paquet qui ne lui est pas destiné, sauf si le routage est activé. Transmettre les paquets d’autres machines est précisément le rôle d’un routeur de sous-réseau. Cette étape est donc obligatoire.

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

Vérifiez le réglage avec sysctl net.ipv4.ip_forward. La commande doit afficher net.ipv4.ip_forward = 1.

Cette étape est souvent configurée à moitié. sudo sysctl -w net.ipv4.ip_forward=1 fonctionne immédiatement, mais sa valeur est perdue au prochain démarrage. Le routeur de sous-réseau fonctionne alors pendant des semaines, puis cesse de fonctionner le matin suivant un redémarrage provoqué par une mise à niveau du kernel. Le problème est difficile à repérer, car rien ne semble défectueux. tailscale status indique toujours que le nœud est en ligne, la console d’administration indique toujours que la route est approuvée et les clients ont toujours installé la route. Les paquets arrivent sur le VPS, puis le kernel les abandonne sans rien écrire dans les journaux. Écrire les valeurs dans /etc/sysctl.d/99-tailscale.conf permet de les restaurer après un redémarrage.

Si vous annoncez des routes alors que le routage est toujours désactivé, tailscale up vous en avertit immédiatement avec une ligne proche de Warning: IPv4 forwarding is disabled. Subnet routes and exit nodes may not work correctly.. Lisez la sortie de cette commande au lieu de la faire défiler sans la consulter.

Annoncer les routes

sudo tailscale up --advertise-routes=10.0.0.0/24

Sur un VPS déjà connecté à votre tailnet, modifiez directement le paramètre :

sudo tailscale set --advertise-routes=10.0.0.0/24

Utilisez tailscale set pour toutes les modifications ultérieures. Relancer tailscale up avec un seul indicateur réinitialise les indicateurs que vous n’avez pas répétés. La CLI s’arrête alors avec une erreur indiquant que cette méthode de modification exige de mentionner tous les indicateurs non définis par défaut. tailscale set modifie un seul paramètre et laisse les autres inchangés.

Plusieurs plages s’inscrivent dans une seule liste séparée par des virgules, sans espaces : --advertise-routes=10.0.0.0/24,192.168.50.0/24. Chaque entrée doit être une adresse réseau en notation CIDR (classless inter-domain routing, au format 10.0.0.0/24). Si vous indiquez par erreur votre propre adresse d’hôte, 10.0.0.5/24, la valeur est rejetée, car les bits situés après le préfixe ne sont pas nuls. L’erreur indique le préfixe que vous vouliez probablement utiliser. Pour arrêter l’annonce, définissez une liste vide avec sudo tailscale set --advertise-routes=.

Approuver la route dans la console d’administration

La publication d’une route est une demande, pas une modification effective. Tant qu’un administrateur ne l’a pas approuvée, aucun client ne reçoit cette route et aucune adresse de la plage n’est accessible. Ce fonctionnement est volontaire : une machine capable de s’ajouter à la table de routage de tout le monde pourrait intercepter le trafic de n’importe quelle plage.

Approuvez-la dans la page Machines de la console d’administration. Le VPS apparaît avec un badge de sous-réseau. Ouvrez sa ligne, repérez la section des sous-réseaux, modifiez les paramètres de la route, cochez la route, puis enregistrez.

L’approbation s’applique à chaque préfixe. Si vous publiez 10.0.0.0/24 aujourd’hui, puis 192.168.50.0/24 le mois prochain, le nouveau préfixe apparaît comme non approuvé, tandis que l’ancien continue de fonctionner. Une route approuvée et une route ignorée sont identiques depuis le VPS. Consultez donc la console avant d’entreprendre tout autre diagnostic.

Vous pouvez éviter cette étape manuelle avec un bloc autoApprovers dans le fichier de règles tailnet :

{
  "autoApprovers": {
    "routes": {
      "10.0.0.0/24": ["tag:subnet-router"]
    }
  }
}

Démarrez ensuite le nœud avec cette étiquette, sudo tailscale up --advertise-routes=10.0.0.0/24 --advertise-tags=tag:subnet-router, et la route est approuvée dès sa publication. L’étiquette doit d’abord exister dans la section tagOwners du même fichier de règles. Cette configuration est utile si vous reconstruisez le VPS à partir d’un script, car un nœud reconstruit est un nouveau nœud et ses routes redeviennent non approuvées.

Pourquoi les clients Linux ignorent la route sans --accept-routes

La route est maintenant annoncée et approuvée. Votre téléphone et votre Mac peuvent atteindre 10.0.0.20. Votre ordinateur portable Linux ne le peut pas, et rien dans la console d’administration n’indique de problème.

Accepter une route de sous-réseau consiste à ajouter des entrées dans la table de routage du client. Sous Android, iOS, macOS, tvOS et Windows, le client Tailscale s’en charge. Sous Linux, ce n’est pas le cas, car une machine Linux est souvent un serveur ou un routeur dont la table de routage a été configurée volontairement. Insérer silencieusement une /24 apprise du réseau pourrait interrompre le trafic déjà géré par cette machine. Sous Linux, vous devez donc activer cette option sur chaque client :

sudo tailscale set --accept-routes

Vérifiez ensuite où la route a été installée :

ip route show table 52
ip route get 10.0.0.20

Sous Linux, Tailscale ne place pas les routes acceptées dans la table de routage principale. Il les place dans la table de routage 52 et installe des règles de policy routing, visibles avec ip rule show dans la plage de priorités 5210 à 5270, qui envoient les paquets ne correspondant à aucune règle vers cette table. Ainsi, ip route show seul ne répertorie jamais 10.0.0.0/24, et un lecteur qui vérifie uniquement cette commande peut conclure que --accept-routes n’a rien fait. ip route show table 52 est la commande qui montre la réalité et doit répertorier la plage annoncée sur tailscale0.

Une exception mérite d’être connue. Si ce nœud Linux est lui-même un second subnet router pour son réseau local, --accept-routes lui fait envoyer le trafic destiné à son propre sous-réseau directement connecté via l’autre routeur, au lieu de l’envoyer par sa propre interface. Sur un routeur de secours dans une paire haute disponibilité, laissez --accept-routes désactivé et contentez-vous d’annoncer la route.

Mode d’échec : deux routeurs annoncent des plages qui se chevauchent

Deux subnet routers ne doivent pas annoncer des plages identiques. Les plages qui se chevauchent avec des longueurs de préfixe différentes sont autorisées, et Tailscale sélectionne la correspondance la plus spécifique. Si le routeur A annonce 10.0.0.0/24 et le routeur B annonce 10.0.0.0/16, le trafic vers 10.0.0.20 passe par A.

Le comportement lorsque A est hors ligne est moins intuitif. Tailscale ne bascule pas vers la route moins spécifique. Le trafic vers 10.0.0.20 s’arrête, tandis que le trafic vers 10.1.0.20 continue de fonctionner via B. Le symptôme ressemble à une panne de la moitié du réseau privé, alors que la cause est un nœud hors ligne qui détient le préfixe le plus spécifique. Pour mettre en place un failover, faites aussi annoncer les préfixes plus étroits par le routeur qui annonce la plage la plus large, afin que les deux couvrent les mêmes adresses.

L’autre conflit se situe plus près du client. Si vous êtes connecté à un réseau d’hôtel en 192.168.1.0/24 alors que votre subnet router annonce 192.168.1.0/24, les deux routes se disputent les mêmes destinations. Celle qui l’emporte dépend de la plateforme. Sous Linux, ajoutez une règle avant celle de Tailscale afin que les adresses locales utilisent la table principale :

sudo ip rule add to 192.168.1.0/24 priority 2500 lookup main

Cette règle n’est pas persistante et disparaît au prochain démarrage. La vraie solution consiste à choisir une plage privée que vous ne rencontrerez pas sur les réseaux courants. 192.168.0.0/24 et 192.168.1.0/24 sont les valeurs par défaut de la plupart des routeurs domestiques. Choisissez donc une plage dans 10.0.0.0/8 de manière délibérée. Le même conflit affecte un VPN WireGuard classique configuré manuellement, pour la même raison : la route locale la plus spécifique l’emporte, et le trafic n’entre donc jamais dans le tunnel.

Mode d’échec : le DNS résout le nom vers une adresse couverte par aucune route

Ce cas est difficile à diagnostiquer, car rien ne signale d’erreur. Le nom est résolu. La connexion expire.

Supposons que db.internal.example.com soit résolu vers 10.0.5.20 par votre nameserver privé et que vous ayez annoncé 10.0.0.0/24. La résolution aboutit, car la résolution DNS (domain name system) et le routage IP sont deux étapes distinctes et qu’aucune ne vérifie l’autre. Le paquet destiné à 10.0.5.20 ne trouve alors aucune route correspondante sur le tailnet. Il sort donc par la passerelle par défaut du client, puis disparaît.

Deux commandes permettent de distinguer ces deux étapes :

nslookup db.internal.example.com
ip route get 10.0.5.20

Si la résolution renvoie une adresse, mais que ip route get ne répond pas avec dev tailscale0, le nom est correct et la route est absente. Annoncez une plage qui couvre l’adresse, soit 10.0.0.0/16, soit un second préfixe explicite, puis approuvez le nouveau préfixe dans la console.

Le nameserver lui-même présente un piège similaire. Si vous définissez un nameserver global dans la console d’administration avec une adresse privée telle que 10.0.0.53, cette adresse doit se trouver dans une route approuvée. Sinon, vos appareils ne peuvent pas atteindre le resolver. Si vous activez l’option qui remplace les serveurs DNS locaux tout en indiquant un resolver inaccessible, tous les appareils du tailnet perdent immédiatement la résolution de noms, y compris ceux qui fonctionnaient encore quelques secondes auparavant. Annoncez et approuvez d’abord la route vers le resolver, puis modifiez le paramètre DNS. Si le DNS dans un tunnel est le problème que vous devez constamment résoudre, la façon dont le DNS tombe en panne dans un tunnel WireGuard décrit le même mécanisme, sans la couche de coordination supplémentaire.

NAT source et liaisons site à site

Par défaut, le subnet router réécrit l’adresse source de chaque paquet transféré avec sa propre adresse privée. Il s’agit du SNAT (source network address translation). Cette fonction permet aux réponses de fonctionner sans modifier le réseau privé : la base de données à 10.0.0.20 répond au VPS, qu’elle sait déjà joindre. En contrepartie, la base de données voit toutes les connexions du tailnet comme provenant du VPS. Les règles de pare-feu par source et les journaux d’accès ne vous fournissent donc aucune information utile.

Désactivez cette fonction sous Linux lorsque vous voulez conserver l’adresse tailnet réelle du client :

sudo tailscale set --snat-subnet-routes=false

Les hôtes du réseau privé ont alors besoin d’une route de retour vers 100.64.0.0/10, la plage que Tailscale attribue aux appareils, en passant par le subnet router. Sans cette route de retour, leurs réponses passent par la passerelle par défaut et n’arrivent jamais à destination. Les connexions restent donc bloquées après le premier paquet. Ajoutez la route statique sur la passerelle du réseau privé, ou laissez le SNAT activé.

Une liaison site à site repose sur deux subnet routers qui effectuent cette opération simultanément. Chacun annonce son propre réseau et accepte celui de l’autre :

sudo tailscale up --advertise-routes=10.0.0.0/24 --snat-subnet-routes=false --accept-routes

Exécutez la commande correspondante sur l’autre routeur avec sa propre plage. Les deux plages doivent être différentes. Si les transferts volumineux se bloquent alors que ssh et ping fonctionnent, la cause est la MSS (maximum segment size), c’est-à-dire la taille maximale des données transportées par un paquet TCP. La surcharge du tunnel rend les paquets transférés trop volumineux pour une liaison intermédiaire. Le clamping corrige ce problème :

sudo iptables -t mangle -A FORWARD -o tailscale0 -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

Enregistrez cette règle avec iptables-persistent, sinon elle disparaîtra au prochain démarrage.

Maintenance pour assurer la continuité

Par défaut, les clés des nœuds expirent après 180 jours, depuis août 2026. Lorsque la clé d’un subnet router expire, le nœud est déconnecté et toute la plage annoncée devient inaccessible, sans qu’aucune modification de configuration ne l’explique. Désactivez l’expiration des clés pour cette machine dans la page Machines de la console d’administration, puis notez que vous l’avez fait.

Tailscale privilégie une connexion directe entre les pairs et utilise ses serveurs relais lorsqu’il ne peut pas en établir une. Les relais fonctionnent, mais ils ajoutent de la latence. Un VPS avec une adresse publique est le cas le plus simple : autorisez les connexions UDP entrantes sur 41641 et la plupart des pairs se connecteront directement. Si ufw gère le firewall, les règles ufw réellement nécessaires sur un VPS en indiquent la syntaxe.

Les règles d’accès constituent l’autre partie. Sur un tailnet par défaut, tous vos appareils peuvent joindre les autres, et une route approuvée fonctionne donc directement. Dès que vous écrivez une policy ACL, la destination d’une règle doit nommer la plage privée, car 10.0.0.20 n’est pas une adresse de tailnet et n’est pas couverte par les règles écrites avec des adresses IP de tailnet ou des tags.

Enfin, déterminez si vous acceptez d’utiliser un serveur de coordination que vous n’administrez pas. Le control plane de Tailscale est un service hébergé. Vos clés restent sur vos machines, mais le compte et le fichier de policy y résident. Avant de lui donner une route vers votre réseau privé, il est important de déterminer ce qu’une personne pourrait réellement faire avec un control plane compromis ou des identifiants de connexion volés. Le modèle de confiance de Tailscale précise où se situe cette limite. Le coût pousse rarement les utilisateurs à abandonner ce modèle, car le forfait gratuit couvre jusqu’à six utilisateurs avec un nombre illimité de leurs propres appareils. Toutefois, un subnet router lancé avec un tag est comptabilisé différemment d’un subnet router connecté avec votre compte. Au-delà, la facturation dépend du nombre de personnes et non du nombre de machines. Il est donc utile de calculer ce qu’un foyer ou une équipe de cinq personnes paie réellement une fois le forfait gratuit dépassé avant d’ajouter le compte qui vous fait franchir le seuil. Headscale, le serveur de contrôle Tailscale auto-hébergé permet de conserver cette fonction sur votre propre VPS, au prix de sa maintenance. L’autre réponse à cette question consiste également à ne plus utiliser les clients Tailscale : auto-héberger le serveur VPN NetBird place la couche de coordination et ses propres clients mesh sur une machine que vous contrôlez. Si vous hésitez encore entre ce modèle et une configuration écrite manuellement, la comparaison entre WireGuard et Tailscale explique ce que la couche de coordination apporte et ce qu’elle coûte.

FAQ

Quelle est la différence entre un subnet router et un exit node ?

Un subnet router annonce une plage d’adresses privées. Les appareils du tailnet peuvent ainsi accéder à des machines qui n’exécutent pas Tailscale. Un exit node s’annonce comme une route vers l’ensemble d’Internet. Un appareil envoie alors tout son trafic via l’adresse publique de ce nœud. Un même VPS peut remplir les deux fonctions. Il s’agit de deux flags distincts, --advertise-routes et --advertise-exit-node. Chacun nécessite sa propre approbation dans la console d’administration.

Pourquoi mon client Linux ignore-t-il la route de subnet annoncée ?

Les clients Linux n’acceptent pas les routes de subnet tant que vous ne leur demandez pas de le faire. Exécutez sudo tailscale set --accept-routes sur le client. Vérifiez ensuite avec ip route show table 52, et non avec ip route show. Tailscale installe les routes acceptées dans la table de routage 52 et les utilise via des policy rules. La table principale ne les liste donc jamais, ce qui peut donner l’impression qu’une route fonctionnelle est absente.

Mon subnet ne fonctionne plus après un redémarrage. Que s’est-il passé ?

Il s’agit probablement de l’IP forwarding. Une valeur définie avec sysctl -w ne survit pas à un redémarrage. Écrivez-la donc dans /etc/sysctl.d/99-tailscale.conf, puis vérifiez-la avec sysctl net.ipv4.ip_forward. Si le forwarding est activé et que la plage reste inaccessible, consultez le nœud dans la console d’administration. Par défaut, les node keys expirent après 180 days. Un subnet router dont la clé a expiré ressemble alors à un problème réseau plutôt qu’à un problème de compte.

Deux subnet routers peuvent-ils annoncer la même plage ?

Pas des plages identiques. Les plages qui se chevauchent avec des longueurs de préfixe différentes sont acceptées. La route la plus spécifique est alors utilisée. Le failover nécessite toutefois de la prudence : lorsque le routeur qui détient le préfixe le plus spécifique est hors ligne, Tailscale ne bascule pas vers la route plus large. Le trafic est donc interrompu. Pour mettre en place une véritable paire standby, faites annoncer les mêmes préfixes spécifiques par les deux routeurs.

Le hostname est résolu, mais la connexion expire. Pourquoi ?

La résolution DNS et le routage sont deux étapes distinctes. Un nom peut être résolu vers une adresse qui n’est couverte par aucune route approuvée. Le paquet sort alors via la default gateway du client. Exécutez ip route get <address> sur le client. Si la réponse n’inclut pas dev tailscale0, annoncez une plage qui couvre cette adresse, puis approuvez le nouveau préfixe dans la console d’administration.