Mettre en place un VPN facilement
Pour mon entreprise, je gère un ensemble de serveurs hébergeant nos outils internes, nos instances de test ainsi que certaines instances de production. C’est un job à plein temps que de gérer ces serveurs et, comme la plupart des services n’ont pas énormément d’utilisateurs, c’est souvent exagérément long de mettre en place des points d’accès sécurisés voir de faire les configurations minimales.
L’an passé, j’ai passé pas mal d’heures à configurer des interfaces Wireguard sur chaque serveur. J’adore Wireguard pour son côté minimal et bas niveau mais avec le nombre de serveurs et d’utilisateurs augmentant, ça devient rapidement galère de gérer les configs sur chaque serveur.
Après quelques recherches, je suis tombé sur Tailscale et son alter-ego Open-Source auto-hébergeable Headscale. Ce système repose sur Wireguard mais s’occupe de toute la partie config redondante tout en ajoutant des fonctionnalités supplémentaires: DNS automatique des nodes connectés, gestion facilité du SSH, règles ACL, file sharing et d’autres encores.
Cependant, la doc de Headscale est plutôt limitée et celle de Tailscale me perd rapidement. Je profite donc de cet article pour documenter les quelques étapes utiles pour mettre en place un réseau privé Open-Source en 10 minutes.
Mise en place du control plane
Headscale est à installer sur un serveur accessible en ligne. Soit directement sur la machine, soit en utilisant un container Docker.
Pour la méthode Docker, le programme headscale doit être lancé avec la commande suivante:
docker exec -it headscale headscale
Ce qui n’est pas très pratique donc je préfère ajouter un alias au niveau de Bash:
alias headscale=`docker exec -it headscale headscale`
De mon côté, j’utilise généralement Docker Compose avec une auto-config Traefik:
services:
headscale:
image: headscale/headscale:stable
container_name: headscale
restart: unless-stopped
volumes:
- ./config:/etc/headscale:ro
- ./lib:/var/lib/headscale
command: serve
healthcheck:
test: ["CMD", "headscale", "health"]
interval: 10s
timeout: 5s
retries: 3
labels:
- traefik.enable=true
- traefik.http.routers.headscale.rule=Host(`headscale.myhost.ch`)
- traefik.http.routers.headscale.entrypoints=websecure
- traefik.http.services.headscale.loadbalancer.server.port=8080
- traefik.http.routers.headscale.tls=true
- traefik.http.routers.headscale.tls.certresolver=letsencrypt
Ensuite, on récupère la base de configuration et on l’édite. Elle est bien documentée et facile à adapter.
wget -O config/config.yaml https://github.com/juanfont/headscale/blob/main/config-example.yaml
$EDITOR config/config.yaml
Afin de configuer les ACL, il faut notamment modifier les lignes policy.path pour adapter comme suit:
policy:
path: "/etc/headscale/acl.hujson"
Et on crée le fichier acl.hujson dans le dossier config/ avec le contenu suivant (à adapter selon les besoins):
{
"acls": [
{
"action": "accept",
"src": ["*"],
"dst": ["*:*"]
}
],
"ssh": [
{
"action": "accept",
"src": ["autogroup:member"],
"dst": ["autogroup:member"],
"users": ["root"]
}
]
}
Pour plus d’infos sur la configuration des ACLs, voir la doc de Tailscale.
Ensuite, on (re)démarre Headscale pour appliquer la nouvelle configuration. Avec Docker Compose: docker compose up -d.
Configuration du client
- Sur chaque node que l’on veut connecter au VPN, on installe Tailscale CLI.
- Sur le serveur, on crée un utilisateur
headscale users create <user>
- On génère une PreAuthKey pour cette utilisateur
headscale preauthkeys create --user <user>
- Sur la machine cliente, on se connecte en utilisant la PreAuthKey
tailscale up --login-server https://headscale.myhost.ch --authkey <preAuthKey>
Pour tester que l’on obtient bien une IP dans le VPN:
tailscale status
Une fois que nous avons au moins deux nodes dans le réseau, on peut faire un ping entre les deux pour tester le lien. Grâce au MagicDNS fourni par Headscale, on peut utiliser le hostname de chaque client pour le contacter.
Par exemple, si un client est connecté avec une machine dans le hostname est deer, on peut faire ping deer depuis un autre node pour l’atteindre.
Notes de fin
Ces quelques commandes permettent de créer rapidement un réseau DNS. Je passe sur les configurations nécessaires pour rendre accessible le Headscale depuis le Web car cela dépend fortement du cas d’usage. L’utilisation de Traefik Proxy ou d’un Caddy server rend ça plutôt simple.
Dès que l’on fait grandir le réseau, il devient assez vite nécessaire de mettre en place des ACL un peu réfléchies.
Pour voir toutes les possibilités offertes, cette page est une bonne référence.