Installer un VPN Wireguard sur un serveur Linux Debian (ainsi qu'un Raspberry Pi)

Le but de cet article est de vous permettre de créer un VPN Wireguard sur votre propre serveur et d'être capable de l'administrer, c'est à dire ajouter facilement de nouveaux profils pour se connecter à ce VPN. Vous pourrez ainsi :

  • Bénéficier de l'adresse IP V4 et V6 ainsi que de la localisation de votre serveur.
  • Communiquer avec les autres appareils connectés à ce serveur VPN.
  • N'autoriser certains services du serveur qu'aux appareils connectés au VPN.

Et d'autres cas d'usage plus ou moins avancés que je partagerai dans de futurs articles.

À noter que j'utilise un certain nombre d'automatisations et de variables pour accélerer et simplifier la création de certains fichiers, libre à vous de réaliser cela à la main.

00 | Pré-requis

  • Avoir un serveur Linux Debian ou bien un Raspberry Pi à jour.
  • Un nom de domaine ou un sous-domaine associé à une adresse IP V4 et/ou V6 fixe(s) qui pointe vers le serveur.
  • Avoir les droits sudo avec l'utilisateur qui va réaliser l'installation.
  • Définir un numéro de port UDP qui sera attribué à Wireguard.

01 | Ouvrir le port UDP dédié à Wireguard

J'ai choisi pour cet article le port par défaut 51820 mais je vous conseille d'en choisir un autre par sécurité.

Action à réaliser avec votre logiciel de pare-feu, avec iptables par exemple :

sudo iptables -A INPUT -p udp –dport 51820 -j ACCEPT

Attention à rendre la règle persistente, avec une solution comme iptables-persistent, pour ne pas perdre cette configuration au redémarrage de votre serveur.

Personnellement j'utilise ufw qui est plus simple à prendre en main pour une configuration de pare-feu simple et mémorise par défaut les règles au redémarrage du serveur. Voici ce que donne la commande avec ufw :

sudo ufw allow 51820/udp

02 | Activer la redirection IPv4/IPv6 au niveau système

Les instructions ci-dessous permettre d'activer les redirections IPv4 et IPv6 au niveau du système :

sudo sed -r -i "s/^\#net\.ipv4\.ip\_forward\=1$/net.ipv4.ip_forward=1/" /etc/sysctl.conf && \
sudo sed -r -i "s/^\#net\.ipv6\.conf\.all\.forwarding\=1$/net.ipv6.conf.all.forwarding=1/" /etc/sysctl.conf && \
sudo sysctl -p

Nous avons simplement éditer le fichier de configuration /etc/sysctl.conf avec la commande sed puis nous avons rechargé le service du système de configuration globale pour prendre en compte ces nouveaux paramètres. Sans cela, la communication Internet ne serait pas effective une fois connecté au VPN.

03 | Installer le paquet Wireguard

sudo apt install wireguard

Celui-ci est disponible par défaut avec les sources officielles de Debian.

04 | Créer les clés de sécurité du VPN Wireguard

privateKey=$(wg genkey | sudo tee /etc/wireguard/private.key) && \
sudo chmod go= /etc/wireguard/private.key && \
publicKey=$(sudo cat /etc/wireguard/private.key | wg pubkey | sudo tee /etc/wireguard/public.key)

Nous avons ici créé la clé privée private.key ainsi que la clé publique public.key qui se trouvent chacune dans le dossier /etc/wireguard, avec une sécurité accrûe sur la clé privée qui n'est lisible uniquement que par le système. Nous mémorisons dans la session actuelle les valeurs de chacune de ces clés dans les variables privateKey et publicKey qui nous serons utiles pour la suite de l'installation.

05 | Créer le fichier de configuration du VPN Wireguard

Nous allons dans un premier temps définir les valeurs des variables suivantes :

  • Le numéro de port portNumber (dédié à Wireguard)
    • Attention à bien utiliser la même valeur que précedemment ou laisser vide ce champ pour laisser la valeur par défaut à 51820.
  • L'interface réseau externe interfaceName (utilisée pour communiquer avec Internet)
    • Le nom de l'interface sera récupérée automatiquement.
  • Le sous-réseau IPv4 ipv4Subnet (dédié à Wireguard)
    • Attention à bien utiliser un format d'un réseau IPv4 privé, en omettant le dernier chiffre, si vous ne renseignez rien, la valeur par défaut sera 10.0.1..
  • Le sous-réseau IPv6 ipv6Subnet (dédié à Wireguard)
    • Le sous réseau IPv6 sera généré automatiquement.

nous allons utiliser ces variables juste après pour créer le fichier de configuration.

while ! (echo "$domainNameOrIpAddress" | grep -qP "^((.+\.\w{2,63})|(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}))$"); do \
read -p "Domain name (or public IP Address): " domainNameOrIpAddress \
; done && \
while ! (echo "$portNumber" | grep -qP "^\d{1,5}$"); do \
read -p "Port number (default: 51820): " portNumber && \
portNumber=${portNumber:-51820} \
; done && \
interfaceName=$(ip route | head -1 | cut -d " " -f5) && \
while ! (echo "$ipv4Subnet" | grep -qP "^\d{1,3}\.\d{1,3}\.\d{1,3}\.$"); do \
read -p "IPv4 subnet (default: 10.0.1.): " ipv4Subnet && \
ipv4Subnet=${ipv4Subnet:-10.0.1.} \
; done && \
ipv6Subnet=$(echo -e 'fd'$(echo -e $(date +%s%N)$(cat /var/lib/dbus/machine-id) | sha1sum | awk '{print $1}' | cut -c 31-)':' | sed 's/.\{4\}/&:/g')

Nous allons maintenant créer le fichier de configuration principal du VPN Wireguard en s'appuyant sur les variables générées précedemment.

Par convention, le fichier de configuration principal du serveur s'appelle wg0.conf. Vous êtes libres de choisir un autre nom si vous préférez. Pour cela, modifier simplement les valeurs au niveau des commandes sudo tee et sudo chmod sur la dernière ligne ci-dessous.

echo -e "[Interface] \n\
Address = ${ipv4Subnet}1/24 \n\
Address = ${ipv6Subnet}1/64 \n\
SaveConfig = true \n\
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -I FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o $interfaceName -j MASQUERADE \n\
PostUp = ip6tables -I FORWARD -i %i -j ACCEPT; ip6tables -I FORWARD -o %i -j ACCEPT; ip6tables -t nat -A POSTROUTING -o $interfaceName -j MASQUERADE \n\
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o $interfaceName -j MASQUERADE \n\
PostDown = ip6tables -D FORWARD -i %i -j ACCEPT; ip6tables -D FORWARD -o %i -j ACCEPT; ip6tables -t nat -D POSTROUTING -o $interfaceName -j MASQUERADE \n\
ListenPort = $portNumber \n\
PrivateKey = $privateKey"
| sudo tee /etc/wireguard/wg0.conf > /dev/null && sudo chmod go= /etc/wireguard/wg0.conf

Nous avons donc renseigné dans le fichier /etc/wireguard/wg0.conf les valeurs du sous-réseau IPv4 & IPv6, créer les règles iptables indispensables au lancement ou l'arrêt du VPN pour permettre la bonne communication entre les clients et le VPN Wireguard, nous avons indiqué le numéro du port, renseigné la clé privée du VPN Wireguard et nous avons enfin sécuriser ce fichier.

Vous devriez pouvoir afficher ce fichier grâce à la commande suivante :

sudo cat /etc/wireguard/wg0.conf

Et vérifier que le contenu ressemble à cet exemple :

[Interface]
Address = 10.0.1.1/24
Address = fdc8:1911:07cd::1/64
SaveConfig = true
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -I FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostUp = ip6tables -I FORWARD -i %i -j ACCEPT; ip6tables -I FORWARD -o %i -j ACCEPT; ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
PostDown = ip6tables -D FORWARD -i %i -j ACCEPT; ip6tables -D FORWARD -o %i -j ACCEPT; ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
ListenPort = 51820
PrivateKey = <contenu-du-fichier-/etc/wireguard/private.key>

Si vous constatez une erreur ou une absence, vous pouvez bien entendu éditer le fichier à la main en utilisant la commande sudo vi ou sudo nano sur le fichier /etc/wireguard/wg0.conf.

05 | Activer le VPN Wireguard au démarrage du serveur et lancer le VPN immédiatement

sudo systemctl enable wg-quick@wg0 && \
sudo systemctl start wg-quick@wg0

Vérifiez le bon fonctionnement grâce à la commande suivante :

sudo systemctl status wg-quick@wg0

Vous devriez voir le statut "active" en vert.

Vérifiez également que l'interface virtuelle de Wireguard a bien été créée :

sudo ifconfig wg0

Si tout est bon, passons maintenant à la suite, à savoir la configuration d'un client qui pourra se connecter à ce VPN.

06 | Créer les clés de sécurité du client

sudo mkdir -p /etc/wireguard/.clients && \
clientNumber=$((2 + $(sudo ls /etc/wireguard/.clients | grep --count \.conf || true))) && \
clientId=$(printf "%02d" $clientNumber) && \
clientPrivateKey=$(wg genkey | sudo tee /etc/wireguard/.clients/client-${clientId}-private.key) && \
sudo chmod go= /etc/wireguard/.clients/client-${clientId}-private.key && \
clientPublicKey=$(sudo cat /etc/wireguard/.clients/client-${clientId}-private.key | wg pubkey | sudo tee /etc/wireguard/.clients/client-${clientId}-public.key)

Nous avons ici créé ou vérifié l'existance du dossier /etc/wireguard/.clients, nous avons également vérifier si un ou plusieurs clients existaient déjà, dans ce cas nous incrémentons l'ID du client en en comptant l'ensemble des clients déjà créés. Sinon, on partira de 02. (01 étant si l'on veut déjà attribué au VPN, on y reviendra plus tard, notamment sur la désignation des adresses IP). Par exemple si j'ai déjà deux clients de créés, le nouveau client aura l'ID "04", sa clé privée sera /etc/wireguard/.clients/client-04-private.key.

07 | Créer le fichier de configuration du client

echo -e "[Interface] \n\
PrivateKey = $clientPrivateKey \n\
Address = ${ipv4Subnet}${clientNumber}/24, ${ipv6Subnet}${clientNumber}/64 # IPv4 & IPv6 that will be defined for the Wireguard's client \n\
DNS = ${ipv4Subnet}1/24, ${ipv6Subnet}1/64 \n\
# DNS = 1.1.1.1, 2606:4700:4700::1111 \n\
\n\
[Peer] \n\
PublicKey = $publicKey \n\
AllowedIPs = 0.0.0.0/0, ::0 # To be used to tunnel all the traffic through the VPN between the client & the server \n\
# AllowedIPs = ${ipv4Subnet}.0/24, ${ipv6Subnet}/64 # To be used to be only connected remotely to the server, but not sending through all the traffic \n\
Endpoint = ${domainName}:{portNumber} # Endpoint to be configure as domain name or IP plus the port that is listened by Wireguard's server \n\
# PersistentKeepalive = 60 # To keep the connection alive in case of connectivity issues"
| sudo tee /etc/wireguard/.clients/client-${clientId}.conf > /dev/null && sudo chmod go= /etc/wireguard/.clients/client-${clientId}.conf

Plusieurs remarques ici, la partie DNS part du principe que vous avez déjà un service DNS fonctionnel hébergé sur votre serveur, ce que je vous recommande chaudement. Si ce n'est pas le cas, vous pouvez remplacer la ligne par DNS = 1.1.1.1, 2606:4700:4700::1111 si vous souhaitez utiliser le DNS public de Cloudflare par exemple. Libre à vous d'indiquer le DNS public de votre choix.

Pour la partie AllowedIPs, je pars du principe que l'on souhaite en général que tout le trafic Internet passe par le serveur une fois connecté au VPN Wireguard. Si vous avez un besoin différent, à savoir simplement être connecté au serveur en mode "local" mais sans vouloir passer tout le trafic par le serveur, vous pouvez décommenter la seconde ligne AllowedIPs et commenter la première. Enfin, si vous rencontrez des problèmes d'instabilité, vous pouvez tenter de décommenter la dernière ligne PersistentKeepalive, et ajouter à nouveau cette configuration sur votre appareil.

Votre fichier devrait ressembler à cela en faisant sudo cat /etc/wireguard/.clients/client-${clientId}.conf :

[Interface]
PrivateKey = <contenu-du-fichier-/etc/wireguard/.clients/client-${clientId}-private.key>
Address = 10.0.1.2/24, fdc8:1911:07cd::2/64 # IPv4 & IPv6 that will be defined for the Wireguard's client
DNS = 10.0.1.1, fdc8:1911:07cd::1
[Peer]
PublicKey = <contenu-du-fichier-/etc/wireguard/public.key>
AllowedIPs = 0.0.0.0/0, ::0 # To be used to tunnel all the traffic through the VPN between the client & the server
# AllowedIPs = 10.0.1.0/24, fdc8:1911:07cd::/64 # To be used to be only connected remotely to the server, but not sending through all the traffic
Endpoint = wg.domain.tld:51820 # Endpoint to be configure as domain name or IP plus the port that is listened by Wireguard's server
# PersistentKeepalive = 60 # To keep the connection alive in case of connectivity issues

08 | Autoriser le nouveau client à se connecter sur le VPN Wireguard

Grâce à cette commande, le client sera autorisé à se connecter au VPN Wireguard :

sudo wg set wg0 peer $clientPublicKey allowed-ips ${ipv4Subnet}${clientNumber},${ipv6Subnet}${clientNumber}

Pour vérifier que l'autorisation a bien été prise en compte, utilisez cette commande :

sudo wg

Il ne reste maintenant qu'à ajouter la configuration de ce client sur votre appareil, que ce soit un ordinateur ou un mobile.

09 | Installer Wireguard sur votre appareil

Avant de pouvoir vous connecter au VPN Wireguard, vous devez installer sur votre ordinateur ou téléphone mobile le logiciel Wireguard qui vous permettra d'ajouter la configuration client que nous avons créé précédemment.

09.01 | Se connecter à Wireguard sur ordinateur

Une fois le logiciel installé, il ne vous reste plus qu'à copier le fichier /etc/wireguard/.clients/client-${clientId}.conf ou bien copier le contenu de ce fichier au moment d'ajouter une connexion via le logiciel nouvellement Wireguard installé sur l'ordinateur. Pensez bien à supprimer le fichier qui aurait été copié sur votre ordinateur, une fois la configuration effectuée, par mesure de sécurité.

09.02 | Se connecter à Wireguard sur mobile

Une fois l'application mobile installée, vous pouvez facilement ajouter une nouvelle connexion au VPN en scannant un QR Code. Pour cela, nous pouvons générer un QR code directement via la ligne de commande du serveur en installant déjà l'utilitaire qrencode :

sudo apt install qrencode

Puis pour générer et afficher le QR code à l'écran :

sudo cat /etc/wireguard/.clients/client-${clientId}.conf  | qrencode -t ansiutf8

10 | Vérifier votre connexion au VPN Wireguard

Vous devriez maintenant être capable de vous connecter au VPN Wireguard installé sur votre serveur depuis votre appareil.

Pour vérifier votre adresse IP, je vous invite à vous connecter sur le célèbre site whatismyip.com.


Pour toute question, clarification ou remarque, n'hésitez pas à me contacter sur Mastodon.