Aller au contenu

Fonctionnement du réseau

Le réseau DNF se comprend à deux échelles : une zone locale isolée, puis plusieurs zones reliées par un VPN maillé. Le vocabulaire est défini dans Concepts.

Une zone, c’est une passerelle et ses machines.

Diagram
  • La passerelle partage Internet (NAT) et protège la zone (pare-feu).
  • dnsmasq distribue les adresses (DHCP) et résout les noms locaux (<hôte>.<zone>).
  • Côté Internet (WAN), tout est fermé. Côté local (LAN), seuls SSH, DNS, DHCP et la page d’accueil sont ouverts.

Service optionnel, activé sur la passerelle. Il s’intercale devant dnsmasq.

Diagram
  • AdGuardHome devient le résolveur DNS des postes (port 53).
  • Il bloque publicités et traceurs, et chiffre les requêtes vers l’extérieur.
  • dnsmasq recule sur un port interne et garde les noms locaux et le DHCP.
  • Aucune limite de débit : résolveur de zone, fermé au WAN. Une rafale de requêtes (mise à jour du parc) ne perd aucune réponse.

Plusieurs zones sont reliées par un VPN maillé, le tailnet, coordonné par le serveur de coordination (HCS).

Diagram
  • Le HCS (Headscale) est public et coordonne le maillage ; le trafic passe en direct d’un nœud à l’autre.
  • Chaque passerelle est subnet router : elle publie le sous-réseau de sa zone dans le VPN.
  • Les zones se voient entre elles ; les machines distantes (smartphone, PC) rejoignent le réseau via Tailscale.
  • Rien ne passe par défaut : une politique d’accès, générée depuis etc/config.yaml, dit qui joint quoi.
  • Un résolveur pivot sur le HCS aiguille les noms de chaque zone vers sa passerelle.

Routage, DNS, MagicDNS, politique d’accès et clés d’activation sont détaillés dans Fonctionnement du tailnet.

Une passerelle route, et un paquet routé ne passe jamais par les règles d’ouverture de ports : celles-ci ne concernent que ce qui lui est adressé à elle. Les deux filtrages sont indépendants.

Seuls ces flux traversent une passerelle :

FluxUsage
Zone → WANPartage d’Internet (NAT)
Zone → liaison de secoursPartage d’Internet quand la box tombe (liaisons de secours)
Zone ↔ VPNLes autres zones, les machines distantes
Réponses et redirections de portsRetour du trafic sortant, forwardPorts

Tout le reste est jeté. En particulier, une machine d’Internet qui poserait une route statique vers le sous-réseau d’une zone n’atteint rien : sans ce filtrage, une passerelle à adresse publique laisserait passer.

Un besoin de routage supplémentaire s’ajoute dans le fichier de l’hôte :

networking.firewall.extraForwardRules = ''
iifname "lan0" oifname "wg0" accept
'';

Le port 22 n’est jamais ouvert « partout ». Une règle sans nom d’interface s’applique à toutes les interfaces, WAN compris : sur une passerelle, cela publierait le SSH sur Internet.

HôteSSH joignable depuis
Passerelle de zoneson réseau local et le VPN
Hôte de la zone globale (HCS)Internet — décision assumée, il porte le VPN
Machine de zone (poste, serveur)sa seule interface, donc le réseau local

Conséquence pratique : une passerelle ne répond pas au SSH depuis Internet. L’accès distant passe par le VPN :

Fenêtre de terminal
just enter gw

Un service interne s’ouvre sur l’interface qui correspond à son périmètre réel, jamais sur toutes. Trois périmètres coexistent :

PérimètreOuvertureExemples
Tailnettailscale0Loki (journaux), relais des services exposés
Réseau locallan0 sur une passerelle, l’interface unique ailleursDNS, DHCP, page d’accueil, cache Nix
Liste d’adressesrègle ip saddr, ou liste de clients côté servicepartages NFS, jeux en réseau local

Le troisième cas existe parce qu’un préfixe de zone n’est pas une identité : toute machine qui obtient une adresse locale en fait partie, invité Wi-Fi compris. Là où le service le permet, la liste des hôtes déclarés remplace le préfixe.

Trois familles de noms cohabitent sur le réseau. Toutes sont générées depuis etc/config.yaml.

NomFormePortéeExemple
Nom simple<hôte>Tout le réseau interneserveur
FQDN de zone<nom>.<zone>.<domaine>Tout le réseau internecloud.maison.domain.tld
Service global<nom>.<domaine>Internet inclusgit.domain.tld
  • Noms simples : ce sont les machines (hôtes déclarés). Résolus partout sur le réseau, vers l’adresse réelle de la machine, quelle que soit sa zone.
  • FQDN de zone : ce sont les services d’une zone. Ils pointent vers la passerelle de cette zone, qui les sert via son proxy inverse.
  • Services globaux : les services marqués global dans etc/config.yaml. Exposés sur le HCS avec un DNS public : joignables depuis n’importe où.

Qui résout quoi :

  • dnsmasq, sur chaque passerelle, connaît tous les noms internes (machines et services de toutes les zones) : il résout les noms simples et les FQDN.
  • La zone courante est résolue localement ; les autres zones et le domaine global sont aiguillés vers la bonne passerelle, ou vers le résolveur pivot du HCS.
  • Les noms publics (Internet) partent vers les DNS chiffrés en amont, filtrés par AdGuardHome s’il est activé.
  • Seuls les noms déclarés existent : un nom inconnu sous une zone répond NXDOMAIN, sans renvoi vers la passerelle.
  • Les noms du tailnet (<nœud>.tailnet.internal) sont relayés par chaque passerelle à MagicDNS : résolus aussi depuis les LAN.

Sur le serveur de coordination (HCS), un résolveur pivot (unbound) centralise la résolution interne du VPN. Il connaît le découpage en zones et se contente d’aiguiller :

  • chaque FQDN de zone part vers la passerelle de sa zone, à son adresse tailnet ;
  • les services globaux hébergés sur le HCS sont résolus sur place ;
  • le reste part vers un DNS externe chiffré.

Les appareils distants l’interrogent par MagicDNS (DNS scindé), les passerelles pour les noms du domaine qu’elles ne connaissent pas. Entre deux zones, une passerelle interroge directement la passerelle de l’autre zone. Détail dans DNS.

Une machine hors de toute zone (portable en déplacement, smartphone) rejoint le réseau par le VPN. Sa résolution DNS est scindée (split-DNS) selon la nature du nom demandé :

  • noms internes : dirigés, à travers le VPN, vers le résolveur pivot du HCS, qui les aiguille ensuite vers la bonne passerelle ;
  • noms des nœuds du tailnet (<nœud>.tailnet.internal, ou le nom court) : résolus sur l’appareil même, par MagicDNS ;
  • noms publics : résolus par le résolveur local du réseau visité (box, point d’accès public), sans passer par le VPN.
Diagram

Une machine est déclarée dans une zone, mais elle ne s’y trouve pas toujours. Un portable part en déplacement. Une passerelle neuve est installée depuis une autre zone, avant d’être livrée sur place.

Sans disposition particulière, cette machine reçoit une adresse quelconque de la plage DHCP de la zone visitée, et son nom continue de désigner son adresse d’origine, injoignable depuis là. Rien ne permet de la joindre de façon fiable.

Diagram

Chaque zone réserve le bloc <préfixe>.6.x aux machines des autres zones. Le générateur y place une réservation DHCP pour chaque adresse MAC connue du réseau qui n’appartient pas à la zone.

Le numéro est attribué à l’échelle du réseau entier : une machine garde le même dernier octet dans toutes les zones où elle passe.

MachineZone déclaréeChez elleEn visite dans atelier
portablemaison10.0.2.410.1.6.3
serveuratelier10.1.1.2(elle y est chez elle)

L’adresse est donc connue avant que la machine ne démarre, sans rien observer sur le réseau.

La réservation vient avec un nom DNS dans la zone visitée. Le nom simple, lui, ne change pas de sens.

NomRésout vers
portableson adresse d’origine, partout sur le réseau
portable.atelier.domain.tldson adresse dans la zone atelier

dnsmasq indexe les baux sur la seule adresse MAC, et non sur l’identifiant client DHCP.

La raison : un même équipement n’annonce pas le même identifiant selon le système qui tourne dessus. Une image d’installation et le système installé passent pour deux machines différentes, et reçoivent deux adresses. En s’appuyant sur la MAC, l’adresse ne change plus entre l’installation et le premier démarrage réel.

Les recettes d’installation calculent l’adresse toutes seules. Elles identifient d’abord la zone où se trouve la machine d’administration, à partir de sa passerelle par défaut réelle et non de sa zone déclarée (un portable d’administration est précisément ce qui se déplace), puis en déduisent l’adresse de la cible.

Cette adresse est ensuite vérifiée avant d’être utilisée : une réservation dit où la machine serait si elle était branchée ici, ce qui est juste pendant l’installation et faux dès qu’elle est rentrée chez elle. Si rien ne répond à l’adresse réservée, l’outillage retombe sur le nom de l’hôte lorsque celui-ci répond — port 22, ou 2222 pour une machine chiffrée en attente dans son initrd. Si rien ne répond nulle part, l’adresse réservée est conservée : c’est celle sur laquelle l’installateur apparaîtra.

Le calcul ci-dessus donne une adresse pour démarrer. Après le redémarrage qui clôt une installation, ce n’est plus suffisant : la machine peut réapparaître ailleurs, ou n’être pas encore vraiment démarrée.

just full-install sonde donc toutes les adresses connues de l’hôte, dans cet ordre, sur les ports 22 et 2222, et poursuit sur la première qui répond :

  1. l’adresse utilisée pour l’installation ;
  2. l’adresse fixe de sa zone d’origine, celle que le DNS publie partout ;
  3. l’adresse de passage que réserve la zone locale ;
  4. son nom, résolu par la passerelle locale.

Une réponse sur le port 2222 signifie que l’hôte attend sa passphrase LUKS dans son initrd : just unlock y répond sans intervention. Voir Chiffrement des disques.

Colmena 🡕 (just apply), fleet-update et just enter visent un hôte par son nom, qui désigne son adresse d’origine. Sur une machine d’administration, chaque connexion SSH vers un hôte du réseau passe par dnf-locate, qui essaie :

  1. le nom seul, d’abord : le cas courant ne coûte rien de plus ;
  2. sinon, en parallèle, sa réservation dans chaque zone (portable.atelier.domain.tld) et son nom tailnet (portable.tailnet.internal).

Le premier chemin qui répond l’emporte. dnf-locate --print portable affiche celui qu’il trouve.

Le chemin tailnet ne vaut que pour une machine d’administration (tag:admin) : la politique d’accès n’ouvre aux zones aucun autre client du tailnet.

Pour imposer une adresse, just configure pose une redirection SSH temporaire pour un hôte en visite, retirée en fin d’installation ou à la main :

Fenêtre de terminal
just roaming # afficher les redirections en cours
just roaming-clear # toutes les retirer