Login Logout

Howto OpenVPN

OpenVPN permet de monter des tunnels VPN (Virtual Private Network) en utilisant SSL/TLS 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 (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. Voir le README 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 ou pour OpenBSD, à 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 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 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 --now 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

IPv6

Pour configurer l’IPv6, il suffit d’ajouter le paramètre server-ipv6 en plus du paramètre server. Il faut, pour l’IPv6, soit utiliser un réseau publique que l’on possède et que l’on dédie à cette utilisation (et pour lequel on fait le routage nécessaire dans notre infrastructure), soit utiliser le préfixe local fd00::/64 sur lequel on peut faire du NAT :

server 192.0.2.0 255.255.255.0
server-ip6 2001:db8:10::/64

On peut ensuite pousser les routes IPv6 aux clients :

push "route-ipv6 2001:db8:20::/64"
push "route-ipv6 2001:db8:30::/64"

Si l’on veut faire écouter le serveur OpenVPN en IPv6 et en IPv4 à la fois, il faut remplacer proto udp par proto udp6 ou proto tcp par proto tcp6. Attention cependant : sur certains OS, dont OpenBSD, udp6 et tcp6 n’impliquent pas udp et tcp, donc seul l’IPv6 écoutera. Il faudra alors choisir entre l’IPv4 et l’IPv6.

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 enable --now 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 et F-Droid 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 :

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

Je ne passe pas par le VPN pour joindre cette IP alors que je devrais : réseaux mobiles et NAT64/DNS64

Dans le cas d’utilisation d’un partage de connexion depuis un réseau mobile (en particulier Bouygues, mais ça concerne aussi les autres opérateurs), un tunnel IPv6 est effectué par l’opérateur pour forcer l’utilisation d’IPv6, via du NAT64.

Si un site que je veux joindre, disons example.com, a un enregistrement DNS A sur 192.0.2.15 mais pas d’enregistrement DNS AAAA IPv6, alors le résolveur DNS du réseau mobile renverra à la fois l’enregistrement DNS A 192.0.2.15 et son enregistrement DNS AAAA équivalent en NAT64, par exemple 64:ff9b::c000:20f si la RFC6052 est appliquée. Étant donné que les OS ont généralement une préférence pour l’IPv6, c’est cette adresse IPv6 que le système va essayer de joindre.

Vu que le préfixe NAT64 utilisé n’est pas routé par le VPN, alors je joindrais ce site sans passer par le VPN. Pour résoudre le problème, il faut forcer l’utilisation d’un résolveur DNS dans la configuration du serveur OpenVPN :

push "dhcp-option DNS 198.51.100.53"

Avec 198.51.100.53 étant l’IP du serveur DNS à adapter.

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, en se basant sur la configuration serveur classique, 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.

Router tout le trafic des clients par le VPN

Si l’on veut router tout le trafic des clients OpenVPN par le serveur OpenVPN, il faut ajouter cette configuration sur le serveur :

push "redirect-gateway def1"

Le mot-clé def1 permet à OpenVPN de ne pas remplacer et donc supprimer la route par défaut déjà en place, mais de seulement ajouter 2 routes en utilisant 0.0.0.0/1 et 128.0.0.0/1, qui seront plus précises que la route par défaut (0.0.0.0/0) et seront donc utilisées à la place de celle-ci.

Si l’on ne veut pas que tous les clients aient cette configuration, alors on peut l’ajouter du côté du client qui la souhaite uniquement :

redirect-gateway def1

À l’inverse, si le serveur est configuré pour que tous les clients aient tout leur trafic routé par le VPN, mais qu’un client en particulier ne souhaite pas cette option, il peut la refuser dans sa configuration client (source) :

pull-filter ignore "redirect-gateway"

On peut utiliser cette option directement depuis la ligne de commande :

# openvpn --pull-filter ignore redirect-gateway --config …

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 :

verify-client-cert none
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

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.

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.