<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

 <title>blog.folf.fr</title>
 <link href="https://blog.folf.fr/atom.xml" rel="self"/>
 <link href="https://blog.folf.fr/"/>
 <updated>2026-05-06T08:27:27+00:00</updated>
 <id>https://blog.folf.fr</id>
 <author>
   <name>Tristan BRINGUIER</name>
   <email>blog@folf.fr</email>
 </author>

 
 
 
 
 <entry>
   <title>Naim Uniti — API HTTP</title>
   <link href="https://blog.folf.fr/snippets/2026/03/16/naim-uniti/"/>
   <updated>2026-04-27T08:19:13+00:00</updated>
   <published>2026-04-22T14:16:25+00:00</published>
   <id>https://blog.folf.fr/snippets/2026/03/16/naim-uniti/</id>
   <content type="html">&gt; [!NOTE]
&gt; Il n&apos;existe **aucune documentation officielle** de Naim Audio pour cette API. Tout a été reverse-engineered depuis le trafic réseau de l&apos;app Naim et confirmé par des intégrations open-source (Home Assistant, Homebridge, Unfolded Circle, etc.).

## Connexion

- **Port HTTP** : `15081`
- **Port TCP streaming** : `4545` (push JSON temps réel, pas HTTP)
- **Pas d&apos;authentification** (réseau local uniquement)
- **URL de base** : `http://&lt;IP&gt;:15081`
- **Hostname mDNS** : `&lt;modèle&gt;-&lt;serial&gt;.local`

```
http://192.168.1.42:15081
```

## Informations système

- ```shell
  curl http://&lt;IP&gt;:15081/
  ```

  - Retourne la version de l&apos;API, le changestamp, la classe (`object.api.support`), la charge CPU.

- ```shell
  curl http://&lt;IP&gt;:15081/system
  ```

  - Infos complètes : `model`, `hostname`, `hardwareSerial`, `hardwareType`, `appVer` (firmware), `ipAddress`, `kernel`, `machine`, `udid`, `displayType`, `firstTimeSetupComplete`.

## Alimentation

- ```shell
  curl http://&lt;IP&gt;:15081/power
  ```

  - État actuel : `system` (`on` / `lona`), `state` (`on` / `standby`), `powerMode`, `serverMode`, `standbyTimeout`.

- ```shell
  curl -X PUT &quot;http://&lt;IP&gt;:15081/power?system=on&quot;
  ```

  - Allumer l&apos;appareil.

- ```shell
  curl -X PUT &quot;http://&lt;IP&gt;:15081/power?system=lona&quot;
  ```

  - Mettre en veille. La valeur est bien `lona`, pas `off` ni `standby`.

## Volume / Audio

- ```shell
  curl http://&lt;IP&gt;:15081/levels/room
  ```

  - Retourne `volume` (0-100), `mute` (0/1), `balance` (-50 à 50), `headphoneDetect` (0/1).

- ```shell
  curl http://&lt;IP&gt;:15081/levels
  ```

  - Vue d&apos;ensemble des niveaux audio (idem + `mode`).

- ```shell
  curl -X PUT &quot;http://&lt;IP&gt;:15081/levels/room?volume=45&quot;
  ```

  - Régler le volume (entier, 0 à 100).

- ```shell
  curl -X PUT &quot;http://&lt;IP&gt;:15081/levels/room?mute=1&quot;
  ```

  - Couper le son.

- ```shell
  curl -X PUT &quot;http://&lt;IP&gt;:15081/levels/room?mute=0&quot;
  ```

  - Rétablir le son.

- ```shell
  curl -X PUT &quot;http://&lt;IP&gt;:15081/levels/room?balance=-20&quot;
  ```

  - Régler la balance (-50 = tout à gauche, 50 = tout à droite).

## Lecture / Transport

- ```shell
  curl http://&lt;IP&gt;:15081/nowplaying
  ```

  - Métadonnées complètes : `transportState`, `title`, `artist`, `album`, `artwork`, `codec`, `bitDepth`, `bitRate`, `sampleRate`, `channels`, `duration`, `transportPosition`, `repeat`, `shuffle`, `source`, `station`, `genre`, `live`.

  - **transportState** : `0` = arrêté, `1` = en pause, `2` = en lecture, `3` = buffering.

- ```shell
  curl &quot;http://&lt;IP&gt;:15081/nowplaying?cmd=play&quot;
  ```

  - Lecture.

- ```shell
  curl &quot;http://&lt;IP&gt;:15081/nowplaying?cmd=pause&quot;
  ```

  - Pause.

- ```shell
  curl &quot;http://&lt;IP&gt;:15081/nowplaying?cmd=playpause&quot;
  ```

  - Basculer lecture/pause.

- ```shell
  curl &quot;http://&lt;IP&gt;:15081/nowplaying?cmd=stop&quot;
  ```

  - Arrêt.

- ```shell
  curl &quot;http://&lt;IP&gt;:15081/nowplaying?cmd=next&quot;
  ```

  - Piste suivante.

- ```shell
  curl &quot;http://&lt;IP&gt;:15081/nowplaying?cmd=prev&quot;
  ```

  - Piste précédente.

- ```shell
  curl &quot;http://&lt;IP&gt;:15081/nowplaying?cmd=seek&amp;position=120000&quot;
  ```

  - Seek à la position donnée (en millisecondes, ici 2 min).

- ```shell
  curl -X PUT &quot;http://&lt;IP&gt;:15081/nowplaying?repeat=0&quot;
  ```

  - Répétition désactivée.

- ```shell
  curl -X PUT &quot;http://&lt;IP&gt;:15081/nowplaying?repeat=1&quot;
  ```

  - Répéter la piste en cours.

- ```shell
  curl -X PUT &quot;http://&lt;IP&gt;:15081/nowplaying?repeat=2&quot;
  ```

  - Répéter toute la file.

- ```shell
  curl -X PUT &quot;http://&lt;IP&gt;:15081/nowplaying?shuffle=1&quot;
  ```

  - Activer la lecture aléatoire.

- ```shell
  curl -X PUT &quot;http://&lt;IP&gt;:15081/nowplaying?shuffle=0&quot;
  ```

  - Désactiver la lecture aléatoire.

## Sources / Entrées

- ```shell
  curl http://&lt;IP&gt;:15081/inputs
  ```

  - Liste toutes les sources disponibles. Chaque entrée contient `name`, `ussi`, `class`, `alias`, `disabled`, `selectable`, `multiroomMaster`.

- ```shell
  curl http://&lt;IP&gt;:15081/inputs/spotify
  ```

  - Infos sur une source spécifique.

- ```shell
  curl &quot;http://&lt;IP&gt;:15081/inputs/spotify?cmd=select&quot;
  ```

  - Basculer sur cette source.

- ```shell
  curl &quot;http://&lt;IP&gt;:15081/inputs/radio?cmd=play&quot;
  ```

  - Sélectionner et lancer la lecture d&apos;une source streaming.

### Identifiants de source connus

| ID | Nom | Classe |
|---|---|---|
| `ana1` – `ana4` | Analogique 1–4 | `object.input.analogue` |
| `dig1` – `dig5` | Numérique 1–5 | `object.input.digital` |
| `hdmi` | HDMI (ARC) | `object.input.hdmi` |
| `bluetooth` | Bluetooth | `object.input.bluetooth` |
| `radio` | Radio Internet | `object.input.radio.internet` |
| `spotify` | Spotify Connect | `object.input.spotify` |
| `tidal` | TIDAL | `object.input.tidal` |
| `qobuz` | Qobuz | `object.input.qobuz` |
| `usb` | USB | `object.input.usb` |
| `airplay` | AirPlay | `object.input.airplay` |
| `gcast` | Chromecast built-in | `object.input.googlecast` |
| `upnp` | Serveurs UPnP | `object.input.upnp` |
| `playqueue` | File de lecture | `object.input.playqueue` |
| `files` | Fichiers locaux / Démo | `object.input.files` |
| `roon` | Roon Ready | — |
| `multiroom` | Multiroom | — |

&gt; [!TIP]
&gt; Toutes les sources ne sont pas présentes sur tous les modèles. L&apos;endpoint `/inputs` retourne uniquement celles disponibles sur votre appareil.

## Favoris / Presets

- ```shell
  curl http://&lt;IP&gt;:15081/favourites
  ```

  - Liste tous les favoris. Chaque favori contient `name`, `ussi`, `available`.

- ```shell
  curl &quot;http://&lt;IP&gt;:15081/favourites/3754de0b49624983ab2179ed8524e9a2?cmd=play&quot;
  ```

  - Lancer un favori par son UUID (portion après `favourites/` dans le champ `ussi`).

## File de lecture

- ```shell
  curl http://&lt;IP&gt;:15081/inputs/playqueue
  ```

  - Infos sur la file de lecture. Le champ `current` contient le chemin vers la piste en cours (utilisable comme endpoint GET pour les métadonnées détaillées).

## Réseau

- ```shell
  curl http://&lt;IP&gt;:15081/network
  ```

  - Configuration réseau : `connectionState`, `current` (`network/wired` ou `network/wifi`), `dhcp`, `dns1`, `dns2`, `dnsName`, `gateway`, `hostname`, `ipAddress`, `macAddress`, `netmask`, `workgroup`.

## Découverte SSDP/UPnP

Les appareils Naim s&apos;annoncent comme **MediaRenderer UPnP**. Pour les trouver sur le réseau :

- ```shell
  gssdp-discover -t urn:schemas-upnp-org:device:MediaRenderer:2 --timeout=5
  ```

  - Recherche SSDP des MediaRenderers. L&apos;en-tête `LOCATION` pointe vers le XML de description contenant `manufacturer`, `friendlyName`, `modelName`, `serialNumber`, `UDN`.

## Socket TCP temps réel (port 4545)

&gt; [!IMPORTANT]
&gt; Ce n&apos;est **pas du HTTP**. C&apos;est une connexion TCP brute qui pousse du JSON en continu.

- ```shell
  nc &lt;IP&gt; 4545
  ```

  - Se connecter et recevoir les mises à jour en temps réel (état de lecture, métadonnées, position).

  - Valeurs de `state` : `playing`, `paused`, `stopped`.

Structure JSON poussée :

```json
{
  &quot;data&quot;: {
    &quot;state&quot;: &quot;playing&quot;,
    &quot;trackRoles&quot;: {
      &quot;title&quot;: &quot;Nom de la piste&quot;,
      &quot;icon&quot;: &quot;https://url-artwork...&quot;,
      &quot;mediaData&quot;: {
        &quot;metaData&quot;: {
          &quot;artist&quot;: &quot;Artiste&quot;,
          &quot;album&quot;: &quot;Album&quot;
        },
        &quot;activeResource&quot;: {
          &quot;bitsPerSample&quot;: &quot;24&quot;,
          &quot;sampleFrequency&quot;: &quot;96000&quot;
        }
      }
    },
    &quot;mediaRoles&quot;: {
      &quot;title&quot;: &quot;Nom de la source&quot;,
      &quot;mediaData&quot;: {
        &quot;metaData&quot;: {
          &quot;serviceID&quot;: &quot;spotify&quot;
        }
      }
    },
    &quot;status&quot;: {
      &quot;duration&quot;: 355000
    }
  },
  &quot;playTime&quot;: {
    &quot;i64_&quot;: 45000
  }
}
```
</content>
 </entry>
 
 
 
 <entry>
   <title>PipeWire Tips &amp; Tricks</title>
   <link href="https://blog.folf.fr/snippets/2026/03/01/pipewire/"/>
   <updated>2026-04-27T08:19:13+00:00</updated>
   <published>2026-04-22T14:16:25+00:00</published>
   <id>https://blog.folf.fr/snippets/2026/03/01/pipewire/</id>
   <content type="html">## Identifier les propriétés de son DAC

- ```shell
  wpctl status
  ```

  - Identifier le périphérique de sortie actuellement utilisé par PipeWire

- ```shell
  cat /proc/asound/cards
  ```

  - Identifier le numéro de la carte ALSA correspondant au DAC

- ```shell
  cat /proc/asound/cardX/stream0
  ```

  - Identifier les capacités de décodage du DAC

## Créer la configuration adéquate

- ```shell
  mkdir -p ~/.config/pipewire/pipewire.conf.d/
  ```

  - Créer un dossier de configuration PipeWire propre à notre compte utilisateur

- ```shell
  ~/.config/pipewire/pipewire.conf.d/10-hires-dac.conf
  
  context.properties = {
  	# Fréquence par défaut
  	default.clock.rate          = 384000
  	
  	# Autoriser PipeWire à basculer automatiquement sur ces fréquences sans rééchantillonner
  	default.clock.allowed-rates = [ 44100 48000 88200 96000 176400 192000 352800 384000 ]
  	
  	# Profondeur de bits maximale pour exploiter le DAC
  	default.audio.format        = &quot;S32_LE&quot;
  	
  	# Amélioration de la latence et réduction des craquements
  	default.clock.quantum       = 1024
  	default.clock.min-quantum   = 32
  	default.clock.max-quantum   = 8192
  }
  ```

  - Adapter la configuration avec les paramètres spécifique au modèle du DAC, récupérés avec les commandes précédentes.

- ```shell
  systemctl --user restart pipewire pipewire-pulse wireplumber
  ```

  - Redémarrer PipeWire pour appliquer la nouvelle configuration.

## Tester et Vérifier la qualité de lecture

- ```shell
  grep -i &quot;Momentary freq&quot; /proc/asound/card*/stream0
  ```

  - Après avoir lancé la lecture d&apos;un fichier Hi-Res, permet de voir en quelle qualité est lue le fichier en temps réel.

- ```shell
  pw-top
  ```

  - Petit outil GUI/CLI permettant de voir quel processus décode actuellement du contenu audio et à quelle qualité.

Il est important de ne pas modifier le volume et de laisser tout à 100% pour ne pas forcer Linux à re-encoder le flux audio !</content>
 </entry>
 
 
 
 <entry>
   <title>Linux / Debian / Proxmox Tips &amp; Tricks</title>
   <link href="https://blog.folf.fr/snippets/2026/03/01/linux-debian-proxmox/"/>
   <updated>2026-04-27T08:19:13+00:00</updated>
   <published>2026-04-22T14:16:25+00:00</published>
   <id>https://blog.folf.fr/snippets/2026/03/01/linux-debian-proxmox/</id>
   <content type="html">## APT

- ```shell
  apt-cache policy (package)
  ```

  - Permet de déterminer à partir de quel dépôt est installé / téléchargé un paquet. Ainsi, si jamais plusieurs dépôts proposent le même paquet, il est possible de savoir celui qui aura la plus haute priorité.

- ```shell
  apt-cache show (package)
  ```

  - Permet d&apos;obtenir les métadonnées d&apos;un paquet.

## GRUB

- ```shell
  /etc/default/grub
  
  GRUB_CMDLINE_LINUX=&quot;net.ifnames=0 biosdevname=0&quot;
  ```

  - Permet de forcer le nommage des interfaces réseau en ethX plûtot que enpXsX. Les interfaces en enpXsX sont succeptibles de changer aléatoirement en cas de modification matérielle ou montée de version logicielle.
  
- ```shell
  /etc/default/grub
  
  GRUB_CMDLINE_LINUX=&quot;console=tty0 console=ttyS0,115200n8&quot;
  GRUB_TERMINAL=&quot;console serial&quot;
  GRUB_SERIAL_COMMAND=&quot;serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1&quot;
  
  update-grub
  update-initramfs -u -k all
  
  sudo systemctl enable serial-getty@ttyS0.service
  ```

  - Permet d&apos;activer GRUB / un shell sur le port console.


## LVM

- ```shell
  lvmconfig --validate
  ```

  - Permet de vérifier la syntaxe de configuration du fichier `/etc/lvm/lvm.conf`

## BASH

- ```shell
  ~/.bashrc
  
  export HISTSIZE=-1
  export HISTFILESIZE=-1
  export HISTTIMEFORMAT=&quot;%F %T &quot;
  export PROMPT_COMMAND=&quot;history -a; $PROMPT_COMMAND&quot;
  shopt -s histappend
  ```

  - Permet de sauvegarder de manière illimitée l&apos;historique bash.
  
- ```shell
  grep -rnw &apos;/path/où/chercher/&apos; -e &quot;string&quot;
  ```
  
  - Permet de chercher une string de manière récursive dans un dossier voulu.
  

## Proxmox

- ```shell
  bash -c &quot;$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/pve/kernel-clean.sh)&quot;
  ```

  - Permet de désinstaller les anciennes versions du noyau Linux qui subsistent en cas de mise à jour Proxmox.

## Git

- ```shell
  git rebase -i sha256commit(^)
  ```

  - Permet de lancer un rebase interactif à partir du commit indiqué (^ indique son parent)

- ```shell
  git fetch --all
  git reset --hard origin/main
  ```

  - Permet de forcer git à revenir à la version sur le serveur (pour annuler les modifications locales)

## Qemu

- ```shell
  qemu-img convert -f vmdk -O qcow2 source.vmdk destination.qcow2
  ```

  - Permet de convertir une image de disque virtuelle VMDK en QCOW2.

## VirtualBox

- ```shell
  VBoxManage modifymedium disk &quot;/chemin/vers/image/disque&quot; --compact
  ```

  - Permet de compacter un fichier d&apos;image disque

- ```shell
  zerofree -v /dev/sdaX
  ```

  - Permet de remplir de zéros les emplacements vides d&apos;un disque dur Linux formaté en ext4.

## systemd

- ```shell
  systemctl list-jobs
  systemctl list-units --type=service --state=activating
  ```

  - Identifier les services qui sont en cours de démarrage, pouvant bloquer le démarrage complet de l&apos;hôt.e

    ```shell
    systemctl status mon-service.service
    journalctl -u mon-service.service -f
    ```

    - Permet d&apos;approfondir pourquoi un service ne démarre pas en regardant l&apos;intégralité de ses logs.

## openssh

- ```shell
  ~/.ssh/config
  
  Host monserveur
          HostName mon.serveur.fr
          User utilisateur
          ForwardAgent yes
  ```

  - Permet de pré-définir / enregistrer des paramètres de session SSH pour voir se connecter en une seule commande rapidement.
  - `ForwardAgent yes` permet de passer l&apos;agent SSH du client vers l&apos;hôte pour transférer les clés SSH entre les deux.

</content>
 </entry>
 
 
 
 <entry>
   <title>Dell Tips &amp; Tricks</title>
   <link href="https://blog.folf.fr/snippets/2026/03/01/dell/"/>
   <updated>2026-04-27T08:19:13+00:00</updated>
   <published>2026-04-22T14:16:25+00:00</published>
   <id>https://blog.folf.fr/snippets/2026/03/01/dell/</id>
   <content type="html">## M1000e

- ```shell
  racadm getfaninfo -d -p glacier -w 50
  ```

  - Écrase la vitesse des ventilateurs par 50%.

- ```
  racadm getfanreqinfo
  ```

  - Récupère la vitesse des ventilateurs effective et demandée par les blades.</content>
 </entry>
 
 
 
 <entry>
   <title>Mettre en place un reverse-proxy sécurisé grâce au WAF BunkerWeb</title>
   <link href="https://blog.folf.fr/bunkerweb/"/>
   <updated>2026-04-27T08:19:13+00:00</updated>
   <published>2026-04-22T14:16:25+00:00</published>
   <id>https://blog.folf.fr/bunkerweb/</id>
   <content type="html">## Introduction

**Depuis que je peux héberger toutes sortes d’applications**, **[accessibles via des adresses IPv4 publiques](https://blog.folf.fr/wireguardl)**, **la question de leur sécurité m’est devenue centrale**.

**Beaucoup se tournent vers** **[NGINX](https://nginx.org/)** — parfois accompagné d’**interfaces conviviales** **comme** **[NGINX Proxy Manager](https://github.com/NginxProxyManager/nginx-proxy-manager)** — ou vers d’**autres reverse proxies** tels que **[Caddy](https://github.com/caddyserver/caddy)** ou **[HAProxy](https://github.com/haproxy/haproxy)**. Pourtant, **ces solutions restent *[peu sécurisées](https://www.reddit.com/r/selfhosted/comments/176znvu/security_of_sites_behind_reverse_proxy/) par défaut***.

**Un certificat** **TLS/SSL** **assure** certes **le chiffrement des échanges**, **empêchant l’interception des données** sensibles (***sauf en cas d’attaque [MITM](https://fr.wikipedia.org/wiki/Attaque_de_l%27homme_du_milieu)***), **mais la sécurité ne s’arrête pas là** : **de nombreux** autres **aspects** **doivent être pris en compte** !

Il faut notamment **se prémunir contre les exploits applicatifs**, par exemple (*liste non exhaustive*) :

- les injections **SQL** ;
- le **cross-site scripting** ;
- l’**élévation de privilèges**.

**Un reverse-proxy se contente de relayer le trafic** ; **s’il n’intègre pas de protections**, **il transmettra l’exploit** sans sourciller.

La **généralisation de l’hébergement** via des **conteneurs** **Docker** **offre** un **certain niveau d’isolation** au niveau du **noyau Linux**, **mais une application compromise** **reste une porte d’entrée** potentielle **pour la fuite de données**.

**Il existe aussi des WAF grand public** et **professionnels**, comme **Cloudflare**, **qui proposent gratuitement** de **nombreuses fonctionnalités**. ***Malheureusement**, **ces solutions sont souvent mal déployées** (par ex. : non-restriction des IP à [**celles de Cloudflare**](https://www.cloudflare.com/ips/)) et **soulèvent des** [**questions éthiques**](https://0xacab.org/dCF/deCloudflare/-/blob/master/readme/fr.md) : confier son trafic à une société américaine, c’est accepter un intermédiaire puissant, ce qui, dans le contexte politique actuel, peut prêter à débat.*

**Toutes ces réflexions m’ont conduit à chercher un WAF** **simple d’utilisation et souverain 🇫🇷**, **c’est ainsi que j’ai découvert** **[BunkerWeb](https://bunkerweb.io)** !


## Présentation de BunkerWeb

**[BunkerWeb](https://bunkerweb.io)** est un **pare-feu d’applications Web** (**[Web Application Firewall](https://fr.wikipedia.org/wiki/Web_application_firewall)**) **open-source** de **nouvelle génération** qui fonctionne comme un [**reverse-proxy**](https://fr.wikipedia.org/wiki/Proxy_inverse) **complet** **basé** **sur** **NGINX**. Il est **développé** et **maintenu** par **Bunkerity**, **entreprise française** spécialisée en cybersécurité, ce qui inscrit la solution dans une **démarche** de **souveraineté numérique**. Publié **sous licence** **AGPL v3**, son **code** reste **entièrement** **auditable** et **modifiable**, **garantissant** à chacun la maîtrise de ses briques de **sécurité** et de leur évolution.

**Conçu pour la souveraineté** jusqu’au bout, BunkerWeb est totalement **auto-hébergeable** : il se déploie **[on-premises](https://en.wikipedia.org/wiki/On-premises_software)** sur un **Linux** ou via **Docker**. **Sans aucune dépendance** **à** un **SaaS externe**, toutes les règles, journaux et certificats TLS **demeurent sous votre contrôle**, répondant aux **exigences** **les plus strictes** en matière de **résidence** et de **conformité des données.**

**Par défaut**, BunkerWeb **protège** vos **services** avec une approche secure by default : **intégration** **de** **[ModSecurity](https://github.com/owasp-modsecurity/ModSecurity)** **et** **de** l’[**OWASP CRS**](https://github.com/coreruleset/coreruleset), **durcissement TLS**, **bannissement automatique** des **comportements anormaux**, **défis pour les robots**, **rate limiting**, **blacklists IP** **et bien plus**. Un système de **plugins** **permet** d’**étendre** **les capacités** (PHP, notifications, etc.), tandis que l’**interface Web** **simplifie** **la gestion** depuis n’importe où.

**Après avoir examiné l’ensemble des critères évoqués plus haut** et **échangé** **avec plusieurs développeurs** du projet lors du [**FIC**](https://europe.forum-incyber.com/), j’ai **décidé de déployer** **BunkerWeb au sein de mon** **homelab**. Quelques mois plus tard, **le bilan est sans appel** : **j’en suis pleinement satisfait**.

**Dans cet article**, **nous verrons pas à pas comment installer et configurer BunkerWeb**.

## Pré-requis

&gt; [!NOTE]
&gt; **BunkerWeb peut s&apos;exécuter sur n&apos;importe quel environnement Docker.**
&gt; **Prévoyez** au **minimum** **2 vCPU** et **4 Go de RAM** pour un **usage standard** ; dans des **contextes plus exigeants**, **préférez** plutôt **4 vCPU** et **16 Go de RAM**.

#### Pourquoi autant de ressources ?

- **La mémoire est mise à contribution** parce qu’un **processus ModSecurity dédié** est **lancé pour chaque sous-domaine** — une option que l’**on peut désactiver** sur les **machines disposant de peu de RAM**, comme nous le verrons plus loin.  
- **La charge CPU, quant à elle**, provient surtout du **chiffrement avancé** et des **optimisations à la volée** (compression **[GZip](https://fr.wikipedia.org/wiki/Gzip)** ou **[Brotli](https://fr.wikipedia.org/wiki/Brotli)**), qui **allègent le poids des fichiers** **transmis aux clients** au détriment d’un surcroît de calcul.

#### Ports réseau à autoriser

| Port | Protocole | Rôle |
|------|-----------|------|
| **80**  | TCP | HTTP |
| **443** | TCP | HTTPS |
| **443** | UDP | HTTP/3 🚀 |

&gt; [!NOTE]
&gt; **Pour le trafic réseau**, **pensez à autoriser les ports** **80/TCP**, **443/TCP** et **443/UDP**.
&gt; Le port **443 en UDP est indispensable pour la prise en charge de HTTP/3 : le futur 🚀 est à nos portes !**

#### Règles DNS

**Assurez-vous également** de **créer un enregistrement** **DNS** **pour l’interface d’administration Web** ; disposer de cette entrée **dès le départ** permet d’**effectuer la configuration initiale** de BunkerWeb **directement depuis l’URL** correspondante.  
De même, **chaque sous-domaine que vous protégerez avec BunkerWeb devra auparavant avoir son enregistrement DNS approprié** !!

**Une fois ces prérequis validés, passons au déploiement de notre WAF !**

## Déploiement de BunkerWeb avec Docker Compose

**Commencez par créer un fichier** **`compose.yaml`**, **puis** **copiez-y** **le bloc de configuration ci-dessous** :

```yaml
################################################################################
##                          BunkerWeb – Docker Compose                         #
## Ce fichier déploie BunkerWeb (reverse-proxy + WAF), son ordonnanceur,       #
## l’interface Web d’administration et une base PostgreSQL pour le stockage.   #
##                                                                             #
## → AVANT DE PASSER EN PROD :                                                 #
##   - Changez le mot de passe « motdepasseachanger »                          #
##                                                                             #
## → POUR LE RÉSEAU EXTERNE &apos;bw-apps&apos; :                                        #
##   - Créez-le avec : docker network create bw-apps                           #
################################################################################

################################ Variables globales ############################
## Regroupées sous une ancre YAML (&amp;bw-env) pour pouvoir être ré-utilisées
## (« merge key » &lt;&lt;) dans les différents services.
x-bw-env: &amp;bw-env
  ## Liste d’IP autorisées à appeler l’API interne de BunkerWeb.
  ## Indiquer le même subnet que celui du réseau « bunker »
  ## Format : réseaux CIDR séparés par des espaces.
  API_WHITELIST_IP: &quot;127.0.0.0/8 10.20.30.0/24&quot;
  ## Chaîne de connexion à la base PostgreSQL (SQLAlchemy).
  ## ➜ Changez le mot de passe.
  DATABASE_URI: &quot;postgresql://bunkerweb:motdepasseachanger@bw-db:5432/db&quot;

###############################################################################
##                                   Services                                ##
###############################################################################
services:
  ###########################################################################
  ## 1. Reverse-proxy / WAF                                                ##
  ###########################################################################
  bunkerweb:
    image: bunkerity/bunkerweb:latest      ## Utilise la dernière image stable
    ## ── Ports exposés ──────────────────────────────────────────────────────
    ports:
      - &quot;80:8080/tcp&quot;    ## HTTP  vers port interne 8080
      - &quot;443:8443/tcp&quot;   ## HTTPS vers port interne 8443
      - &quot;443:8443/udp&quot;   ## HTTP/3 (QUIC) sur le même port 8443 en UDP
    ## ── Variables d’environnement ─────────────────────────────────────────
    environment:
      &lt;&lt;: *bw-env                       ## Fusionne les variables communes
    ## ── Redémarrage automatique ───────────────────────────────────────────
    restart: unless-stopped             ## Relance sauf si vous l’arrêtez manuellement
    ## ── Réseau ────────────────────────────────────────────────────────────
    networks:
      - bunker                          # Place le conteneur sur le réseau « bunker »
      - bw-apps                         # Place le conteneur sur le réseau externe « bw-apps »
    ## ── Logs ──────────────────────────────────────────────────────────────
    logging:
      driver: json-file
      options:
        max-size: &quot;10m&quot;                 ## Rotation : 10 Mo par fichier
        max-file: &quot;10&quot;                   ## Garde 10 fichiers

  ###########################################################################
  ## 2. Ordonnanceur (scheduler)                                           ##
  ###########################################################################
  bw-scheduler:
    image: bunkerity/bunkerweb-scheduler:latest
    environment:
      &lt;&lt;: *bw-env
      BUNKERWEB_INSTANCES: &quot;bunkerweb&quot;
      SERVER_NAME: &quot;&quot;
      MULTISITE: &quot;yes&quot;
      UI_HOST: &quot;http://bw-ui:7000&quot;
    volumes:
      - bw-data:/data                    ## Monte les données persistantes (policies, etc.)
    restart: unless-stopped
    networks:
      - bunker                           ## Même réseau que bunkerweb
      - bunker-db                        ## Accès direct à la base

  ###########################################################################
  ## 3. Interface Web d’administration                                     ##
  ###########################################################################
  bw-ui:
    image: bunkerity/bunkerweb-ui:latest
    environment:
      &lt;&lt;: *bw-env
    restart: unless-stopped
    networks:
      - bunker                           ## Doit voir le proxy
      - bunker-db                        ## Doit voir PostgreSQL

  ###########################################################################
  ## 4. Base de données PostgreSQL                                         ##
  ###########################################################################
  bw-db:
    image: postgres:17
    environment:
      POSTGRES_DB: &quot;db&quot;
      POSTGRES_USER: &quot;bunkerweb&quot;
      ## ☠️ À CHANGER ABSOLUMENT AVANT PROD !
      ##   ➜ Pensez aussi à mettre à jour DATABASE_URI plus haut.
      POSTGRES_PASSWORD: &quot;motdepasseachanger&quot;
    volumes:
      - bw-dbdata:/var/lib/postgresql/data ## Persistance des données SQL
    restart: unless-stopped
    networks:
      - bunker-db                        ## Isolé du reste pour sécurité

###############################################################################
##                                  Réseaux                                  ##
###############################################################################
networks:
  ## Réseau frontal (reverse-proxy, scheduler, UI, etc.)
  bunker:
    name: bunker
    ipam:
      driver: default
      config:
        - subnet: 10.20.30.0/24          ## Réseau identique à celui autorisé dans BunkerWeb

  ## Réseau backend (UI &amp; scheduler ↔ PostgreSQL). Non exposé au proxy.
  bunker-db:
    name: bunker-db

  ## Réseau pour connecter vos applications backend à BunkerWeb.
  ## Doit être créé manuellement sur l&apos;hôte Docker avant de lancer ce compose :
  ## → docker network create bw-apps
  bw-apps:
    name: bw-apps
    external: true

###############################################################################
##                                  Volumes                                  ##
###############################################################################
volumes:
  ## Policies, certificats, listes IP, etc.
  bw-data:
  ## Données SQL de PostgreSQL
  bw-dbdata:
```

**N’oubliez pas de changer le mot de passe** `&quot;motdepasseachanger&quot;` **par un autre aléatoire** 🔐 ! **Vous pouvez également le faire avec la commande suivante** (qui génère un mot de passe aléatoire de 32 caractères et remplace compose.yaml à votre place) :

```shell
sed -i -e &quot;s|motdepasseachanger|$(openssl rand -base64 32 | tr -dc &apos;A-Za-z0-9&apos; | head -c32)|g&quot; -e &apos;/^\s*#/d&apos; -e &apos;s/\s*#.*$//&apos; compose.yaml
```

```shell
docker network create bw-apps
```

**Une fois le fichier compose.yaml prêt**, il vous suffit de **`docker compose up -d`** **puis passez à la première configuration via l’interface web** !

**Le premier démarrage peut prendre un certain temps** ⏰, vous pouvez **observer l’avancement** via les **logs** avec la commande suivante : 

**`docker compose logs --follow`**

## Premier démarrage via l’interface web

1. **Rendez vous sur `https://url-de-votre-bunker.web/setup` afin de retrouver la page de démarrage suivante :**

   ![bunkerweb-setup1.avif](/assets/contenu/img/posts/bunkerweb/bunkerweb-setup1.avif)

   **Dans un premier temps**, vous devez **renseigner** les **propriétés** du **compte administrateur**.
2. **Ensuite, vous devez renseigner le hostname public de votre instance BunkerWeb.**  
   ![bunkerweb-setup2.avif](/assets/contenu/img/posts/bunkerweb/bunkerweb-setup2.avif)


   &gt; [!WARNING]
   &gt; Il ne faut **surtout pas toucher** à **UI Host** et **UI URL** !!

**En ce qui en est de la gestion des certificats TLS/SSL**, **l’implémentation de Let’s Encrypt** est **très simple d’utilisation** !  
Il vous **suffit de cocher** **« Auto Let’s Encrypt »** pour que cela soit **géré de manière automatique**, et de **mentionner un mail** pour **recevoir les informations Let’s Encrypt**.

**Vous avez aussi la possibilité de demander des certificats TLS/SSL via** **DNS**, **permettant** ainsi donc **l’usage de** **Wildcards** (`*.votredomaine.tld`).  
Pour cela :

- **Sélectionnez** comme **Challenge Type** : `dns`  
- **Choisissez** votre **DNS Provider**  
- **Renseignez** la **clé d’API** adéquate

3. **Une fois toutes les informations renseignées, BunkerWeb propose un récapitulatif des paramètres renseignés précédemment.**  
   Vous pouvez **valider** et **lancer l’installation**.

   ![bunkerweb-setup3.avif](/assets/contenu/img/posts/bunkerweb/bunkerweb-setup3.avif)
   
   **Après avoir patienté** le temps de **la** **mise en place** de BunkerWeb, vous devriez être **redirigé sur la page de** **login**. **Vous pouvez vous y connecter**.

   ![bunkerweb-setup4.avif](/assets/contenu/img/posts/bunkerweb/bunkerweb-setup4.avif)

## Présentation de l’interface web et paramétrage rapide

**Bienvenue sur l’interface web de** **BunkerWeb** !

![bunkerweb-interface1.avif](/assets/contenu/img/posts/bunkerweb/bunkerweb-interface1.avif)

**Sur la page d’accueil**, vous **retrouverez** quelques **statistiques** **essentielles** liées à **votre** **instance**.  
**Dans la barre latérale**, à gauche, se trouvent les **menus suivants** :

- **Home** : ***Page d’accueil***
- **Instances** : ***Uniquement utile pour un cluster**, c’est dans cette rubrique que sont renseignées les **différentes instances composant le cluster***
- **Global Config** : ***Gérer la configuration générale** **et commune à tous les services***
- **Services** : ***Gérer la configuration de chaque VirtualHost** / **service***
- **Configs** : ***Gérer les configurations NGINX avancées***
- **Plugins** : ***Gérer les modules supplémentaires***
- **Cache** : ***Gérer les fichiers mis en cache***
- **Reports** : ***Consulter les alertes et blocages***
- **Bans** : ***Consulter les bannissements***
- **Jobs** : ***Gérer les tâches planifiées***
- **Logs** : ***Consulter les fichiers de journalisation***

**Les catégories principales** **que j’utilise régulièrement** sont **Global Config**, **Services** et **Bans** / **Report**.

**Nous allons maintenant passer en revue** **quelques paramètres** **pratiques**, pour ce faire, **rendez-vous dans la rubrique** « **Global Config** »

![bunkerweb-interface2.avif](/assets/contenu/img/posts/bunkerweb/bunkerweb-interface2.avif)

**En haut à gauche**, le **menu déroulant** vous **permet de choisir la configuration de chaque plug-in** ; **en haut à droite**, le **bouton** **Save** enregistre vos changements.
**Ci-dessous**, vous trouverez **les principaux réglages** sur mon **instance personnelle** :

#### ⚙️ Général

* `LISTEN_STREAM` : **false** – *désactive la fonctionnalité Stream de NGINX (permettant de forward les ports).*
* `USE_TCP` : **false**
* `USE_UDP` : **false**

#### 🗜️ Brotli

* `USE_BROTLI` : **true** – *active la compression Brotli pour des transferts encore plus légers (vous pouvez ensuite affiner niveau et types MIME).*

#### 📦 Cache client

* `USE_CLIENT_CACHE` : **true** – *autorise le cache côté navigateur, soulageant ainsi votre serveur.*

#### 🗜️ Gzip

* `USE_GZIP` : **true** – *démarre la compression Gzip, largement reconnue ; ajustez ensuite les paramètres selon vos besoins.*

#### 🔐 Let’s Encrypt

* `AUTO_LETS_ENCRYPT` : **true** – *préremplit les champs Let’s Encrypt lors de la création d’un service.*
* `EMAIL_LETS_ENCRYPT` : **mail@votredomaine.tld**


#### 🛡️ ModSecurity

* `USE_MODSECURITY_GLOBAL_CRS` : **true** – *⚠️⚠️ à envisager seulement si votre machine dispose de peu de RAM⚠️⚠️.*

#### 🔄 Reverse Proxy

* `REVERSE_PROXY_INTERCEPT_ERRORS` : **false** – *permet d’afficher l’erreur native du service (utile, par exemple, avec Guacamole).*

#### 🔒 SSL

* `REDIRECT_HTTP_TO_HTTPS` : **true** – *force la redirection vers HTTPS.*
* `SSL_PROTOCOLS` : **TLSv1.3** – *limite les échanges au protocole le plus récent.*

**Passons à présent au déploiement d’un service.**

## Déployer un service pas à pas

&gt; [!NOTE]
&gt; **Prérequis :** **assurez-vous d’avoir créé au préalable l’enregistrement DNS du service** ; il servira à l’**émission automatique du certificat** **Let’s Encrypt**.

Ouvrez la section **Services** puis cliquez sur **Create new service**. Suivez ensuite les étapes décrites ci-après.

### 1 | Web service – *Front service*

![Capture : création d’un service — étape 1](/assets/contenu/img/posts/bunkerweb/bunkerweb-createservice1.avif)

* **`SERVER_NAME`** : nom(s) de domaine à protéger.
* **Let’s Encrypt** : si **`AUTO_LETS_ENCRYPT`** n’est *pas* à `true`, renseignez les champs manuellement.
* **Template** : choisissez un profil de sécurité (*low*, *medium*, *high*) adapté à la criticité de l’application.

Ces réglages concernent la *face publique* du reverse-proxy exposée sur Internet.

### 2 | Web service – *Upstream server*

![Capture : création d’un service — étape 2](/assets/contenu/img/posts/bunkerweb/bunkerweb-createservice2.avif)

* **`REVERSE_PROXY_HOST`** : URL interne du service (incluant le schéma `http://` ou `https://`).
* **`REVERSE_PROXY_WS`** : activez-le pour la prise en charge des WebSockets.

### 3 | HTTP – *General*

![Capture : création d’un service — étape 3](/assets/contenu/img/posts/bunkerweb/bunkerweb-createservice3.avif)

| Variable              | Rôle                            | Suggestion                                                       |
| --------------------- | ------------------------------- | ---------------------------------------------------------------- |
| **`ALLOWED_METHODS`** | Méthodes HTTP autorisées        | Conservez les valeurs du template, sauf besoin spécifique.       |
| **`MAX_CLIENT_SIZE`** | Taille max. du corps de requête | Ex. `1024m` pour autoriser des uploads massifs.                  |
| **`SSL_PROTOCOLS`**   | Versions TLS admises            | Restreignez à `TLSv1.3` si vous exigez le niveau le plus strict. |

### 4 | HTTP – *Headers*

![Capture : création d’un service — étape 4](/assets/contenu/img/posts/bunkerweb/bunkerweb-createservice4.avif)

Vous pouvez ici :

* ajouter ou supprimer des en-têtes personnalisés ;
* activer **`USE_CORS`** pour contrôler le partage de ressources entre sites (pratique pour limiter le vol de cookies).

&gt; [!TIP]
&gt; Les valeurs par défaut conviennent à la plupart des cas.

### 5 | Security – *Bad behavior*

![Capture : création d’un service — étape 5](/assets/contenu/img/posts/bunkerweb/bunkerweb-createservice5.avif)

Le module **Bad behavior** bannit les clients générant trop d’erreurs.

| Variable                        | Par défaut                    | Fonction                             |
| ------------------------------- | ----------------------------- | ------------------------------------ |
| **`BAD_BEHAVIOR_STATUS_CODES`** | `400 401 403 404 405 429 444` | Codes suivis.                        |
| **`BAD_BEHAVIOR_THRESHOLD`**    | `10`                          | Nombre d’erreurs déclenchant le ban. |
| **`BAD_BEHAVIOR_COUNT_TIME`**   | `60 s`                        | Fenêtre de comptage.                 |
| **`BAD_BEHAVIOR_BAN_TIME`**     | `86400 s` (24 h)              | Durée du ban.                        |

Les valeurs par défaut sont généralement suffisantes.

### 6 | Security – *Blacklisting*

![Capture : création d’un service — étape 6](/assets/contenu/img/posts/bunkerweb/bunkerweb-createservice6.avif)

Activez **`USE_BLACKLIST`** pour bloquer immédiatement les IP ou user-agents référencés dans les listes internes ou personnelles. Par défaut, la configuration protège déjà contre les robots les plus agressifs.

### 7 | Security – *Limiting*

![Capture : création d’un service — étape 7](/assets/contenu/img/posts/bunkerweb/bunkerweb-createservice7.avif)

* **`USE_LIMIT_CONN`** : limite le nombre de connexions simultanées.
* **`USE_LIMIT_REQ`** : plafonne le débit de requêtes (HTTP 429 en cas d’excès).

&gt; Ajustez les quotas uniquement si un service légitime se voit bloqué.

### 8 | Security – *Antibot*

![Capture : création d’un service — étape 8](/assets/contenu/img/posts/bunkerweb/bunkerweb-createservice8.avif)

* **`USE_ANTIBOT`** : active la protection.
* **`ANTIBOT_MODE`** : `captcha` (résolution manuelle) ou `javascript` (tests invisibles).
* **`ANTIBOT_PROVIDER`** : *reCAPTCHA*, *hCaptcha*, *Turnstile*, etc. (clé site &amp; secret requis).

Si jamais vous avez besoin de rajouter un captcha, choisissez `javascript` tant que possible pour préserver l’ergonomie. Si besoin de sécurité supplémentaire. puis passez en `captcha` sur les pages les plus sensibles.

### 9 | Security – *Auth basic*

![Capture : création d’un service — étape 9](/assets/contenu/img/posts/bunkerweb/bunkerweb-createservice9.avif)

Placez un verrou HTTP Basic en activant **`USE_AUTH_BASIC`** puis :

* renseignez `login:password` (ou hashés) dans **`AUTH_BASIC_LIST`**,
* ou référencez un fichier `.htpasswd` avec **`AUTH_BASIC_FILE`**.

### 10 | Security – *Country*

![Capture : création d’un service — étape 10](/assets/contenu/img/posts/bunkerweb/bunkerweb-createservice10.avif)

* **`BLACKLIST_COUNTRY`** : bloque la liste de pays indiqués (`RU KP` par ex.).
* **`WHITELIST_COUNTRY`** : autorise *uniquement* les pays listés (`FR BE`, etc.).

Toute requête provenant d’un pays exclu reçoit un **403 Forbidden**.

### 11 | Security – *ModSecurity*

![Capture : création d’un service — étape 11](/assets/contenu/img/posts/bunkerweb/bunkerweb-createservice11.avif)

ModSecurity analyse chaque requête / réponse à l’aide du Core Rule Set (OWASP). Conservez les réglages par défaut, puis excluez au besoin des règles via la rubrique **Custom configuration**.

### 12 | Finaliser le déploiement

Cliquez sur **Save** : BunkerWeb lance immédiatement le déploiement en arrière-plan (**patientez ≈ 1 min**).
**Votre service est maintenant protégé et accessible à l’extérieur !**

## Conclusion

**Et voilà**, **vous avez maintenant un reverse-proxy sécurisé pour toutes vos applications !**

J’améliorerai cette documentation au fil du temps en fonction des situations et problèmes que je rencontrerais à l’avenir.

###### [Mettre en place un reverse-proxy sécurisé grâce au WAF BunkerWeb]({{ site.url }}/bunkerweb) by [{{ site.author.name }}]({{ site.url }}) is licensed under [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/)

#### Implémentations futures :

- Ajout d’exceptions ModSecurity
- Ajout de cas par cas applications Authentik</content>
 </entry>
 
 
 
 <entry>
   <title>Avoir des adresses IPv4/IPv6 chez soi avec un tunnel Wireguard</title>
   <link href="https://blog.folf.fr/wireguard/"/>
   <updated>2026-05-06T08:26:45+00:00</updated>
   <published>2026-04-22T14:16:25+00:00</published>
   <id>https://blog.folf.fr/wireguard/</id>
   <content type="html"># Introduction

J&apos;ai chez moi un **serveur** sur lequel tourne [**Proxmox**](https://www.proxmox.com/), un **hyperviseur** qui me permet de créer des **machines virtuelles** et des [**conteneurs Linux**](https://linuxcontainers.org/) afin d&apos;héberger **différents services** pour mes diverses activités d&apos;**auto-hébergement**.

Seulement, ne possédant qu&apos;un seul abonnement internet de particulier, et par conséquent **une seule IP résidentielle**, je suis vite limité par le **nombre de ports disponibles** et je ne peux pas faire tourner tous les services que je souhaite dans les meilleures conditions.

Encore heureux, je peux **ouvrir mes ports**, mais certains opérateurs en France **retirent cette** option au fil du temps, ou bien les **box 4G/5G** ne proposent pas cette option à cause du **[CG-NAT](https://fr.wikipedia.org/wiki/Carrier-grade_NAT)**.

Ces **limitations** m&apos;ont amené à **mettre en place une solution pour avoir plusieurs adresses IP** **chez soi**, **dédiées**, **protégées** par un **Anti-DDOS** et **peu chères**. N&apos;ayant trouvé aucune solution existante, j&apos;ai bidouillé et mis en place la mienne.

# Principe de fonctionnement

![Comment fonctionne l&apos;internet](/assets/contenu/img/posts/tunnel-wireguard-ip-homelab/doc-schema-hms.avif)

# Le choix de l&apos;hébergeur

J&apos;ai choisi [**HostMyServers**](https://www.hostmyservers.fr/), un **hébergeur français** 🇫🇷 avec **plusieurs années d&apos;existence**, car ils proposent des **tarifs très intéressant**s au niveau du **réseau** et la **qualité de service est correcte**. Le premier **[VPS SSD](https://www.hostmyservers.fr/vps-ssd)** suffit amplement pour un **traffic raisonnable (~250Mbps)** dans le **tunnel** et inclus une **protection Anti-DDOS basique** **contre les attaques simples**. Leur **support** via le site est relativement **réactif**, mais je n&apos;ai **pas rencontré de problèmes** après plus de deux ans chez eux.

![tarifs HMS](/assets/contenu/img/posts/tunnel-wireguard-ip-homelab/doc-prixhms.avif)

Ce qui nous concerne le plus, c&apos;est le **tarif des adresses IP supplémentaires**. Chez HMS, elles **coûtent 2€ à vie**.

D&apos;**autres hébergeurs** comme [**RoyaleHosting**](https://royalehosting.net/store/vps) ou [**OVH**](https://www.ovhcloud.com/fr/vps/) peuvent proposer un **réseau de meilleure qualité** mais à un **prix bien plus important**. Ce tutoriel se concentrera sur HMS.

# Achat d&apos;adresses IP supplémentaire

**Pour faire marcher cette documentation, il est nécessaire d&apos;avoir plusieurs adresses IPv4 sur le VPS.**

Depuis la rubrique &quot;**Configuration**&quot; sur votre VPS vous pouvez cliquer sur &quot;**Commander IP Supplémentaires**&quot; afin d&apos;en acheter.

Voici les tarifs proposés par **HostMyServers** :

![Tarif IP HMS](/assets/contenu/img/posts/tunnel-wireguard-ip-homelab/doc-prixiphms.avif)

Je vous **recommande** de **prendre des adresses IPv4 Supplémentaires à l&apos;unité**. (les blocs ne sont pas assez intuitifs à mon goût dans l&apos;espace client pour le moment)

Une fois l&apos;**adresse IP achetée**, votre panel devrait **ressembler à ceci** :

![Panel HMS IP](/assets/contenu/img/posts/tunnel-wireguard-ip-homelab/doc-ip1.avif)

![Panel HMS IP](/assets/contenu/img/posts/tunnel-wireguard-ip-homelab/doc-ip2.avif)

**Notez bien** pour la suite du tutoriel que :

- **L&apos;adresse IP principale du VPS** est celle qui **possède** un **reverse DNS associée**.
- **L&apos;adresse IP supplémentaire** est celle qui ne **possède** **pas** de **reverse DNS**.

**Notez sur un bloc note** quelle IP est laquelle **afin de ne pas vous emmêler les pinceaux dans la suite** du tuto.

&gt; [!WARNING]
&gt; Commandez raisonnablement des adresses IPv4, il n&apos;y en a plus beaucoup, et il est inutile d&apos;en claim si elles restent inutilisées.

# Préparation du VPS

**Cette partie de la documentation s&apos;applique uniquement aux clients HMS / RoyaleHosting. Si vous avez un VPS avec Debian 12 et systemd-networking, vous pouvez ignorer cette étape.**

**Une fois votre VPS livré**, rendez-vous dans votre **espace client** pour **choisir sa distribution**. Nous installons **Debian 12**.

![Install VPS](/assets/contenu/img/posts/tunnel-wireguard-ip-homelab/doc-panelhmsinstallvps.avif)

**Une fois le VPS installé**, vous **recevrez** les **identifiants** pour s&apos;y connecter sur votre **adresse email** client.

![VPS installé](/assets/contenu/img/posts/tunnel-wireguard-ip-homelab/doc-hmsmailinstalled.avif)

**Connectez-vous** y avec un **client SSH** comme [**PuTTY**](https://www.putty.org/) ou [**Termius**](https://termius.com/).

Nous allons d&apos;abord **préparer** **le VPS** en désinstallant **netplan** et réinstallant **systemd-networking**.

J&apos;ai déjà préparé un **script** qui fais tout cela **automatiquement**, il vous suffit d&apos;**effectuer la commande ci-dessous** :

```bash
curl -sSL https://raw.githubusercontent.com/tbringuier/wireguard/refs/heads/master/preparevps.sh | bash
```

Le VPS **redémarrera automatiquement** une fois la **préparation effectuée**.

# Installation de Wireguard

**Une fois votre VPS préparé**, nous pouvons nous y **connecter en SSH** grâce à un **client SSH** comme [**PuTTY**](https://www.putty.org/) ou [**Termius**](https://termius.com/)

**Commençons** par **mettre à jour** et **installer** les **paquets principaux** sur le **VPS** :

```bash
apt update
apt full-upgrade -y
apt install wireguard-tools resolvconf iptables arping sudo bash curl arping wget -y
apt autoremove -y
reboot
```

Une fois notre VPS **redémarré**, nous pouvons **déployer le serveur Wireguard** :

```bash
curl -O https://raw.githubusercontent.com/angristan/wireguard-install/master/wireguard-install.sh
chmod +x wireguard-install.sh
bash wireguard-install.sh
```

Un long **setup va démarrer**, nous pouvons **laisser les paramètres par défaut**.

```plaintext
Welcome to the wireguard installer!
The git repository is available at: https://github.com/angristan/wireguard-install

I need to ask you a few questions before starting the setup.
You can keep the default options and just press enter if you are ok with them.

IPv4 or IPv6 public address: 146.19.168.213
Public interface: eth0
wireguard interface name: wg0
Server wireguard IPv4: 10.66.66.1
Server wireguard IPv6: fd42:42:42::1
Server wireguard port [1-65535]: 62052
First DNS resolver to use for the clients: 1.1.1.1
Second DNS resolver to use for the clients (optional): 1.0.0.1

wireguard uses a parameter called AllowedIPs to determine what is routed over the VPN.
Allowed IPs list for generated clients (leave default to route everything): 0.0.0.0/0,::/0

Okay, that was all I needed. We are ready to setup your wireguard server now.
You will be able to generate a client at the end of the installation.
Press any key to continue...
```

Une fois ceci-fait, il nous demandera **le nom de notre profil wireguard**. Dans mon cas je l&apos;appelle MaVM :

```plaintext
The client name must consist of alphanumeric character(s). It may also include underscores or dashes and can&apos;t exceed 15 chars.
Client name: MaVM
```

**On laisse** les adresses IP proposées **par défaut** :

```plaintext
Client wireguard IPv4: 10.66.66.2
Client wireguard IPv6: fd42:42:42::2
```

Une fois le **client créé**, **un QR-Code vous sera affiché** et un **fichier aura été créé** dans le **répertoire actuel**.

**Préparons** notre **serveur wireguard**. **Vous n&apos;avez qu&apos;à faire cette étape une seule fois**.

```bash
nano /etc/wireguard/wg0.conf
```

Voici à quoi ressemble notre **fichier** wg0.conf **initial** :

```ini
[Interface]
Address = 10.66.66.1/24,fd42:42:42::1/64
ListenPort = 62052
PrivateKey = qA0nlMcMHLUGLgbsQ7zsVlvg2NartzikMUMJRNwdeVs=
PostUp = iptables -I INPUT -p udp --dport 62052 -j ACCEPT
PostUp = iptables -I FORWARD -i eth0 -o wg0 -j ACCEPT
PostUp = iptables -I FORWARD -i wg0 -j ACCEPT
PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostUp = ip6tables -I FORWARD -i wg0 -j ACCEPT
PostUp = ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D INPUT -p udp --dport 62052 -j ACCEPT
PostDown = iptables -D FORWARD -i eth0 -o wg0 -j ACCEPT
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT
PostDown = iptables -t nat -D POSTROUTING -o eth0 -s 10.66.66.0/24 -j MASQUERADE
PostDown = ip6tables -D FORWARD -i wg0 -j ACCEPT
PostDown = ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

### Client MaVM
[Peer]
PublicKey = VApiknwvlZmUewjbwZGFYp/77M3XUOSVde8AGcAdgzg=
PresharedKey = t+rgwqN3j8LccHtgi7GULlwBrf8ghY8HAbZN6cagP8s=
AllowedIPs = 10.66.66.2/32,fd42:42:42::2/128
```

Nous devons simplement **remplacer** **les lignes PostUp et PostDown** **par celles ci-dessous** :

```ini
PostUp = iptables -I FORWARD -i eth0 -o wg0 -s 10.66.66.0/24 -j ACCEPT; iptables -I FORWARD -i wg0 -d 10.66.66.0/24 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -s 10.66.66.0/24 -j MASQUERADE; iptables -I INPUT -p udp -s 10.66.66.0/24 -j ACCEPT; ip6tables -I FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i eth0 -o wg0 -s 10.66.66.0/24 -j ACCEPT; iptables -D FORWARD -i wg0 -d 10.66.66.0/24 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -s 10.66.66.0/24 -j MASQUERADE; iptables -D INPUT -p udp -s 10.66.66.0/24 -j ACCEPT; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
```

&gt; [!WARNING]
&gt; N&apos;oubliez pas de remplacer `eth0` par le vrai nom de votre interface (cela peut changer en fonction de l&apos;OS / provider) !

Voici à quoi ressemble notre **fichier** de configuration **after modification** :

```ini
[Interface]
Address = 10.66.66.1/24,fd42:42:42::1/64
ListenPort = 62052
PrivateKey = qA0nlMcMHLUGLgbsQ7zsVlvg2NartzikMUMJRNwdeVs=
PostUp = iptables -I FORWARD -i eth0 -o wg0 -s 10.66.66.0/24 -j ACCEPT; iptables -I FORWARD -i wg0 -d 10.66.66.0/24 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -s 10.66.66.0/24 -j MASQUERADE; iptables -I INPUT -p udp -s 10.66.66.0/24 -j ACCEPT
PostDown = iptables -D FORWARD -i eth0 -o wg0 -s 10.66.66.0/24 -j ACCEPT; iptables -D FORWARD -i wg0 -d 10.66.66.0/24 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -s 10.66.66.0/24 -j MASQUERADE; iptables -D INPUT -p udp -s 10.66.66.0/24 -j ACCEPT

### Client MaVM
[Peer]
PublicKey = VApiknwvlZmUewjbwZGFYp/77M3XUOSVde8AGcAdgzg=
PresharedKey = t+rgwqN3j8LccHtgi7GULlwBrf8ghY8HAbZN6cagP8s=
AllowedIPs = 10.66.66.2/32,fd42:42:42::2/128
```

Après avoir **sauvegardé** le fichier, nous pouvons **activer l&apos;ip forwarding** :

```bash
echo &apos;net.ipv4.ip_forward=1
net.ipv4.conf.all.proxy_arp=1
net.ipv6.conf.all.forwarding=1&apos; | tee -a /etc/sysctl.conf
```

On peut ensuite **redémarrer** notre **VPS** **HMS** :

```bash
reboot
```

Nous pouvons maintenant **modifier la configuration serveur et client** pour **associer** l&apos;**ip supplémentaire**.

```bash
nano /etc/wireguard/wg0.conf
```

```ini
[Interface]
Address = 10.66.66.1/24,fd42:42:42::1/64
ListenPort = 62052
PrivateKey = qA0nlMcMHLUGLgbsQ7zsVlvg2NartzikMUMJRNwdeVs=
PostUp = iptables -I FORWARD -i eth0 -o wg0 -s 10.66.66.0/24 -j ACCEPT; iptables -I FORWARD -i wg0 -d 10.66.66.0/24 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -s 10.66.66.0/24 -j MASQUERADE; iptables -I INPUT -p udp -s 10.66.66.0/24 -j ACCEPT
PostDown = iptables -D FORWARD -i eth0 -o wg0 -s 10.66.66.0/24 -j ACCEPT; iptables -D FORWARD -i wg0 -d 10.66.66.0/24 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -s 10.66.66.0/24 -j MASQUERADE; iptables -D INPUT -p udp -s 10.66.66.0/24 -j ACCEPT

### Client MaVM
[Peer]
PublicKey = VApiknwvlZmUewjbwZGFYp/77M3XUOSVde8AGcAdgzg=
PresharedKey = t+rgwqN3j8LccHtgi7GULlwBrf8ghY8HAbZN6cagP8s=
AllowedIPs = 10.66.66.2/32,fd42:42:42::2/128
```

Nous avons **créé** le **client** MaVM précédemment, il faut maintenant **ajouter** dans les **AllowedIPs** l&apos;**adresse ip supplémentaire**.

```ini
AllowedIPs = 10.66.66.2/32,fd42:42:42::2/128,163.5.121.254/32
```

Voici à quoi ressemble le **fichier modifié** :

```ini
[Interface]
Address = 10.66.66.1/24,fd42:42:42::1/64
ListenPort = 62052
PrivateKey = qA0nlMcMHLUGLgbsQ7zsVlvg2NartzikMUMJRNwdeVs=
PostUp = iptables -I FORWARD -i eth0 -o wg0 -s 10.66.66.0/24 -j ACCEPT; iptables -I FORWARD -i wg0 -d 10.66.66.0/24 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -s 10.66.66.0/24 -j MASQUERADE; iptables -I INPUT -p udp -s 10.66.66.0/24 -j ACCEPT
PostDown = iptables -D FORWARD -i eth0 -o wg0 -s 10.66.66.0/24 -j ACCEPT; iptables -D FORWARD -i wg0 -d 10.66.66.0/24 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -s 10.66.66.0/24 -j MASQUERADE; iptables -D INPUT -p udp -s 10.66.66.0/24 -j ACCEPT

### Client MaVM
[Peer]
PublicKey = VApiknwvlZmUewjbwZGFYp/77M3XUOSVde8AGcAdgzg=
PresharedKey = t+rgwqN3j8LccHtgi7GULlwBrf8ghY8HAbZN6cagP8s=
AllowedIPs = 10.66.66.2/32,fd42:42:42::2/128,163.5.121.254/32
```

Une fois le fichier **sauvegardé**, nous pouvons modifier la **configuration côté client** :

```bash
nano wg0-client-MaVM.conf
```

```ini
[Interface]
PrivateKey = MM2OFVfYrJFtdAgebfPJL2hDtjaslufqoJ1yzvdN+X8=
Address = 10.66.66.2/32,fd42:42:42::2/128
DNS = 1.1.1.1,1.0.0.1

[Peer]
PublicKey = udEYVLpHnWb4o7kgjZ4pCnfUaVjqd9inXAUmak9mXxM=
PresharedKey = t+rgwqN3j8LccHtgi7GULlwBrf8ghY8HAbZN6cagP8s=
Endpoint = 146.19.168.213:62052
AllowedIPs = 0.0.0.0/0,::/0
```

Il faut **remplacer l&apos;adresse IP** **10.66.66.2** **par l&apos;adresse ip supplémentaire** et également **rajouter la ligne** ci-dessous **en dessous de DNS** :

```ini
PostUp = iptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -o wg0 -j TCPMSS --clamp-mss-to-pmtu
```

Voici à quoi ressemble le **fichier modifié** :

```ini
[Interface]
PrivateKey = MM2OFVfYrJFtdAgebfPJL2hDtjaslufqoJ1yzvdN+X8=
Address = 163.5.121.254/32,fd42:42:42::2/128
DNS = 1.1.1.1,1.0.0.1
PostUp = iptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -o wg0 -j TCPMSS --clamp-mss-to-pmtu

[Peer]
PublicKey = udEYVLpHnWb4o7kgjZ4pCnfUaVjqd9inXAUmak9mXxM=
PresharedKey = t+rgwqN3j8LccHtgi7GULlwBrf8ghY8HAbZN6cagP8s=
Endpoint = 146.19.168.213:62052
AllowedIPs = 0.0.0.0/0,::/0
```

Une fois les **modifications apportées**, nous pouvons **relancer le serveur wireguard** pour **appliquer la configuration des clients** :

```bash
systemctl restart wg-quick@wg0
```

Vous pouvez **vérifier l&apos;état du serveur** avec les commandes

```bash
systemctl status wg-quick@wg0
wg show
```

**Notre client est maintenant prêt à être déployé!**

# Déploiement du profil wireguard :

Notre **profil** est maintenant **prêt** à être **déployé** sur **n&apos;importe quelle plateforme** (Windows, Linux, Android, macOS, IOS et plein d&apos;autres!)

Voici les **commandes** **pour** **déployer le profil** **sur un linux** en base Debian :

```bash
# Installer wireguard, Resolvconf et IPTables
apt install wireguard-tools resolvconf iptables

# Installer le profil Wireguard :
nano /etc/wireguard/wg0.conf
(puis coller le profil wireguard (wg0-client-) modifié à l&apos;intérieur)

# Activer et lancer notre profil wireguard au démarrage :
systemctl enable wg-quick@wg0 --now

# Et voilà ! Votre IP est maintenant montée sur cet appareil !
# Vous pouvez vérifier en faisant un
ip a
# ou un
curl ifconfig.me
```

# Diagnostics

**Si jamais le profil ne fonctionne pas**, **vérifiez que vous n&apos;avez pas mélangé les adresses IPs** et **relisez la documentation**. Il peut arriver qu&apos;il y ai des soucis de routage sur le VPS HMS. Dans ce cas **Voici les commande à exécuter SUR LE VPS HMS** pour **résoudre le problème** :

## Étape 1 : Créer le fichier `ips`

1. **Créer le fichier `ips`** dans le répertoire `/root` :

   ```bash
   sudo nano /root/ips
   ```

2. **Ajouter les adresses IP** que vous utilisez avec Wireguard, une par ligne. Par exemple :

   ```
   &lt;ip-additionnelle1&gt;
   &lt;ip-additionnelle2&gt;
   ```

3. **Enregistrer et quitter** l&apos;éditeur (`CTRL + X`, puis `Y`, puis `Entrée`).

## Étape 2 : Configurer le script

1. **Créer le script** ``arping-loop.sh`` dans ``/usr/local/bin`` et coller dedans :

   ```bash
   #!/bin/bash
   while true; do
       for arg in $(&lt; /root/ips); do
           arping -q -c1 -P $arg -S $arg -i eth0 &amp;
       done
       sleep 1
       wait
   done
   ```
   &gt; [!WARNING]
   &gt; N&apos;oubliez pas de remplacer `eth0` par le vrai nom de votre interface (cela peut changer en fonction de l&apos;OS / provider) !

2. **Enregistrer et quitter** l&apos;éditeur (`CTRL + X`, puis `Y`, puis `Entrée`).

3. **Donner la permission** au script de s&apos;exécuter
   ```bash
   chmod +x /usr/local/bin/arping-loop.sh
   ```

4. **Créer le service systemd** ``arping-loop.service`` dans ``/etc/systemd/system/``

   ```ini
   [Unit]
   Description=ARP Loop for keep connection on additional IPs
   After=network.target

   [Service]
   Type=simple
   ExecStart=/usr/local/bin/arping-loop.sh
   Restart=always

   [Install]
   WantedBy=multi-user.target
   ```

5. **Enregistrer et quitter** l&apos;éditeur (`CTRL + X`, puis `Y`, puis `Entrée`).

6. **Activer le service**

   ```bash
   systemctl daemon-reload
   systemctl enable arping-loop
   systemctl start arping-loop
   ```

## Étape 4 : Vérifier la configuration

1. **Vérifier que la tâche cron a été ajoutée correctement** :

   ```bash
   systemctl status arping-loop
   ```

2. **Vérifier que le script fonctionne** en l&apos;exécutant manuellement une première fois :

   ```bash
   bash /usr/local/bin/arping-loop.sh
   ```

Tout devrait être opérationnel si aucune erreur ne survient !

# Conclusion &amp; Remerciements

**Et voilà**, **vous avez maintenant des IP Failovers disponibles chez vous**, **protégées par Anti-DDOS**, **sur n&apos;importe quel appareil !**

Cette **astuce** m&apos;a permis de franchir un **grand pas dans l&apos;auto-hébergement**, que ce soit pour des **services pour moi** ou **pour les autres**, car elle m&apos;offre la puissance d&apos;avoir des **VPS** avec des **IP dédiées à prix réduit** et avec un **service de qualité similaire**.

**Ce tutoriel existe initialement depuis juillet 2020**, mais a été remasterisé **récemment** en **septembre 2024** avec beaucoup d&apos;**améliorations** et de **mises à jour**.

## Je tiens à remercier :

- [@Aven678](https://github.com/Aven678/) : Pour avoir simplifié énormément la gestion des IPs et la création de profils.
- [@DrKnaw](https://github.com/DrKnaw) : Pour avoir patché des bugs liés à mon système qui n&apos;était pas tout à fait fini à l&apos;époque.
- [@MaelMagnien](https://web.archive.org/web/20240108141946/https://github.com/maelmagnien) : Qui a entièrement testé le tutoriel pour voir que tout fonctionne.
- [@Gogow_](https://github.com/Gogowwww) : Qui m&apos;a également fait débugger plusieurs fois ma doc.
- [@Diggyworld](https://github.com/Diggyworld) : Qui a remarqué et passé toute une soirée à trouver une solution pour ces fichus soucis de MTU
- [@titin](https://git.feelb.io/Titin) : Pour avoir trouvé la commande arping pour régler certains soucis de routage
- [@Hecate](https://github.com/TheHecateII) : Pour la commande iptables pour les soucis de MTU
- [@TheOrion-OVH](https://github.com/TheOrion-OVH) : Pour le correctif ARP qui fonctionnais une fois sur 2 et quelques erreurs de typo dans la documentation.

Et plein d&apos;autres personnes qui m&apos;ont envoyé un message sur Discord pour m&apos;aider à améliorer cette documentation ou me remercier.

## Si vous souhaitez approfondir

Il est possible d&apos;**implémenter différemment** ces **tunnels** **wireguard**, avec un **routeur** **centralisé** qui **distribue** ensuite **les IPs** **aux VMs**. Cela permet d&apos;**éviter** de **déployer** un **profil** **wireguard** **par** **client**. Un **ami** a moi a **rédigé** une **super documentation** pour monter les addresses sur un **routeur** **VyOS** :

[Router un subnet IPv4 chez soi avec WireGuard + VyOS](https://blog.azernet.xyz/router-un-subnet-ipv4-chez-soi-avec-wireguard-vyos-2/)

Si d&apos;autres personnes souhaitent faire figurer leurs « forks » de cette documentation, n&apos;hésitez pas à me DM Discord ou Telegram !

## [Avoir des adresses IPv4/IPv6 chez soi avec un tunnel Wireguard]({{ site.url }}/wireguard) by [{{ site.author.name }}]({{ site.url }}) is licensed under [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/)

### Implémentations futures (quand j&apos;aurais le temps de les écrire) :

- Firewalling avec UFW
- Routage bloc IPv6
</content>
 </entry>
 

</feed>
