Le VPN (Headscale / Tailscale)
Le VPN maille les zones, le serveur de coordination et les appareils distants : Headscale 🡕 coordonne depuis le HCS, Tailscale 🡕 est le client de chaque nœud. Cette page réunit les gestes d’exploitation. Routage, DNS, MagicDNS, politique d’accès et clés sont expliqués dans Fonctionnement du tailnet.
Activer le VPN
Section intitulée « Activer le VPN »Activer la coordination et déclarer le HCS (profile: hcs) suffit :
network: coordination: enable: true hostname: "hcs" domain: "headscale"Le rôle de chaque nœud se déduit de la topologie :
| Nœud | Identité | Rôle |
|---|---|---|
| HCS | tag:hcs | coordination, DNS pivot, services globaux, exit node (fermé) |
| Passerelle | tag:gw-<zone> | routeur de sous-réseau : publie le /16 de sa zone |
| Poste d’administration | tag:admin | SSH vers toutes les machines |
| Appareil personnel | son propriétaire | services, selon ses groupes |
Un poste d’administration est un hôte dont groups contient admin et dont le
fichier d’hôte active le client :
darkone.service.tailscale.enable = true;darkone.service.tailscale.autoPauseOnLan.enable = true;autoPauseOnLan met le client en pause quand le portable est branché dans une zone
(NetworkManager requis).
Enrôler une machine
Section intitulée « Enrôler une machine »Les machines rejoignent le tailnet sans clé partagée : le HCS crée pour
chacune une clé à usage unique, avec ses tags déclarés. just configure s’en charge,
donc just full-install aussi. La recette seule se relance à tout moment :
just tailnet-enroll gw[ DNF ] TAILNET • gw not enrolled, backend NeedsLogin: sending a single-use key...[ DNF ] TAILNET • gw: gw tag:gw-maison 100.64.0.8Elle est idempotente :
| Situation | Effet |
|---|---|
| Nœud enrôlé, nom et tags conformes | rien (already enrolled) |
| Tags ou nom différents | corrigés sur le HCS, sans reconnexion |
| Jamais enrôlé, supprimé ou réinstallé | nouvelle clé, enregistrement |
| Ancien nœud du même nom hors ligne | supprimé, le nouveau prend le nom |
| Ancien nœud du même nom en ligne | refus : deux machines portent ce nom |
| Hôte sans client Tailscale | ignoré |
Le mécanisme est détaillé dans Clés d’activation et enrôlement.
Enregistrer une passerelle
Section intitulée « Enregistrer une passerelle »Une passerelle s’enrôle comme toute machine ; deux points lui sont propres.
-
Vérifier la route de sa zone
La passerelle annonce le
/16de sa zone, que la politique approuve d’office pourtag:gw-<zone>. Sur le HCS :Fenêtre de terminal sudo headscale nodes list-routes -
Déclarer son adresse tailnet
Le HCS joint le résolveur de la zone par cette adresse (DNS pivot), comme les services qui la visent (sauvegardes, supervision). La relever dans la sortie de
just tailnet-enroll, puis la reporter :etc/config.yaml zones:maison:gateway:vpn:ipv4: "100.64.0.8" -
Propager l’adresse
Fenêtre de terminal just generatejust apply hcsRedéployer aussi les hôtes qui visent cette adresse.
HeadscaleNodeDriftsignale une adresse déclarée qui ne correspond plus.
Connecter un appareil personnel
Section intitulée « Connecter un appareil personnel »Un smartphone ou un ordinateur personnel se connecte avec l’identité Kanidm de son propriétaire : ni clé, ni validation manuelle.
| Peut se connecter | Condition dans etc/config.yaml |
|---|---|
| Administrateur | profil admin ou nix-admin |
| Membre d’une zone | groupe zone-<zone> |
Ces comptes forment le groupe Kanidm tailnet, provisionné tout seul ; Kanidm
refuse les autres. Pour ouvrir l’accès, ajouter le groupe à l’utilisateur,
régénérer, puis just apply hcs. L’utilisateur suit ensuite Connecter un
appareil.
L’appareil appartient à la personne (alice@) et expire après 180 jours :
elle se reconnecte alors avec son identifiant.
sudo headscale nodes list # appareils, propriétaires, expirationsudo headscale nodes expire -i <id> # forcer une reconnexionsudo headscale nodes delete -i <id> # retirer l'appareilAdapter la politique d’accès
Section intitulée « Adapter la politique d’accès »La politique est générée depuis la topologie : ses règles sont détaillées dans Politique d’accès. Des options l’ajustent, sur le HCS :
Option darkone.service.headscale. | Défaut | Effet |
|---|---|---|
policy.adminDevices | { } | appareils personnels autorisés en SSH : nom → IPv4 tailnet |
policy.exitNodeSources | [ ] | sources autorisées à sortir sur Internet par le HCS |
policy.extraHosts | { } | alias supplémentaires : nom → CIDR |
policy.extraAcls | [ ] | règles ajoutées après les règles générées |
policy.enforce | true | false : tout autorisé, pour une migration seulement |
nodeExpiry | "180d" | expiration des appareils personnels (0 : jamais) |
darkone.service.headscale.policy = {
# SSH depuis le téléphone d'Alice (adresse lue dans `headscale nodes list`) adminDevices.phone-alice = "100.64.0.9";
# Exit node du HCS ouvert aux administrateurs exitNodeSources = [ "group:admins" ];
# Imprimante réseau pour tous les appareils personnels extraHosts.printer = "10.0.4.10/32"; extraAcls = [ { action = "accept"; src = [ "autogroup:member" ]; dst = [ "printer:631" ]; } ];};Puis just apply hcs : la politique est vérifiée à la construction, et Headscale
la recharge sans redémarrer.
Administration
Section intitulée « Administration »Sur le HCS (just enter hcs) :
| Commande | Usage |
|---|---|
sudo headscale nodes list | nœuds, propriétaire, tags, adresses, expiration |
sudo headscale nodes list-routes | routes annoncées et approuvées |
sudo headscale nodes rename -i <id> <nom> | renommer un nœud |
sudo headscale nodes expire -i <id> | forcer une reconnexion |
sudo headscale nodes delete -i <id> | supprimer un nœud |
sudo headscale users list | propriétaires d’appareils personnels |
sudo headscale preauthkeys list | clés pré-autorisées : tags, usage, expiration |
sudo headscale policy get | politique servie |
sudo dnf-tailnet-enroll status <hôte> | identité déclarée d’un hôte |
Tags et routes ne se règlent pas à la main : just tailnet-enroll pose les tags
déclarés, la politique approuve les routes. Les autres réglages du client (routes
annoncées, SSH Tailscale coupé, exit node) sont réalignés par
tailscaled-autoconnect, au démarrage et aux déploiements qui le modifient.
Introspecter et dépanner
Section intitulée « Introspecter et dépanner »Sur un nœud
Section intitulée « Sur un nœud »| Commande | Répond à |
|---|---|
tailscale status | pairs, en ligne ou non, chemin direct ou relais |
tailscale ping <nœud> | chemin réel : via <ip>:41641 (direct) ou via DERP |
tailscale whois <ip> | nœud, tags ou propriétaire derrière une adresse |
tailscale dns status | MagicDNS, DNS scindé, domaines de recherche reçus |
journalctl -u tailscaled-autoconnect | dernier enregistrement ou réalignement des réglages |
Tester une politique
Section intitulée « Tester une politique »Sans option --bypass…, headscale policy check compile un fichier contre les
vrais nœuds et exécute son bloc tests, sans toucher à la politique en place.
-
Partir de la politique servie :
Fenêtre de terminal sudo headscale policy get > /tmp/policy.json -
Ajouter un bloc
tests: une source, puis les destinations attendues, chacune un hôte unique (adresse et port) :"tests": [{ "src": "alice@", "accept": ["100.64.0.8:443"], "deny": ["100.64.0.8:22"] }] -
Vérifier :
Fenêtre de terminal sudo headscale policy check -f /tmp/policy.json
Pannes courantes
Section intitulée « Pannes courantes »| Symptôme | Vérifier | Remède |
|---|---|---|
TailscaleUnhealthy, backend NeedsLogin | tailscale status sur le nœud | just tailnet-enroll <hôte> |
| Zone injoignable depuis le tailnet | headscale nodes list-routes | passerelle enrôlée avec son tag, route approuvée |
| Service de zone refusé à un appareil | groupes de l’utilisateur, tailscale whois <ip> | ajouter zone-<zone>, just apply hcs |
| SSH refusé sur une adresse tailnet | poste tag:admin ou appareil adminDevices | déclarer l’appareil |
| Noms internes non résolus hors zone | tailscale dns status | activer « Use Tailscale DNS » |
| Trafic lent | tailscale ping affiche via DERP | UDP sortant filtré, ou NAT strict des deux côtés |
no declared tailnet identity | hôte tagué, HCS déployé depuis sa déclaration | just apply hcs |
named … is online, not deleting it | deux machines portent le même nom | éteindre l’ancienne ou renommer l’hôte |
Audit et alertes
Section intitulée « Audit et alertes »Toutes les 15 minutes, headscale-audit compare les nœuds réels à la topologie
déclarée, sans rien modifier. Le détail des écarts est dans son journal :
journalctl -u headscale-audit -n 20| Alerte | Signale | Après |
|---|---|---|
HeadscaleNodeDrift | HCS ou passerelle absent, tags faux, adresse différente de celle déclarée | 30 min |
HeadscaleUnexpectedNode | nœud tagué non déclaré, ou appareil d’un compte hors du groupe tailnet | aussitôt |
HeadscalePolicyInvalid | politique refusée, ou politique servie différente du fichier | 30 min |
HeadscaleOidcFallback | Kanidm absent au démarrage de Headscale : connexions OIDC coupées | aussitôt |
HeadscaleNodeExpiring | appareil personnel qui expire sous 7 jours | 1 h |
HeadscaleAuditStale | audit sans succès depuis plus d’une heure | aussitôt |
Toutes sont en warning, sur le Prometheus qui supervise le HCS. Un poste
d’administration absent n’est pas une anomalie ; présent, ses tags sont
vérifiés.
Auto-réparation du client
Section intitulée « Auto-réparation du client »Un tailscaled peut décrocher silencieusement de Headscale : la connexion de
contrôle est perdue alors que le service reste « actif », et le sous-réseau d’une
passerelle devient injoignable. Un watchdog local détecte et corrige ce cas, sur
chaque client Tailscale.
| Aspect | Comportement |
|---|---|
| Sonde | toutes les 60 s : tailscale status (backend, état en ligne) |
| Anti-rebond | 3 sondes en échec d’affilée (~3 min) avant d’agir |
| Correction | redémarre tailscaled, qui se reconnecte au plan de contrôle |
| Anti-boucle | une seule correction par fenêtre de 10 min |
| Nœud non enrôlé | aucun redémarrage (NeedsLogin) : just tailnet-enroll |
| Portable en pause | watchdog à l’arrêt, métrique retirée |
| Observabilité | dnf_tailscale_healthy, dnf_tailscale_selfheal_restarts_total (textfile node_exporter) |
Deux alertes accompagnent le mécanisme :
TailscaleUnhealthy: toujours décroché après 10 min, malgré la correction ;TailscaleFlapping: plus de 3 corrections en une heure.
Amorçage du plan de contrôle
Section intitulée « Amorçage du plan de contrôle »Sur une passerelle, dnsmasq envoie tout domain.tld au résolveur du HCS à travers
le tailnet : le client aurait besoin du VPN pour trouver le serveur qui monte
le VPN. Au démarrage, en plus, le résolveur local n’écoute pas encore.
Chaque client Tailscale reçoit donc l’adresse publique du HCS dans son
/etc/hosts, déduite de etc/config.yaml (le HCS lui-même est exclu). dnsmasq
répond à ce nom depuis ce fichier, sans jamais le transmettre :
grep headscale /etc/hosts # 203.0.113.10 headscale.domain.tldLe client se connecte ainsi sans aucun résolveur, y compris quand le DNS local est en panne, précisément quand l’auto-réparation doit pouvoir agir.
Hors d’une zone
Section intitulée « Hors d’une zone »- Appareil personnel : voir Connecter un appareil personnel.
- Portable d’administration : en déplacement, il joint toutes les zones par
le tailnet (
just enter <hôte>). Rebranché dans une zone, son client se met en pause et la passerelle locale reprend la main.