Mettre en place un VPN Mesh avec tinc sur Debian/Ubuntu

Il peut-être intéressant (ou nécessaire) de mettre en place un VPN  pour inter-connecter plusieurs serveurs, principalement pour garantir le chiffrement des échanges entre ces derniers. Si des solutions comme OpenVPN sont très populaires car elles proposent des clients sur toutes les plateformes, elles ne sont pas nécessairement les plus pertinentes lorsqu'il s'agit de créer un réseau privé entre plusieurs serveurs linux. Pour répondre à ce besoin, il existe heureusement d'autres solutions, notamment Tinc, le sujet que nous allons aborder aujourd'hui.

Dans ce tutoriel nous allons voir comment installer la dernière version stable de Tinc et comment créer un réseau privé pour connecter 3 serveurs. Cet exemple est basé sur mon utilisation actuelle précédente de Tinc, à savoir connecter mon raspberry pi (derrière un NAT) et mon cluster de stockage GlusterFS, réparti sur deux serveurs dédiés. Tinc était alors la solution à deux problématiques :

  • établir une connexion securisée entre les noeuds GlusterFS (j'ai préféré mettre en place un VPN à cause des nombreux problèmes rencontrés avec les connexions SSL/TLS et GlusterFS 4.X)
  • accéder aux données d'un cluster GlusterFS depuis un client derrière un NAT

Les termes utilisés dans ce tutoriel :

  • une instance Tinc = un réseau privé Tinc
  • un noeud = un serveur du réseau

Installer Tinc

La méthode la plus simple pour installer Tinc est d'utiliser les dépôts APT d'Ubuntu ou de Debian. Cependant les paquets disponibles ne sont pas vraiment à jour. La version actuelle de Tinc est 1.0.35, mais les dépôts Ubuntu ne propose que la version 1.0.33 et ceux de Debian la version 1.0.31.


Edit du 10/07/2019 : Les mises à jour de sécurité des paquets Debian sont rétro-actives sur les versions précédentes. Il n'y a donc pas de danger particulier à utiliser des versions antérieures à 1.0.35 sur Debian.


Il est donc préférable/recommandé de compiler Tinc depuis les sources, notamment lorsqu'on sait que la version 1.0.35 est une release de sécurité suite à la découverte de deux failles qui touchent toutes les versions antérieures (CVE-2018-16737, CVE-2018-16738).

Ajout du 10/07/2019 : Pour simplifer l'installation sur Ubuntu 18.04 LTS, j'ai réalisé un backport du paquet tinc 1.0.35 depuis les dépôts d'Ubuntu 19.04. Le backport est disponible via le service PPA launchpad : https://launchpad.net/~virtubox/+archive/ubuntu/tinc

Cette version n'est pas vulnérable aux CVE-2018-16737 et CVE-2018-16738.
Pour l'installer rien de plus simple :

sudo add-apt-repository ppa:virtubox/tinc -u -y
apt install tinc -t bionic-backports

Compilation

On commence par installer les dépendances permettant de compiler tinc :

sudo apt-get install git libssl-dev zlib1g-dev liblzo2-dev \
build-essential automake autoconf gettext texinfo -y

Puis on clone le dépôt Git :

cd /usr/local/src
git clone git://tinc-vpn.org/tinc
cd tinc

On réalise la configuration avant de compiler :

autoreconf -fsi
./configure --prefix=

Puis on lance la compilation :

# -j définit le nombre de threads utilisés pour la compilation 
# $(nproc) permet d'obtenir le nombre de threads disponibles sur le CPU 
make -j"$(nproc)"

Si la compilation se déroule sans erreur, on peut alors installer tinc avec la commande :

sudo make install

Ajout des services systemd

La dernière étape pour terminer l'installation est la création des services systemd permettant d'exécuter Tinc et ses instances (réseaux privés) dès le démarrage de la machine.
Il faut en effet créer deux services distincts, le premier permettant de gérer l'exécution de Tinc, et le second l'exécution des instances Tinc (sous le format tinc@nom_du_reseau).

Le service tinc

Le fichier à créer est /lib/systemd/system/tinc.service dont le contenu est le suivant :

# This is a mostly empty service, but allows commands like stop, start, reload
# to propagate to all tinc@ service instances.
[Unit]
Description=Tinc VPN
After=network.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/true
ExecReload=/bin/true
WorkingDirectory=/etc/tinc

[Install]
WantedBy=multi-user.target

On peut ensuite activer le service via la commande :

sudo systemctl enable tinc.service

Le service pour les instances tinc@

Le second service qui permet la gestion des instances Tinc est à créer dans /lib/systemd/system/tinc@.service, voici son contenu :

[Unit]
Description=Tinc net %i
PartOf=tinc.service
ReloadPropagatedFrom=tinc.service

[Service]
Type=simple
WorkingDirectory=/etc/tinc/%i
ExecStart=/usr/sbin/tincd -n %i -D
ExecReload=/usr/sbin/tincd -n %i -kHUP
KillMode=mixed
TimeoutStopSec=5
Restart=always
RestartSec=60

[Install]
WantedBy=tinc.service

Il permettra par la suite d'activer séparément les réseaux privés (instances) Tinc via la commande :

sudo systemctl enable tinc@nom_du_reseau

Il n'est donc pas nécessaire d'utiliser cette commande immédiatement, puisqu'il faut tout d'abord réaliser la configuration de notre réseau privé.

Configurer Tinc

La configuration d'une instance Tinc

L'ensemble des fichiers de configuration de Tinc sont à placer dans le répertoire /etc/tinc, dans lequel la configuration de chaque instance se fera dans un répertoire portant le nom de l'instance.

Quelques informations sur la configuration utilisée pour notre exemple :

  • notre instance/réseau privé se nomme jesuisadmin_reseau, sa configuration se trouve donc dans le répertoire /etc/tinc/jesuisadmin_reseau
  • nos 3 serveurs se nomment respectivement gfs1, gfs2 et rbpy.
  • Nous avons choisi d'utiliser la plage d'adresses 10.0.0.0/24 pour notre réseau privé Tinc

Afin vous donner tout de suite une vue d'ensemble de la configuration d'un réseau privé avec Tinc, voici le répertoire de configuration du réseau jesuisadmin_reseau, une fois toutes les étapes du tutoriel terminées :

├── jesuisadmin_reseau
│   ├── hosts
│   │   ├── gfs1
│   │   ├── gfs2
│   │   └── rbpy
│   ├── rsa_key.priv
│   ├── tinc-down
│   ├── tinc-up
│   └── tinc.conf

On y retrouve :

  • tinc.conf : fichier de configuration principal qui contient notamment le nom de la machine, l'interface réseau à utiliser et le protocole de l'instance (ipv4/ipv6).
  • tinc-up et tinc-down : les scripts permettant de démarrer et d'arrêter l'instance Tinc
  • rsa_key.priv : la clé privée du serveur
  • répertoire hosts : le répertoire qui contient les configurations partagées de chacun des noeuds connectés au réseau privé.

Les étapes pour configurer nos 3 machines vont donc être :

  1. Réaliser la configuration initiale de chaque machine
  2. Générer les clés publiques/privées de chaque machine
  3. Synchroniser le répertoire hosts entre les machines

Configuration initiale

-- À réaliser sur les 3 serveurs --

On commence donc par créer le répertoire `/etc/tinc/jesuisadmin_reseau` :

mkdir -p /etc/tinc/jesuisadmin_reseau

Puis on créer le fichier de configuration principal tinc.conf dans ce nouveau répertoire :

nano /etc/tinc/jesuisadmin_reseau/tinc.conf

Dans lequel nous allons définir la configuration de notre réseau privé, en commençant par gfs1 :

# Interface réseau à utiliser
Interface = tun0
# Identifiant de la machine sur le VPN
Name=gfs1
AddressFamily = ipv4

On réalise la même opération sur gfs2, avec une petite différence dans le fichier tinc.conf puisqu'on y ajoute la directive `ConnectTo` :

# Interface réseau à utiliser
Interface = tun0
# Identifiant de la machine sur le VPN
Name=gfs2
AddressFamily = ipv4
# sur le client
ConnectTo = gfs1

On termine par le troisième serveur rbpy dont la configuration sera similaire à gfs2 :

# Interface réseau à utiliser
Interface = tun0
# Identifiant de la machine sur le VPN
Name=rbpy
AddressFamily = ipv4
# sur le client
ConnectTo = gfs2

Générer les clés publiques/privées

Pour pouvoir initier la connexion entre les différents serveurs, Tinc se base sur un échange de clés cryptographiques, sur le même principe que les clés SSH. Il faut donc créer un répertoire hosts dans lequel nous allons définir les adresses IP publiques et privées de chacun des serveurs, ainsi que leurs clés publiques.

On commence donc par créer le répertoire hosts :

mkdir -p /etc/tinc/jesuisadmin_reseau/hosts

Avant de générer la clé publique et privée d'un serveur, en utilisant la commande :

sudo tincd -n jesuisadmin_reseau -K4096

L'argument -K4096 définit la taille de la clé RSA à générer. Lors de l'exécution de cette commande, vous devriez obtenir deux nouveaux fichiers :

  • la clé privée du serveur /etc/tinc/jesuisadmin_reseau/rsa_key.priv
  • la clé publique du serveur dans le fichier de configuration portant le nom de l'hôte : /etc/tinc/jesuisadmin_reseau/hosts/nom_du_serveur

Dans ce dernier fichier, nous allons devoir ajouter avant la clé publique, l'adresse publique et privée de l'hôte. Il est également possible d'y ajouter d'autres paramètres, comme par exemple les ciphers à utiliser pour la connexion.

Voici un exemple de fichier de configuration pour le serveur gfs1 :

Address = 5.9.XXX.XXX
Subnet = 10.0.0.1/32
Cipher=aes-256-cbc
Digest=sha256

-----BEGIN RSA PUBLIC KEY-----
MIICCgKCAgEApd4Gf48I1Cnvgb8Hw67yIWmlhoe9yiz80Fr1IF0gjjbDpzsZwkg+
6r7KaDIWmVdoSYiOlrutohH0105daS+YyJbTVP6heGYAlStVqMFL/rT2CbZvYEfe
F1l/PYtEGrbTRJDQgpwByXbmgvha2DcKBJFcfduH85FnYv7KzZ94vmYBwhZe8ArA
f/0XeEpR7fYfIdxN7Z5jS0olkd5mUyrpXVwkmbJ/9q3j5vuVMon9BLDAf1XP4oXn
ehRPLdh39XswFfF35rrxtLy03a+iPTZuhDBbVl2V/UVcVtyQHUNwTzrOvqBgYfaa
Q2L8hW6U/bvvOpj2NCN3YIm8cDR2NNScORXVSqm0xpTk+vCjETrOpBGR1z2JEWdT
3nPw+a7oAwfgCzSOvRx1MW+w1GqF+iil/ADQXcQa78i0xRIl/xCG0taI5EdUnRAq
7R5Y2kDtMt6LUdvOLPGpYFdIP859jTxSXSkkvWeEO7syuvVMdMLfBIGG1zczqQ6+
RLKCV+l0JwZpw4YEiJLHlzZQax3J7eBxlsv3gJoEWeuPZaPP/dUcREisqhrXLLT3
Jiq+aqMolbSzcXvRIGrcNVko4d82SStzpSJwehREhyDrgzOSMhEhTy7m/G3YvcGQ
v0F0bnuk1tqf6VUT9+MTBstaRTLEaRsc5RqI26lkCWwfO7c0WHkDLg0CAwEAAQ==
-----END RSA PUBLIC KEY-----

Dans lequel on retrouve les options :

  • Address est l'IP publique du serveur
  • Subnet est l'IP privée du serveur
  • Cipher & Digest les paramètres TLS (facultatif)

Synchroniser le répertoire hosts

Une fois cette étape réalisée sur chacun des serveur, il faut également procéder à l'échange des clés publiques entre les serveurs. Autrement dit, le contenu du répertoire hosts doit être le même sur chaque serveur. Dans notre cas, on doit y retrouver trois fichiers configurations :  gfs1, gfs2 et rpby.

Vous êtes libre d'utiliser la méthode de votre choix pour synchroniser le contenu du répertoire hosts entre vos serveurs, voici quelques propositions pour échanger les fichiers de configuration entre les serveur :

  • Synchroniser le répertoire avec rsync
  • Transférer les fichiers avec scp
  • Utiliser un dépôt git pour ajouter chaque serveur

Une fois de répertoire hosts synchronisé entre les serveurs, il ne reste plus qu'à configurer les scripts d'initialisation et d'arrêt de Tinc.

Configuration des exécutables Tinc

La dernière étape avant de pouvoir connecter nos serveurs est la création des scripts exécutables de créer et démarrer/arrêter l'interface réseau virtuelle utilisée pour se connecter au réseau privé. Pour cela il faut créer les fichiers tinc-up et tinc-down dans /etc/tinc/jesuisadmin_reseau dont voici le contenu pour gfs1 :

tinc-up

#!/bin/sh
# /etc/tinc/jesuisadmin_reseau/tinc-up 
ip addr add 10.0.0.1/24 dev $INTERFACE
ifconfig $INTERFACE up

tinc-down

#!/bin/sh
# /etc/tinc/jesuisadmin_reseau/tinc-down
ifconfig $INTERFACE down

Sur les deux autres serveurs, le contenu des deux scripts sera quasiment le même, puisque l'unique différence sera l'adresse IP de l'interface réseau.

Une fois les deux fichiers créés sur chacun des serveurs, il ne reste plus qu'à les rendre exécutables :

sudo chmod 755 /etc/tinc/jesuisadmin_reseau/tinc-*

Démarrer et administrer Tinc

Vérifier la configuration du pare-feu

Avant d'initialiser la connexion entre les serveurs, il est important de faire une vérification : le port utilisé par Tinc est-il ouvert ?
Par défaut, Tinc utilise le port 655, qu'il est donc nécessaire d'ouvrir préalablement. Si vous utilisez ufw, il vous suffit d'utiliser la commande

ufw allow 655

Mais vous pouvez également le faire directement via iptables :

iptables INPUT -p tcp --dport 655 -j ACCEPT
iptables INPUT -p udp --dport 655 -j ACCEPT

Démarrer et arrêter Tinc

Si vous avez réussi à suivre toutes les étapes du tutoriel, vous êtes enfin arrivés**** au bout du tunnel (meilleur jeu de mot de l'année) puisque vous allez pouvoir initialiser votre réseau privé depuis votre premier noeud. Cela peut se faire directement via la commande tincd ou en utilisant un service systemd.

Avec tincd

démarrer le réseau jesuisadmin_reseau

sudo tincd -n jesuisadmin_reseau

Vous pouvez ensuite vérifier avec ifconfig ou ip addr show que la création de l'interface réseau tun0 s'est bien déroulée et que l'adresse IP de cette dernière correspond bien à votre configuration. Il ne reste plus qu'à tester le ping entre vos machines.

Un problème de connexion ? Vous pouvez à tout moment arrêter la connexion au réseau tinc avec la commande suivante :

arrêter le réseau jesuisadmin_reseau

sudo tincd -n jesuisadmin_reseau -k

Avec un service systemd

Pour utiliser un service systemd, il faut tout d'abord activer le service associé à notre instance Tinc, ce qui se fait via la commande :

sudo systemctl enable tinc@jesuisadmin_reseau

On peut ensuite démarrer le service via la commande :

sudo service tinc@jesuisadmin_reseau start

Et après ?

Une fois la connexion entre les noeuds établie, vous pouvez librement utiliser votre réseau privé pour faire transiter vos données entre les serveurs.

Il sera peut-être nécessaire d'autoriser le trafic depuis le sous-réseau utilisé par Tinc via votre pare-feu. Dans le cas d'UFW, cela se fait via la commande :

sudo ufw allow from 10.0.0.0/24

Enfin pour un usage derrière un NAT, il vous suffit d'ajouter une redirection de port sur votre routeur/box pour pouvoir connecter votre serveur au réseau privé.

Commentaires

licence creative common

L’ensemble des articles publiés sur jesuisadmin.fr sont mis à disposition
selon les termes de la licence CC BY-NC-SA 4.0.

Article précédent Article suivant