[Tuto] Monter son VPN perso avec OpenVPN

sécurité 21 août 2014

Aujourd’hui, on va prendre le taureau par les cornes. Pour tout un tas de raisons, je suis régulièrement amené à me connecter à des réseaux sans fil ouverts soi-disant sécurisés par une authentification (rigolade !), ou au réseau de la médiathèque de Troyes (quand il fonctionne, quand le serveur DNS est pas tombé, et quand ALCASAR daigne proposer d’entrer ses identifiants) qui a la fâcheuse manie de bloquer plein de ports que j’utilise au quotidien (au hasard : SMTP, XMPP). On peut aussi ajouter le fait que j’aimerais me connecter à mon NAS depuis le bureau, sans pour autant ouvrir grand la porte du routeur avec une pancarte clignotante « All you can eat: mes données sont ici, viendez ! ».

Et systématiquement, je me galère à ouvrir un tunnel SSH entre mon portable et le Raspberry Pi, à faire transiter la connexion au NAS à travers tout ça… Et encore, ça ne sécurise pas ma navigation. Bref. Du coup, la solution, c’est un VPN. On va donc installer le serveur OpenVPN, le configurer, puis installer le client sous Windows, sous Android et sous Linux. Vous suivez ?

 

OpenVPN, quoi-t’est-ce ?

C’est une solution VPN (Virtual Private Network, réseau privé virtuel) libre et gratuite.  Elle se compose de deux composants principaux : le serveur, qui représente le point de sortie de votre VPN, et le client, qui est pour sa part le point d’entrée. La navigation au travers d’un VPN est plus rapide que si vous utilisiez un proxy, en plus d’être mieux sécurisée.

OpenVPN Connect sous Android
OpenVPN Connect sous Android

 

Pré-requis

Je pars du principe que vous disposez déjà d’une machine sous Debian (dans mon cas : Raspberry Pi + Raspbian) installée, configurée avec une IP interne fixe et un accès SSH, et que vous savez ouvrir/rediriger (faites-le, tiens) le port 1194 UDP de votre routeur vers votre serveur.

Alors ça, c’est dans un cas idéal, hein. Dans mon cas, pour des raisons de restrictions d’usages sur le réseau de l’école et/ou RENATER, il m’est impossible d’utiliser la configuration classique via le port 1194, ou de l’UDP tout court, a priori. Du coup, bien que ce soit un poil plus lourd pour mon petit serveur, j’utilise le protocole TCP sur le port 80. Ouais, je sais. Mais plus c’est gros et crade, plus ça passe.

Pour commencer, on installe OpenVPN. Si si : sudo apt-get update && sudo apt-get install openvpn (pas méchant hein !).

 

Configuration du serveur

On est d’accord que vous ne voulez pas (sauf erreur de ma part) ouvrir votre serveur VPN à tout le monde. Comme pour votre porte d’entrée, on va faire une clé, du coup. Et la garder pour nous. Pensez à m’envoyer la vôtre par mail ! :mrgreen:

 

Etape 1 : Easy_RSA

Easy_RSA, c’est un petit utilitaire qui va nous faciliter la vie. Il a été rapatrié quand vous avez installé le paquet openvpn. Aussi surprenant que cela puisse vous paraître, il utilise l’algorithme RSA. #Obvious

On va commencer par se connecter en tant sur superutilisateur : sudo -s. Votre invite de commande (du style pi@raspberrypi ~ $) va changer (pour moi : root@raspberrypi:/home/pi#).

Copions Easy_RSA dans le dossier de OpenVPN, histoire de pouvoir travailler avec : cp –r /usr/share/doc/openvpn/examples/easy-rsa/2.0 /etc/openvpn/easy-rsa. On se place ensuite dans le dossier fraîchement copié, et puis… Au boulot. cd /etc/openvpn/easy-rsa

 

Bon. Attaquons les choses sérieuses, et éditons le fichier vars, qui contient un certain nombre de variables/réglages importants : nano vars. Il faut commencer par adapter la ligne export EASY_RSA="`pwd`", qui devient dans notre cas export EASY_RSA="/etc/openvpn/easy-rsa" .

Par défaut les clés générées font 1024 bits. Le fichier dit que si vous êtes paranos, vous pouvez monter ça à 2048 bits. Moi je le suis, donc j’ai changé le 1024 en 2048 dans la ligne export KEY_SIZE=1024… On ne se refait pas !

Vous pouvez éditer la dernière partie qui concerne la génération des certificats, pour gagner du temps ensuite, mais rien d’obligatoire (pays, tout ça).

Un petit Ctrl+X pour enregistrer et quitter nano, et hop !

 

On va générer certificats de l’autorité de certification. OK, dans la vraie vie, il faudrait utiliser une vraie autorité de certification, reconnue, qui vérifierait que vous êtes bien celui/celle que vous prétendez être, et j’en passe, tout en vous soutirant au passage une coquette somme. Là, on fait notre truc dans notre coin, alors on va (si ça vous va… mais si ça vous va pas, c’est pareil, moi je fais comme ça 😀 ) dire qu’on est notre propre autorité de certification.

Toujours dans notre répertoire easy-rsa et en tant que root, on va charger le fichier vars édité plus haut : source ./vars, nettoyer d’éventuels restes d’essais précédents (gaffe à pas virer un truc que vous auriez déjà fait volontairement !) : ./clean-all, et lancer la génération du certificat racine : ./build-ca. Place à l’interrogatoire maintenant :

  • Country Name : France pour moi, donc : FR
  • State or Province : je mets France
  • Locality Name : votre ville ? Pour moi, Troyes
  • Organization Name : perso je mets le nom de ce blog, Open-Freax
  • Organization Unit : vide ?
  • Common Name : je mets le nom de mon serveur, PrincessKenny
  • Name : au hasard, Maxime Auvy ?
  • Email Adress : c’est assez clair là non ? :mrgreen:

Plus qu’à faire la clé : ./build-key-server <nom_du_serveur> . Donnez-lui un nom au choix, hein, mais suffisamment explicite des fois que vous ayez plusieurs VPN sur votre machine. Dans mon cas, j’ai fait preuve d’une grande imagination et il s’appelle donc Mamayzon. Deuxième interro, le Common Name *doit* correspondre à celui entré juste avant (il devrait le savoir tout seul). Le Challenge Password reste vide. Et à la question qui demande si vous voulez signer le certificat (Sign the certificate? [y/n])… Bien évidemment, la réponse est oui. Si vous avez pas trop tripatouillé le fichier vars, c’est valable pour 10 ans ! Dernière question (1 out of 1 certificate requests certified, commit? [y/n] ), réponse positive, là aussi.

Ouais, on est content, la clé côté serveur est générée !

 

Reste à générer les clés côté client(s). On va le faire une fois, pis vous reproduirez les étapes au besoin. Concrètement, il faut une clé cliente par client. Si vous avez un ordinateur portable et un smartphone, par exemple, il vous faudra deux clés, pour tout un tas de bonnes raisons, dont le fait que si vous vous faites tirer votre iPhone (qui a dit « sécurisation du contexte » ?!), vous bloquez juste sa clé à lui, sans vous refaire la configuration VPN de toutes les autres machines… Donc : ./build-key-pass <nom_du_client>. Encore une fois, un truc un minimum explicite, Machine1 si ça vous chante, ou le hostname de la machine concernée, ou je sais pas… Dans le cas de mon PC portable, j’ai mis son nom d’hôte, MrSlave (no comment). Fournissez un mot de passe que vous retiendrez (PEM passphrase), laissez le Challenge password vide là aussi. Evidemment, on va signer le certificat ! 😉

Parlons sécurité, maintenant. Comme on est un peu parano, et qu’on tient malgré tout à ce que notre VPN ne soit pas utilisé par le premier pécore venu, on va demander (gentiment) à OpenSSL de passer 3 fois sur notre clé cliente, à coup de 3DES.

On se place donc dans le répertoire contenant nos clés (cd keys) puis on appelle OpenSSL : openssl rsa -in Machine1.key -des3 -out Machine1.3des.key (là, on dit à OpenSSL d’utiliser RSA puisque nos clés sont de ce type, de prendre en entrée notre clé générée un poil plus tôt, et de lui appliquer 3DES pour générer une nouvelle clé en sortie). Il faudra reproduire cette étape pour chaque clé cliente générée. Logiquement, on va vous demander un mot de passe… Vous pouvez utiliser le même que précédemment, je pense. A vous de voir.

 

Etape 2 : un peu de sécurité…

Ça y est, on a un certificat serveur et (au moins) un certificat client. On progresse. Replaçons nous dans le dossier /etc/openvpn/easy-rsa (un cd .. devrait suffire). On va maintenant sécuriser un peu l’échange des clés. Vous comprenez bien que le client et le serveur doivent échanger des informations, sensibles en l’occurrence, pour identifier qui est qui et établir la connexion, le cas échéant. Il faut donc éviter autant que faire se peut qu’un tiers puisse « intercepter » tout ça et se faire passer pour un de nos clients, par exemple. Pour cela, on va utiliser l’échange de clés dit « Diffie-Hellman ».

Dans notre cas, c’est super simple à initialiser : ./build-dh. Euh… là, ça peut être un peu long, ça a bien mis 5min sur mon Raspberry Pi, et la durée est d’autant plus longue que j’ai choisi d’utiliser des clés de 2048 bits. Ce sera plus rapide avec « seulement » 1024 bits, évidemment, mais moins sécurisé. Coffee-time, donc.

 

Autre sécurité, tant qu’à faire. On ne présente plus les attaques « par déni de service » (DoS, pour Denial of Service) qui se sont popularisées ces dernières années. Même le premier Kévin venu peut avoir accès à des outils simples pour les réaliser, alors autant les prendre en compte. Chance (anticipation, pardon), OpenVPN implémente une première barrière contre ce type d’attaques. On va l’activer !

OpenVPN utilise (si on lui demande de le faire !) un système ingénieux : le HMAC (Hash-based Message Authentication Code). C’est un code d’authentification partagé entre le serveur et le client, connu des deux dès le départ, qui précède la réelle authentification du client auprès du serveur. Techniquement, si un client « tiers » demande à s’authentifier auprès de notre serveur sans entamer le dialogue par l’envoi de ce HMAC, OpenVPN ne va même pas entamer la procédure : ce client n’est pas connu, on l’ignore, on ne lance pas la grosse machinerie, donc on ne surcharge pas le serveur.

Allez, c’est parti : openvpn --genkey --secret keys/ta.key (et c’est tout !).

 

Etape 3 : configuration du serveur

On a ce qu’il faut pour la communication client-serveur. Reste un détail : dire au serveur comment se comporter ! 😛

On est toujours connecté en tant qu’utilisateur root, hein. Ou à grands coups de sudo, si vous préférez. Ouvrons le fichier de configuration qui va bien : nano /etc/openvpn/server.conf. Ce fichier est vide, je vais vous donner mon fichier de configuration initial commenté, à vous d’adapter à votre cas !

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
local 192.168.0.125 # adresse IP locale de votre serveur
dev tun # type de VPN, tun (tunnel IP) ou tap (tunnel Ethernet/bridge)
proto tcp # protocole à utiliser : tcp ou udp, généralement udp
port 1194 # le port par défaut pour OpenVPN, à ajuster au besoin
ca /etc/openvpn/easy-rsa/keys/ca.crt
cert /etc/openvpn/easy-rsa/keys/mamayzon.crt # à ajuster à votre serveur
key /etc/openvpn/easy-rsa/keys/mamayzon.key # idem
dh /etc/openvpn/easy-rsa/keys/dh2048.pem # si vous êtes restés sur du 1024 bits, changez ici
server 10.8.0.0 255.255.255.0 #le réseau au sein duquel vous allez attribuer des IP
ifconfig 10.8.0.1 10.8.0.2 # serveur et point de sortie distant
push "redirect-gateway def1"
push "route 10.8.0.1 255.255.255.255" # route vers le serveur VPN
push "route 10.8.0.0 255.255.255.0" # route vers le sous-réseau VPN
push "route 192.168.0.125 255.255.255.0" #sous-réseau local - adaptez l'adresse IP locale de votre serveur
push "dhcp-option DNS 192.168.0.1" # votre serveur DNS primaire (votre routeur, souvent)
# vous pouvez aussi utiliser le DNS Google 8.8.8.8 ou OpenDNS 208.67.222.222
# pour le reste, a priori pas de raisons d'y toucher à moins de savoir ce que vous faites !
client-to-client
duplicate-cn
keepalive 10 120
tls-auth /etc/openvpn/easy-rsa/keys/ta.key 0
cipher AES-128-CBC
comp-lzo
user nobody
group nogroup
persist-key
persist-tun
status /var/log/openvpn-status.log 20
log /var/log/openvpn.log
verb 1

Enregistrez, et basta !

 

Bon, c’est bien gentil tout ça, mais on a pas fini. Par défaut, Raspbian (la Debian trafiquée pour Raspberry Pi) n’autorise pas le transit de paquets entre deux réseaux comme ça, sans rien dire. C’est problématique pour notre VPN. Du coup, activons cette fonctionnalité en éditant le fichier idoine : nano /etc/sysctl.conf. Une ligne dans la deuxième section commence par  Uncomment the next line to enable packet forwarding for IPv4, et c’est pile ce qu’il nous faut. Décommentez donc la ligne en dessous en lui enlevant le # en début de ligne. On a donc : net.ipv4.ip_forward=1 . Enregistrez et fermez ce fichier, et rechargez les paramètres afin de les prendre en compte : sysctl -p.

C’est presque suffisant. Le truc, c’est que Raspbian (comme d’autres hein !) utilise un pare-feu pour vous protéger, et que ce dernier ne va pas laisser passer vos requêtes. On va le lui imposer (c’qui l’patron, après tout ?!). Créez un fichier comme ceci : nano /etc/firewall-openvpn-rules.sh et collez-y :

1
2
#!/bin/sh
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE

Et pensez bien à changer l’IP de la fin en y plaçant celle de votre serveur ! On va maintenant donner des permissions « correctes » à ce fichier, afin que tout le monde ne fasse pas n’importe quoi avec : chmod 700 /etc/firewall-openvpn-rules.sh et chown root /etc/firewall-openvpn-rules.sh. Concrètement, on commence par donner les permissions 700 (le propriétaire du fichier peut lire, écrire, exécuter ; les autres se touchent), puis par affecter « root » (le superutilisateur) comme propriétaire.

Maintenant, on va charger ce fichier lors de la configuration de l’interface réseau : ouvrons cette configuration (nano /etc/network/interfaces) et ajoutons une ligne sous l’interface concernée, dans mon cas eth0. Et avec l’indentation, svp. La ligne : pre-up /etc/firewall-openvpn-rules.sh . Comme ça, en gros :

interfaces_vpn

 

Maintenant, redémarrez votre serveur (reboot) !

Et vous savez quoi ? Bah… Votre serveur est opérationnel ! \o/

 

Configuration du client

Soyons honnêtes deux minutes, même si c’est simple depuis le début (pour vous qui êtes guidés, parce que moi, j’ai un peu galéré :mrgreen: ), c’est long/chiant. Alors se taper un fichier de configuration à écrire à la main, passe encore, mais dans mon cas j’ai déjà 3 clients (ordinateur portable en dual-boot Windows 8 / elementaryOS, smartphone, tablette). Comme d’autres (en l’occurrence, Eric Jodoin) ont écrit un script qui les génère pour nous… Ne nous privons pas !

On se replace en tant que root, comme pour la première partie du tutoriel : sudo -s. Et éditons un nouveau fichier : nano /etc/openvpn/easy-rsa/keys/Default.txt, puis plaçons-y le contenu suivant (attention, adaptez-le si vous avez fait des modifications (genre protocole, port…) côté serveur) :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
client
dev tun
proto udp
remote XX.XX.XX.XX 1194
resolv-retry infinite
nobind
persist-key
persist-tun
mute-replay-warnings
ns-cert-type server
key-direction 1
cipher AES-128-CBC
comp-lzo
verb 1
mute 20

Remplacez les XX.XX.XX.XX par votre adresse IP externe (ou votre domaine hein), c’est-à-dire celle fournie par votre fournisseur d’accès (pas une qui commence par 192.168, donc). Si vous n’avez pas d’IP fixe, vous pouvez passer par un service comme DynDNS, No-IP…

Maintenant, on va créer le script pour générer le fichier de configuration client. Comme précisé, il a été écrit par Eric Jodoin, et je n’ai fait que l’adapter à mon cas, et vous le traduire en français. Il est disponible sur Github. Vous avez juste à l’insérer dans le fichier nouvellement créé : nano /etc/openvpn/easy-rsa/keys/MakeOpenVPN.sh .

On se replace dans ce même répertoire (cd /etc/openvpn/easy-rsa/keys/), on donne les permissions adaptées au script (chmod 700 MakeOpenVPN.sh), et… on l’exécute : ./MakeOpenVPN.sh. Répondez à l’unique question de la moulinette, à savoir lui fournir le nom d’un des clients créés tout à l’heure ! Normalement, aucune erreur. Recommencez pour chaque client à créer. 😉

Plus qu’à récupérer les fichiers créés. On va les copier dans le répertoire de notre utilisateur « normal » pour pouvoir les récupérer plus facilement sans être superutilisateur… cp *.ovpn /home/pi suffit, en remplaçant /home/pi par votre chemin perso si besoin.

 

Récupérez ensuite ces fichiers de la manière qui vous semble la plus adaptée (clé USB, partage réseau, SCP…) et distribuez les fichiers de configuration à chacun des clients, comme vous feriez avec n’importe quel fichier ! 😉

 

Sous Windows

Il vous faut télécharger le client officiel et l’installer. Placez ensuite votre fichier client.ovpn dans le dossier C:\Program Files\OpenVPN\config et lancez OpenVPN (attention : il faut le lancer en tant qu’administrateur pour qu’il puisse fonctionner correctement !). Le démon apparaît dans la barre de notification : vous pouvez vous connecter après avoir saisi le mot de passe associé à ce client !

 

Sous Android

Vous pouvez installer l’application officielle OpenVPN Connect et lui indiquer de charger la configuration depuis un fichier présent sur la carte SD. Pointez sur le fichier client.ovpn, et c’est tout. Vous pourrez vous connecter, également après avoir saisi le mot de passe 😉

Vous pouvez également installer OpenVPN for Android qui fonctionne de la même façon, mais est disponible via le dépôt F-Droid.

 

Sous Linux

Comme souvent, c’est le plus simple : sur une Debian-based (Debian, Ubuntu et dérivées… Mint, eOS, et j’en passe), un petit sudo apt-get install openvpn network-manager-openvpn et c’est quasiment réglé. Il vous suffit d’utiliser le gestionnaire de connexions par défaut, de choisir Connexions VPN > Configurer un VPN… et de sélectionner « Importer une configuration VPN enregistrée… » puis d’indiquer votre fichier client.ovpn. Le système ouvre une fenêtre pré-remplie, plus qu’à valider ! 😉

Il y a d’autres façons de faire, la doc Ubuntu est assez fournie sur le sujet pour que je ne fasse pas doublon.

 

vpncat

 

C’est fini !

Voilà, un article de plus… qui arrive à son terme. J’espère qu’il vous sera utile, et que vous comprenez tout l’enjeu d’utiliser un VPN au quotidien, même si effectivement, un VPN auto-hébergé, c’est un peu pénible, parce que quand on est sur du « simple » ADSL ça sature plus que rapidement. M’enfin quand vous êtes sur un Wi-Fi public, chez des gens, ou où que ce soit mais que vous n’avez pas confiance dans le réseau (ou les autres utilisateurs) (et vous ne devriez pas avoir confiance), pour ce qui est « sensible » (ne serait-ce que consulter votre banque en ligne), ayez le réflexe VPN.

Et c’est encore plus utile quand vous avez un partage de fichiers à la maison, ou une imprimante… Et que clairement c’est pas une bonne idée d’ouvrir tout ça sur l’extérieur. Autant s’y connecter de façon sécurisée.

S’il y a besoin d’éclaircissements, je suis là, comme toujours. Bonne lecture, et bon courage à celles et ceux qui vont se lancer dans l’aventure. Franchement, j’aurais eu un guide comme ça, ça aurait été tout seul, et il m’aurait pas fallu 2 tentatives + un effacement de clés malencontreux ! 😉

A très vite ! J’vous bisouille !

Mots clés