Remarque préliminaire : cet article traite du démarrage d’instances d’OpenVPN sur un système Linux, ici une Debian Stretch, avec systemd. Il ne traite pas de la manière dont on configure une instance OpenVPN (paramètres et clés).

Avec SysV, un démon maître était lancé et chaque instance à démarrer automatiquement se faisait par configuration dans le fichier « /etc/default/openvpn » (du moins sur les Debian-like).

systemd est conçu pour gérer nativement ces problématiques de multi-instances, alors autant en profiter.

Contexte

Supposons que votre ordinateur portable nécessite d’être raccordé à trois infrastructures distantes via VPN, dont une de manière permanente. Imaginez que vous êtes un prestataire qui prend le contrôle à distance chez ses clients, tout en gardant en permanence un lien vers son serveur NAS à la maison,

On a donc 3 configurations différentes que nous appellerons « maison », « client-a » et « client-b ». Ces trois configurations et tous les fichiers nécessaires (notamment les clés) se placent dans leurs dossiers respectifs. Ce qui donne :

$ ls /etc/openvpn
client   client-a   client-b   maison   server

Cela dit, on remarque la présence de deux dossiers supplémentaires appelés « client » et « server ». Ils sont liés au fonctionnement prédéfini par les gabarits d’unités systemd pour OpenVPN 2.4.

Mise en œuvre

Pour chaque dossier créé, on trouve un certain nombre d’éléments, dont le fichier de configuration. Voici un exemple :

$ ls /etc/openvpn/maison
maison.conf   shared.key

Remarque : on pourrait tout bourrer comme des sagoins dans le dossier « client », mais je ne trouve pas ça très propre et très maintenable si les tunnels se multiplient.

Cependant, c’est bien le dossier « client » qui va faire foi dans un premier temps, vu la manière dont le gabarit est construit. Un simple lien symbolique suffit :

# ln -s /etc/openvpn/maison/maison.conf /etc/openvpn/client/maison.conf

Le gabarit n’est pas amorçable directement, il faut nommer explicitement une instance. Ici le fichier s’appelle « maison.conf ». Inscrire l’instance « maison » (qui ira bien chercher « maison.conf » dans le dossier « client ») est enfantin :

# systemctl enable openvpn-client@maison
Created symlink /etc/systemd/system/multi-user.target.wants/openvpn-client@maison.service → /lib/systemd/system/openvpn-server@.service.

Désormais, le VPN vers la maison se lance automatiquement au démarrage du système !

Et pour lancer les autres instances, pas besoin de les inscrire, systemd se débrouille à partir du nom indiqué pour retrouver ses petits.

# systemctl start openvpn-client@client-a

Remarques

Le paquet OpenVPN exploite donc désormais les services systemd, et non plus les scripts de type UNIX System V. Pour bien décortiquer l’affaire, il faut donc comprendre le fonctionnement des « unités » systemd. La petite bête réside dans ce paragraphe (en langue de Shakespeare) :

Optionally, units may be instantiated from a template file at runtime. This allows creation of multiple units from a single configuration file. If systemd looks for a unit configuration file, it will first search for the literal unit name in the file system. If that yields no success and the unit name contains an « @ » character, systemd will look for a unit template that shares the same name but with the instance string (i.e. the part between the « @ » character and the suffix) removed. Example: if a service getty@tty3.service is requested and no file by that name is found, systemd will look for getty@.service and instantiate a service from that configuration file if it is found.

Soit en gros : il détecte la présence d’un arobase, donc il suppose une instanciation. Il extrait le nom de l’instance entre le ‘@’ et le ‘.’, et lance le gabarit (reconnaissable au ‘@.service’) avec en paramètre le nom de l’instance.

Le paquet lui-même installe ces fichiers :

# ls -l /lib/systemd/system/openvpn*
-rw-r--r-- 1 root root 707 juil. 18 22:15 /lib/systemd/system/openvpn-client@.service
-rw-r--r-- 1 root root 780 juil. 18 22:15 /lib/systemd/system/openvpn-server@.service
-rw-r--r-- 1 root root 320 juil. 18 22:15 /lib/systemd/system/openvpn.service
-rw-r--r-- 1 root root 894 juil. 18 22:15 /lib/systemd/system/openvpn@.service

Dans le fichier « openvpn-client@.service », on trouve ces directives (parmi d’autres) :

WorkingDirectory=/etc/openvpn/client
[...]
ExecStart=/usr/sbin/openvpn --suppress-timestamps --nobind --config %i.conf

Et voilà grosso modo comment systemd s’y retrouve pour lancer des instances différentes à partir d’un même fichier. Même principe pour le gabarit « openvpn-server ».

Et les deux derniers ? Ce sont les versions pour OpenVPN 2.3, que je recommande d’abandonner si vous le pouvez. Ces instances cherchent leur configuration dans le dossier « /etc/openvpn » et sont lancées de manière significativement différentes. Si vous n’êtes pas un expert OpenVPN, ou ne recherchant pas explicitement ces détails de lancement, vous pouvez les abandonner sans regret. Sachez qu’un OpenVPN 2.4 peut parfaitement discuter avec un OpenVPN 2.3 moyennant de les laisser s’entendre sur les algorithmes et certains paramètres nouvellement introduits : c’est testé et approuvé !

systemd, faut en manger ! C’est bon ! (Mais des fois ça croque un peu sous la dent…)