11.2. Configuration

Avant de procéder à la configuration d'OpenVPN, il faudra procéder à un choix d'architecture. L'authentification d'OpenVPN peut utiliser soit des clefs, soit des certificats. On peut évidemment utiliser les deux (certificats pour un client, clef pour un autre, ...), mais pour simplifier l'exploitation, on évitera d'avoir les deux.

Comme nous avons déja pas mal avancé dans la création d'une petite PKI, nous utiliserons des certificats. L'avantage des certificats est que leur transmission est potentiellement beaucoup plus simple : le client peut générer son propre certificat (et sa propre clef) et transmettre à l'autorité de certification une « requète de signature de certificat » que le CA pourra signer. Ainsi, aucune donnée sensible ne transitera entre le client et le serveur et la seule signature du certificat par le CA lui permettra à OpenVPN d'autoriser le client à se connecter. Le client pourra d'ailleurs utiliser un seul certificat pour tous ses besoins cryptographiques (VPN, client HTTPS, déclaration d'impôts, MySQL, ...).

Nous aurons aussi un autre intérêt à utiliser les certificats : notre certificat serveur et notre CA sont déja en place pour Postfix, MySQL, ProFTPD et Apache. Notre certificat serveur servira donc aussi pour OpenVPN.

Figure 11.1. Principe de fonctionnement d'une PKI

Principe de fonctionnement d'une PKI

Dernier avantage : en fonctionnant en mode certificat, nous n'aurons qu'un fichier de configuration sur le serveur alors que dans le mode « clef partagée », nous avons un fichier de configuration (et un port tcp/udp) par client.

OpenVPN propose toute une batterie d'outils pour gérer les différents certificats dans /usr/share/doc/openvpn/examples/easy-rsa/. Mais ces scripts ne sont pas adaptés à notre situation, car nous avons déja notre petite PKI en marche. Nous invoquerons donc openssl directement.

11.2.1. Génération des paramètres Diffie-Hellman

Diffie-Hellman est un protocle d'échange de clefs cryptographiques qui est utilisé pour changer périodiquement les clefs de chiffement dans une communication protégée par TLS. Ce changement de clefs apporte une fonctionnalité appellée Perfect Forward Secrecy (PFS), qui garanti que si votre clef est compromise, il ne sera pas possible à l'attaquant de décoder des anciens messages chiffrés avec une clef précédente : grâce à Diffie-Hellman elle est indépendante de la clef compromise.

L'échange Diffie-Hellman nécessite quelques paramètres (nombres premiers par exemple) qui sont particulièrement longs à calculer. On devra donc les pré-générer avec openssl.

root@ubuntu:~# openssl dhparam -out /etc/ssl/private/dh1024.pem 1024
Generating DH parameters, 1024 bit long safe prime, generator 2
This is going to take a long time
..................+.............+...................................+...........
.+..............................................................................
...coupé...
...................+................+........................+..................
...........+..............+....+.........................................+...+..
++*++*++*
root@ubuntu:~# 

Le fichier /etc/ssl/private/dh1024.pem sera utilisé par la suite dans la configuration OpenVPN. Ce fichier n'est pas secret.

11.2.2. Génération de la requète de signature de certificat client

Nous avons déja notre autorité de certification et notre certificat serveur. Il nous reste donc à générer des certificats pour les clients. Dans notre exemple, Alice va générer un certificat accompagné d'une demande de signature afin de le transmettre au CA.

alice@linus:~$ openssl req -days 3650 -new -keyout alice.key -out alice.csr
Generating a 1024 bit RSA private key
...............................................++++++
......................++++++
writing new private key to 'alice.key'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:FR
State or Province Name (full name) [Some-State]:Rhone
Locality Name (eg, city) []:Souris City
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Souris SARL
Organizational Unit Name (eg, section) []:Servers
Common Name (eg, YOUR name) []:linus.exemple.org
Email Address []:alice@exemple.org

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

La clef privée générée sera protégée par un mot de passe. Cela protège la clef en cas de vol. En revanche, on devra taper un mot de passe lors de l'établissement de la connexion. Si l'on désire une clef sans mot de passe, on ajoutera l'option -nodes à la ligne de commande d'openssl.

Le « CSR » généré, alice peut l'envoyer au CA. Dans notre exemple, elle dépose directement son CSR sur le serveur du CA mais dans la pratique, il est recommandé d'utiliser un CA déconnecté du réseau (voir Section 10.2.2, « Création d'une autorité de certification »).

alice@linus:~$ scp alice.csr root@ubuntu:
Enter passphrase for key '/home/alice/.ssh/id_dsa': 
alice.csr                                          100%  720     0.7KB/s   00:00    
alice@linus:~$ 

11.2.3. Signature de la demande de signature

Le CA utilise ensuite sa clef privée afin de signer le la demande émise par Alice.

root@ubuntu:~# openssl ca -days 3650 -out alice.pem -in alice.csr
Using configuration from /usr/lib/ssl/openssl.cnf
Enter pass phrase for ./demoCA/private/cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number:
            93:02:12:ea:93:09:59:f6
        Validity
            Not Before: Jun 30 19:15:54 2007 GMT
            Not After : Jun 27 19:15:54 2017 GMT
        Subject:
            countryName               = FR
            stateOrProvinceName       = Rhone
            organizationName          = Souris SARL
            organizationalUnitName    = Servers
            commonName                = linus.exemple.org
            emailAddress              = alice@exemple.org
        X509v3 extensions:
            X509v3 Basic Constraints: 
                CA:FALSE
            Netscape Comment: 
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier: 
               00:00:7F:25:F7:A6:63:83:53:68:99:ED:DF:6E:08:D3:77:21:AC:37
            X509v3 Authority Key Identifier: 
               keyid:FD:12:E1:CA:84:81:87:A3:E4:A1:DD:43:5B:88:E3:0D:E0:5B:D4:25

Certificate is to be certified until Jun 27 19:15:54 2017 GMT (3650 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
root@ubuntu:~# 

La signature du CSR crée un certificat signé par notre CA que l'on pourra renvoyer à Alice (dans notre exemple, elle se sert elle-même avec scp). Elle pourra ensuite l'utiliser pour prouver son identité à tous les serveurs qui nous acceptent en tant qu'autorité de confiance. Alice pourra aussi vérifier l'identité des serveurs auquels elle se connecte en vérifiant que leur certificats sont bien signés par notre CA.

alice@linus:~$ scp root@ubuntu:alice.pem .
Enter passphrase for key '/home/alice/.ssh/id_dsa': 
alice.pem                                          100% 3297     3.2KB/s   00:00    
alice@linus:~$

11.2.4. Fichier de configuration serveur

Le fichier de configuration serveur sera déposé dans /etc/openvpn et devra avoir l'extension .conf.

port 1194 ❶
proto udp

dev tun ❷

ca /etc/ssl/certs/cacert.pem ❸
cert /etc/ssl/certs/cert_serveur.pem
key /etc/ssl/private/key_serveur.pem
dh /etc/ssl/private/dh1024.pem 

server 192.168.18.0 255.255.255.0 ❹
ifconfig-pool-persist ipp.txt ❺
keepalive 10 120 ❻

comp-lzo ❼

status /var/log/openvpn-status.log ❽
verb 3 

Définition du port et du protocole. OpenVPN peut fonctionner sur UDP ou TCP. On préfèrera UDP si possible, plus léger.

Mode tunnel. OpenVPN peut fonctionner en mode tunnel (routé) ou tap (bridgé). Ce dernier mode consituera un bridge entre le LAN du client et le LAN du serveur, qui seront virtuellement connectés sur un même switch.

Chemins des différents certificats (CA, serveur, clef privée) et des paramètres Diffie-Hellman

Subnet utilisé pour l'attribution automatique d'adresse au client

Demande à OpenVPN de conserver une association client/IP (et donne le chemin du fichier d'association).

Ce paramètre permet d'envoyer régulièrement (toutes les 10 secondes ici) un message au client afin qu'il puisse vérifier le fonctionnement du lien. Si au bout de 120 s. le client ne recoit pas de paquets, il redémarrera son process OpenVPN. Le serveur attendra de don coté 120x2 = 240 secondes avant de redémarrer.

Active la compression du traffic.

OpenVPN écrira régulièrement son état dans ce fichier : statistiques de trafic, liste des clients, ...

Verbosité des logs.

11.2.5. Fichier de configuration client

La configuration client est encore plus simple que celle du serveur. Elle comprend essentiellement les paramètres IP d'établissement du tunnel (dont l'adresse du serveur) et la liste des certificats à mettre en œuvre.

remote ubuntu.example.com 1194 ❶
proto udp ❷
dev tun ❸ 

client ❹

ca /etc/ssl/certs/cacert.pem ❺
cert alice.pem
key alice.key

tls-remote ubuntu.example.com ❻

comp-lzo ❼
verb 3 

Adresse IP et port du serveur distant.

Choix du protocole (doit correspondre au choix sur le serveur).

Mode tunnel (doit correspondre au choix sur le serveur).

Indique à OpenVPN qu'il pourra recevoir des paramètres par push (voir Section 11.2.7, « Autres paramètres »

Certificat du CA et certificat client accompagné de sa clef.

Permet de vérifier que le commonName du certificat serveur est bien celui attendu.

Active la compression sur le lien (doit correspondre au choix sur le serveur).

Verbosité des logs.

En utilisant un nom de certificat générique au lieu de alice, on pourra même utiliser la même configuration pour tous les clients.

11.2.6. Test de la configuration

Pour vérifier le fonctionnement du tunnel, on devra démarrer le serveur avec invoke-rc.d (invoke-rc.d openvpn start). Si le démarrage passe sans accroc, on pourra tester la configuration cliente depuis le poste distant. Ce test peut être fait directement « à la main », permettant de voir le résultat de l'opération sans avoir à consulter les logs.

root@linus:/etc/openvpn# openvpn alice.cfg
Thu Jun 28 13:59:48 2007 OpenVPN 2.0.9 i486-pc-linux-gnu [SSL] [LZO] [EPOLL] ...
Thu Jun 28 13:59:48 2007 IMPORTANT: OpenVPN's default port number is now 1194, 
                         based on an official port number assignment by IANA. 
                         OpenVPN 2.0-beta16 and earlier used 5000 as the defa...
Enter Private Key Password:xxxxxx
Thu Jun 28 13:59:51 2007 LZO compression initialized
Thu Jun 28 13:59:51 2007 Control Channel MTU parms [ L:1542 D:138 EF:38 EB:0 E ]
Thu Jun 28 13:59:51 2007 Data Channel MTU parms [ L:1542 D:1450 EF:42 EB:135 E ]
Thu Jun 28 13:59:51 2007 Local Options hash (VER=V4): '41690919'
Thu Jun 28 13:59:51 2007 Expected Remote Options hash (VER=V4): '530fdded'
Thu Jun 28 13:59:51 2007 UDPv4 link local: [undef]
Thu Jun 28 13:59:51 2007 UDPv4 link remote: 192.168.17.139:1194
Thu Jun 28 13:59:52 2007 TLS: Initial packet from 192.168.17.139:1194, sid=0b28e
Thu Jun 28 13:59:52 2007 VERIFY OK: depth=1, /C=FR/ST=Rhone/O=Souris_SARL/OU=...
Thu Jun 28 13:59:52 2007 VERIFY X509NAME OK: /C=FR/ST=Rhone/L=Souris_City/O=S...
Thu Jun 28 13:59:52 2007 VERIFY OK: depth=0, /C=FR/ST=Rhone/L=Souris_City/O=S...
Thu Jun 28 13:59:52 2007 Data Channel Encrypt: Cipher 'BF-CBC' initialized wi...
Thu Jun 28 13:59:52 2007 Data Channel Encrypt: Using 160 bit message hash 'SHA1'
Thu Jun 28 13:59:52 2007 Data Channel Decrypt: Cipher 'BF-CBC' initialized wi...
Thu Jun 28 13:59:52 2007 Data Channel Decrypt: Using 160 bit message hash 'SHA1'
Thu Jun 28 13:59:52 2007 Control Channel: TLSv1, cipher TLSv1/SSLv3 DHE-RSA-AES256
Thu Jun 28 13:59:52 2007 [ubuntu.example.com] Peer Connection Initiated with ...
Thu Jun 28 13:59:53 2007 SENT CONTROL [ubuntu.example.com]: 'PUSH_REQUEST' (s...
Thu Jun 28 13:59:53 2007 PUSH: Received control message: 'PUSH_REPLY,route 19...
Thu Jun 28 13:59:53 2007 OPTIONS IMPORT: timers and/or timeouts modified
Thu Jun 28 13:59:53 2007 OPTIONS IMPORT: --ifconfig/up options modified
Thu Jun 28 13:59:53 2007 OPTIONS IMPORT: route options modified
Thu Jun 28 13:59:53 2007 TUN/TAP device tun1 opened
Thu Jun 28 13:59:53 2007 ifconfig tun1 192.168.18.6 pointopoint 192.168.18.5 ...
Thu Jun 28 13:59:53 2007 route add -net 192.168.18.1 netmask 255.255.255.255 ...
Thu Jun 28 13:59:53 2007 Initialization Sequence Completed

11.2.7. Autres paramètres

OpenVPN possède un nombre conséquent de paramètres que l'on pourra découvrir sur le site officiel ou dans sa page de man (openvpn(8)). Certains sont très utilisés et méritent une attention particulière.

  • push permet d'envoyer des paramètres de configuration au client. C'est extrèmement pratique puisque l'on peut modifier la configuration du client sans avoir à lui renvoyer un nouveau fichier de configuration. Pour que le client accepte des paramètres du serveur, il devra avoir pull ou client dans son propre fichier de configuration.

  • route suivi d'un subnet et d'un masque permet d'insérer une route dans la table de routage de l'OS lorsque la connexion sera active. Par exemple, si un client utilise la directive route 192.168.19.0 255.255.255.0, cette route sera ajoutée dans sa table de routage lorsque le tunnel sera monté et le next-hop pour ce subnet sera le serveur auquel ce client sera connecté. Pour plus de souplesse, on préfèrera envoyer ce paramètre au client avec la commande push : push "route 192.168.19.0 255.255.255.0"

  • user et group demandent à openvpn de délaisser les droits de root dès que possible, et d'utiliser l'utilisateur et le groupe donnés en paramètres. En cas de faille dans OpenVPN permettant à un attaquant de prendre le contrôle du dæmon (débordement de pile par exemple), cet attaquant héritera des droits restreints de l'utilisateur spécifié.

  • chroot force OpenVPN à s'installer sous une nouvelle racine du système de fichiers (voir l'entrée du glossaire chroot). En cas de faille, l'attaquant sera cantoné sous le répertoire pointé par chrrot.

  • crl-verify permet d'indiquer à OpenVPN l'emplacement de la liste de révocation de certificats. On l'utilise en général sur le serveur pour indiquer la liste des certificats clients qui ne doivent plus avoir accès au service (voir aussi Section 10.2.4, « Liste de révocation »).

11.2.8. Démarrage au boot

Le comportement au boot d'OpenVPN est défini dans /etc/default/openvpn. Le paramètre AUTOSTART liste les configurations OpenVPN à charger au démarrage. Ces configurations correspondent à des fichiers *.conf situés dans /etc/openvpn. Par exemple, si l'on a :

AUTOSTART="vpn1 vpn2"

OpenVPN essaiera automatiquement de charger les configuration /etc/openvpn/vpn1.conf et /etc/openvpn/vpn2.conf au boot. Si AUTOSTART est à none, aucune configuration ne sera chargée (donc OpenVPN ne démarrera pas) tandis que si ce paramètre est à all, OpenVPN tentera de charger toutes les configurations se terminant en .conf. Coté serveur, on aura dans notre cas une seule configuration (puisque le mode de fonctionnement utilisé ici est « multi-client ». En revanche, un client peut avoir de multiples configurations (i.e. des VPN vers des destinations différentes). Il pourra dans ce fichier spécifier le liste des tunnels qu'ils souhaite monter au démarrage de la machine.

Un autre paramètre, STATUSREFRESH, pour lequel nous pouvons spécifier un nombre entier, demande au script de démarra d'OpenVPN d'invoquer le service avec le paramètre --status. Cela aura pour effet de créér un fichier d'état dans /var/run/openvpn.conf.status ou conf est le nom de fichier de configuration. Si cette variable est indéfinie ou est 0, OpenVPN ne sera pas invoqué avec --status. Dans le cas contraire, le fichier d'état sera créé et rafraichi toutes les n secondes, ou n est la valeur affectée à la variable. Si l'on utilise cette possibilité, on devra supprimer la directive status du fichier de configuration.

root@ubuntu:~# cat /var/run/openvpn.openvpn.status
OpenVPN CLIENT LIST
Updated,Sun Jul  1 17:51:02 2007
Common Name,Real Address,Bytes Received,Bytes Sent,Connected Since
alice.exemple.org,213.245.112.213:1194,9610,9795,Sun Jul  1 17:31:53 2007
ROUTING TABLE
Virtual Address,Common Name,Real Address,Last Ref
192.168.18.6,alice.exemple.org,213.245.112.213:1194,Sun Jul  1 17:31:53 2007
GLOBAL STATS
Max bcast/mcast queue length,0
END
root@ubuntu:~#