Lerm-IT

Blog traitant de technologies informatiques. Logiciel libre, AdminSys, DevOps et GNU/Linux !

05 Dec 2012

[OpenVPN] Mise en place d'un serveur OpenVPN et d'un client avec authentification par certificat.

Installation d’un serveur OpenVPN.

OpenVPN est une solution OpenSource permettant de mettre en place simplement et efficacement un VPN. L’avantage de la solution d’OpenVPN est sa relative simplicité d’utilisation mais aussi son support pour différentes plateformes (GNU/Linux, Apple Mac OS, Microsoft Windows, …) Nous verrons dans cet article un cas d’utilisation standard d’OpenVPN.

Contexte

Comme dit précédement nous ne tenterons pas ici de montrer des configurations “exotiques”. Notre contexte de base est très simple. Nous avons deux machines

  • Un serveur
  • Un client

Notre serveur hébergera le service OpenVPN et sera à l'écoute d'éventuelles connexions par des clients. C’est cette machine qui sera garante de la sécurité de l’authentification et des connexions. Notre client sera un simple client GNU/Linux se connectant sur notre serveur OpenVPN via un certificat. Pour corser un peu notre exemple notre serveur tournera sur un système GNU/Linux Debian et notre client sur un système GNU/Linux Gentoo.

Installation d’OpenVPN

La quasi totalité des distributions GNU/Linux proposent un package d’installation pour OpenVPN. Que se soit sous Gentoo ou sous Debian le nom de ce paquet est “openvpn”.

Installation sous GNU/Linux Gentoo

Comme toujours sous Gentoo il convient de faire attention à la liste des use-flags disponibles pour le ebuild. Un ’emerge -vp’ nous donne la liste des use-flags disponibles pour OpenVPN.

$ emerge -vp openvpn
...
[ebuild  N     ] net-misc/openvpn-2.2.2  USE="pam ssl -examples -iproute2 -minimal -passwordsave -pkcs11 (-selinux) -static" 890 kB
...

Quelques un sont assez explicites :

pam
permet d’activer ou non la compatibilité avec le système d’authentification unifié de GNU/Linux
ssl
permet d’activer le suport du SSL (Indispensable pour faire fonctionner le VPN)
examples
permet de compiler des examples de configurations

minimal :permet d’installer qu’une version minimale du logiciel. Ceci peut s’avérer utile si votre serveur manque de performances.

D’autres options sont un peu plus obscures :

iproute2
Cette option permet d’utiliser la commande “ip” en lieu et place des traditionnelles “ifconfig” et “route”. La commande “ip” est l'évolution des commandes “ifconfig” et “route” et tend (??) à terme à remplacer les traditionnels “net-tools” (ifconfig et route).
passwordsave
permet d’ajouter à openvpn la possibilité de sauvegarder des mots de passes. Nous n’utiliserons pas cette option.
pkcs11
PKCS signifit Public Key Cryptographic Standards et représente un ensemble de standards utilisés pour le chiffrement. L’un de ces standards, le 11, est celui définissant une API pour les cartes à puce leurs permettant de contenir un ensemble de clefs. Nous ne nécessitons pas dans notre exemple d’une telle fonctionnalité mais, suivant vos besoins, cette option pourrait etre activée.

Au final, nous utiliserons ici les options pam, ssl et iproute2. Les use-flags pam et ssl étant déjà activés nous ajouterons seulement iproute2 à notre variable USE.

# echo "net-misc/openvpn iproute2" > /etc/portage/package.use/openvpn

L’installation se déroule ensuite de manière tout à fait standard.

# emerge openvpn

L’installation sous GNU/Linux Debian

Comme souvent sous Debian un paquet pré-compilé existe déjà. Ce paquet contient la plupart du temps un maximum d’options de compilations activées, ceci pour couvrir la majorité des cas d’utilisations. Nous n’avons pas de problématique de sécurité poussée et deciderons d’utiliser le paquet pré-compilé. L’installation est donc très simple.

# aptitude install openvpn

L’installation étant terminée nous allons pouvoir opérer à la configuration.

Configurations

Les bases

  • Les fichiers de configuration

Nous allons commencer par faire un petit topo sur les fichiers de configurations. Les fichiers de configurations d’OpenVPN se trouvent dans /etc/openvpn. Dans ce dossier nous allons retrouver l’ensemble de nos fichiers permettant à notre serveur ou à notre client de fonctionner. En faite quand openvpn démarre, il lit l’ensemble des fichiers avec l’extension .conf de se dossier et applique les configurations présentent dans ces derniers. Dans notre exemple nous utiliserons le fichier server.conf pour la configuration du server et le fichier openvpn.conf pour le client mais ceci n’est pas une obligation (Du moins sous GNU/Linux Debian).

  • L’authentification par certificat

OpenVPN propose plusieurs méthodes d’authentifications :

  • Une méthode simple utilisant un couple nom d’utilisation/mot de passe
  • Une méthode dite de “pre-shared key” où tous les clients doivent avoir une clef pour pouvoir s’authentifier. Cette clef étant la meme pour tout le monde.
  • Une méthode d’authentification par certificat où chaque client possède un certificat (et donc une clef privée) validé par une authorité de certification.

La méthode de l’authentification par certificat est la plus sécurisée et la plus flexible d’administration. Chaque client ayant un certificat différent il est possible de révoquer un utilisateur en particulier sans interférer sur la totalité des utilisateurs. La contre partie d’une telle architecture est la “relative” complexité de l’installation. Qui dit certificat, dit mise en place d’une authorité de certification. Nous utiliserons dans cette article la méthode d’authentification par certificat et verrons comment mettre en place une PKI.

  • Les types de tunnels

OpenVPN peut fonctionner sur differrentes couches du modèle OSI (pas en meme temps) : La couche 2 et 3. Comme nous le savons la couche 2 du modèle OSI est la couche ethernet tandis que la couche 3 est la couche IP. Ainsi, si nous configurons un serveur OpenVPN pour créer des tunnels sur ethernet, quand un client se connectera à ce serveur il aura les memes possibilités que s’il était connecté à un switch. Aucun routage ne sera nécessaire. Inversement si nous créons un tunnel de couche 3 nos connexions prendront l’aspect d’un routeur. C’est à dire que OpenVPN devra maintenir une table de routage pour rediriger les clients dans les bonnes directions. Sous GNU/linux les tunnels de couche 2 sont représentés par des interfaces tap tandis que les tunnels de couche 3 le sont par des interfaces tun.

Le serveur

Après ces quelques informations théoriques nous allons entrer dans le vif du sujet. L’installation. Celle-ci se découpera en deux parties :

  • La création de l’authorité de certification
  • La configuration de notre serveur OpenVPN

Dans le cadre de cet article nous utiliserons indifféremment les termes Authorité de certification (abrégé CA) et PKI (pour Public Key Infrascruture, ou infrastructure à clefs publiques en francais).

  • Mise en place de la PKI

OpenVPN propose un ensemble de scripts nommé easy-rsa et permettant de mettre en place rapidement et simplement une authorité de certification. De nombreux articles sont déjà présents sur la toile et traitent de l’utilisation de ces scripts. Nous avons donc decidé de réaliser la mise en place de notre authorité de certification à l’aide des outils openssl de base sans les scripts easy-rsa. Néanmoins, si vous souhaitez utiliser ces scripts vous pouvez les retrouver, sur Debian, dans /usr/share/doc/openvpn/examples/easy-rsa.

Nous commençons donc par installer openssl, le logiciel qui nous permettra de génerer l’ensemble des clefs et certificats nécessaires à notre travail.

# aptitude install openssl

Les fichiers de configurations d’OpenSSL se trouvent dans /etc/ssl. C’est dans ce dossier que nous retrouverons le fichier openssl.cnf contenant la configuration par défaut utilisée par OpenSSL. Nous modifirons donc ce fichier pour coller avec les besoins de notre PKI. Notre Authorité de certification devrat créer et maintenir un certain nombre de fichier (les certificats générés, sa propre clef privée, etc …). Ces différents fichiers seront stockés dans le répertoire /etc/openssl suivant la structure suivante.

/etc/openssl/
.............certs/
.............private/
.............newcerts/
.............crl/
.............serials
.............index.txt

Le dossier certs contiendra tous les certificats générés, que ce soit pour les clients ou pour le serveur. Le dossier private, quand à lui, contiendra les clefs privées. Il ne devrait contenir que très peu de clefs privées (seulement celles du serveur) et il convient de faire tout particulièrement attention aux droits appliqués à ce dossier. N’oubliez en aucun cas qu’une clef privée est l’organe garante de la validité du certificat associé. Le dossier newcerts sera utilisé en interne par openssl pour y copier les nouveaux certificats créé. Ceux-ci seront renommés par openssl de manière à pouvoir etre réutilisé plus tard (pour révoquer un certificat par exemple). Enfin le dossier crl contiendra les fichiers ayant trait à la révocation des certificats. Nous créons aussi deux fichiers : index.txt et serials qui seront utilisés par openssl pour maintenir une base de données des certificats générés, révoqués, etc … Attention, le fichier serials devrat etre créer avec “01” comme contenu.

# mkdir /etc/ssl/{certs,private,newcerts,crl}
# touch /etc/ssl/index.txt
# echo "01" > /etc/ssl/serials

Nous allons ensuite configurer openssl pour lui spécifier l’ensemble de ces chemins. Editer donc le fichier /etc/ssl/openssl.cnf comme ceci.

...
[ CA_default ]
dir             = /etc/ssl              # Where everything is kept
certificate     = $dir/certs/ca.cert          # The CA certificate
private_key     = $dir/private/ca.key   # The private key
...

Nous n’avons pas listé l’ensemble des paramètres disponibles ici mais seulement ceux à modifier. Les choix fait ici sont les miens (nom du certificat et emplacements). Ils peuvent ne pas correspondre à vos envies ou besoins.

Une fois ce fichier modifié, nous allons pouvoir commencer à generer quelques fichiers.

La première des étapes à réaliser pour la mise en place d’une authorité de certification est la création du certificat de l’authorité de certification elle meme. Ce certificat, comme tous certificats, a besoin d’etre signé par une autre authorité de certification. Dans le cadre de cet article nous ne souhaitons pas réaliser cette étapes (couteuse) et avons donc décidé de signer le certificat de notre authorité … avec lui meme ! Nous aurons donc une authorité de certification auto-signé. Comme tous certificats, un certificat autosigné est généré à partir d’une clef privée. Nous allons générer la clef privée de notre PKI dans /etc/ssl/private/ca.key

# openssl genrsa 1024 > /etc/ssl/private/ca.key

Une fois la clé privée générée, créons un certificat autosigné.

# openssl req -new -x509 -key /etc/ssl/private/ca.key -out certs/ca.cert
# openssl req -new -x509 -key /etc/ssl/private/ca.key  -out /etc/ssl/certs/ca.cert
...
Country Name (2 letter code) [AU]:FR
State or Province Name (full name) [Some-State]:Rhone
Locality Name (eg, city) []:Lyon
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Romain THERRAT cie
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:PKI
Email Address []:[email protected]
...

Une série de question va vous etre posée. Les réponses que vous allez fournir vont permettre de générer un DN pour votre certificat. Un DN, pour Distinguish Name, permet d’identifier de manière unique une resource, ici le propriétaire d’un certificat. De plus, ces différentes informations peuvent faire l’objet de validation lors de la création d’un certification par votre PKI.

Bonne nouvelle ! Votre authorité de certification est installée, configurée et fonctionnelle ! Nous allons l’utiliser pour générer maintenant le certificat de notre serveur OpenVPN.

Comme pour notre certificat de base nous allons commencer par créer une clé privée, nous créerons ensuite un fichier CSR. Un fichier CSR est un fichier utilisé pour demander à une PKI de nous générer un certificat sans pour autant lui donner notre clé privée (celle-ci doit rester privée !). Nous générerons ensuite un certificat pour notre serveur OpenVPN.

# openssl genrsa 1024 > /etc/ssl/private/openvpn.key
# openssl req -new -key /etc/ssl/private/openvpn.key -out /etc/ssl/openvpn.csr
...
Country Name (2 letter code) [AU]:FR
State or Province Name (full name) [Some-State]:Rhone
Locality Name (eg, city) []:Lyon
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Romain THERRAT cie
Organizational Unit Name (eg, section) []:VPN
Common Name (eg, YOUR name) []:OpenVPN Server
Email Address []:[email protected]

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

Les memes questions que tout à l’heure vous sont posées. Il vous est aussi proposé de rentrer une chaine de caractères (challenge password). Ceci permet d’ajouter un protection à votre futur certificat via un mot de passe. Dans le cas de notre serveur VPN nous ne souhaitons pas un tel fonctionnement nous laissont donc les réponses à ces questions vides.

# openssl ca -out /etc/ssl/certs/openvpn.cert -infiles /etc/ssl/openvpn.csr 

...

Certificate is to be certified until Dec  5 23:03:11 2013 GMT (365 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

Après vous avoir proposé un résumé du certificat à signer openssl vous demande si vous accepté de créer le certificat et vous demande si vous accepté de mettre à jour sa base de données interne. Une fois ceci fait votre certificat OpenVPN est créé.

Nous allons donc pouvoir passer à la configuration de notre serveur OpenVPN.

Configuration du serveur OpenVPN
Comme nous l’avons dis plus haut nous allons créer la configuration de notre serveur openvpn arbitrairement dans /etc/openvpn/server.conf. OpenVPN propose un fichier de configuration de base que nous allons copier et modifier pour nos besoins. Nous ne présenterons ici qu’une petite partie des directives de configurations disponibles avec OpenVPN, si vous souhaitez plus d’informations, libre à vous de vous rendre sur le site officiel d’OpenVPN1.

La configuration serveur d’exemple d’OpenVPN est disponible sous la forme d’un fichier compressé en gzip dans le dossier /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz. Nous allons la copier.

# zcat /usr/share/doc/openvpn/sample-config-files/server.conf.gz > /etc/openvpn/server.conf

Editer ensuite ce fichier. Voici un extrait de celui-ci avec les directives de configurations importantes que nous avons modifié.

local 192.168.42.10
port  1194
proto udp
dev tun
ca /etc/ssl/certs/ca.cert
cert /etc/openvpn/openvpn.cert
key /etc/openvpn/openvpn.key
dh /etc/openvpn/512.dh
server 10.42.42.0 255.255.255.0
user nobody
group nogroup

Voici un résumé explicatif des différentes directives précédentes.

  • local : Précise sur quelle adresse IP notre serveur OpenVPN va écouter pour d'éventuelles connexions de clients. Si vous ne spécifier pas ce paramètre OpenVPN va écouter sur toutes les interfaces disponibles.
  • port : Le port d'écoute d’OpenVPN
  • proto : Le protocole (tcp ou udp) utilisé par OpenVPN. L’utilisation du TCP assure une meilleur qualité de liaison au pris d’une dégradation des performances.
  • dev : Permet de spécifier si nous souhaitons mettre en place une connexion sur la couche 2 ou 3 du modèle OSI. Les deux valeurs disponibles sont tap (couche 2) et tun (couche 3). Certaines directives de configurations dépendent de la valeur appliquée à ce paramètre.
  • ca : Chemin vers le certificat de notre authorité de certification. OpenVPN utilisera ce certificat pour authentifier nos clients.
  • cert et key : Le certificat et la clé privée associée de notre serveur OpenVPN. Il convient de déplacer ces fichiers dans un dossier accessible par OpenVPN mais aussi de faire attention aux privilèges appliqués à la clé privée. Encore une fois : Ce fichier doit rester privé, les autres utilisateurs du système ne doivent pas y avoir d’accès en lecture.
  • dh : Un fichier diffie-hellman. Nous reviendrons sur l’utilité et comment le créer dans la suite de cet article.
  • server : Cette directive est utilisée uniquement pour les tunnels de type tun (couche 3). Elle spécifit l’adresse IP qui sera utilisé par le réseau créé ainsi que le masque de sous réseau. Le serveur OpenVPN prendra la première adresse disponible sur ce réseau.
  • user et group : Ces paramètres de sécurité spécifient à quel utilisateur sera lié le processus OpenVPN une fois démarré. Les utilisateurs nobody et nogroup n’ont aucuns droits sur notre système.

Revenons maintenant sur le fichier diffie hellman. Dans le cadre de la mise en place d’un tunnel chiffré nous avons deux possibilités pour échanger des données : 1/ Utiliser des couples de clef public/privée entre nos clients et notre serveur et ainsi avoir un chiffrement asymétrique. 2/ Utiliser un secret partagé.

La première méthode est de loins la méthode la plus sécurisée qu’il existe mais elle est malheureusement très consomatrice de ressources. La seconde, quant à elle, est beaucoup plus performante mais souffre d’un problème de sécurité vis à vis de son modèle de conception.

L’utilisation de fichier diffie hellman permet de mettre en place une solution plus performante que la méthode asymétrique mais tout de meme alléatoire (non partagé par tous les membres du VPN). Les deux machines souhaitant dialoguer ensemble (client et serveur) vont ensemble générer une clé secrète symétrique connue d’eux seuls. Pour cela ils utiliseront la méthode Diffie-Hellman. La complexité de la clé générée est directement liée à la valeur d’un nombre premier partagé (en clair) entre les deux machines. Ce nombre premier permet ensuite aux deux interlocuteurs de se mettre d’accord sur une clé symetrique. La génération de nombre premier est complexe pour un ordinateur car il n’existe pas d’algorithmes mathématiques de génération. Aussi nous allons pré-générer ce chiffre pour nos clients. Openssl nous permet de faire ceci simplement.

# openssl gendh -out /etc/openssl/512.dh 512

Ceci fait il ne nous reste plus qu'à démarrer notre serveur OpenVPN.

# /etc/init.d/openvpn restart

Le client

La configuration du client est un peu plus simple que pour le serveur. Tout d’abord procedons à l’installation d’OpenVPN comme vu en début d’article. Le paquet que vous aller installer est le meme que pour le serveur.

Pour que votre client puisse se connecter au serveur OpenVPN il est necessaire qu’il possède un certain nombre de fichiers. Tout d’abord le certificat de la PKI. Il sera utilisé par notre client pour authentifier notre serveur OpenVPN. Ainsi notre client sera certain de bien dialoguer avec un serveur authorisé. Nous avons fait le souhait, plus haut dans ce document, de mettre en place un système d’authentification par certificats pour nos clients. Aussi nous allons créer un ensemble clef privée/certificat pour notre client.

Comme toujours créons notre clé privée.

$ openssl genrsa 1024 > ~/.openvpn/client.key

Cette ligne de commande est à executer sur la machine du client. Nous devrons ensuite, toujours sur cette machine, générer notre CSR (Certificat Signing Request) que nous transmettrons au serveur de PKI pour que celui-ci nous génère un certificat.

... Sur le client
$ openssl req -new -key ~/.openvpn/client.key -out ~/.openvpn/client.csr
... Envoyer le fichier client.csr au serveur
... et sur le serveur
# openssl ca -out /etc/openssl/certs/client.cert -infiles client.csr

Vous pouvez ensuite supprimer le fichier CSR.

Une fois que notre client aura récupéré l’ensemble de ces fichiers, nous pourrons le configurer. Sous gentoo il est necessaire de modifier le fichier de configuration /etc/openvpn/openvpn.conf c’est donc ce que nous allons faire. Voici la configuration que nous avons appliqué.

client
dev tun
proto udp
remote vpn.example.com 1194
ca /home/romain/.openvpn/ca.cert
cert /home/romain/.openvpn/client.cert
key /home/romain/.openvpn/client.key

Nous retrouvons les memes informations de configuration que dans le serveur (dev tun, proto udp, ca, cert et key). La ligne 1 permet de spécifier à OpenVPN que nous ne configurons pas un serveur ici mais un client quand à la ligne 4 elle permet de spécifier l’adresse du serveur vpn et son port.

Il est possible que vous rencontriez cette erreur chez votre client

WARNING: 'comp-lzo' is present in remote config but missing in local config, remote='comp-lzo'

et celle-ci chez sur votre serveur

Dec  6 09:40:43 vpn ovpn-server[2277]: MyCommonName/x.x.x.x:1194 Bad LZO decompression header byte: 42

Ceci est dut au fait que votre serveur VPN est configuré pour compresser les données qu’il envoye (qui plus est en lzo) mais que votre client ne l’est pas. Ajouter donc la ligne comp-lzo à la fin de votre fichier de configuration client et le tour est joué.

Il ne vous reste plus qu'à redemarrer OpenVPN et votre VPN est fonctionnel.

# /etc/init.d/openvpn restart

Conclusion

La mise en place d’un serveur VPN à l’aide d’OpenVPN est assez simple. Nous n’avons vu dans cet article seulement la mise en place du serveur sous l’angle de l’authentification. Il est à noter que sans un routage adéquat OpenVPN ne sert qu'à peut de chose. Ceci pourra un jour donner lieu à un autre article mais en attendant je vous invite à reprendre vos cours de réseau (oui ce modèle OSI) et le man des commandes “ip” et “iptables” pour mettre en place un routage fonctionnel !


  1. La documentation d’OpenVPN. ↩︎