Fonctionnement du tailnet
Le tailnet est le VPN maillé du réseau : il relie les zones, le serveur de coordination (HCS) et les appareils distants. Headscale 🡕 le coordonne, Tailscale 🡕 le fait vivre sur chaque nœud. Cette page explique qui y figure, par où passent paquets et requêtes DNS, qui peut joindre quoi, et comment une machine y entre. Les gestes d’exploitation sont dans VPN.
Plan de contrôle, plan de données
Section intitulée « Plan de contrôle, plan de données »Headscale distribue les informations, jamais le trafic : les nœuds échangent directement entre eux, chiffrés par WireGuard 🡕.
| Plan | Porté par | Contenu |
|---|---|---|
| Contrôle | Headscale sur le HCS (HTTPS) | identités, clés publiques, adresses, routes, DNS, filtres ACL |
| Données | chaque client Tailscale (UDP 41641) | le trafic, d’un nœud à l’autre |
| Relais | serveurs DERP publics de Tailscale | le trafic chiffré, faute de chemin direct |
- Les nœuds percent le NAT pour se joindre en direct. Le port UDP 41641 est ouvert sur le HCS et sur le WAN des passerelles, ce qui aide derrière un NAT strict.
- Sans chemin direct (UDP filtré, NAT strict des deux côtés), le trafic passe par un relais DERP : toujours chiffré de bout en bout, mais plus lent.
- HCS indisponible : les tunnels établis continuent de fonctionner, mais rien ne change (nouveau nœud, nouvelle route, nouvelle politique) jusqu’à son retour.
Qui est sur le tailnet
Section intitulée « Qui est sur le tailnet »Deux sortes d’identités coexistent : les machines, identifiées par un tag qui dit leur rôle, et les appareils personnels, rattachés à leur propriétaire.
| Nœud | Identité | Obtenue par | Expiration |
|---|---|---|---|
| HCS | tag:hcs | clé à usage unique (just tailnet-enroll) | jamais |
| Passerelle d’une zone | tag:gw-<zone> | clé à usage unique | jamais |
| Poste d’administration | tag:admin | clé à usage unique | jamais |
| Appareil personnel | son propriétaire (alice@) | connexion Kanidm | 180 jours |
- Les tags se déduisent de la topologie : profil
hcs, passerelle de zone, hôte dontgroupscontientadminet qui active le client Tailscale. - Un nœud tagué n’appartient à personne (
tagged-devicesdans Headscale). - Seuls les comptes du groupe Kanidm
tailnetconnectent un appareil : administrateurs et membres d’une zone (groupezone-<zone>). - Les
tagslibres d’un hôte dansetc/config.yamln’accordent aucun droit. - Chaque nœud porte un nom MagicDNS :
<nœud>.tailnet.internal.
Le tailnet donne une adresse à chaque nœud et relie les sous-réseaux des zones.
Trajet d’un poste de la zone maison vers un serveur de la zone atelier :
| Trajet | Chemin | Mécanisme |
|---|---|---|
| Poste d’une zone → autre zone | sa passerelle, le tailnet, la passerelle distante | routes de sous-réseau |
| Appareil distant → service d’une zone | le tailnet, la passerelle de la zone | route de sous-réseau de la zone |
| Appareil distant → service global | le tailnet, le HCS | adresse tailnet du HCS |
| Nœud → nœud | direct | adresses 100.64.x.y |
| Nœud → Internet | sa propre connexion | exit node du HCS fermé par défaut |
- Adresses : Headscale les attribue dans l’ordre, dans
100.64.0.0/10(etfd7a:115c:a1e0::/48). Une machine réinstallée (nouvelle clé de machine) en reçoit une nouvelle. - Routes annoncées : chaque passerelle annonce le
/16de sa zone. La politique l’approuve d’office pour le seultag:gw-<zone>: une passerelle ne peut pas détourner le sous-réseau d’une autre zone. - Routes acceptées : chaque client installe les
/16des autres zones dans la table de routage 52 de Tailscale, consultée avant la table principale. Une passerelle n’y installe pas sa propre zone. - Sans SNAT : une passerelle relaie sans masquer la source
(
--snat-subnet-routes=false). Une machine de la zone voit la vraie adresse tailnet et répond par sa route par défaut, la passerelle ; d’où le filtrage de chemin inverse souple des passerelles (règleR12de la sécurité). - Exit node : le HCS s’annonce comme sortie vers Internet, approuvée d’office,
mais aucune règle ne l’autorise tant que
policy.exitNodeSourcesest vide. - Filtrage : la politique s’applique à l’arrivée. Pour une zone, c’est sa passerelle qui trie ce qui entre depuis le tailnet.
Ce qu’une passerelle laisse traverser est détaillé dans Ce qui traverse une passerelle.
Chaque machine interroge un résolveur différent, mais les noms d’une zone finissent toujours chez le même détenteur : la passerelle de cette zone.
| Machine | Résolveur | Noms d’une zone | Services globaux | Internet |
|---|---|---|---|---|
| Poste d’une zone, passerelle | dnsmasq de la passerelle, derrière AdGuard Home s’il est activé | dnsmasq, ou passerelle de la zone | dnsmasq, ou unbound du HCS | DNS publics, filtrés par AdGuard Home |
| HCS | unbound, local | passerelle de la zone | unbound | Quad9, chiffré |
| Appareil distant | MagicDNS (100.100.100.100) | par unbound du HCS | par unbound du HCS | résolveur du réseau visité |
- Passerelle : dnsmasq connaît les machines de toutes les zones et les
services déclarés. Un nom inconnu d’une autre zone part vers la passerelle de cette
zone (adresse LAN, à travers le tailnet) ; le reste de
domain.tldpart vers unbound, sur le HCS. - Services d’une zone :
*.<zone>.domain.tldpointe vers l’adresse LAN de la passerelle de la zone, qui les sert derrière son proxy. - HCS : unbound écoute sur
127.0.0.1et sur l’adresse tailnet du HCS, pour les seules adresses du tailnet. Il transmet<zone>.domain.tldau résolveur de la passerelle, à son adresse tailnet : d’où l’importance de déclarervpn.ipv4. headscale.domain.tld: jamais demandé au tunnel qu’il sert à monter, voir Amorçage du plan de contrôle.
MagicDNS
Section intitulée « MagicDNS »MagicDNS est le petit résolveur que chaque client Tailscale embarque, à l’adresse
100.100.100.100. Headscale l’active pour tout le tailnet et lui transmet ses
consignes :
| Consigne | Valeur | Effet |
|---|---|---|
| Noms des nœuds | tailnet.internal | gw-atelier.tailnet.internal → adresse tailnet, tenue à jour par Headscale |
| Domaine de recherche | tailnet.internal | ssh gw-atelier suffit |
| DNS scindé | domain.tld → unbound du HCS | les noms internes partent, par le tunnel, au résolveur pivot |
| Résolveur global | aucun | le reste va au résolveur habituel de l’appareil |
Où il intervient
Section intitulée « Où il intervient »Un client ne s’en sert comme résolveur que s’il accepte le DNS du tailnet
(--accept-dns).
| Machine | --accept-dns | Rôle de MagicDNS |
|---|---|---|
| Appareil personnel, portable hors zone | oui | résolveur du système : noms des nœuds et DNS scindé |
| Portable rebranché dans sa zone | client en pause | aucun, la passerelle locale reprend la main |
| Passerelle | non | noms inverses des adresses 100.x, pour les statistiques d’AdGuard Home |
| HCS | oui | présent, mais le système interroge unbound (127.0.0.1) |
| Poste d’une zone | pas de client | aucun |
Pourquoi
Section intitulée « Pourquoi »- Nommer les nœuds hors des zones : un portable en déplacement joint
gw-atelieren direct sur le tailnet, sans dépendre d’une route de sous-réseau ni du DNS d’une zone. C’est ce que faitjust enter gw-atelierhors de chez soi. - Résoudre les noms internes partout : le DNS scindé suffit, sans faire passer tout le DNS dans le VPN.
- Garder Internet hors du tunnel : si le chemin VPN faiblit, la résolution des noms publics tient (pourquoi).
- Laisser la main aux passerelles : elles gardent leur propre DNS
(
--accept-dns=false), dont dépendent leur zone et ses clients.
Comment ça s’articule
Section intitulée « Comment ça s’articule »Un appareil distant ouvre un service de la zone maison :
- MagicDNS reconnaît
domain.tldet transmet la question, par le tunnel, à unbound. - unbound la transmet au résolveur de la passerelle
maison, à son adresse tailnet. - La réponse est l’adresse LAN de la passerelle (
10.0.1.1). - L’appareil l’atteint par la route de sous-réseau de la zone ; la politique
l’autorise sur le port 443 (
gateway-maison).
Politique d’accès (ACL)
Section intitulée « Politique d’accès (ACL) »Sur le tailnet, rien ne passe par défaut. Headscale compile une politique en filtres qu’il pousse à chaque nœud ; chacun jette ce qu’aucune règle n’autorise. Pour une zone, le tri se fait sur sa passerelle.
La politique n’est pas écrite à la main : DNF la génère depuis
etc/config.yaml (zones, hôtes, utilisateurs), la vérifie à la construction
(headscale policy check), puis Headscale la recharge à chaud au déploiement.
Les briques
Section intitulée « Les briques »| Brique | Contenu généré |
|---|---|
groups | group:admins (profils admin, nix-admin), group:zone-<zone> (groupe zone-<zone>) |
tagOwners | tag:hcs, tag:gw-<zone>, tag:admin, détenus par group:admins |
hosts | zone-<zone> (sous-réseau), gateway-<zone> (adresse LAN de la passerelle), postes d’administration (adresse LAN), adminDevices, extraHosts |
autoApprovers | route de chaque zone → tag:gw-<zone> ; exit node → tag:hcs |
acls | les règles ci-dessous |
Les règles
Section intitulée « Les règles »| # | Source | Destination | Pour |
|---|---|---|---|
| 1 | machines taguées, sous-réseaux des zones | toutes les machines et zones, tous ports | l’infrastructure : DNS, supervision, sauvegardes, déploiement |
| 2 | appareils personnels (autogroup:member) | HCS, ports 53 et 443 | DNS interne, services globaux |
| 3 | group:admins | passerelles de toutes les zones, port 443 | les services de toutes les zones |
| 4 | group:zone-<zone> | passerelle de la zone, port 443 | les services de ses zones |
| 5 | appareils personnels | appareils du même propriétaire | entre ses propres appareils |
| 6 | tag:admin, postes d’administration, adminDevices | toutes les machines et zones, port 22 | l’administration SSH |
| 7 | policy.exitNodeSources | Internet | l’exit node du HCS, s’il est ouvert |
| 8 | policy.extraAcls | libre | les besoins propres au réseau |
- Le SSH suit le poste, pas la personne : un administrateur sur son téléphone
n’a pas le SSH, sauf appareil déclaré dans
adminDevices. gateway-<zone>en plus du tag : les services d’une zone se résolvent vers l’adresse LAN de sa passerelle, quetag:gw-<zone>ne couvre pas (il ne désigne que ses adresses tailnet).- Un groupe vide disparaît de la politique : une règle qui le citerait la ferait refuser en entier.
- Mode ouvert (
policy.enforce = false) : une règle unique autorise tout. Réservé à une migration, le temps de taguer les nœuds.
Les options qui ajustent la politique sont décrites dans Adapter la politique d’accès.
Clés d’activation et enrôlement
Section intitulée « Clés d’activation et enrôlement »Un nœud prouve une seule fois à Headscale qu’il a le droit d’entrer. Ensuite, sa clé de nœud suffit : pour toujours s’il est tagué, jusqu’à expiration pour un appareil personnel.
| Clé | Où | Rôle |
|---|---|---|
| Clé de machine | /var/lib/tailscale du nœud | identifie la machine auprès de Headscale ; perdue à la réinstallation |
| Clé de nœud | /var/lib/tailscale du nœud | chiffre le trafic ; Headscale publie sa partie publique aux pairs |
| Clé pré-autorisée | créée par Headscale | autorise un enregistrement sans navigateur, avec les tags qu’elle porte |
| Session OIDC | Kanidm | autorise l’enregistrement d’un appareil personnel |
Machines : une clé à usage unique
Section intitulée « Machines : une clé à usage unique »just tailnet-enroll <hôte> fait entrer une machine, sans clé partagée :
- Tags imposés : le HCS crée la clé pour les tags déclarés de l’hôte
(
dnf-tailnet-enroll), quoi que demande l’appelant. - Usage unique, 10 minutes : sans valeur une fois servie.
- Aucune trace : la clé passe par un tube, jamais par une ligne de commande,
une variable, un disque ou le journal d’entrées et sorties de sudo (règles
NOLOG_INPUTetNOLOG_OUTPUT). - Déposée en mémoire :
dnf-tailnet-joinla pose dans/run/tailscale-enroll,tailscaled-autoconnectl’utilise (tailscale up --force-reauth) puis l’efface. - Portable en pause dans sa zone : il s’enregistre sans routes ni DNS, puis se remet en pause.
- Contrôle final :
adoptpose les tags et le nom déclarés, remplace un ancien nœud hors ligne du même nom, et la recette vérifie le résultat.
Appareils personnels : OIDC
Section intitulée « Appareils personnels : OIDC »- L’application Tailscale contacte Headscale, qui la renvoie vers Kanidm.
- Kanidm n’accepte que les membres du groupe
tailnet; Headscale le vérifie aussi. - L’appareil est enregistré au nom de la personne (
alice@) et expire après 180 jours (nodeExpiry) : elle se reconnecte alors.