Wireguard, le VPN revisité (Linux)

Wireguard est une nouvelle technologie de VPN qui se veut plus sécurisé et plus perfomant que ses concurrents. Il est différent de l'IPSEC et de l'OPENVPN par sa facilité de mise en place et sa volonté de rester simple.

Wireguard, le VPN revisité (Linux)

Wireguard est une nouvelle technologie de VPN qui se veut plus sécurisé et plus performant que ses concurrents.

Il est différent de l'IPSEC et de l'OPENVPN par sa facilité de mise en place et sa volonté de rester simple.

Wireguard se veut aussi simple à configurer et à déployer que le protocole SSH, une session VPN se fait simplement en échangeant les clés publiques - exactement comme l'échange de clés SSH - tout le reste est géré de manière transparente par WireGuard.

L'échange de la clé publique à l'hôte voisin permet à Wireguard d'établir et d'échanger une Preshared-Key.  Un chiffrement assymétrique est donc appliqué pour échanger cette clé entre les deux hôtes, cette PSK est ensuite renouvelée régulièrement.

Wireguard a l'avantage de proposer une interface virtuelle  wg0 qui peut être configurée en utilisant les outils déjà présents sous Linux tels que ip(8) et ifconfig(8).

Nous verrons dans la suite de la présentation comment mettre en place des tunnels VPNs avec Wireguard.

Lexique :

  • private-key : clé privée associée à l'interface wireguard.
  • public-key : clé publique dérivée de la clé privée.
  • endpoint : adresses IPs des peers sur laquelle la session VPN est établie, un port UDP est aussi nécessaire.
  • allowed-ips : réseaux autorisés au sein du VPN.

Installation de wireguard (debian)

echo "deb http://deb.debian.org/debian/ unstable main" > /etc/apt/sources.list.d/unstable.list
printf 'Package: *\nPin: release a=unstable\nPin-Priority: 150\n' > /etc/apt/preferences.d/limit-unstable
apt update
apt install wireguard

Postulat de base  

Schema interconnexion Wireguard

Chacun des 3 sites ci-dessus se trouvent dans des pays différents et sont séparés par des réseaux dits "publiques", ils ont chacun une IP publique attribuée (ici représenté par le réseau 192.168.1.0/24).

Nous établirons des sessions VPNs entre ces trois sites grâce au protocole Wireguard, pour ensuite annoncer les réseaux clients (172.16.1.0/24, 10.0.2.0/24, 77.66.55.0/24) et enfin nous configurerons la sortie Internet via l'un des sites (Moly).

Dans cet exemple, chacun des sites va établir 2 sessions VPN vers les 2 autres voisins car ceux ci sont directement joignables. Dans certains cas ce n'est pas possible (réseau naté, réseau mobile etc.) il faut alors choisir un site accessible publiquement qui aura le rôle de Hub.

Les différentes étapes à réaliser :

  1. Mise en place de tous les peers VPN; giant <-> raspi, giant <-> moly etc.
  2. Routage des réseaux clients des 3 sites.
  3. Mise en place de la sortie internet.

Nous aurons ainsi l'occasion de jouer avec le routage et l'iptable sous Linux (Debian dans notre cas).

Mise en place des sessions VPN entre les trois sites

Tout d'abord nous devons générer une clé privée et sa clé publique associée sur l'ensemble des endpoints (peers):

wg genkey | tee private.key | wg pubkey > public.key

Nous devons ensuite créer sur chacune des machines une interface virtuelle wg0 qui sera capable d'établir autant de peer que l'on souhaite.

Nous associons ensuite la clé privée à l'interface virtuelle wg0.

Cela peut-être fait de deux façons, la première est de rentrer chacune des commandes manuellement, la seconde est d'utiliser le script wg-quick en se basant sur un fichier de configuration. Nous verrons les deux cas.

Sur Moly et Giant (wg-quick) :

Le script wg-quick de Wireguard s'appuie sur un fichier de configuration dans lequel nous devons définir les paramètres de l'interface wg0 et les informations des peers (public-keys, endpoint, allowed-ips). Il améliore grandement le déploiement et permet dans un seul fichier de définir l'ensemble des paramètres.

Respectivement ces deux machines auront une interface virtuelle wg0 avec une clé privée, et deux peers avec leurs clés publiques associées :

#Giant
[Interface]
Address = 172.16.1.1/24
SaveConfig = true
ListenPort = 5555
PrivateKey = UCQhBHQF08IKvMdUXl7IPL8+iPSx41tO4J3q0e1bwGE=

#Moly
[Peer]
PublicKey = p65NVxgVdoeIHQfi/Tmp2MgYDJLjGo0TUBz7iatVXBw=
AllowedIPs = 172.16.1.2/32
Endpoint = 192.168.1.162:5555

#Raspi
[Peer]
PublicKey = KY0qEDi4bOKDxqKj9yt6kczUuZpYetOyQNKkXRfc+Uw=
AllowedIPs = 172.16.1.3/32
Endpoint = 192.168.1.200:5555

On lance ensuite le script qui aura pour rôle de créer l'interface wg0, d'associer l'adresse IP et la clé privée, puis enfin de configurer les peers et d'ajouter les routes.

wg-quick up wg0

On vérifie que la session entre Moly et Giant fonctionne :

La commande wg permet d'afficher les statistiques des peers.

Création de l'interface et association des peers manuellement :

Sur raspi nous n'utiliserons pas la commande wg-quick, nous ferons la configuration manuellement :

Création de l'interface virtuelle :

ip link add dev wg0 type wireguard

Association de l'ip sur l'interface virtuelle :

ip address add dev wg0 172.16.1.3/24

Configuration du peer vers Moly :

wg set wg0 listen-port 5555 private-key private.key peer p65NV.. allowed-ips 172.16.1.2/32 endpoint 192.168.1.162:5555
Il est aussi possible d'utiliser le fichier /etc/network/interfaces afin d'établir la session VPN au démarrage du poste.

Exemple pour moly dans /etc/network/interfaces :

auto wg0
iface wg0 inet static
        address 172.16.1.2
        netmask 255.255.255.0
        pre-up ip link add $IFACE type wireguard
        pre-up wg setconf $IFACE /etc/wireguard/$IFACE.conf
        post-down ip link del $IFACE
	post-up ip route add 77.66.55.0/24 dev wg0

Le fichier wg0.conf doit être rempli avec les informations du peer (endpoint, allowed-ips, public_key etc.) comme vu plus haut.


Si l'on admet que le script wg-quick ait été utilisé sur tous les peers, voici le contenu du fichier wg0.conf et les clés privées/publiques des 3 sites :

Le routage entre les différents sites

Pour imiter le réseau client de chacun des sites nous créeons des interfaces loopbacks dans /etc/network/interfaces.

auto lo:10
iface lo:10 inet static
	address 10.0.2.1
	netmask 255.255.255.0

Par défaut, et lorsque l'on utilise le script wg-quick, les routes des réseaux allowed-ips sont automatiquement ajoutées.

Si l'on ajoute un peer manuellement il faudra alors penser à ajouter manuellement les routes associées.
Ajout des réseaux clients dans wg0.conf - allowed-ips

Route par défaut

Nous allons maintenant considérer Raspi et Giant comme des clients, l'ensemble des flux seront routés vers Molly pour accéder à internet.

Sur le client :

[Peer]
PublicKey = p65NVxgVdoeIHQfi/Tmp2MgYDJLjGo0TUBz7iatVXBw= 
AllowedIPs = 0.0.0.0/0
Endpoint = 192.168.1.162:5555

On relance ensuite wg-quick qui aura pour rôle de remplacer la route par défaut par une nouvelle à destination du tunnel wg0.

Sur le serveur, on NAT les flux provenants des réseaux clients :

On active le routage : echo 1 > /proc/sys/net/ipv4/ip_forward

iptables -t nat -A POSTROUTING -s 77.66.55.0/24 -j MASQUERADE

L'ensemble des flux sont maintenant routés et chiffrés depuis les clients vers le serveur Moly.

Capture de paquet

Ci-dessous une capture de paquet entre Giant et Raspi, on observe l'encapsulation UDP sur le port 5555.

Wireguard encapsulation