Télétravail avec OpenVPN et NetworkManager

Retour à la page Systèmes

Motivation

En cette période de confinement, mon entreprise met pas mal de monde en télétravail, et fournit gentiment un fichier de configuration vpnbureau.ovpn pour se connecter à son VPN.

Les clients de la sociéné n’accepteront que les connexions venues du bureau. Or le débit disponible au bureau étant limité, je veux m’assurer que le trafic personnel ne va pas l’encombrer.

  • station.client.fr doit passer par le VPN du bureau
  • siteperso.free.fr doit passer par ma connexion domestique.

Utiliser openvpn suffirait pour cela. Mais à cause de certains aspects agaçants, on va vite passer, dans ce qui suit, à une automatisation de la configuration par NetworkManager.

Ceux qui ont déjà des repères et veulent juste la recette peuvent sauter directement au résumé à la fin;

Prérequis

On supposera que vous avez installé:

  • openvpn
  • NetworkManager
  • networkmanager-openvpn (le plugin de NetworkManager pour travaille avec OpenVPN)

On suppose aussi que vous avez au moins une vague notion de ce que signifie une plage d’adresses IP comme 192.168.0.0/24.

Pour information seulement, voici une fonction bash pour exécuter, voir et enregistrer en une fois les tests répétitifs de cet article:

# affiche et enregistre les réglages courants dans route-$1.txt
function tester () (
  nom=$1
  {
  echo "-- routes --";       ip route
  echo "-- connexions --";   nmcli connection show
  echo "-- route client --"; traceroute station.client.fr
  echo "-- route perso --";  traceroute siteperso.free.fr
  } | tee route-${nom}.txt
)

Manipulations

Avec OpenVPN seul

Pour tout ce laïus, on supposera que le nom d’utilisateur (login) à utiliser pour le VPN est loginvpn Ouvrons le réseau VPN avec le fichier de configuration fourni:

$ sudo openvpn --config vpnbureau.ovpn
[sudo] password for loginperso:
Sat Mar 28 15:21:18 2020 OpenVPN 2.4.8 x86_64-redhat-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] built on Nov  1 2019
Sat Mar 28 15:21:18 2020 library versions: OpenSSL 1.1.1d FIPS  10 Sep 2019, LZO 2.08
Enter Auth Username: loginvpn
Enter Auth Password: ********
...
Sat Mar 28 15:21:35 2020 TUN/TAP device tun0 opened
...
Sat Mar 28 15:21:35 2020 Initialization Sequence Completed

Ça fonctionne, mais le shell ne rend pas la main. Travaillons donc dans un autre shell, où nous pouvons voir la connexion créée tun0:

$ nmcli connection show
NAME            UUID                                  TYPE      DEVICE
p2p1            f68054b9-8e9c-4190-beae-dbb5889f4613  ethernet  enp3s0
tun0            2003f2a3-3840-4d23-a8e5-d78326e1b64b  tun       tun0
virbr0          8dd7068e-089c-41c5-b0bc-9b10dab7e854  bridge    virbr0
...

Et on peut voir que toutes les adresses 192.168.0.0/24 sont dirigées vers cette connexion tun0 créée par la commande OpenVPN:

$ ip route
default via 192.168.1.1 dev enp3s0 proto dhcp metric 100
10.0.0.0/24 dev tun0 proto kernel scope link src 10.0.0.4
192.168.0.0/24 via 10.0.0.1 dev tun0
...

Note: ne surtout pas confondre la plage de mon réseau domestique 192.168.**1**.0/24 et celle du VPN 192.168.**0**.0/24;

A part cela, je suis chagriné de ne voir ci-dessus aucune mention d’un routage de l’adresse du client IP.CLIENT.FR vers notre VPN, ce que confirme un traceroute

$ traceroute station.client.fr
traceroute to station.client.fr (IP.CLIENT.FR), 30 hops max, 60 byte packets
1  livebox.home (192.168.1.1)  0.506 ms  7.133 ms  0.805 ms
2  80.10.234.161 (80.10.234.161)  4.352 ms  4.417 ms  4.503 ms
...
$ traceroute siteperso.free.fr
traceroute to siteperso.free.fr (...), 30 hops max, 60 byte packets
1  livebox.home (192.168.1.1)  0.964 ms  1.192 ms  1.360 ms
2  80.10.234.161 (80.10.234.161)  4.672 ms  4.774 ms  4.869 ms
...

Corrigeons tout de suite le tir en ajoutant une route:

$ sudo ip route add IP.CLIENT.FR/24 dev tun0
$ traceroute
$ traceroute station.client.fr
traceroute to station.client.fr (IP.CLIENT.FR), 30 hops max, 60 byte packets
1  10.0.0.1 (10.0.0.1)  34.593 ms  35.697 ms  36.638 ms
2  192.168.0.254 (192.168.0.254)  38.541 ms  39.482 ms  41.119 ms
...

Bien, ça marche, et nous pouvons, pour la cause de la pédagogie, tout fermer avant de passer à l’automatisation de ces opérations par NetworkManager.

  • sudo ip route del IP.CLIENT.FR/24;
  • mettre fin au VPN par un Ctrl-c dans le terminal qui l’avait ouvert;

Avec NetworkManager

La commande de gestion de NetworkManager est nmcli, préférable aux applets graphique existantes trop incomplètes.

Les sous-commandes de nmcli peuvent être abrégées (par exemple «nmcli c s» signifie «nmcli connection show»), mais pour la clarté ce qui suit mentionne les noms complets.

Importer et démarrer la connexion

D’abord, il faut que le service soit en marche pour disposer de nmcli

  • nmcli connection show
  • Si ça ne marche pas: systemctl start NetworkManager

Demandons gentiment à NetworkManager de créer un profil pour cette connexion VPN:

$ nmcli connection import type openvpn file vpnbureau.ovpn
Connection 'vpnbureau' (b6c86d0c-6228-443e-8c04-4b0de38ad933) successfully added.
$ nmcli connection show
NAME            UUID                                  TYPE      DEVICE
p2p1            f68054b9-8e9c-4190-beae-dbb5889f4613  ethernet  enp3s0
tun0            a86fb362-d418-4ebe-a976-a54d962cb20e  tun       --
vpnbureau       8a718226-20bc-4f2c-b69a-c6133ff3de7f  vpn       --
...

Maintenant on démarre la connexion:

$ nmcli connection up vpnbureau
You need to authenticate to access the Virtual Private Network “vpnbureau”.
Warning: password for 'vpn.secrets.password' not given in 'passwd-file' and nmcli cannot ask without '--ask' option.
...

Ajoutons donc l’option --ask si obligeamment suggérée par le message d’erreur:

$ nmcli connection up --ask vpnbureau
You need to authenticate to access the Virtual Private Network “vpnbureau”.
Password: (vpn.secrets.password): ••••••••
A password is required.
Password: (vpn.secrets.password): ....

Ce refus du mot de passe est étrange. Mais au fait, est-il demandé pour le bon login ?

Il se trouve que NetworkManager utilise en catimini, le même login que sur la machine perso. Il faut donc lui dire d’utiliser, à la place, le login du vpn:

$ nmcli connection modify vpnbureau +vpn.user-name loginvpn
$ nmcli connection up --ask vpnbureau
You need to authenticate to access the Virtual Private Network “vpnbureau”.
Password: (vpn.secrets.password): ••••••••
...
Connection successfully activated (D-Bus active path: /org/freedesktop/...)

Contrairement à ce qui arrivait pour un lancement naïf de OpenVPN, le shell rend la main, et l’on peut passer à autre chose.

Vérifier et corriger le routage

Maintenant que le VPN fonctionne, le trafic passe-t-il par les machines voulues?

$ traceroute station.client.fr
traceroute to station.client.fr (IP.CLIENT.FR), 30 hops max, 60 byte packets
1  _gateway (10.0.0.1)  34.157 ms  35.347 ms  36.294 ms
2  192.168.0.254 (192.168.0.254)  37.949 ms  38.940 ms  40.570 ms
...
$ traceroute siteperso.free.fr
traceroute to siteperso.free.fr (......), 30 hops max, 60 byte packets
1  _gateway (10.0.0.1)  27.410 ms  27.796 ms  36.402 ms
2  192.168.0.254 (192.168.0.254)  37.354 ms  39.000 ms  40.193 ms
...

Ce qui fait une bonne et une mauvaise nouvelle:

  • station.client.fr est atteint via 192.168.0.254 qui est le routeur voulu (VPN du bureau)
  • siteperso.free.fr passe par le routeur, le chargeant inutilement

En quoi cela différait-il des routes configurées précédemment avec OpenVPN ?

$ ip route # avec OpenVPN seul
default via 192.168.1.1 dev enp3s0 proto dhcp metric 100
...
$ ip route # Avec nmcli
default via 10.0.0.1 dev tun0 proto static metric 50
default via 192.168.1.1 dev enp3s0 proto dhcp metric 100
...

Voilà la cause: nmcli a décrété que la route créée par vpnbureau serait celle par défaut;

Pour dire que non, il faut mettre le paramètre ipv4.never-default:

$ nmcli connection modify vpnbureau ipv4.never-default yes
$ nmcli connection up --ask vpn-bureau
...
$ traceroute station.client.fr
traceroute to station.client.fr (IP.CLIENT.FR), 30 hops max, 60 byte packets
1  livebox.home (192.168.1.1)  0.506 ms  7.133 ms  0.805 ms
2  80.10.234.161 (80.10.234.161)  4.352 ms  4.417 ms  4.503 ms
...
$ traceroute siteperso.free.fr
traceroute to siteperso.free.fr (...), 30 hops max, 60 byte packets
1  livebox.home (192.168.1.1)  0.964 ms  1.192 ms  1.360 ms
2  80.10.234.161 (80.10.234.161)  4.672 ms  4.774 ms  4.869 ms
...

Horreur! maintenant ça marche pour siteperso.free.fr, mais on ne passe plus par le VPN pour accéder aux machines du client. En effet, le VPN créé couvre pour l’instant les adresses 192.168.0.0/24, et pas les adresses des machines du client, qui elles sont en IP.CLIENT.FR/24 On pourrait corriger temporairement le tir avec ip route add IP.CLIENT.FR/24 tun0, mais comme l’idée est de ne pas avoir à le refaire, il vaut mieux modifier directement dans le profil:

$ nmcli connection modify vpnbureau ipv4.routes IP.CLIENT.FR/24
$ nmcli connection up --ask vpnbureau
...
$ traceroute station.client.fr
traceroute to station.client.fr (IP.CLIENT.FR), 30 hops max, 60 byte packets
1  _gateway (10.0.0.1)  34.157 ms  35.347 ms  36.294 ms
2  192.168.0.254 (192.168.0.254)  37.949 ms  38.940 ms  40.570 ms
...
$ traceroute siteperso.free.fr
traceroute to siteperso.free.fr (...), 30 hops max, 60 byte packets
1  livebox.home (192.168.1.1)  0.964 ms  1.192 ms  1.360 ms
2  80.10.234.161 (80.10.234.161)  4.672 ms  4.774 ms  4.869 ms
...

Ah, là c’est ce qu’on veut. Victoire, j’aurai sans doute les remerciements du routeur du bureau soulagé.

Résumons

La recette en bref

Si l’on retire les phases d’affichage et d’exploration, les commandes utiles se résument à ceci:

nmcli connection import type openvpn file vpnbureau.ovpn
nmcli connection modify vpnbureau +vpn.user-name loginvpn
nmcli connection modify vpnbureau +ipv4.routes IP.CLIENT.FR/24
nmcli connection modify vpnbureau +ipv4.never-default yes
nmcli connection up --ask vpnbureau

L’éditeur de connnections

La commande nmcli connection edit <conn> ouvre un éditeur interactif en ligne de commande que je trouve très commode:

  • les classiques [s]ave, [h]elp, [q]uit, ...
  • les commandes [g]oto (avec suggestions), et [b]ack pour naviguer entre les groupes d’options
  • la commande [d]escribe pour se renseigner sur l’option courante

Pour aller plus loin

A ce stade, vous voulez sûrement en savoir plus:

  • La page de howtoforge.com qui a commencé à me faire comprendre le fonctionnement de nmcli;
  • man openvpn: c’est tout bête, mais il est vraiment pédagogique;
  • nmcli <commande> help : là encore, à consulter avant de googueliser désespérément;