Monter un VPN WireGuard sur un VPS en 20 minutes

WireGuard tient en une centaine de lignes de configuration et sature un lien gigabit sur un VPS à 8,50 $. Voici le montage complet, serveur et clients.

Tunnel chiffré reliant un poste client à un serveur

WireGuard vit dans le noyau Linux depuis la version 5.6. Il n'a ni négociation complexe, ni certificats, ni démon volumineux : une paire de clés par machine, un fichier de configuration d'une vingtaine de lignes, et un tunnel qui sature un lien gigabit sans mobiliser un cœur entier.

L'usage le plus courant sur un VPS : sortir sur Internet depuis une adresse IP stable, atteindre un réseau privé, ou relier plusieurs machines sans les exposer. Le montage ci-dessous couvre le premier cas, dont les deux autres sont des variantes.

1. Installer WireGuard

bash
sudo apt update
sudo apt install -y wireguard qrencode

qrencode servira à enrôler les téléphones sans recopier une clé à la main.

2. Générer les clés

Chaque participant du tunnel possède sa paire. La clé privée reste sur sa machine, la clé publique est distribuée. Le umask 077 évite qu'un autre compte du serveur puisse lire la clé privée.

bash
umask 077
wg genkey | sudo tee /etc/wireguard/serveur.key | wg pubkey | sudo tee /etc/wireguard/serveur.pub

# et une paire par client
wg genkey | tee client-laptop.key | wg pubkey > client-laptop.pub

3. Activer le routage

Un serveur Linux ne transfère pas de paquets par défaut. Activez-le pour les deux familles d'adresses, de façon persistante.

bash
sudo tee /etc/sysctl.d/99-wireguard.conf <<'EOF'
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
EOF

sudo sysctl --system

4. Configurer l'interface serveur

On choisit un préfixe privé pour le tunnel : 10.8.0.0/24 en IPv4 et un ULA fd42:42:42::/64 en IPv6. Repérez d'abord le nom de votre interface publique.

bash
ip -brief addr   # souvent ens3, eth0 ou enp1s0
bash
sudo tee /etc/wireguard/wg0.conf <<'EOF'
[Interface]
Address    = 10.8.0.1/24, fd42:42:42::1/64
ListenPort = 51820
PrivateKey = <contenu de /etc/wireguard/serveur.key>

PostUp   = nft add table inet wg; \
           nft add chain inet wg postrouting { type nat hook postrouting priority 100 \; }; \
           nft add rule inet wg postrouting oifname "ens3" masquerade
PostDown = nft delete table inet wg

[Peer]
# laptop
PublicKey  = <contenu de client-laptop.pub>
AllowedIPs = 10.8.0.2/32, fd42:42:42::2/128
EOF

sudo chmod 600 /etc/wireguard/wg0.conf

Une table nftables dédiée plutôt que des règles iptables éparpillées : PostDown supprime alors tout le bloc d'un coup, sans laisser de règle orpheline après un redémarrage du tunnel. Adaptez oifname au nom réel de votre interface.

5. Ouvrir le port et démarrer

bash
sudo ufw allow 51820/udp
sudo ufw route allow in on wg0 out on ens3

sudo systemctl enable --now wg-quick@wg0
sudo wg show

wg show doit lister l'interface, son port d'écoute et le pair déclaré. Un pair sans latest handshake est simplement un client qui ne s'est pas encore connecté.

6. Configurer un client

Sur le poste, un fichier symétrique. AllowedIPs = 0.0.0.0/0, ::/0 fait passer tout le trafic par le tunnel ; pour n'y router qu'un réseau précis, remplacez cette ligne par le préfixe concerné.

wg0.conf
[Interface]
Address    = 10.8.0.2/32, fd42:42:42::2/128
PrivateKey = <contenu de client-laptop.key>
DNS        = 9.9.9.9, 2620:fe::fe

[Peer]
PublicKey           = <contenu de /etc/wireguard/serveur.pub>
Endpoint            = 198.51.100.42:51820
AllowedIPs          = 0.0.0.0/0, ::/0
PersistentKeepalive = 25

PersistentKeepalive maintient l'association ouverte à travers les NAT domestiques et mobiles. Sans lui, le tunnel fonctionne du client vers le serveur mais pas dans l'autre sens après quelques minutes d'inactivité.

7. Enrôler un téléphone

L'application WireGuard lit un QR code contenant la configuration complète. Rien à taper, aucune clé à transmettre par messagerie.

bash
qrencode -t ansiutf8 < client-telephone.conf

Chaque nouveau client se déclare côté serveur par un bloc [Peer] supplémentaire, avec sa propre adresse dans AllowedIPs :

bash
sudo wg set wg0 peer <clé publique du client> allowed-ips 10.8.0.3/32,fd42:42:42::3/128
sudo wg-quick save wg0

8. Dépannage

  • Aucune poignée de main : le port 51820/UDP n'est pas joignable. Testez avec nc -zvu 198.51.100.42 51820 et vérifiez UFW.
  • Poignée de main mais pas d'Internet : le masquage NAT ou le transfert IP manque. Contrôlez sysctl net.ipv4.ip_forward et sudo nft list table inet wg.
  • Le nom de domaine ne résout pas : la directive DNS du client est absente ou pointe vers un résolveur inaccessible depuis le tunnel.
  • Fuite IPv6 : si le client dispose d'IPv6 native et que AllowedIPs ne contient pas ::/0, une partie du trafic sort hors du tunnel.

Un dernier réflexe : sudo wg show wg0 latest-handshakes donne l'horodatage de la dernière poignée de main par pair. C'est l'indicateur le plus rapide pour distinguer un problème de réseau d'un problème de configuration.