[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](HowtoSSL) pour le chiffrement. Pour l'authentification, OpenVPN peut utiliser une simple clé partagée (PSK — Pre-Shared Key) ou des couples *utilisateur*/*mot de passe*, mais 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).
On met en place une PKI sur le serveur via [shellpki](https://gitea.evolix.org/evolix/shellpki). Voir le [README](https://gitea.evolix.org/evolix/shellpki/src/branch/master/README.md) du projet.
Puis on corrige les permissions pour qu'OpenVPN puisse lire le CRL en éditant `/usr/local/sbin/shellpki`, pour ajouter les lignes `chmod 604 /etc/shellpki/crl.pem` et `chmod 751 /etc/shellpki/` :
On peut utiliser le check NRPE OpenVPN suivant pour monitorer le service OpenVPN [pour Debian](https://gitea.evolix.org/evolix/ansible-roles/raw/branch/unstable/openvpn/files/check_openvpn_debian.pl) ou [pour OpenBSD](https://gitea.evolix.org/evolix/ansible-roles/raw/branch/unstable/openvpn/files/check_openvpn_openbsd.pl), à ajouter dans la configuration NRPE :
On peut également utiliser le [check NRPE suivant](https://gitea.evolix.org/evolix/ansible-roles/raw/branch/unstable/openvpn/files/check_openvpn_certificates.sh) pour monitorer les dates d'expirations de la CA et du certificat serveur:
permit nopass _nrpe as root cmd /usr/local/libexec/nagios/plugins/check_openvpn_certificates.sh
# doas /usr/local/libexec/nagios/plugins/check_openvpn_certificates.sh
~~~
Un script [cert-expirations.sh](https://gitea.evolix.org/evolix/shellpki/raw/branch/dev/cert-expirations.sh) peut être mis en cron pour avertir régulièrement des prochaines expirations des certificats clients et serveur :
Il ne faut pas oublier les changements suivants à ajouter dans `/etc/default/minifirewall` (en remplaçant `192.0.2.0/24` par le réseau utilisé dans le paramètre `server`) :
Le fichier `/etc/newsyslog.conf` ne permet pas de faire une rotation propre des logs OpenVPN, car OpenVPN continue à écrire dans le file descriptor du fichier précédent. Cela peut mener à une saturation de la partition d'écriture, sans pouvoir supprimer le fichier qui n'existe plus, et où seul un restart d'OpenVPN peut régler le problème.
* Sans utiliser newsyslog si on ne veut pas avoir à redémarrer OpenVPN, on peut utiliser un cron qui va copier le fichier de log, compresser la copie, et vider l'actuel (équivalent d'un copytruncate du logrotate). De cette manière, le file descriptor n'est pas changé :
La configuration client se trouve généralement dans un fichier `<nom_certificat>.ovpn`. Cette extension permet l'exécution d'OpenVPN sous Windows, et est donc généralement utilisée sous n'importe quel système pour l'uniformité. Néammoins, c'est parfois l'extension `.conf` qui est utilisée, puisque sous Linux, OpenBSD, ou d'autres systèmes encore, l'extension n'a pas vraiment d'importance.
Si c'est le certificat du serveur OpenVPN, il faut en plus modifier la configuration `/etc/openvpn/server.conf` pour indiquer la nouvelle key puis relancer le démon.
Attention, si l'option `chroot` est configurée, il faudra au moins y créer un dossier `tmp`, sans lequel OpenVPN ne démarrera pas. Par exemple, avec `chroot /var/empty` :
Une fois installé, copier le fichier `.ovpn` et le certificat de la CA dans le répertoire de configuration d'OpenVPN, par exemple `C:\Program Files\OpenVPN\config`.
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 d'OpenVPN dans les interfaces du système.
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'icônes tout en haut de l'écran.
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 <http://www.bolehvpn.net/forum/index.php?topic=1746.0>.
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.
L'erreur `Bad LZO decompression header byte` signifie que la compression LZOn'est pas activée sur le serveur, il faut donc désactiver la compression au niveau du client.
**Attention** : cette configuration n'est qu'une suggestion pour OpenVPN, il n'y a aucune garantie qu'OpenVPN attribue réellement les IPs indiquées dans ce fichier aux clients. Pour que cela soit garantie, il faut utiliser l'option `client-config-dir`, voir ce-dessous.
Pour attribuer une IP de manière statique de façon garantie sur le temps, par rapport à [configuration serveur classique](#configuration-serveur), il faut :
* Supprimer la ligne de configuration `server 192.0.2.0 255.255.255.0`
* Ajouter les paramètres de configuration suivants :
* Créer le fichier `/etc/openvpn/ccd/client1` (`client1` étant le CN du client auquel attribuer l'IP statique) avec les bons droits, et mettre la configuration suivante :
Ainsi, le serveur est configuré sur l'IP 192.0.2.1, la plage IP 192.0.2.2 jusqu'à .199 sera dynamique, et la plage .200 jusqu'à .254 ne sera jamais attribuée dynamiquement mais ne pourra qu'être statique.
On peut aussi supprimer la ligne `ifconfig-pool 192.0.2.2 192.0.2.199 255.255.255.0` pour ne pas avoir de plage dynamique du tout, et ne forcer que des attributions statiques. Dans ce cas, il faut aussi supprimer la configuration `ifconfig-pool-persist /etc/openvpn/ipp.txt`. Un client qui se connecte alors que son IP statique n'a pas été configurée n'aura pas d'IP, et ne pourra donc pas utiliser OpenVPN malgré sa bonne connexion.
De cette façon, on peut également utiliser des plages d'IPs avec des autorisations spécifiques sur le firewall : par exemple la page dynamique .2 à .199 avec des autorisations limitées, une plage statique .200 à .220 avec certaines autorisations, puis une plage statique .221 à .254 avec d'autres autorisations.
Pour avoir une authentification qui se base à la fois sur les certificats **et** sur un utilisateur UNIX, il faut utiliser le module PAM, en rajoutant à la configuration du serveur :
Si en plus de ça, on veut qu'un certificat ne puisse être utilisé que par un seul utilisateur UNIX, il faut utiliser un script vérifiant que le common_name du certificat équivaut à l'username UNIX, en rajoutant dans la configuration du serveur :
~~~
script-security 2
client-connect /etc/openvpn/cn-validation.sh
~~~
Le script cn-validation.sh est disponible sur [notre dépôt shellpki sur Gitea](https://gitea.evolix.org/evolix/shellpki/raw/branch/dev/cn-validation.sh)
À partir d'OpenVPN 2.4, _comp-lzo_ est déprécié et doit être remplacé par l'option _compress_ pour activer la compression (tant au niveau serveur que client).
Ne préciser que _compress_ n'active cependant aucun algorithme de compression. Il faut préciser l'algorithme, soit _lz4_, soit _lzo_. _compress lz4_ est plus performant, mais _compress lzo_ est rétro-compatible avec l'option _comp-lzo_ et est donc préférable dans le cas où des clients ont une version inférieure à 2.4.
### MTU
Si vous rencontrez des problèmes de connexion au travers d'un VPN, par exemple un transfert de fichiers qui s'interrompt, ou une connexion SSH qui échoue, alors qu'un simple `ping` fonctionne, il est possible que cela soit un problème de [MTU](https://fr.wikipedia.org/wiki/Maximum_transmission_unit).
Une manière de contourner le problème est de forcer le MTU côté client avec le paramètre
Bien sûr vous pouvez ajuster la valeur, mais tester avec une valeur assez basse comme 1300 afin de voir rapidement si cela résoud votre problème avant d'ajuster plus finement votre valeur avec `ping -s <packetsize> <IP>`.
L'option `--mtu-test` d'OpenVPN permet également de mesurer de façon empirique la meilleure valeur OpenVPN à utiliser. Pour cela, OpenVPN envoie des pings de différentes tailles en mesurant le plus gros paquet ayant été reçus avec succès.
### Déconnecter les utilisateurs inactifs après X minutes
Pour déconnecter les utilisateurs après par exemple 15 minutes d'inactivité, on peut configurer ces paramètres sur le serveur :
Étant donné qu'on configure l'option `keepalive` par défaut, il faut la désactiver pour que la déconnexion fonctionne. Configuré sur le serveur, l'option `keepalive` configure les paramètres `ping`, `ping-restart`, `push "ping"`, et `push "ping-restart"`. L'option `ping-restart` écrase l'option `ping-exit`, empêchant la bonne déconnexion.
Côté clients, les paramètres suivants peuvent également être configurés, mais de façon facultative car ils sont poussés par le serveur à l'aide de `push "paramètre"` :
~~~
ping 10
ping-exit 15
~~~
Explication :
*`ping 10` côté serveur et clients : Un ping est envoyé par le serveur et le client toutes les 10s.
*`inactive 900` côté serveur : En parallèle, s'il n'y a aucune activité sur le VPN (en dehors du ping qui n'est pas considérée comme une activité utilisateur) pendant 15min, le serveur déconnecte le client. À ce moment-là, le client ne sait pas qu'il a été déconnecté.
*`ping-exit 15` côté clients : Le client termine sa connexion après 15s sans réception de ping de la part du serveur. En réalité, ça va être 5s si le dernier ping a été envoyé par le serveur 10s avant la déconnexion d'inactivité, ou 15s si le dernier ping a été envoyé par le serveur au même moment que la déconnexion d'inactivité.
Nous n'utilisons pas le paramètre `inactive` côté clients car il ne réagit pas de la même manière que côté serveur. La déconnexion du client pourrait avoir lieu côté serveur avant d'arriver côté client, pouvant perturber l'utilisateur.