---
Title: Serveur Openvpn sous Debian 9 et systemd
Subtitle: : easy-rsa et systemctl inside !
date: 2017-12-12 10:25
Authors: Victor
Slug: serveur-openvpn-sous-debian-9-et-systemd
Category: Réseaux
Tags: openvpn, tunnel, chiffrement, debian, systemd
keywords: openvpn, tunnel, chiffrement, debian, systemd
Status: published
---
[TOC]

# Openvpn, Debian 9 et Systemd
Pas mal de choses ont changées dans la configuration d'un serveur openvpn avec l'arrivée de Debian 9 et la "séparation" de easy-rsa et openvpn.

Entre les services systemd et le fait qu'Openvpn ne vient plus nativement avec easy-rsa, il me fallait une petite remise au point sur le sujet !

C'est chose faite :-)

On va donc voir dans cet article comment configurer un serveur Openvpn sur Debian 9, puis comment faire en sorte qu'il se lance tout seul via les services systemd.  
Normalement cette procédure devrait fonctionner pour toutes les versions de Debian supérieure à Debian 9 Stretch.

Je précise que je vais traiter la partie serveur VPN uniquement. Je pars donc du principe que vous disposez déjà d'un serveur sous Debian 9 (physique, VM, CT, ...), que ce serveur dispose d'une IP publique pour exposer le serveur Openvpn, et/ou que vous maitrisez le NAT de port pour faire en sorte qu'il le soit (exposé :-p)  
J'assume totalement le fait que cet article est un bloc note pour garder les infos sous la mains en cas de besoin !  

D'un autre côté vous me connaissez, je suis obligé de détailler, donc comme d'habitude, si vous rencontrez des difficultés ou que vous avez besoin d'aide, faites moi signe dans les commentaires !

# Préparation du serveur

## Paquets et répertoires
Sur Debian 9, il faut désormais installer 2 paquets pour gérer openvpn en mode serveur.  
Ils sont disponibles par défaut, donc pas de tergiversations :

    aptitude install openvpn easy-rsa

Par convention, on va poser les fichiers dans `/etc/openvpn`, c'est parti :

    cd /etc/openvpn
    YOURSERVER="yourserver"
    make-cadir ${YOURSERVER}

Cela va permettre à easy-rsa d'initialiser un répertoire contenant tous les fichiers (binaires, configurations) pour générer et gérer les clefs, comptes et autre index qui vont servir à votre serveur openvpn.  
Il faut également lui indiquer quel fichier de conf openssl on va utiliser, pas de chichi faites un lien vers le plus récent :

    cd /etc/openvpn/${YOURSERVER}
    ln -s openssl-1.0.0.cnf openssl.cnf

## Variables
Comme d'habitude avec Openvpn, on va utiliser le fichier vars qui contient les différentes variables utiles à la génération des clefs.

Editez donc le fichier `vars` et modifiez les valeurs suivantes pour gagner du temps par la suite :

    vim /etc/openvpn/${YOURSERVER}/vars
    # -----
    export KEY_SIZE=4096 # Une clef de 4096 est le minimum actuellement pour un chiffrement correct
    export KEY_COUNTRY="US"
    export KEY_PROVINCE="CA"
    export KEY_CITY="SanFrancisco"
    export KEY_ORG="Fort-Funston"
    export KEY_EMAIL="me@myhost.mydomain
    	"
    export KEY_OU="MyOrganizationalUnit"

    export KEY_NAME="VPNServerName" # Choisissez un nom qui vous parlera, même dans 6 mois !

Bien entendu modifiez les différentes valeurs pour coller à vos propres souhaits. Cela vous permettra d'avoir une bonne configuration par défaut pour générer plus rapidement les différentes clefs.

## Clefs serveur
On est désormais prêt pour générer toutes les clefs qui vont permettre au serveur de fonctionner, avec un maximum de sécurité.  
Cette partie peut être longue, selon votre CPU et le niveau d'entropie de votre serveur. Plus le CPU est costaud et le serveur est physique, plus ça ira vite, mais dans le cas contraire prenez votre mal en patience, ça va se dépiler ;-)  

Je vous invite d'ailleurs à aller jeter un oeil à mon article sur [l'amélioration de l'entropie pour votre serveur]({filename}/2017/2017-12-08-ameliorer-l-entropie-de-votre-serveur.md).  

Sinon, soit vous disposez d'un bon gros serveur physique des familles, soit vous avez 2 ou 3 thermos de café prêts pour passer le temps ^^

C'est parti !

    cd /etc/openvpn/${YOURSERVER}
    source ./vars # On export toutes les variables qu'on a editées
    # ./clean-all ## ATTENTION ne lancez cette commande que la toute première fois ou vous initialiser votre serveur, car elle va effacer TOUTES les clefs du serveur !
    ./build-ca # Pour construire le certificat d'authorité de votre serveur

Notre autorité est prête, on va pouvoir passer aux clefs du serveur en tant que telles :

    cd /etc/openvpn/${YOURSERVER}
    ./build-key-server ${YOURSERVER} # ${YOURSERVER} indique le nom de la clef générée, vous pouvez bien sûr l'adapter

On génère également une clef HMAC :

    openvpn --genkey --secret /etc/openvpn/${YOURSERVER}/keys/ta.key

Attention, l'étape suivante est probablement la plus longue.  
Il va falloir générer une clef [Diffie Hellman](https://fr.wikipedia.org/wiki/%C3%89change_de_cl%C3%A9s_Diffie-Hellman) de 4096 bits. Cela peut assez facilement prendre des heures si votre CPU est faiblard (bonjour, Intel Atom !). N'hésitez pas à la lancer dans un tmux pour qu'elle tourne tranquillement, et continuez à dérouler la procédure pendant ce temps.

    cd /etc/openvpn/${YOURSERVER}
    openssl dhparam 4096 > keys/dh-4096.pem

On dispose de toutes nos clefs, il est temps d'attaquer la configuration !

## Configuration de base et sécurité
Openvpn vient sur Debian avec une configuration exemple que l'on va simplement réutiliser :

    gunzip -c /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz > /etc/openvpn/${YOURSERVER}.conf

Le fichier est auto-documenté de manière assez complète grâce à ses commentaires. Quelques variables sont bien entendus à changer pour que tout fonctionne, on va s'y intéresser de plus près :-)  
Editez manuellement le fichier pour modifier les quelques variables qui nous intéressent

    vim /etc/openvpn/${YOURSERVER}.conf

puis :

    ca /etc/openvpn/YOURSERVER/keys/ca.crt
    cert /etc/openvpn/YOURSERVER/keys/server.crt
    key /etc/openvpn/YOURSERVER/keys/server.key  # This file should be kept secret
    dh /etc/openvpn/YOURSERVER/keys/dh-4096.pem
    tls-auth /etc/openvpn/YOURSERVER/keys/ta.key 0 # This file is secret

**Bien sûr, remplacez YOURSERVER par le chemin vers vos clefs !**  
Les configuration suivantes vont permettre de relever un peu plus le niveau de sécurité du serveur, au prix d'une utilisation CPU un peu plus intensive. Mais vu l'époque, c'est nécessaire..

    cipher AES-256-CBC
    auth SHA512
    tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-256-CBC-SHA:TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA:TLS-DHE-RSA-WITH-AES-128-CBC-SHA:TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA

## Utilisateur Openvpn
Openvpn tourne en root par défaut, ce qui bien entendu est **mal**. Traditionnellement, on le configure donc pour utiliser l'utilisateur nobody ainsi que son groupe associé pour le lancer.  
Cependant, pour limiter les risques de compromission, il est je pense préférable de le faire tourner avec son propre utilisateur. Après tout, nobody peut être utilisé par d'autres services à côté.

    adduser --system --shell /usr/sbin/nologin --no-create-home openvpn

Puis dans votre configuration openvpn :

    user openvpn
    group nogroup

## Démarrer le serveur

Enfin ! On arrive à la subtilité d'openvpn avec systemd : lancer le serveur :-)  

Heureusement une fois qu'on a choppé le coup, le concept reste assez simple. En fait, openvpn propose une unit systemd, qui va permettre d'aller chercher votre fichier de configuration dans `/etc/openvpn` et de le gérer avec systemctl comme n'importe quel service :

    systemctl start openvpn
    systemctl start openvpn@${YOURSERVER}

Comme on le voit, il suffit de donner à systemctl le nom de votre fichier de conf (sans le .conf), et il va s'occuper de le démarrer.  
Si vous disposez de plusieurs fichiers de configuration, il vous suffit de lancer autant de service @votrefichierdeconf que vous le souhaitez.

Vous pouvez vérifier qu'ils ont bien démarrés avec `systemctl status`, et je vous conseille également de les activer au démarrage :

    systemctl enable openvpn
    systemctl enable openvpn@${YOURSERVER}

Voila, côté serveur, on a finit !

PS : Si vous utilisez un container openvz, il peut y avoir quelques subtilités supplémentaires. Je vous invite à vérifier à la fin de l'article ;-)

# Génération des clients
Comme pour le serveur, la génération d'un compte VPN client va se faire en deux phases : les clefs et le fichier de configuration.

## Clefs client
On retourne dans le répertoire de votre serveur VPN :

    cd /etc/openvpn/${YOURSERVER}
    source ./vars
    ./build-key nom_du_client

De préférence, indiquez un mot de passe pour la clef, sauf si vous savez que votre client se connectera en mode automatique (par exemple au démarrage du PC client)  

Voila, vous avez vos clefs pour votre premier compte client VPN.

## Configuration client

On va là aussi récupérer la configuration exemple fournie par openvpn. Je vous conseille d'ailleurs de vous créer un petit répertoire où caler toutes vos configurations clients, ça sera plus pratique :

    mkdir /etc/openvpn/${YOURSERVER}/clients
    cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf /etc/openvpn/${YOURSERVER}/clients/nom_du_client.ovpn

Quelques champs vont bien sûr devoir être édités !

    remote 192.168.1.5 1194 # Mettez ici l'IP de votre serveur VPN et le port utilisé (par défaut 1194 en UDP)
    user nobody
    group nogroup
    ca ca.crt
    cert nom_du_client.crt
    key nom_du_client.key
    tls-auth ta.key 1
    cipher AES-256-CBC
    auth SHA512
    tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-256-CBC-SHA:TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA:TLS-DHE-RSA-WITH-AES-128-CBC-SHA:TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA

Il faut bien sur remettre les options de chiffrement et d'authentification mise dans le serveur, sinon le client ne pourra pas lui parler :-)  
Pensez également à bien mettre les noms de clefs correspondant au client (pas celles du serveur). Les deux champs ca.crt et ta.key sont des exceptions, ce sont bien les fichiers du serveurs qu'il faut indiquer ici.

Préparons ensuite le fichier à envoyer au client, avec tout ce qui va bien dedans :

    # tar cJf /etc/openvpn/${YOURSERVER}/clients/nom_du_client.tar.xz -C /etc/openvpn/${YOURSERVER}/keys ca.crt nom_du_client.crt nom_du_client.key ta.key -C /etc/openvpn/${YOURSERVER}/clients/ nom_du_client.ovpn

Et voila, vous avez votre compte client à transmettre à votre utilisateur.

Je vous conseille de le tester par vous même, par exemple depuis votre PC, pour être sûr que tout est OK.

## Connexion client automatique

Si vous utilisez ce compte pour une machine qui doit se connecter de manière automatique à votre VPN, vous pouvez là encore utiliser systemd. Attention, sur la machine cliente !

Détarez votre archive dans le `/etc/openvz` de votre client (vous avez bien entendu installé openvpn dessus ;-) )

    cd /etc/openvpn
    tar xJf /path/to/nom_du_client.tar.xz

Il vous suffit ensuite d'activer le service openvpn, qui devrait lancer le fichier de conf.  
**Attention**, selon les versions il faudra peut être renommer le fichier de configuration en .conf au lieu de .ovpn. Linux préfère les .conf, Windows les .ovpn.

    systemctl start openvpn
    systemctl start openvpn@nom_du_client
    systemctl enable openvpn
    systemctl enable openvpn@nom_du_client

Et voila votre connexion s'établit :-)

Vous devriez désormais posséder un serveur VPN parfaitement fonctionnel avec systemd, félicitations !

N'hésitez pas à approfondir le fonctionnement d'openvpn, de nombreuses configurations sont possibles, et laissez moi un commentaire si jamais vous souhaitez plus de détails sur quelque chose ;-)

# Configuration avancée

On est parti ici de la configuration par défaut. Vous avez donc un serveur VPN qui écoute sur toutes les interfaces du serveur, sur le port standard openvpn 1194 en UDP, qui utilise tun et une plage d'ip en 10.8.0.0/24, etc, etc

Il est possible d'aller beaucoup plus loin dans la configuration, en modifiant les plages IP, en branchant le VPN sur un bridge pour étendre un réseau local à travers le VPN, pour lancer des scripts au démarrage du VPN, améliorer les logs, et pleins d'autres choses encore.

Personnellement je me sers d'openvpn pour étendre le LAN de mon chez moi sur tous mes serveurs virtuels, ce qui permet de les joindres comme s'ils étaient dans la maison.

Je ferai (probablement) d'autres articles à ce propos, si ça vous intéresse, n'hésitez pas à me laisser un petit commenaire !

# Openvpn et Openvz (7)
Si vous utilisez un container openvz pour faire tourner votre serveur VPN, il faut savoir qu'il y a quelques subtilités à mettre en place, sans quoi votre serveur refusera de démarrer, ou ne pourra pas atteindre les autres CT hébergés.

## Activer tun/tap dans un CT
Sur les versions antérieures d'openvz, il fallait activer les capability admin ainsi que tun/tap sur le CT depuis l'hyperviseur pour que openvpn puisse démarrer. Pour plus d'information, veuillez vous référer au [wiki](https://openvz.org/VPN_via_the_TUN/TAP_device)

Sur **openvz7**, un CT doit toujours avoir ces options activées, MAIS les commandes vzctl n'ont plus aucun effet !  
Il semble qu'à l'heure actuelle, l'activation ne marche pas. vzctl se termine avec succès, dit que tout est ok, mais rien n'est activé, et prlctl ne connait pas ces options...

Il est donc nécessaire d'activer directement ces options dans le fichier de conf du CT..

    vim /etc/vz/conf/CTID.conf
    #Ajoutez les lignes suivantes :
    FEATURES="bridge:on"
    DEVNODES="net/tun:rw "
    DEVICES="c:10:200:rw "
    CAPABILITY=" NET_ADMIN:on"

Il est ensuite nécessaire de redémarrer le CT

    prlctl restart CTID

## Pas de communication entre client VPN et les autres CT

Si vous utilisez votre VPN en tant que pont pour vous permettre d'accéder à d'autres CT hébergés, voir à des serveurs physiques présents derrière le VPN, par exemple via un VLAN ou une interface bridge, il faut savoir que à partir de openvz7, un [anti-spoofing](https://fr.wikipedia.org/wiki/Usurpation_d%27adresse_IP) est présent par défaut quand on mets une interface réseau à un CT. Ce dernier ne peut donc pas sortir avec une IP que l'hyperviseur ne connait pas dans le cas d'un venet, ou dans le cas d'un veth avec une MAC que l'hyperviseur ne connait pas.

Ce qui bien evidemment pose souci si vous souhaitez utiliser des adresses IP derrière votre serveurs VPN.  

Plutôt que monter un NAT, et si vous avez confiance dans votre réseau, vous pouvez désactiver cet anti-spoofing pour le CT qui contient votre serveur VPN.  
Il va falloir supprimer son interface réseau et la recréer, à l'heure actuelle prlctl ne gère pas de "set" pour cette option, uniquement un "add" :

    prlctl set CTID --device-del eth0
    prlctl set CTID --device-add net --network votre_reseau --macfilter no eth0

## daemon() failed or unsupported: Resource temporarily unavailable
Vous obtenez cette erreur parfaitement cryptique au démarrage d'Openvpn ?

C'est normal ! :-D  
Openvpn dans son unit systemd par défaut, limite le nombre de process à 10, sauf que dans un CT, vous n'avez pas les droits pour gérer ce genre d'option, qui sont gérées via l'hyperviseur et les limitations accordé au CT.

Pour ça pas le choix, il va falloir éditer cette ligne dans la configuration de l'unit systemd directement..

    vim /lib/systemd/system/openvpn@.service
    # Commentez la ligne LimitNPROC=10
    LimitNPROC=10 => # LimitNPROC=10

Puis reloadez les unit systemd :

    systemctl daemon-reload

Votre openvpn devrait ensuite fonctionner.

Cf ce [bugreport](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=819919)
