--- categories: vpn sysadmin security network title: Howto OpenVPN ... * Documentation : [OpenVPN](https://openvpn.net/) permet de monter des tunnels [VPN](https://fr.wikipedia.org/wiki/Réseau_privé_virtuel) (Virtual Private Network) en utilisant [SSL/TLS](https://fr.wikipedia.org/wiki/Transport_Layer_Security) pour le chiffrement. Bien qu'OpenVPN sache utiliser aussi une clé partagé (PSK — Pre-Shared Key) ou des couples *utilisateur*/*mot de passe*, nous préférons utiliser des certificats avec une [PKI](https://fr.wikipedia.org/wiki/Infrastructure_%C3%A0_cl%C3%A9s_publiques) (Public Key Infrastructure). ## Installation ### Debian ~~~ # apt install openvpn $ /usr/sbin/openvpn --version OpenVPN 2.4.0 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] built on Jul 18 2017 library versions: OpenSSL 1.0.2l 25 May 2017, LZO 2.08 # systemctl status openvpn ● openvpn.service - OpenVPN service Loaded: loaded (/lib/systemd/system/openvpn.service; enabled) Process: 20889 ExecStart=/bin/true (code=exited, status=0/SUCCESS) Main PID: 20889 (code=exited, status=0/SUCCESS) CGroup: /system.slice/openvpn.service ~~~ ### OpenBSD ~~~ # pkg_add openvpn $ openvpn --version OpenVPN 2.4.4 x86_64-unknown-openbsd6.2 [SSL (OpenSSL)] [LZO] [LZ4] [MH/RECVDA] [AEAD] built on Sep 29 2017 library versions: LibreSSL 2.6.3, LZO 2.10 ~~~ ## Configuration On gère une PKI sur le serveur via shellpki (voir ci-dessous). On crée clé/certificat pour le serveur VPN avec la commande suivante : ~~~ # cd /etc/openvpn/ssl # sh shellpki.sh create ~~~ Note : le CN (*Common Name*) sera par exemple de la forme `fw.vpn.example.com` (il sera demandé de le saisir deux fois). La configuration se fait via un fichier `/etc/openvpn/server.conf` avec les paramètres suivants à adapter : * `server` : réseau privé sur lequel le serveur VPN et les clients communiqueront * `local` : adresse IP du serveur, sur laquelle les clients se connecteront (adresse IP publique généralement) * `push` : route vers le réseau que les clients VPN pourront joindre * `cert` : certificat du serveur VPN (créé précédemment) * `key` : clé du serveur VPN (créée précédemment) * `ifconfig-pool-persist` : permet aux clients de conserver la même IP en cas de redémarrage ### Serveur, sous OpenBSD ~~~ daemon port 1194 proto udp dev tun0 dev-type tap verb 4 user nobody group nobody chroot /var/empty #comp-lzo max-clients 50 keepalive 15 120 tls-exit persist-key persist-tun client-to-client resolv-retry infinite server 10.11.99.0 255.255.255.0 local 198.51.100.1 #client-to-client ifconfig-pool-persist /etc/openvpn/ipp.txt #route-method exe #route-delay 2 push "route 192.0.2.0 255.255.255.0 10.11.99.1" ca /etc/openvpn/ssl/ca/cacert.pem dh /etc/openvpn/ssl/ca/dh1024.pem cert /etc/openvpn/ssl/files/fw.vpn.example.com-1278421834/fw.vpn.example.com.crt key /etc/openvpn/ssl/files/fw.vpn.example.com-1278421834/fw.vpn.example.com.key log /var/log/openvpn.log status /var/log/openvpn-status.log cipher AES-128-CBC # AES #fragment 1350 #mssfix ~~~ Pour créer automatiquement une interface `TUN` au démarrage de la machine et démarrer OpenVPN : ~~~ # cat << EOF > /etc/hostname.tun0 up !/usr/local/sbin/openvpn --daemon --config /etc/openvpn/server.conf EOF ~~~ Pour lancer manuellement OpenVPN sans redémarrer la machine : ~~~ # ifconfig tun0 up # /usr/local/sbin/openvpn --daemon --config /etc/openvpn/server.conf ~~~ Pour que les logs générés par OpenVPN soient "rotatés", il faut rajouter la ligne en question dans le fichier `/etc/newsyslog.conf` : ~~~ /var/log/openvpn.log 600 52 * $W6D4 Z ~~~ ### Serveur, sous Debian ~~~ # # General settings # user nobody group nogroup # Do not try to re-read key file and reopen tun device on restart since it runs # without root privileges. persist-key persist-tun #persist-remote-ip #persist-local-ip # Status file status /var/log/openvpn/status.log 1 #log /var/log/openvpn/openvpn.log # Logging verbosity. Logs are sent to syslog. verb 3 # Keepalive keepalive 10 120 #reneg-sec 300 # # Network settings # port 1194 proto udp dev tun # Enable compression comp-lzo # # key/certificate # ca /etc/openvpn/ssl/ca/cacert.pem cert /etc/openvpn/ssl/files/fw.vpn.example.com-1278421834/fw.vpn.example.com.crt key /etc/openvpn/ssl/files/fw.vpn.example.com-1278421834/fw.vpn.example.com.key dh /etc/openvpn/ssl/ca/dh1024.pem # # private network # server 172.16.0.0 255.255.0.0 mode server # Management interface (used by check_openvpn for Nagios) management 127.0.0.1 1195 /etc/openvpn/management-pwd ~~~ Générer un mot de passe pour l'accès à l'interface de management (nécessaire au check Nagios) : ~~~ # apg -n1 -m 12 >/etc/openvpn/management-pwd ~~~ Puis ajouter le check Nagios dans la conf NRPE : ~~~ # echo "command[check_openvpn]=/usr/lib/nagios/plugins/check_openvpn.pl -H 127.0.0.1 -p 1195 -P $(cat /etc/openvpn/management-pwd)" >>/etc/nagios/nrpe.d/evolix.cfg ~~~ Enfin on installe les dépendances du check ~~~ # apt install libnet-telnet-perl ~~~ ### Client Pour simplifier la configuration pour les utilisateurs finaux on peut générer un fichier de configuration embarquant les certificats : ~~~ client dev tap0 tls-client proto udp #comp-lzo #ns-cert-type server tls-client remote vpn.example.com 1194 persist-key persist-tun pull cipher AES-128-CBC -----BEGIN CERTIFICATE----- […] -----END CERTIFICATE----- Certificate: Data: […] -----END CERTIFICATE----- -----BEGIN RSA PRIVATE KEY----- […] -----END RSA PRIVATE KEY----- ~~~ ## PKI avec shellPKI (OpenBSD et Debian) OpenVPN s'appuie par défaut sur des certificats, il est donc nécessaire de mettre en place une PKI. On utilisera [shellPKI](https://forge.evolix.org/projects/shellpki) permettant de gérer une PKI très simplement en ligne de commande. ### Mise en place * Créer le répertoire `/etc/openvpn/ssl`, et cloner le dépôt shellpki : ~~~ # mkdir /etc/openvpn/ssl # cd /etc/openvpn/ssl # git clone https://forge.evolix.org/shellpki.git . ~~~ * Créer le répertoire `/var/www/htdocs/vpn/ssl` (OpenBSD) ou `/var/www/vpn/ssl` (Debian) dans lequel les certificats seront copiés par défaut pour être distribués. Cet emplacement est configurable dans `shellpki.sh` * Editer les paramètres de la section `[ req_distinguished_name ]` du fichier `openssl.cnf`, notamment : * `countryName_default` * `stateOrProvinceName_default` * `localityName_default` * `0.organizationName_default` * `emailAddress_default` * Exécuter : ~~~ # sh shellpki.sh init ~~~ * Confirmer l'initialisation, et choisir la passphrase qui sera demandée à chaque création de nouveaux certificats, puis le `Common Name` des futurs certificats créés (ex : `vpn.example.com`) ### Créer un nouveau certificat ~~~ # cd /etc/openvpn/ssl # sh shellpki.sh create ~~~ * Choisir un CN unique pour la machine (ex : `client1.vpn.example.com`) * Récupérer le certificat et la clé dans `/var/www/htdocs/vpn/ssl` * Dans la conf client, rajouter la directive `nobind`. Par défaut le client se bind sur l'ip locale et le port 1194, `nobind` force l'utilisation d'un port aléatoire. ### Renouveller un certificat Il faut le révoquer, puis en recréer un : ~~~ # cd /etc/openvpn/ssl # sh shellpki.sh revoke # sh shellpki.sh create # cp /etc/openvpn/ssl/crl.pem /var/empty/ ~~~ Si c'est le certificat du serveur OpenVPN, il faut en plus modifier la configuration puis relancer le démon. ## Permettre aux clients de conserver la même IP au fil de connexions Le fichier `ipp.txt` contient une liste des clients et de leur adresse IP afin qu'en cas de redémarrage du serveur, ils conservent la même adresse. Dans le `server.conf` ou `server.ovpn` : ~~~ ifconfig-pool-persist /etc/openvpn/ipp.txt 0 ~~~ Cela rend le fichier `ipp.txt` en lecture seule pour OpenVPN. Il faudra donc ajouter une nouvelle ligne de la forme `CN,IP` à chaque ajout d'un nouveau client. ## Configuration du client ### Template systemd pour démarrer le client OpenVPN Pour démarrer le client OpenVPN, il existe un template systemd, pour le démarrer et l'activer au démarrage : ~~~ # systemctl start openvpn@client # systemctl enable openvpn@client ~~~ ### Client OpenVPN sous Mac OS X Télécharger la dernière version stable de Tunnelblick sur On suit les instructions d'installation (en anglais), puis : * on choisit de générer la configuration (indiquer qu'on n'a pas de fichiers de configuration) ; * cela génère une configuration standard, notamment un dossier sur le bureau avec un fichier `config.ovpn` ; * on édite le `config.ovpn` en ajustant les options `remote`, `ca`, `cert` et `key` ; * on copie également la clé et les certificats (ca et cart) dans ce dossier ; * on doit ensuite renommer ce dossier avec un nom se terminant par `.tblk` ; * on "double-clic" ensuite dessus, et cela installe configuration ; * on peut ensuite lancer le VPN via l'icone présente, puis choisir diverses options (connexion automatique, etc.). ### Client OpenVPN sous Android On utilise l'application libre "OpenVPN for Android" disponible sur [Google Play](https://play.google.com/store/apps/details?id=de.blinkt.openvpn) et [F-Droid](https://f-droid.org/packages/de.blinkt.openvpn/) qui ne nécessite pas de droits "root" avec Android 4 ou supérieur. La configuration d'un VPN nécessite les informations suivantes : * le certificat CA peut être importé sous format PEM * le certificat client doit être au format PKCS#12 (fichier .p12 ou .pfx), on pourra ainsi le créer à partir de la clé/certificat : ~~~ $ openssl pkcs12 -export -in goyk3OkjeuPread8Sluld.privacy.example.com.crt -inkey goyk3OkjeuPread8Sluld.privacy.example.com.key -out goyk3OkjeuPread8Sluld.privacy.example.com.p12 ~~~ * décocher "Compression LZO" si ce n'est pas supporté par votre serveur * décocher "Vérification du certificat de l'hôte" (sinon cela ne fonctionne pas a priori…) * forcer "Algorithme de chiffrement" à AES-128-CBC (à ajuster selon votre serveur) Si erreur `ca md too weak` cela signifie que le certificat utilise du MD5. Pour forcer quand même, il faut mettre dans les options personnalisées : ~~~ tls-cipher "DEFAULT:@SECLEVEL=0" ~~~ ### Client OpenVPN sous iOS Les systèmes iOS d'Apple disposent nativement du support de plusieurs types de VPN (IKEv2, IPsec ou L2TP), mais pas pour OpenVPN. On utilise alors l'application "OpenVPN Connect" (éditée par "OpenVPN Technologies") qui va exploiter les API bas niveau de l'OS pour un support complet d'OpenVPN dans les interfaces du système. Pour ajouter une configuration cliente, il suffit de s'envoyer le fichier `.ovpn` par mail ou via un partage de fichier quelconque et il s'ouvrira dans l'application. Il est possible d'avoir plusieurs configuration disponibles. Pour activer la connexion VPN il faut alors se rendre dans l'application "Réglages", puis "VPN" où sont listés les profils disponibles. On peut choisir celui à utiliser et activer la connexion. Si tout se passe bien, le symbole "VPN" apparaît dans la barre d'icones tout en haut de l'écran. ## Erreurs fréquentes ### Erreur "--crl-verify fails" (serveur OpenVPN – OpenBSD) ~~~ Options error: --crl-verify fails with 'crl.pem': No such file or directory Options error: Please correct these errors. ~~~ Il faut parfois regénérer un fichier CRL. Si l'on utilise une version récente de [shellpki](https://forge.evolix.org/projects/shellpki) : ~~~ # cd /tmp # shellpki.sh crl # cp crl.pem /var/empty ~~~ ### Erreur "createipforwardentry" (client OpenVPN – Windows) En cas d'erreur `ROUTE: route addition failed using createipforwardentry`, l'utilisateur n'a pas les droits suffisants pour ajouter une nouvelle route. Il faut essayer d'exécuter les logiciels (`openvpn.exe` et `openvpngui.exe`) dans un mode de compatibilité _lancer en Administrateur_. Pour plus de détails, voir . ### Erreur "no more TUN/TAP adapter" (client OpenVPN – Windows) En cas d'erreur `no more TUN/TAP adapter` aller dans "menu démarrer" > "OpenVPN" > "Add new TUN/TAP Adapter" ### Erreur "cipher final failed" (client OpenVPN – Android) L'erreur `Authentificate/Decrypt packet error: cipher final failed` signifie que l'algorithme de chiffrement n'est pas synchronisé entre le client et le serveur. Il faut donc ajuster la directive "cipher" sur le client. ### Erreur "Bad LZO decompression header byte" (client OpenVPN – Android) L'erreur `Bad LZO decompression header byte` signifie que la compression LZO n'est pas activée sur le serveur, il faut donc désactiver la compression au niveau du client.