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 devpn 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).