---
categories: vpn sysadmin security network
title: Howto OpenVPN
...

* Documentation : <https://openvpn.net/index.php/open-source/documentation.html>
* Rôle Ansible : <https://gitea.evolix.org/evolix/ansible-roles/src/branch/stable/openvpn>

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


## Installation

### Debian

~~~
# apt install openvpn

$ /usr/sbin/openvpn --version
OpenVPN 2.5.1 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] built on May 14 2021
library versions: OpenSSL 1.1.1k  25 Mar 2021, LZO 2.10

# systemctl status openvpn
● openvpn.service - OpenVPN service
     Loaded: loaded (/lib/systemd/system/openvpn.service; enabled; vendor preset: enabled)
     Active: active (exited) since Tue 2022-01-04 15:11:48 CET; 27s ago
    Process: 74469 ExecStart=/bin/true (code=exited, status=0/SUCCESS)
   Main PID: 74469 (code=exited, status=0/SUCCESS)
        CPU: 819us
~~~

### OpenBSD

~~~
# pkg_add openvpn
$ openvpn --version
OpenVPN 2.5.1 x86_64-unknown-openbsd6.9 [SSL (OpenSSL)] [LZO] [LZ4] [MH/RECVDA] [AEAD] built on Apr 19 2021
library versions: LibreSSL 3.3.2, LZO 2.10
~~~

## Configuration serveur

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.

Une fois fait, on génère le dhparam :

~~~
# openssl dhparam -out /etc/shellpki/dh2048.pem 2048
~~~

La configuration se fait via le fichier `/etc/openvpn/server.conf` avec les paramètres suivants à adapter :

* `local` : adresse IP du serveur, sur laquelle les clients se connecteront (adresse IP publique généralement)
* `cert` : certificat du serveur VPN (créé précédemment)
* `key` : clé du serveur VPN (créée précédemment)
* `server` : réseau privé sur lequel le serveur VPN et les clients communiqueront
* `push` : route vers le réseau que les clients pourront joindre à travers OpenVPN ; ce paramètre peut être indiqué plusieurs fois
* `ifconfig-pool-persist` : permet aux clients de conserver la même IP en cas de redémarrage

~~~
user  _openvpn
group _openvpn

local 198.51.100.1
port 1194
proto udp
dev tun
mode server
topology subnet
keepalive 10 120
tls-exit

cipher AES-256-GCM # AES

persist-key
persist-tun

ifconfig-pool-persist /etc/openvpn/ipp.txt

status /var/log/openvpn-status.log
log-append  /var/log/openvpn.log

ca   /etc/shellpki/cacert.pem
cert /etc/shellpki/certs/fw.vpn.example.com.crt
key  /etc/shellpki/private/fw.vpn.example.com-1621504035.key
dh   /etc/shellpki/dh2048.pem

crl-verify /etc/shellpki/crl.pem

server 192.0.2.0 255.255.255.0

#push "route 192.0.3.0 255.255.255.0"

# 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
~~~

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 :

~~~
## Debian
# wget https://gitea.evolix.org/evolix/ansible-roles/raw/branch/unstable/openvpn/files/check_openvpn_debian.pl -O /usr/local/lib/nagios/plugins/check_openvpn
# chmod 755 /usr/local/lib/nagios/plugins/check_openvpn
# chown root:nagios /usr/local/lib/nagios/plugins/check_openvpn
# apt install libnet-telnet-perl
# /usr/local/lib/nagios/plugins/check_openvpn -H 127.0.0.1 -p 1195 -P $MANAGEMENT_PWD

## OpenBSD
# wget https://gitea.evolix.org/evolix/ansible-roles/raw/branch/unstable/openvpn/files/check_openvpn_openbsd.pl -O /usr/local/libexec/nagios/plugins/check_openvpn.pl
# chmod 755 /usr/local/libexec/nagios/plugins/check_openvpn.pl
# chown root:wheel /usr/local/libexec/nagios/plugins/check_openvpn.pl
# pkg_add p5-Net-Telnet
# /usr/local/libexec/nagios/plugins/check_openvpn.pl -H 127.0.0.1 -p 1195 -P $MANAGEMENT_PWD
~~~

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:

~~~
## Debian
# wget https://gitea.evolix.org/evolix/ansible-roles/raw/branch/unstable/openvpn/files/check_openvpn_certificates.sh -O /usr/local/lib/nagios/plugins/check_openvpn_certificates.sh
# chmod 755 /usr/local/lib/nagios/plugins/check_openvpn
# chown root:nagios /usr/local/lib/nagios/plugins/check_openvpn
# visudo -f /etc/sudoers.d/openvpn
nagios  ALL=NOPASSWD: /usr/local/lib/nagios/plugins/check_openvpn_certificates.sh
# sudo /usr/local/lib/nagios/plugins/check_openvpn_certificates.sh

## OpenBSD
# wget https://gitea.evolix.org/evolix/ansible-roles/raw/branch/unstable/openvpn/files/check_openvpn_certificates.sh -O /usr/local/libexec/nagios/plugins/check_openvpn_certificates.sh
# chmod 755 /usr/local/libexec/nagios/plugins/check_openvpn_certificates.sh
# chown root:wheel /usr/local/libexec/nagios/plugins/check_openvpn_certificates.sh
# vim /etc/doas.conf 
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 :

~~~
# wget https://gitea.evolix.org/evolix/shellpki/raw/branch/dev/cert-expirations.sh -O /usr/share/scripts/cert-expirations.sh
# chmod +x /usr/share/scripts/cert-expirations.sh
# crontab -e
@monthly /usr/share/scripts/cert-expirations.sh | mail -E -s "PKI OpenVPN XXX : recapitulatif expirations" mail@example.com
~~~

Penser à remplacer :

* L'horaire d'exécution du cron, si voulu ;
* L'emplacement des certificats dans le script (/etc/shellpki/certs/), ceux-ci peuvent se trouver dans "/etc/openvpn/ssl/certs/" ou ailleurs encore ;
* Le nom du serveur XXX dans le sujet "PKI OpenVPN XXX" ;
* L'adresse mail de contact.

### Serveur sous Debian

On crée un utilisateur `_openvpn` sous lequel OpenVPN tournera :

~~~
# useradd _openvpn --system -M --home-dir /nonexistent --shell /usr/sbin/nologin
~~~

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`) :

~~~
# Public services (IPv4/IPv6)
[…]
SERVICESUDP1='1194'

[…]

# OpenVPN
/sbin/iptables -t nat -A POSTROUTING -s 192.0.2.0/24 -o $INT -j MASQUERADE
~~~

Ainsi qu'autoriser le routage via sysctl :

~~~
# echo "net.ipv4.ip_forward=1" >> /etc/sysctl.d/openvpn.conf
# sysctl -p /etc/sysctl.d/openvpn.conf
~~~

Rotation des logs, en créant un fichier `/etc/logrotate.d/openvpn` :

~~~
/var/log/openvpn.log
{   
    weekly 
    rotate 52
    missingok
    notifempty
    delaycompress
    compress
    copytruncate
}
~~~

Le service s'active et se démarre ensuite via :

~~~
# systemctl enable openvpn@server.service
# systemctl start openvpn@server.service
~~~

### Serveur sous OpenBSD

On autorise la connexion au serveur VPN en modifiant `/etc/pf.conf` :

~~~
# OpenVPN
pass in quick on $ext_if proto udp from any to self port 1194
~~~

Puis on recharge PacketFilter :

~~~
# pfctl -nf /etc/pf.conf && pfctl -f /etc/pf.conf
~~~

Rotation des logs :

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.

* Pour tout de même utiliser newsyslog, il faut rajouter la ligne suivante dans le fichier `/etc/newsyslog.conf` :

~~~
/var/log/openvpn.log                    600  52    *    $W6D4 Z
~~~

Ainsi que plannifier en crontab un restart d'OpenVPN juste après cette rotation, pour qu'il puisse récupérer le nouveau file descriptor :

~~~
05 	4 	* 	* 	6	/etc/rc.d/openvpn restart
~~~

* 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é :

~~~
0       4       *       *       6       cp /var/log/openvpn.log /var/log/openvpn.log.$(date +\%F) && echo "$(date +\%F' '\%R) - logfile turned over via cron" > /var/log/openvpn.log && gzip /var/log/openvpn.log.$(date +\%F) && find /var/log/ -type f -name "openvpn.log.*" -mtime +365 -exec rm {} \+
~~~

Pour activer OpenVPN au démarrage :

~~~
# rcctl enable openvpn
# rcctl set openvpn flags "--daemon --config /etc/openvpn/server.conf"
~~~

Pour lancer OpenVPN :

~~~
# rcctl start openvpn
~~~

## Configuration client

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.

Pour simplifier la configuration pour les utilisateurs finaux on peut générer un fichier de configuration embarquant les certificats :

~~~
client
dev tun
tls-client
proto udp

remote vpn.example.com 1194

nobind
user nobody
group nogroup
persist-key
persist-tun

cipher AES-256-GCM

<ca>
-----BEGIN CERTIFICATE-----
[…]
-----END CERTIFICATE-----
</ca>

<cert>
Certificate:
    Data:
[…]
-----END CERTIFICATE-----
</cert>

<key>
-----BEGIN RSA PRIVATE KEY-----
[…]
-----END RSA PRIVATE KEY-----
</key>
~~~

### Nouveau certificat avec shellpki

Pour une nouvelle connexion VPN, il faudra créer un nouveau certificat :

~~~
# shellpki create <commonName>
~~~

* Choisir un _Common Name_ unique pour la machine (ex : `client1.vpn.example.com`)

* Récupérer la configuration client dans `/etc/shellpki/openvpn/`

### Renouveller un certificat avec shellpki

Il faut utiliser l'option `--replace-existing` :

~~~
# shellpki create --replace-existing <commonName>
~~~

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.

### Révoquer un certificat avec shellpki

~~~
# shellpki revoke <commonName>
~~~

#### Vérifier les certificats révoqués

~~~
# openssl crl -inform PEM -text -noout -in /etc/shellpki/crl.pem
~~~

L'association entre le numéro de série indiqué et le CN du certificat correspondant peut être faite à l'aide du fichier `/etc/shellpki/index.txt`

### Client sous Linux

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
~~~

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` :

~~~
mkdir /var/empty/tmp/
chown $OPENVPN_USER:$OPENVPN_GROUP /var/empty/tmp/
chmod 700 /var/empty/tmp/ 
~~~

En remplaçant $OPENVPN_USER et $OPENVPN_GROUP selon les paramètres configurés pour `user` et `group` (souvent `nobody`).

### Client sous Windows

On peut télécharger un client 32 bits ou 64 bits sur <https://openvpn.net/community-downloads/>.

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`.

Attention, il faut exécuter OpenVPN en tant qu'administrateur, cela peut se faire via un clic droit : `Exécuter en tant qu'administrateur`.

OpenVPN est alors disponible dans la barre des tâches.
Pour lancer une session, effectuez un clic-droit et sélectionnez `Connecter`.

### Client sous macOS

Télécharger la dernière version stable de Tunnelblick sur <https://tunnelblick.net/downloads.html>

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 fichier `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.).

Si on souhaite faire passer tout le trafic par le VPN, on peut cocher la case « Rediriger tout le trafic IPv4 au travers du VPN »

### Client 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-256-GCM (à 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 sous Apple 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 d'OpenVPN dans les interfaces du système.

Pour ajouter une configuration cliente, il suffit d'ouvrir le fichier `.ovpn`. Il est possible d'avoir plusieurs configurations 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'icônes 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 ancienne de [shellpki](https://gitea.evolix.org/evolix/shellpki) :

~~~
# cd /tmp
# shellpki.sh crl
# cp crl.pem /var/empty
~~~

Sur les versions récentes, la CRL est re-générée à chaque révocation d'un certificat, ou peut être re-générée ainsi :

~~~
# openssl ca -gencrl -keyfile /etc/shellpki/cakey.key -cert /etc/shellpki/cacert.pem -out /etc/shellpki/crl.pem -config /etc/shellpki/openssl.cnf
~~~

### Erreur « CRL has expired » (serveur OpenVPN – OpenBSD)

~~~
VERIFY ERROR: depth=0, error=CRL has expired: C=FR, ST=FR, L=Versailles, O=foo.bar, CN=SoX, emailAddress=hostmaster@foo.bar
~~~

Il est possible que la CRL ne soit plus valide, et qu'il faille la regénérer comme ci-dessus.
Dans le cas de firewalls redondés, si une bascule sur le backup a récemment eu lieu, le fichier n'est sans doute pas synchronisé et expiré.

### 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 <http://www.bolehvpn.net/forum/index.php?topic=1746.0>.

### 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.

### Erreur « Temporary directory (--tmp-dir) fails with '/var/empty//tmp': No such file or directory (errno=2) »

Un chroot est configuré dans `/var/empty` mais le dossier est vide. Il faut créer un répertoire `tmp` dedans :

~~~
# mkdir /var/empty/tmp/
# chown _openvpn:_openvpn /var/empty/tmp/
# chmod 700 /var/empty/tmp/
~~~

## FAQ

### Permettre aux clients de conserver la même IP au fil de connexions

#### ipp.txt

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.

**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.

#### /etc/openvpn/ccd

Doc complète : <https://community.openvpn.net/openvpn/wiki/Concepts-Addressing>

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 :

~~~
tls-server
push "topology subnet"
ifconfig 192.0.2.1 255.255.255.0
push "route-gateway 192.0.2.1"
ifconfig-pool 192.0.2.2 192.0.2.199 255.255.255.0
client-config-dir /etc/openvpn/ccd
~~~

* Créer le dossier `/etc/openvpn/ccd/` avec les bons droits :

~~~
# cd /etc/openvpn/
# mkdir ccd
# chmod 700 ccd
# chown _openvpn:_openvpn ccd
~~~

* 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 :

~~~
# cd /etc/openvpn/ccd/
# echo "ifconfig-push 192.0.2.200 255.255.255.0" > client1
# chmod 600 client1
# chown _openvpn:_openvpn client1
~~~

* Répéter la configuration dans `/etc/openvpn/ccd/` pour chaque CN auquel attribuer une IP statique

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.

### Authentification via Radius

Il faut installer le plugin :

~~~
# apt install openvpn-auth-radius
# cp /usr/share/doc/openvpn-auth-radius/examples/radiusplugin.cnf /etc/openvpn/
# openvpn --genkey --secret /etc/openvpn/ta.key
~~~

On ajoute dans la configuration du serveur :

~~~
client-cert-not-required
username-as-common-name
tls-auth ta.key 0
topology subnet
plugin /usr/lib/openvpn/radiusplugin.so /etc/openvpn/radiusplugin.cnf
status /var/log/openvpn/status.log 1
~~~

et on modifie le paramètre _sharedsecret_ du fichier `/etc/openvpn/radiusplugin.cnf` pour se connecter au serveur Radius.

Puis dans la configuration du client :

~~~
auth-user-pass
#auth-user-pass /etc/openvpn/passwd
auth-nocache
~~~

### Authentification via PAM et certificat

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 :

~~~
plugin /usr/lib/x86_64-linux-gnu/openvpn/plugins/openvpn-plugin-auth-pam.so login
~~~

Et dans la configuration du client :

~~~
auth-user-pass
auth-nocache
~~~

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)

### comp-lzo ou compress ?

<https://community.openvpn.net/openvpn/wiki/DeprecatedOptions#a--comp-lzo>

À 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

~~~
link-mtu 1300
~~~

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 :

~~~
#keepalive 10 120

inactive 900
ping 10
push "ping 10"
push "ping-exit 15"
~~~

É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.