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.

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 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

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 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


Victor Avatar Victor est le rédacteur principal du blog.
Comments

Si vous avez des questions, si quelque chose n'est pas clair, n'hésitez pas à commenter !

  • Avatar
    Permalink

    THH

    Posted on

    You may change :
    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

    to:
    ca /etc/openvpn/${YOURSERVER}/keys/ca.crt
    cert /etc/openvpn/${YOURSERVER}/keys/${YOURSERVER}.crt
    key /etc/openvpn/${YOURSERVER}/keys/${YOURSERVER}.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

    thanks for this post


    • Avatar
      Permalink

      Victor

      Posted on

      Not really, as here I edit manually the file, so variables will no be automatically replaced.
      I use uppercase to avoid confusion, apparently not with heavy success :-/

      You could use variables with some echo or cat << EOF tricks, but in this case all the file is crushed, and there are some very interesting documentation inside the example file I would avoid to destroy.

      Of course, the perfect way would be to use some deployment tools like Ansible to deploy the server and edit configuration file, but this is out of scope ^^

      Thank you!

  • Avatar
    Permalink

    gudbes

    Posted on

    Super tuto !!!!
    bon boulot super complet !!
    Cette partie là me plairait bien en complément : en branchant le VPN sur un bridge pour étendre un réseau local à travers le VPN


    • Avatar
      Permalink

      Victor

      Posted on

      Hello, merci pour ces compliments !

      Je prends bonne note de ton souhait, j'ai un peu de mal à être constant dans les articles en ce moment, mais je vais voir ce que je peux faire promis ;-)

  • Avatar
    Permalink

    vincent

    Posted on

    bon tuto bien pratique, merci! ant le VPN sur un bridge pour étendre un réseau local à travers le VPN

  • Avatar
    Permalink

    Clément

    Posted on

    Bonjour, j'ai suivi ton tuto, mais je voulais utiliser mon vpn pour rediriger ma connexion dessus. J'ai donc décommenté les lignes :

    push "redirect-gateway def1" push "dhcp-option DNS 1.1.1.1" push "dhcp-option DNS 1.0.0.1"

    Le client se connecte bien au serveur mais je n'ai plus accès à internet sur le client. Peut tu m'aider ?


    • Avatar
      Permalink

      Victor

      Posted on

      Hello !

      J'imagine que tu veux avoir Internet à travers le VPN ? Est ce que tu as modifié les adresses DNS du dhcp-option pour qu'elle correspondent à un vrai DNS (soit un des tiens, soit un DNS public comme 9.9.9.9)? Sinon en effet la résolution DNS ne marchera pas si les DNS ne sont pas bons.

      La 2eme étape pour que la redirection passe est que ton serveur VPN NAT ton traffic sortant pour aller sur Internet, sinon tes paquets qui le traversent ne sauront pas où aller.

      Par exemple, en envoyant ton flux dans le VPN avec une adresse en 10.8.0.1, ça va arriver tel quel sur le serveur VPN à l'autre bout, et ensuite essayer d'aller sur Internet avec cette adresse, ce qui n'est pas possible. Du coup sur ton serveur VPN il te faut NATer le flux sortant du VPN avec par exemple l'adresse IP du serveur VPN lui même pour que ton flux puisse sortir sur le net :-)

      J'espère que ça aide !

Ajouter un commentaire / Add a Comment

Vous pouvez utiliser la syntaxe Markdown pour formatter votre commentaire.

You can use the Markdown syntax to format your comment.

Flux Atom pour commentaire / Comment Atom Feed

Published

Category

Réseaux

Tags

Restez en contact