Introduction

Quand vous installez un ensemble de service, vous êtes parfois tenté de faire sortir sur le réseau public vos interfaces d'administration. Par exemple, lors d'articles précédents, nous avons vu comment configurer Traefik avec nos outils de supervision et comment les rendre accessible depuis l'extérieur afin de les consulter.

Nous aurions pu très bien ne pas faire cela, en faisant sortir uniquement ce qui est public (blog, site perso, etc.) et accéder aux interfaces d'administration uniquement en local (traefik, grafana, prometheus, etc.). Ce qui permet de ne pas exposer les données sensibles, néanmoins il est possible d'accéder à ces contenus critiques quel que soit l'endroit via un VPN et c'est ce que nous allons mettre en place dans cet article.

Le VPN qui est l'abréviation de Virtual Private Network, soit dans la langue de Molière : réseau privé virtuel qui permet d'établir un tunnel sécurisé entre un client et un serveur de manière à protéger les communications entre ces deux interlocuteurs.

Ce qui permet au client de faire comme s'il était sur le réseau privé du serveur VPN, et donc, d'accéder à l'ensemble du réseau privé via quelques règles de routage (et surtout en fonction des contraintes de sécurité mises en place).

Enfin, un VPN en plus d'accéder au réseau privé, permet d'avoir l'IP publique du serveur pour contourner des restrictions régionales par exemple ou masquer votre identité c'est-à-dire votre adresse IP.

Pourquoi Wireguard ?

Wireguard est un protocole VPN qui est décrit comme fiable, sécurisé et très rapide. Il est intégré dans le noyau Linux depuis la version 5.6 (ce qui améliore considérablement les performances). Il est Open Source et le projet se découpe en plusieurs dépôts de code pour l'ensemble des systèmes d'exploitations / terminaux mobiles. Le projet principal ne contient que 4 000 lignes de code, ce qui permet des audits rapides et facilite la détection de faille de sécurité.

Wireguard utilise pour chiffrer ses connexions des algorithmes de cryptographie avancés : Curve25519, ChaCha20, Poly1305, BLAKE2, SipHash24, HKDF.

De plus, il prend en charge l’itinérance, ce qui permet de changer de réseau (passer du Wi-Fi à la 4G par exemple) sans perdre la connexion.

Il est très facile à installer et à mettre en place pour une utilisation personnelle.

Enfin, Wireguard utilise le mot interface pour le serveur et chaque client est un peer.

Installer Wireguard

Dans la suite de l'article, je vais vous montrer comment installer Wireguard sur un raspberry afin de pouvoir créer une connexion VPN sur le réseau privé, c'est pourquoi il est nécessaire de créer une règle au niveau de sa box pour faire sortir le port de Wireguard sur le réseau public et l'atteindre de l'extérieur via l'adresse IP publique de son fournisseur d'accès.

Vous pouvez télécharger le dépôt de code qui permettra d'installer Wireguard avec Ansible à cette adresse :

https://github.com/axinorm/wireguard

Si vous n'êtes pas trop familier avec Ansible, vous pouvez très bien suivre l'installation manuelle qui se trouve dans le fichier INSTALL.md.

Le playbook Ansible va faire plusieurs choses :

  • Installer les paquets nécessaires à l'exécution de Wireguard ;
  • Initialiser le dossier /etc/wireguard ;
  • Créer les clés publiques et privées pour le serveur ;
  • Créer les clés publiques et privées pour l'ensemble des clients ;
  • Générer la configuration du serveur /etc/wireguard/wg0.conf ;
  • Générer la configuration pour les clients wg0-<nom du client>.conf ;
  • Récupérer les configurations des clients sur la machine qui exécute Ansible ;
  • Genérer un QRCode si qrencode est installé pour faciliter la configuration des clients ;
  • Modifier les paramètres noyaux pour l'ip forward ;
  • Démarrer l'interface réseau wg0 pour démarrer notre serveur VPN et l'activer pour le prochain redémarrage.

Configuration

Avant d'exécuter quoi que ce soit, il est nécessaire de configurer différentes valeurs :

Définition des variables globales dans le fichier inventory/groups_vars/all.yml :

---
# Plage d'adresse du réseau VPN
range_ip_addresses: 10.10.0.0/24
# Port de Wireguard
port: 51820
 # IP du DNS, ici j'utilise Quad9
dns_ip: 9.9.9.9
# Interface à utiliser pour la connexion VPN
network_interface: eth0
# Définition du Keep Alive
keep_alive: 25

# Adresse publique de votre box
public_ip_address: x.x.x.x

# Définition des clients sous forme de liste YAML
clients: 
  # Nom du client
- name: client1 
  # IP associé en fonction du réseau VPN définit plus haut
  ip_address: 10.10.0.1/32 
...

On va ensuite modifier notre fichier inventaire inventory/hosts pour spécifier sur quelle machine on va installer Wireguard :

[raspberry]
mon_rpi ansible_host=<ip rpi> ansible_port=22 ansible_ssh_user=<utilisateur rpi>

Comme vous pouvez le voir, Wireguard est assez simple à paramétrer, il faut un fichier de configuration côté serveur /etc/wireguard/wg0.conf qui contient la clé privée et d'autres informations essentielles avec une rubrique Peer qui est répétée pour chaque client, c'est ce que l'on voit ci-dessous avec l'instruction for.

Fichier wg0.conf.j2 :

[Interface]
# Plage d'adresse privée allouée pour le VPN
Address = {{ range_ip_addresses }}
# Port d'écoute
ListenPort = {{ port }}  
# IP du DNS ici Quad9
DNS = {{ dns_ip }}
# Clé privée du serveur
PrivateKey = {{ server_private_key.content | b64decode }}
# Règles de routage en fonction de l'interface
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o {{ network_interface }} -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o {{ network_interface }} -j MASQUERADE

# On vient créer une section Peer pour chaque client
{% for client in clients %}
[Peer]
# {{ client.name }}
PublicKey = {{ lookup('vars', client.name + '_public_key').content | b64decode }}
# IP pour le {{ client.name }}
AllowedIPs = {{ client.ip_address }}
PersistentkeepAlive = 60
{% endfor %}

Le fichier pour le Peer : /etc/wireguard/wg0-<nom du client>.conf contient la clé publique du serveur et la clé privée du client ainsi que son adresse IP.

Fichier wg0.conf.j2 :

[Interface]
# Client
# IP 
Address = {{ item.ip_address }}
# Clé privée
PrivateKey = {{ lookup('vars', item.name + '_private_key').content | b64decode }}

[Peer]
# Clé publique du serveur
PublicKey = {{ server_public_key.content | b64decode }}

# IP publique pour atteindre le VPN
Endpoint = {{ public_ip_address }}:{{ port }}
# Permettre à tout le trafic d'être routé vers le VPN
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = {{ keep_alive }}

Si vous souhaitez obtenir un QRCode pour simplifier la configuration de vos clients, il faudra installer qrencode qui créera un fichier .png pour chaque client.

Exécution du playbook

Une fois l'ensemble des fichiers configurés avec les bonnes valeurs, il ne reste plus qu'à jouer notre playbook :

ansible-playbook site.yml --inventory=inventory/hosts

Une fois l'ensemble des tâches exécutées, vous pouvez exécuter cette commande sur le serveur :

$ wg

Et vous devriez avoir ce genre de retour :

interface: wg0
  public key: xxx
  private key: (hidden)
  listening port: 51820

peer: /xxx
  endpoint: xxx
  allowed ips: 10.10.0.1/32
  latest handshake: 1 minute, 40 seconds ago
  transfer: 5.16 KiB received, 88.16 KiB sent
  persistent keepalive: every 1 minute

Conclusion

Wireguard est une solution VPN très rapide à mettre en place, il permet d'avoir un accès sur ses machines sans avoir à faire sortir l'ensemble des interfaces administrations ou accès SSH.

C'est une solution assez jeune mais performante qui permet d'avoir un tunnel sécurisé sans se casser la tête sur la configuration.

L'installation que je vous ai partagée met moins de deux minutes à s'exécuter avec Ansible, rapide non ?