OpenVPN les doigts dans le nez

Mmmmm, j’angoissais à l’idée d’installer à nouveau un serveur OpenVPN en urgence (psychose de la grippe A-H1N1-truc oblige, ‘faut que le pékin lambda puisse bosser à distance…). En effet, la génération des certificats, ce genre de trucs, ça m’énerve, je ne me souviens jamais des lignes de commandes.
Renseignements pris, ça tombe bien, les choses ont dû évolué depuis… euh… la dernière fois. Et le projet OpenVPN fournit un bel outil “easy-rsa” pour générer facilement les clefs serveurs, client, les inscrire dans la base de clefs autorisées, les révoquer etc.
Ca rend OpenVPN installable et exploitable facilement en 10 minutes + le temps de faire un peu de firewalling propre à votre configuration (et de prendre un café).

Toujours à mon habitude, j’essaye d’utiliser ce qu’a fait Debian pour moi. Point de compilation, de création de machin-bidule à la main lorsque ce n’est pas une absolue nécessité.

Pour le contexte, on va dire que le VPN va être installé sur une machine de type passerelle Internet-LAN. Pourquoi pas une Debian avec shorewall et 2 pattes : loc, net (et $FW of course). Je parlerai rapidement des modifications de firewall à la fin. Vous pouvez trouver une introduction à shorewall sur ma doc d’initiation à Debian.

Je vais développer en 3 parties : thèse, anti-thèse, foutaises, comme disait mon prof de philo au siècle dernier installation, paramétrage du serveur, paramétrage du client, firewalling. Ca fait 4 ? bien, au moins y’en a qui suivent.

Let’s go.

Installation de l’outil

Ca devient presque rasoir, on commence direct dans le feu de l’action :

aptitude install openvpn

Par dépendances, SSL descend. Enfin bon, si sur cette machine vous n’avez pas SSH, donc openssl, je serais étonné.
Je n’ai pas pris de notes, mais je pense qu’à ce niveau là déjà, une interface réseau “tun0″ est créée. Le futur sous-réseau du VPN est 10.0.8.x. Le serveur n’est pas lancé car il n’a aucune conf. Ca veut dire /etc/openvpn/ vide ou pas loin. Et c’est tant mieux.

Paramétrage serveur

Rappel : permissions

On va jouer avec les clefs cryptées et les clefs publiques d’un outil donnant accès à l’intérieur de votre réseau. Faites un peu attention aux permissions des fichiers.

Clef privée = permission limitée au niveau de l’OS, root:root + chmod 600
Clef publique = root:root + chmod 644
Ce qui ne concerne que le service et son lancement = root:root + chmod 640

Notez que le service openvpn sera lancé par root même s’il tournera au nom d’un utilisateur “openvpn”.

Traditionnellement, les clefs privées ont un nom en .key, les certificats publics en .crt.
Notez bien les permissions de votre conf OpenVPN lorsqu’on l’aura monté et gardez ça à l’esprit tout le long :

serveur:/etc/openvpn# ls -l
total 40
-rw-r--r-- 1 root root  1176 2009-09-14 14:46 ca.crt
-rw------- 1 root root   245 2009-09-14 14:47 dh1024.pem
-rw------- 1 root root    16 2009-09-23 08:23 ipp.txt
-rw------- 1 root root   232 2009-09-23 08:32 openvpn-status.log
-rw-r----- 1 root root 10560 2009-09-22 17:02 server.conf
-rwxr-xr-x 1 root root  1352 2008-09-18 00:33 update-resolv-conf
-rw-r--r-- 1 root root  3813 2009-09-14 14:46 vpnserveur.crt
-rw------- 1 root root   887 2009-09-14 14:46 vpnserveur.key

En résumé, seules la clef publique de l’autorité de certification et la clef publique du serveur doivent être publiques.

Présentation rapide de easy-rsa

“easy-rsa” est un ensemble de scripts simplifiant votre vie pour gérer les certificats. Que ce soient ceux du serveur pour créer sa configuration ou ceux de vos postes clients.
Vous savez aussi sans doute qu’il vous faudra gérer votre base de certificats autorisés (et surtout révoqués). Lorsque le portable de votre collègue est oublié dans le train, il est intéressant d’être mis au courant dans la seconde pour révoquer le certificat en question. Sinon c’est la porte d’entrée dans l’entreprise, suivant le profil du voleur type qui a trouvé le portable.
Cet outil descend avec OpenVPN et l’ensemble des scripts se situe dans /usr/share/doc/openvpn/examples/easy-rsa/2.0/. Il y a une version 1.0. J’ai opté pour la 2.0. Je ne me suis pas trop documenté sur le sujet.

Il y a un tout petit peu de paramétrage à faire sur easy-rsa.
Je recommande de dupliquer le fichier /usr/share/doc/openvpn/examples/easy-rsa/2.0/vars en /usr/share/doc/openvpn/examples/easy-rsa/2.0/vars.maconf et de travailler dedans.
Je vous montre un “diff” entre le fichier d’origine et le mien. C’est le minimum syndical à renseigner :

serveur:/usr/share/doc/openvpn/examples/easy-rsa/2.0# diff -h vars vars.maconf
64,68c64,68
< 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_COUNTRY="FR"
> export KEY_PROVINCE="France"
> export KEY_CITY="Petaouana"
> export KEY_ORG="MaBoite"
> export KEY_EMAIL="adminvpn@maboite.fr"

Notez : pour utiliser les scripts Easy-RSA, il faut à chaque fois positionner les variables d’environnement du fichier vars.maconf. Donc, à chaque nouvelle session dans laquelle vous jouez avec les scripts easy-rsa, il faudra commencer par la commande suivante :

. /usr/share/doc/openvpn/examples/easy-rsa/2.0/vars.maconf #sans oublier le point au début !!!

.

Le répertoire où sont stockées les clefs générées (et d’autres choses, liste de certificats, certificats révoqués etc) est le sous-répertoire keys/. Inutile de préciser (?) que ce répertoire doit être archi-protégé :

serveur:/usr/share/doc/openvpn/examples/easy-rsa/2.0# ls -ld keys
drwx------ 2 root root 4096 2009-09-14 18:22 keys

Enfin, la première fois uniquement (ou tant que vous testez), vous pouvez nettoyer ce répertoire via la commande ./clean-all.

Création de l’autorité de certification

Maintenant que vos “variables” sont prêtes et chargées dans votre session, on attaque.
Bien évidemment, cette manip n’est à faire qu’une fois. Seule la manip de création de certificats pour vos clients (postes clients) sont à faire X fois.
L’autorité de certification est “un nom et des clefs” signant vos certificats. Un exemple connu est Verisign. Ici, on va signer nous-même. Sur un serveur web, ça ferait des warnings de certificats bidouilleux, ici on s’en fout.

./build-ca

Vous obtenez le baratin standard de génération de clefs, lisez ce qui y est dit et renseignez le “Common Name”. Le reste doit descendre du fait du fichier “vars” chargé au préalable. Pour “Common Name”, mettez le nom de votre serveur.

Création de la clef Diffie-Hellman

La clef Diffie-Hellman est une clef permettant au client et au serveur de s’entendre sur une clef secrète pour crypter la conversation.
Si je me souviens bien, les clefs publiques/privées servent à l’initialisation de la communication, mais, étant lourdes en calculs, on opte pour un cryptage plus simple pour le reste de la communication. C’est la clef DH. En gros hein. Et pardon aux puristes. Ou dites moi si je me trompe complètement.

On la génère comme suit, grâce aux script Easy-RSA :

./build-dh

Rien à saisir, ça prend juste un peu de temps.

Génération du certificat serveur

On continue, pour le dernier élément du serveur : sa propre clef.

./build-key-server

(trop cool les scripts Easy-RSA non ?)
Ca sort aussi le baratin standard de génération de clefs. Vous devrez préciser le “Common Name”, éventuellement un mot de passe (je ne l’ai pas fait, je suppose qu’il demanderait du coup un mot de passe au lancement du service openvpn ; ça peut être contraignant lors de reboot).
Par défaut, votre certificat sera valable 10 ans.
Ca termine par l’inscription du certificat dans la “base” :

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

Création des certificats d’un client

Rappel : lorsque plus tard, vous créerez un autre certificat pour un autre PC, pensez à “sourcer” le fichier vars.maconf.
Le script de génération se lance comme suit :

./build-key pc123

Je suggère un nom éloquent rappelant ou bien le PC, ou bien la personne.
Là non plus, rien de sorcier : le “Common Name” sera le nom du PC et vous “committez” le certificat.

Création des certificats d’un client avec mot de passe

Tout pareil que le paragraphe du dessus, mais le script est ./build-key-pass pc123
Il faudra alors renseigner le mot de passe là :

Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:

Rien à voir avec le “Challenge password” demandé plus tard.

La révocation de certificats

Si à ce niveau là de la configuration on n’a pas besoin de révoquer des certificats, ça deviendra obligatoire à mesure que les utilisateurs arriveront, partiront et perdront leur PC portables. Evidemment que c’est du vécu :)
La commande Easy-RSA est :

./revoke-full pc123

Il faut copier le fichier résultant, après chaque révocation :

cp keys/crl.pem /etc/openvpn/

Ce fichier est lu dès l’instant que vous avez mis en place l’option “crl-verify” dans votre fichier de conf serveur (voir plus haut).
Notez aussi qu’il est relu à chaque tentative de connexion. Pas besoin de recharger OpenVPN après une révocation. Juste de recopier le fichier à jour. Si vous pensez faire un lien symbolique, attention aux permissions (c’est l’utilisateur openvpn qui fait tourner openvpn). Je n’ai pas testé la solution par lien symbolique.

Vous pourrez consulter la liste des certificats révoqués grâce à la commande :

openssl crl -in /chemin/vers/keys/crl.pem -text

CRL = Certificate Revocation List

Lancement du service

A ce niveau là, on a généré tout ce qu’il faut, mais le service ne tourne pas.
Le contenu de votre sous-répertoire keys ressemble à ça :

serveur:/usr/share/doc/openvpn/examples/easy-rsa/2.0# ls -l keys/
total 80
-rw-r--r-- 1 root root  3813 2009-09-14 14:06 01.pem
-rw-r--r-- 1 root root  3698 2009-09-14 14:29 02.pem
-rw-r--r-- 1 root root  1176 2009-09-14 14:03 ca.crt
-rw------- 1 root root   887 2009-09-14 14:03 ca.key
-rw-r--r-- 1 root root  3698 2009-09-14 14:29 client_test.crt
-rw-r--r-- 1 root root   668 2009-09-14 14:29 client_test.csr
-rw------- 1 root root   887 2009-09-14 14:29 client_test.key
-rw-r--r-- 1 root root   245 2009-09-14 14:32 dh1024.pem
-rw-r--r-- 1 root root   205 2009-09-14 14:29 index.txt
-rw-r--r-- 1 root root    20 2009-09-14 14:29 index.txt.attr
-rw-r--r-- 1 root root    21 2009-09-14 14:06 index.txt.attr.old
-rw-r--r-- 1 root root   101 2009-09-14 14:06 index.txt.old
-rw-r--r-- 1 root root     3 2009-09-14 14:29 serial
-rw-r--r-- 1 root root     3 2009-09-14 14:06 serial.old
-rw-r--r-- 1 root root  3813 2009-09-14 14:06 vpnserveur.crt
-rw-r--r-- 1 root root   664 2009-09-14 14:05 vpnserveur.csr
-rw------- 1 root root   887 2009-09-14 14:05 vpnserveur.key

On y retrouve les clefs de l’autorité de certification (ca*), le certificat serveur (vpnserveur.crt et vpnserveur.key) et un futur poste client (client*.[crt|key]). Les fichiers .csr sont les demandes de signatures, étape intermédiaire de la création des certificats, masquée par l’enrobage de commandes d’Easy-RSA. Inutile par la suite
Il faut recopier (avec les bonnes permissions !!!) les fichiers suivants :

cp -p dh1024.pem vpnser*crt vpnser*key ca* /etc/openvpn

Ensuite, on va faire tourner le service sous un utilisateur/groupe sans droit, c’est mieux côté sécurité.

groupadd openvpn
useradd -d /dev/null -g openvpn -s /bin/false openvpn

Enfin, il faut créer le fichier de conf du serveur. Un exemple est donné dans le fichier /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz. Une fois dézippé et mis dans /etc/openvpn, on l’adapte.
Voici son contenu, sans les commentaires :

serveur:/etc/openvpn# egrep -v "^$|^#|^;" server.conf
port 1194
proto udp
dev tun
ca ca.crt
cert vpnserveur.crt
key vpnserveur.key  # This file should be kept secret
dh dh1024.pem
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "route 192.168.X.0 255.255.255.0"
push "dhcp-option DNS 192.168.X.Y"
push "dhcp-option DOMAIN maboite.net"
push "dhcp-option WINS 192.168.X.Y"
keepalive 10 120
comp-lzo
user openvpn
group openvpn
persist-key
persist-tun
status openvpn-status.log
verb 3
;crl-verify crl.pem # j'ai triché, j'ai ajouté le ";" il n'aurait pas dû sortir vu la commande egrep passée. Voir ci-dessous.

Les 4 paramètres push route et push dhcp-option sont à adapter. Ce sont eux qui feront ajouter à votre PC client les règles de routages et DNS, domaine (et optionnellement WINS) à utiliser. Sinon, point de résolution de nom, point de routage depuis votre PC, tantôt vers sa connexion web, tantôt vers le VPN.
Suivant la configuration de votre passerelle, le simple ajout de ces push ne sera pas suffisant pour permettre à vos postes client VPN de rebondir de votre passerelle vers le LAN. Voir plus bas le chapitre dédié.
Enfin, le paramètre “crl-verify” prendra son importance avec les révocations de certificats (voir plus bas).Pour l’instant, il est en commentaire car j’ai noté que OpenVPN plantait (volontairement ?) lorsqu’on lui dit de tenir compte d’une liste de révocation et que cette liste n’existe pas, ou est un fichier vide. Ce sera donc à activer plus tard, après votre première révocation.

Ah, j’oubliais :

/etc/init.d/openvpn start

Vérifiez dans les logs que tout va bien. Et ifconfig qui doit avoir affecté une IP à tun0, probablement 10.8.0.1.

Paramétrage client (poste Windows dans mon cas)

On a généré un premier ensembles de clefs d’un poste client.
Dans le cas d’un PC sous Windows (cas à mon avis le plus courant lorsqu’il s’agit de fourni des portables d’appoint à des utilisateurs distants), installez OpenVPN avec le GUI.
Injectez (par un moyen sûr, éviter d’envoyer la clef cryptée par mail à votre destinataire) les fichiers suivants dans le répertoire C:Program FilesOpenVPNconfig :

ca.crt # et pas le .key !!!
client_test.key
client_test.crt

Puis créez un fichier de configuration client nommé nimportequoi.ovpn dans le même sous-répertoire config. Il contiendra la conf suivante, si on oublie les commentaires :

client
dev tun
proto udp
remote votre.serveur.vpn.votresociete.fr 1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
cert client_test.crt
key client_test.key
comp-lzo
verb 3

Enfin, lancez le GUI d’OpenVPN situé dans le sous-répertoire bin/ d’OpenVPN, bouton droit dans le “system tray” sur l’icône qui vient d’apparaitre, menu “Connect” et lisez ce qui passe pour commencer à débugger s’il y a un hic niveau réseau entre le PC portable et le serveur VPN. Attention à vos règles de firewalling en vigueur, que vous testiez de l’extérieur ou de l’intérieur (ce qui semble un peu stupide), vous pourriez ne pas être en mesure d’atteindre le service, d’où le chapitre ci-dessous.

Considérations de firewalling

Bon là, c’est bien beau, vous atteignez votre serveur VPN depuis l’extérieur, et encore, si vous avez bien ouvert la porte d’entrée vers le port UDP 1194 de votre serveur.
Mais pour l’instant, point de rebond vers le LAN. Et heureusement que ça ne marche pas par défaut.

Méthode gore pour tester vite fait

En activant l’IP Forwarding à la main et en définissant quelques routes entre votre réseau VPN et votre LAN, vous obtiendrez vite fait un résultat. Mais c’est pas terrible je trouve.
Activation de l’IP Forwarding comme un cochon :

echo 1 > /proc/sys/net/ipv4/ip_forward

Puis définition de routes. Plutôt que de donner un exemple qui ne sera pas le votre, tâchez plutôt de raisonner sur la liste des routes que vous avez et ajoutez celles qu’il faut, avec les commandes route, route add et route delete.

Méthode réfléchie pour shorewall

Si vous utilisez iptables, je ne peux rien pour vous. Enfin si, un conseil : songez à utiliser shorewall.
Si vous ne connaissez rien à shorewall, c’est le moment de vous y mettre. Mais dans ce cas, faites vous la main *avant* d’installer le VPN, quand même. Voyez ma doc Debian au besoin, il y a un chapitre consacré à shorewall.
Sinon, dans une conf shorewall à 2 pattes (net, loc), on la modifie pour qu’elle passe à 3 pattes. Dans un cas idéal (mais néanmoins courant), ça se passera comme ça :

  • Ajout de la ligne vpn ipv4 dans /etc/shorewall/zones.
  • Ajout de la ligne vpn tun0 detect dans /etc/shorewall/interfaces
  • Ajout de la ligne eth0 tun0 dans /etc/shorewall/masq pour activer le Masquerading entre votre VPN et votre LAN, ici situé sur l’interface eth0
  • Ajout de toutes les règles par défaut dans /etc/shorewall/policy, concernant la probable interdiction par défaut d’aller de n’importe quelle zone vers le VPN et réciproquement. Le VPN doit en effet, à mon avis, être un moyen de secours pour donner accès à quelques services internes, pas à tout le LAN. A base de vpn loc REJECT info + réciproque.
  • Enfin, le vrai travail, l’ouverture du minimum d’autorisation entre toutes vos zones et le VPN. J’y consacre le paragraphe suivant.

Ouvertures minimum sur le firewall

En considérant net=eth1 ; loc=eth0 et vpn=tun0, voici ce qu’il faudra ajouter au minimum, à mon avis :
Déjà l’accessibilité du service VPN depuis le NET :

ACCEPT          net     $FW         udp     openvpn

Ensuite des règles du VPN vers le LAN :

ACCEPT          vpn     loc:$dns1      tcp     domain # sinon on ne touche pas le serveur DNS => pas de résol de nom => problème...
ACCEPT          vpn     loc:$dns1      udp     domain # je ne sais pas s'il faut le TCP ou l'UDP. Oops.
Ping/ACCEPT     vpn     loc # pratique pour du dépannage
ACCEPT          vpn     loc:$leserveurapplicatif1 # c'est un exemple
ACCEPT          vpn     loc:$leserveurapplicatif2 tcp 80 # un exemple plus restreint, limité au port http

Les variables “$dns1″ (par exemple), sont à définir dans /etc/shorewall/params, ou alors vous tapez l’IP en dur.

Et enfin quelques accès minimums vers la passerelle elle-même :

Ping/ACCEPT     $FW     vpn # pratique pour les tests
SSH/ACCEPT      vpn     $FW # pour les admins tout au moins ?
ACCEPT          vpn     $FW     tcp     80 # s'il y a des intranets à consulter (outil de supervision, par exemple)

A noter aussi, pour le Masquerading, de forcer l’activer (valeur “On”) ou de laisser tel quel (valeur “Keep”) l’IP forwarding. Ca se passe dans /etc/shorewall/shorewall.conf, paramètre IP_FORWARDING.
Il me semble que c’est ce paramètre qui force ou pas la modification du paramètre noyau /proc/sys/net/ipv4/ip_forward. Il me semble.

Voilà. Ca devrait marcher.
Evidemment, comme c’est fortement lié à toute votre infrastructure réseau, tout ce qui précède est plutôt un guide des trucs-à-pas-oublier-pour-que-ça-marche.

Divers

Ce que je n’ai pas abordé

  • Testez avant de déployez !!!! notamment les certificats révoqués, et avec eux la CRL et l’option crl-verify.
  • Il y a une notion de règles de routages paramétrables par certificat client. Ca peut être utile.
  • Vous utilisez Orange Business Everywhere pour votre clef 3G ? attention, ça semble intercaler un proxy sur votre Internet Explorer. Résultat, l’accès à des Intranets via le VPN ne marchait pas. Firefox passait bien. Je n’ai pas creusé plus pour l’instant.

Comportement lors d’une connexion avec un certificat révoqué

Côté serveur, on voit cette discrète ligne dans /var/log/syslog :

Sep 23 11:57:49 gw ovpn-server[24224]: 192.X.Y.Z:1120 CRL CHECK FAILED: /C=FR/ST=France/L=Petaouana/O=SOCIETE/CN=pctest/emailAddress=adminvpn@chezmoi.fr is REVOKED

Côté client, c’est moins flagrant, on tourne en rond et tente de se reconnecter.
Peut-être qu’en montant le niveau de verbosité (paramètre verb), on en saurait plus. Mais à la limite, ça intéresse qui ? (à part l’utilisateur qui s’est fait révoquer son certificat par erreur).

Vus : 375
Publié par Michauko : 64