Construire son réseau privé souverain : Macs, iPhone, iPad, NAS
Un réseau souverain, accessible de partout : relier Macs, iPhone, iPad et NAS en privé chiffré, sans ouvrir de port ni confier l'annuaire à un tiers. Le guide complet, des choix d'architecture aux configurations commentées.
Le problème, et les deux mauvaises réponses
Vos appareils sont sur des réseaux différents : le Mac au bureau, le NAS à la maison, le téléphone en 5G dans le train. Pour qu’ils se parlent, il y a traditionnellement deux solutions, et elles sont mauvaises toutes les deux.
Ouvrir un port sur la box : votre NAS devient joignable depuis Internet entier. Des robots le trouveront dans l’heure. Vous passerez le reste de votre vie à surveiller ses mises à jour de sécurité.
Un VPN classique : tout le trafic remonte à un serveur central, qui redescend vers la destination. Le téléphone qui veut parler au NAS situé dans la même pièce fait un aller-retour par un datacenter. C’est lent, et le serveur central voit tout passer.
Un mesh fait autre chose. Chaque appareil reçoit une adresse privée stable, valable partout : au bureau, en 5G, chez un ami. Deux appareils qui veulent se parler établissent une connexion directe et chiffrée, sans passer par un intermédiaire. Le réseau se comporte comme si tous vos appareils étaient branchés au même switch, où qu’ils soient.
D’où la question qui gouverne tout le reste : à qui confie-t-on l’annuaire ?
Pourquoi : quatre objectifs, pas un
Un mesh n’est pas une fin en soi. Voici les quatre raisons qui justifient l’effort ; si une seule vous concerne, une solution plus simple existe probablement.
1. Réduire la surface d’attaque. C’est le vrai gain. Un tableau de bord domotique, une interface d’administration de NAS, une passerelle d’API : chacun exposé sur Internet est une porte à surveiller à vie. Sur un mesh, ils ne sont joignables que par vos appareils. Un service qui n’est pas joignable n’a pas de faille exploitable à distance. Ce n’est pas du durcissement, c’est de la soustraction.
2. L’accès distant sans exposition. Voir sa domotique depuis un train, atteindre ses fichiers depuis l’hôtel : sans qu’aucun de ces services n’ait d’adresse publique.
3. Des noms stables. Sur un réseau domestique, tout bouge : les adresses changent, on déménage une application d’une machine à l’autre, on remplace un serveur. Un mesh permet de donner un nom fixe à un service, indépendant de la machine qui l’héberge.
4. Le filtrage. Le mesh fournit un point de passage naturel pour un résolveur DNS maison : qui sert les noms internes et bloque publicités et traqueurs, y compris sur les téléphones en déplacement.
La doctrine, en une phrase
Le plan de contrôle ne se confie pas à un tiers. Il détient la carte de qui parle à qui et les identités de vos appareils. Un service hébergé par quelqu’un d’autre : même excellent, même gratuit : signifie qu’un tiers peut, en principe, ajouter un appareil à votre réseau privé. C’est le seul critère qui a écarté d’emblée les offres clés en main.
Une prémisse fausse, et la leçon
Le projet a d’abord été justifié par un incident : un serveur devenu injoignable, qu’on croyait dû à un changement d’adresse. Vérification faite, l’adresse était fixe : la machine était simplement éteinte, bloquée avant le démarrage sur un écran de déverrouillage de disque.
Un nom stable n’aurait rien changé. Le projet restait justifié par les quatre objectifs ci-dessus, mais la raison qu’on s’en donnait était fausse. Vérifiez la prémisse avant de construire : un projet qui se justifie par un incident qu’il ne répare pas se construira dans la mauvaise direction.
Les choix : et surtout ce qu’on a écarté
WireGuard seul : écarté
WireGuard est le protocole de chiffrement sous-jacent de toutes les solutions ci-dessous, et il est excellent. Mais utilisé nu, il ne fournit ni résolution de noms, ni traversée de NAT automatique, ni gestion d’autorisations. Il faut écrire à la main chaque couple de clés, chaque adresse, chaque route. Pour trois appareils c’est faisable ; pour dix, avec des mobiles qui changent de réseau, c’est un travail permanent.
Tailscale en service hébergé : écarté
Ergonomie excellente, offre gratuite généreuse, ça fonctionne en dix minutes : et le client est le meilleur du marché. Mais le plan de contrôle appartient à l’éditeur. Critère éliminatoire pour qui vise la souveraineté, pas critique du produit : si ce critère ne vous concerne pas, prenez Tailscale et fermez cet article, vous aurez fini avant midi.
Le TLD réservé (.internal, .local) : écarté, et c’est contre-intuitif
L’idée naturelle est de nommer son réseau interne avec un suffixe réservé, prévu pour cet usage. Erreur : aucune autorité de certification n’émettra jamais de certificat pour un nom réservé. Vous vous condamnez soit au HTTP en clair, soit à installer votre propre autorité de certification sur chaque appareil : y compris ceux de vos proches, y compris les téléphones, et à recommencer à chaque appareil neuf.
Utilisez un sous-domaine d’un domaine que vous possédez. mesh.exemple.fr ne coûte
rien de plus que votre nom de domaine, et il ouvre la porte aux vrais certificats. Voir
plus bas : c’est le meilleur truc de tout le dossier.
Headscale ou NetBird : les deux sérieux
Deux implémentations libres et auto-hébergeables, très proches à l’usage :
- Headscale : une ré-implémentation libre du plan de contrôle de Tailscale. Vous gardez les clients officiels Tailscale, matures et disponibles partout (App Store, paquet Synology officiel, module domotique clé en main), en les pointant vers votre propre serveur. Mono-binaire, peu de surface à maintenir. Contrepartie : projet encore en 0.x, changements incompatibles possibles entre versions.
- NetBird : un produit complet, clients maison, interface d’administration et API pour les autorisations, authentification unique intégrée. Plus abouti côté exploitation quotidienne. Contrepartie : clients moins éprouvés que ceux de Tailscale, et le relais de secours doit être auto-hébergé : ce qui est nettement plus lourd à opérer.
Le départage s’est fait par un banc d’essai comparatif : les deux installés, les deux mesurés sur les mêmes critères : puis par une revue à quatre lecteurs indépendants. Verdict : Headscale, à l’unanimité des relecteurs, pour la maturité des clients et la faible surface de maintenance. Mais le comparatif a failli donner l’inverse.
Voici pourquoi, et le piège vaut pour n’importe quel comparatif. Sur Headscale, la résolution de noms ne fonctionnait pas sous macOS : bug connu, largement documenté, plusieurs années d’existence. NetBird y arrivait nativement. Avantage décisif, apparemment.
Sauf que ce bug frappe le client en ligne de commande installé par Homebrew : pas l’application Tailscale officielle de l’App Store, qui obtient du système des autorisations que l’autre n’a pas. Le banc d’essai avait testé le mauvais client. L’avantage structurel de NetBird n’existait pas, et le seul argument qui aurait justifié son surcoût d’exploitation tombait avec lui.
La leçon dépasse le cas : quand vous mesurez un défaut, vérifiez que vous mesurez le composant que vous allez déployer. Un bug documenté peut être réel, largement rapporté, et ne pas concerner votre configuration.
L’architecture
Le nommage : la règle qui vous fera gagner des années
Un nom de service ne désigne jamais une machine.
Nommez vos nœuds (serveur, portable, nas) : c’est inévitable. Mais tout ce que
consomme votre code, vos favoris, vos scripts, doit passer par un nom de service
découplé :
| Ce qu’on écrit partout | Ce que ça désigne aujourd’hui |
|---|---|
passerelle.mesh.exemple.fr | un conteneur sur le NAS |
domotique.mesh.exemple.fr | un boîtier dédié |
notes.mesh.exemple.fr | une application sur le portable |
Le jour où vous déplacez l’application, vous changez un enregistrement DNS. Rien d’autre ne bouge : ni les favoris, ni les scripts, ni les configurations des autres machines, ni la mémoire de vos collaborateurs.
L’anti-pattern coûteux est d’écrire l’adresse d’un appareil dans une configuration. Ça marche le premier jour, et ça se paie pendant des années : à chaque déménagement de service, il faut retrouver toutes les traces.
Le certificat : HTTPS reconnu sur des services jamais publics
Voici le truc le plus utile du dossier, et le moins connu.
Le problème. Vous voulez https://domotique.mesh.exemple.fr avec un cadenas vert sur
l’iPhone, sur le Mac, sur la tablette. Mais ce service n’est joignable de nulle part
sur Internet : une autorité de certification ne peut donc pas le visiter pour vérifier
que vous le contrôlez. La méthode habituelle (l’autorité appelle votre serveur sur le
port 80) est impossible.
La solution : la validation par DNS. Les autorités gratuites proposent une seconde
méthode : vous prouvez que vous contrôlez le domaine en y déposant un enregistrement
temporaire, via l’API de votre hébergeur DNS. Aucune connexion entrante n’est nécessaire.
Et cette méthode est la seule qui permette un certificat joker : un seul
certificat *.mesh.exemple.fr couvre tous vos services, présents et futurs.
Ce que vous obtenez : du HTTPS reconnu par tous les navigateurs et tous les systèmes, sur des services jamais exposés, sans installer la moindre autorité de certification sur les appareils. Un iPhone neuf fonctionne immédiatement. Un invité aussi.
Ce que ça coûte, et il faut le dire : tout certificat émis est inscrit dans des
registres publics consultables par n’importe qui. Un joker n’y publie que *.mesh.exemple.fr :
les noms de vos services individuels n’y apparaissent pas. Vous révélez que ce
sous-domaine existe, pas ce qu’il contient. Un certificat par service, à l’inverse,
publierait la liste complète de votre infrastructure.
Un contresens à éviter, que nous avons nous-mêmes écrit avant de le corriger : on croit souvent qu’un certificat interne « fait maison » est plus sûr parce qu’il ne sort pas de chez soi. C’est l’inverse. Une autorité maison exige que chaque appareil lui fasse confiance a priori : vous distribuez une autorité de certification, et quiconque met la main dessus peut usurper n’importe quel site pour ces appareils. Le certificat public, lui, est vérifié par une chaîne indépendante.
Deux points opérationnels : le renouvellement doit être automatique (ces certificats sont courts), et sa surveillance doit vivre en dehors du réseau qu’il protège : sinon le jour où il expire, votre alerte est injoignable.
Le point dur : la poule et l’œuf de l’enrôlement
C’est la difficulté d’architecture, et celle sur laquelle il faut passer du temps.
Pour qu’un appareil rejoigne le mesh, il doit contacter le plan de contrôle. Mais il n’est pas encore sur le mesh : donc il ne peut pas le joindre par le mesh. Le plan de contrôle doit donc être joignable publiquement. C’est la seule chose que vous exposez, et c’est aussi la plus sensible : c’est lui qui distribue les identités.
Trois conséquences pratiques :
1. Prouvez-le avant de fermer le reste. Le test qui compte n’est pas « ça marche depuis mon salon ». C’est : un appareil neuf, en 5G, wifi coupé, réussit-il à s’enrôler ? Tant que ce test n’est pas vert, ne dépubliez rien : sinon vous découvrirez le problème le jour où vous êtes dehors, sans accès.
2. Le nom du plan de contrôle sort probablement du domaine du mesh. Beaucoup
d’implémentations interdisent que l’adresse du serveur soit un sous-domaine du domaine
utilisé pour la résolution interne. Autrement dit : si votre mesh est mesh.exemple.fr,
le plan de contrôle sera vpn.exemple.fr, pas ctrl.mesh.exemple.fr. Conséquence
souvent ratée : ce nom n’est pas couvert par votre certificat joker, il lui faut le
sien.
3. Vous n’avez pas besoin d’un port de plus. Si votre box sert déjà un site en 443, faites passer le plan de contrôle par le même reverse proxy, en routant selon le nom demandé. Zéro nouvelle ouverture. À vérifier sur banc d’essai : certains proxys gèrent mal les protocoles de mise à niveau de connexion utilisés par ces outils : c’est le genre de chose qui se teste avant, pas pendant.
Et les relais
Deux appareils derrière des box différentes n’arrivent pas toujours à établir une liaison directe. Le protocole prévoit alors des relais. Point important pour la tranquillité : le relais ne déchiffre rien : il transporte des paquets déjà chiffrés de bout en bout. Utiliser les relais publics du projet ne compromet pas la confidentialité, seulement la latence.
En pratique, si votre connexion a une IPv6 fixe, la liaison directe s’établit presque toujours : y compris depuis un téléphone en 5G. Nous l’avons mesuré : liaison directe en IPv6 depuis un mobile en itinérance.
Sept pièges qui coûtent une soirée chacun
1. Le NAS ne laisse pas réécrire son résolveur. Sur les systèmes de NAS grand public, le client mesh n’a pas les droits de modifier la configuration DNS du système. La résolution automatique des noms ne fonctionnera donc pas sur cette machine. Prévoyez un résolveur DNS local dès le départ : ce n’est pas une rustine, c’est un composant d’architecture. Bonus : il servira aussi de filtre anti-publicité pour tout le réseau.
2. Le client en ligne de commande et l’application officielle ne se valent pas. Voir plus haut : le bug de résolution de noms sous macOS frappe l’un et pas l’autre. Testez le client que vous déploierez réellement.
3. Le routeur-portable est un point de défaillance unique. Il est tentant de faire passer le trafic vers un appareil non compatible (domotique, imprimante) à travers une machine du mesh qui sert de routeur. Ça marche : jusqu’à ce que cette machine soit éteinte, en veille ou en déplacement. Faites de l’appareil lui-même un nœud du mesh quand c’est possible ; beaucoup de plateformes domotiques ont un module dédié.
4. Le plan de contrôle sur la machine instable. Il doit tourner sur ce qui ne redémarre jamais. Un NAS, pas un poste de travail : même puissant, surtout s’il a un historique de plantages.
5. Les œufs dans le même panier. Corollaire du précédent : si le plan de contrôle tourne sur le NAS qui porte aussi vos données, une compromission de la machine expose les clés du réseau en plus des données. L’isolation par conteneur ne protège pas d’un accès administrateur à l’hôte. C’est un risque acceptable pour un particulier : mais il doit être choisi et écrit, pas subi par défaut. Prévoyez la porte de sortie : un petit hôte dédié le jour où l’occasion se présente.
6. La base de données du plan de contrôle, c’est votre réseau. Elle contient les identités et les clés. Sauvegardez-la hors de la machine qui l’héberge, et testez la restauration. Sans elle, vous ré-enrôlez tous vos appareils à la main.
7. Les autorisations par défaut sont trop larges. Par défaut, tout le monde parle à tout le monde. Passez en refus par défaut et ouvrez au cas par cas : le téléphone a besoin de la domotique, il n’a aucune raison d’atteindre la base de données. Et vérifiez depuis la destination, pas depuis la console d’administration : la règle affichée et la règle appliquée sont deux choses différentes.
Exemples de configuration (valeurs inventées)
Autorisations : refus par défaut
{
// Les groupes portent des PERSONNES, jamais des machines.
"groups": {
"group:moi": ["alice@exemple.fr"],
"group:famille": ["bob@exemple.fr"],
},
// Étiqueter les machines par RÔLE : la règle survit au remplacement du matériel.
"tagOwners": {
"tag:services": ["group:moi"],
"tag:domotique": ["group:moi"],
},
"acls": [
// Moi : accès complet à mes services.
{ "action": "accept", "src": ["group:moi"], "dst": ["tag:services:*"] },
// La famille : la domotique et RIEN d'autre.
// Écrire le port explicitement : pas de joker par confort.
{ "action": "accept", "src": ["group:famille"], "dst": ["tag:domotique:9123"] },
],
// Ce qui n'est pas écrit ci-dessus est REFUSÉ. C'est le but.
}
Résolveur : servir les noms internes et filtrer
# Le résolveur du mesh. Deux rôles, volontairement réunis :
# 1. il sert les noms *.mesh.exemple.fr (adresses privées du mesh)
# 2. il filtre publicité et traqueurs pour TOUS les appareils, mobiles compris
dns:
bind_hosts: ["10.0.0.53"] # adresse privée du mesh, JAMAIS 0.0.0.0
upstream_dns:
- "https://dns.exemple-public.net/dns-query" # chiffré vers l'extérieur
# Les noms internes ne sortent JAMAIS vers un résolveur public.
# Sans cette ligne, vos requêtes internes fuitent chez votre fournisseur DNS.
upstream_dns_file: ""
rewrites:
- domain: "passerelle.mesh.exemple.fr"
answer: "10.0.0.12"
- domain: "domotique.mesh.exemple.fr"
answer: "10.0.0.31"
filtering:
protection_enabled: true
filters_update_interval: 24
Certificat joker par validation DNS
#!/usr/bin/env bash
# Certificat joker *.mesh.exemple.fr : validation par DNS, aucune connexion entrante.
# Les identifiants de l'API DNS sont injectés au lancement : jamais écrits sur disque,
# jamais passés en argument de commande (un argument se retrouve dans l'historique
# et dans la liste des processus).
set -euo pipefail
acme.sh --issue --dns dns_monhebergeur \
-d '*.mesh.exemple.fr' \
--keylength ec-256
# Le renouvellement est automatique. SA SURVEILLANCE doit vivre AILLEURS que sur le
# mesh : le jour où le certificat expire, une alerte hébergée derrière ce certificat
# est injoignable. Alerte par un canal externe (courriel, SMS).
Service exposé sur le mesh : l’erreur à ne pas faire
services:
application:
image: exemple/application:1.4.2 # version FIGÉE, jamais « latest »
ports:
# BON : écoute UNIQUEMENT sur l'adresse du mesh.
- "10.0.0.12:9000:9000"
# JAMAIS ceci :
# - "9000:9000"
# Docker publie alors sur TOUTES les interfaces, y compris le réseau local,
# et contourne le pare-feu de l'hôte en écrivant ses propres règles.
# Le service que vous croyez réservé au mesh est en réalité ouvert au réseau.
restart: unless-stopped
Ce dernier point mérite d’être souligné : publier un port Docker sans préciser l’adresse d’écoute annule le bénéfice du mesh. C’est l’erreur la plus fréquente et la plus silencieuse : le service fonctionne parfaitement, il est juste aussi accessible à tout votre réseau local.
Ce que je ferais différemment
Commencer par le test d’enrôlement à distance. Nous avons conçu l’architecture, choisi les composants, préparé les certificats : et gardé pour la fin la seule question qui pouvait tout invalider : un appareil neuf, hors du réseau, arrive-t-il à rejoindre le mesh ? C’est le premier test à faire, sur un banc jetable, avant toute décision d’architecture.
Écrire la règle de nommage avant la première machine. Le découplage service/machine coûte cinq minutes au départ et des heures ensuite. La première fois qu’on écrit une adresse « juste pour tester », elle reste trois ans.
Nommer le risque qu’on accepte. Faire cohabiter le plan de contrôle avec ses données est un compromis raisonnable pour un particulier. Ce qui ne l’est pas, c’est de le découvrir après coup. Écrivez-le, avec la condition qui vous ferait changer d’avis.
Se méfier des mesures qu’on n’a pas rejouées. Le comparatif a failli désigner le mauvais candidat parce qu’un bug avait été mesuré sur un composant qui n’était pas celui du déploiement. Avant de trancher sur un défaut mesuré : est-ce que je mesure bien ce que je vais installer ?