{
    "version": "https://jsonfeed.org/version/1",
    "title": "blog.folf.fr",
    "home_page_url": "https://blog.folf.fr/",
    "feed_url": "https://blog.folf.fr/feed.json",
    "description": "Blog technique de Tristan BRINGUIER — auto-hébergement, cybersécurité et réseaux",
    "favicon": "https://blog.folf.fr/assets/static/site/favicon.png",
    "expired": false,
    "author": {
        "name": "Tristan BRINGUIER",
        "url": "https://blog.folf.fr/"
    },
    "items": [
    
    
        
        
        {
            "id": "https://blog.folf.fr/snippets/2026/03/16/naim-uniti/",
            "title": "Naim Uniti — API HTTP",
            "summary": "Cheat sheet complète de l'API HTTP locale des amplis Naim Uniti (Atom, Star, Nova, NDX2, ND5 XS2, ND555, Mu-so 2)",
            "content_text": "> [!NOTE]> Il n'existe **aucune documentation officielle** de Naim Audio pour cette API. Tout a été reverse-engineered depuis le trafic réseau de l'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'authentification** (réseau local uniquement)- **URL de base** : `http://:15081`- **Hostname mDNS** : `-.local````http://192.168.1.42:15081```## Informations système- ```shell  curl http://:15081/  ```  - Retourne la version de l'API, le changestamp, la classe (`object.api.support`), la charge CPU.- ```shell  curl http://:15081/system  ```  - Infos complètes : `model`, `hostname`, `hardwareSerial`, `hardwareType`, `appVer` (firmware), `ipAddress`, `kernel`, `machine`, `udid`, `displayType`, `firstTimeSetupComplete`.## Alimentation- ```shell  curl http://:15081/power  ```  - État actuel : `system` (`on` / `lona`), `state` (`on` / `standby`), `powerMode`, `serverMode`, `standbyTimeout`.- ```shell  curl -X PUT \"http://:15081/power?system=on\"  ```  - Allumer l'appareil.- ```shell  curl -X PUT \"http://:15081/power?system=lona\"  ```  - Mettre en veille. La valeur est bien `lona`, pas `off` ni `standby`.## Volume / Audio- ```shell  curl http://:15081/levels/room  ```  - Retourne `volume` (0-100), `mute` (0/1), `balance` (-50 à 50), `headphoneDetect` (0/1).- ```shell  curl http://:15081/levels  ```  - Vue d'ensemble des niveaux audio (idem + `mode`).- ```shell  curl -X PUT \"http://:15081/levels/room?volume=45\"  ```  - Régler le volume (entier, 0 à 100).- ```shell  curl -X PUT \"http://:15081/levels/room?mute=1\"  ```  - Couper le son.- ```shell  curl -X PUT \"http://:15081/levels/room?mute=0\"  ```  - Rétablir le son.- ```shell  curl -X PUT \"http://:15081/levels/room?balance=-20\"  ```  - Régler la balance (-50 = tout à gauche, 50 = tout à droite).## Lecture / Transport- ```shell  curl http://: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 \"http://:15081/nowplaying?cmd=play\"  ```  - Lecture.- ```shell  curl \"http://:15081/nowplaying?cmd=pause\"  ```  - Pause.- ```shell  curl \"http://:15081/nowplaying?cmd=playpause\"  ```  - Basculer lecture/pause.- ```shell  curl \"http://:15081/nowplaying?cmd=stop\"  ```  - Arrêt.- ```shell  curl \"http://:15081/nowplaying?cmd=next\"  ```  - Piste suivante.- ```shell  curl \"http://:15081/nowplaying?cmd=prev\"  ```  - Piste précédente.- ```shell  curl \"http://:15081/nowplaying?cmd=seek&position=120000\"  ```  - Seek à la position donnée (en millisecondes, ici 2 min).- ```shell  curl -X PUT \"http://:15081/nowplaying?repeat=0\"  ```  - Répétition désactivée.- ```shell  curl -X PUT \"http://:15081/nowplaying?repeat=1\"  ```  - Répéter la piste en cours.- ```shell  curl -X PUT \"http://:15081/nowplaying?repeat=2\"  ```  - Répéter toute la file.- ```shell  curl -X PUT \"http://:15081/nowplaying?shuffle=1\"  ```  - Activer la lecture aléatoire.- ```shell  curl -X PUT \"http://:15081/nowplaying?shuffle=0\"  ```  - Désactiver la lecture aléatoire.## Sources / Entrées- ```shell  curl http://:15081/inputs  ```  - Liste toutes les sources disponibles. Chaque entrée contient `name`, `ussi`, `class`, `alias`, `disabled`, `selectable`, `multiroomMaster`.- ```shell  curl http://:15081/inputs/spotify  ```  - Infos sur une source spécifique.- ```shell  curl \"http://:15081/inputs/spotify?cmd=select\"  ```  - Basculer sur cette source.- ```shell  curl \"http://:15081/inputs/radio?cmd=play\"  ```  - Sélectionner et lancer la lecture d'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 | — |> [!TIP]> Toutes les sources ne sont pas présentes sur tous les modèles. L'endpoint `/inputs` retourne uniquement celles disponibles sur votre appareil.## Favoris / Presets- ```shell  curl http://:15081/favourites  ```  - Liste tous les favoris. Chaque favori contient `name`, `ussi`, `available`.- ```shell  curl \"http://:15081/favourites/3754de0b49624983ab2179ed8524e9a2?cmd=play\"  ```  - Lancer un favori par son UUID (portion après `favourites/` dans le champ `ussi`).## File de lecture- ```shell  curl http://: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://: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/UPnPLes appareils Naim s'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'en-tête `LOCATION` pointe vers le XML de description contenant `manufacturer`, `friendlyName`, `modelName`, `serialNumber`, `UDN`.## Socket TCP temps réel (port 4545)> [!IMPORTANT]> Ce n'est **pas du HTTP**. C'est une connexion TCP brute qui pousse du JSON en continu.- ```shell  nc  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{  \"data\": {    \"state\": \"playing\",    \"trackRoles\": {      \"title\": \"Nom de la piste\",      \"icon\": \"https://url-artwork...\",      \"mediaData\": {        \"metaData\": {          \"artist\": \"Artiste\",          \"album\": \"Album\"        },        \"activeResource\": {          \"bitsPerSample\": \"24\",          \"sampleFrequency\": \"96000\"        }      }    },    \"mediaRoles\": {      \"title\": \"Nom de la source\",      \"mediaData\": {        \"metaData\": {          \"serviceID\": \"spotify\"        }      }    },    \"status\": {      \"duration\": 355000    }  },  \"playTime\": {    \"i64_\": 45000  }}```",
            "content_html": "> [!NOTE]> Il n'existe **aucune documentation officielle** de Naim Audio pour cette API. Tout a été reverse-engineered depuis le trafic réseau de l'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'authentification** (réseau local uniquement)- **URL de base** : `http://<IP>:15081`- **Hostname mDNS** : `<modèle>-<serial>.local````http://192.168.1.42:15081```## Informations système- ```shell  curl http://<IP>:15081/  ```  - Retourne la version de l'API, le changestamp, la classe (`object.api.support`), la charge CPU.- ```shell  curl http://<IP>:15081/system  ```  - Infos complètes : `model`, `hostname`, `hardwareSerial`, `hardwareType`, `appVer` (firmware), `ipAddress`, `kernel`, `machine`, `udid`, `displayType`, `firstTimeSetupComplete`.## Alimentation- ```shell  curl http://<IP>:15081/power  ```  - État actuel : `system` (`on` / `lona`), `state` (`on` / `standby`), `powerMode`, `serverMode`, `standbyTimeout`.- ```shell  curl -X PUT \"http://<IP>:15081/power?system=on\"  ```  - Allumer l'appareil.- ```shell  curl -X PUT \"http://<IP>:15081/power?system=lona\"  ```  - Mettre en veille. La valeur est bien `lona`, pas `off` ni `standby`.## Volume / Audio- ```shell  curl http://<IP>:15081/levels/room  ```  - Retourne `volume` (0-100), `mute` (0/1), `balance` (-50 à 50), `headphoneDetect` (0/1).- ```shell  curl http://<IP>:15081/levels  ```  - Vue d'ensemble des niveaux audio (idem + `mode`).- ```shell  curl -X PUT \"http://<IP>:15081/levels/room?volume=45\"  ```  - Régler le volume (entier, 0 à 100).- ```shell  curl -X PUT \"http://<IP>:15081/levels/room?mute=1\"  ```  - Couper le son.- ```shell  curl -X PUT \"http://<IP>:15081/levels/room?mute=0\"  ```  - Rétablir le son.- ```shell  curl -X PUT \"http://<IP>:15081/levels/room?balance=-20\"  ```  - Régler la balance (-50 = tout à gauche, 50 = tout à droite).## Lecture / Transport- ```shell  curl http://<IP>: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 \"http://<IP>:15081/nowplaying?cmd=play\"  ```  - Lecture.- ```shell  curl \"http://<IP>:15081/nowplaying?cmd=pause\"  ```  - Pause.- ```shell  curl \"http://<IP>:15081/nowplaying?cmd=playpause\"  ```  - Basculer lecture/pause.- ```shell  curl \"http://<IP>:15081/nowplaying?cmd=stop\"  ```  - Arrêt.- ```shell  curl \"http://<IP>:15081/nowplaying?cmd=next\"  ```  - Piste suivante.- ```shell  curl \"http://<IP>:15081/nowplaying?cmd=prev\"  ```  - Piste précédente.- ```shell  curl \"http://<IP>:15081/nowplaying?cmd=seek&position=120000\"  ```  - Seek à la position donnée (en millisecondes, ici 2 min).- ```shell  curl -X PUT \"http://<IP>:15081/nowplaying?repeat=0\"  ```  - Répétition désactivée.- ```shell  curl -X PUT \"http://<IP>:15081/nowplaying?repeat=1\"  ```  - Répéter la piste en cours.- ```shell  curl -X PUT \"http://<IP>:15081/nowplaying?repeat=2\"  ```  - Répéter toute la file.- ```shell  curl -X PUT \"http://<IP>:15081/nowplaying?shuffle=1\"  ```  - Activer la lecture aléatoire.- ```shell  curl -X PUT \"http://<IP>:15081/nowplaying?shuffle=0\"  ```  - Désactiver la lecture aléatoire.## Sources / Entrées- ```shell  curl http://<IP>:15081/inputs  ```  - Liste toutes les sources disponibles. Chaque entrée contient `name`, `ussi`, `class`, `alias`, `disabled`, `selectable`, `multiroomMaster`.- ```shell  curl http://<IP>:15081/inputs/spotify  ```  - Infos sur une source spécifique.- ```shell  curl \"http://<IP>:15081/inputs/spotify?cmd=select\"  ```  - Basculer sur cette source.- ```shell  curl \"http://<IP>:15081/inputs/radio?cmd=play\"  ```  - Sélectionner et lancer la lecture d'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 | — |> [!TIP]> Toutes les sources ne sont pas présentes sur tous les modèles. L'endpoint `/inputs` retourne uniquement celles disponibles sur votre appareil.## Favoris / Presets- ```shell  curl http://<IP>:15081/favourites  ```  - Liste tous les favoris. Chaque favori contient `name`, `ussi`, `available`.- ```shell  curl \"http://<IP>:15081/favourites/3754de0b49624983ab2179ed8524e9a2?cmd=play\"  ```  - Lancer un favori par son UUID (portion après `favourites/` dans le champ `ussi`).## File de lecture- ```shell  curl http://<IP>: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://<IP>: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/UPnPLes appareils Naim s'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'en-tête `LOCATION` pointe vers le XML de description contenant `manufacturer`, `friendlyName`, `modelName`, `serialNumber`, `UDN`.## Socket TCP temps réel (port 4545)> [!IMPORTANT]> Ce n'est **pas du HTTP**. C'est une connexion TCP brute qui pousse du JSON en continu.- ```shell  nc <IP> 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{  \"data\": {    \"state\": \"playing\",    \"trackRoles\": {      \"title\": \"Nom de la piste\",      \"icon\": \"https://url-artwork...\",      \"mediaData\": {        \"metaData\": {          \"artist\": \"Artiste\",          \"album\": \"Album\"        },        \"activeResource\": {          \"bitsPerSample\": \"24\",          \"sampleFrequency\": \"96000\"        }      }    },    \"mediaRoles\": {      \"title\": \"Nom de la source\",      \"mediaData\": {        \"metaData\": {          \"serviceID\": \"spotify\"        }      }    },    \"status\": {      \"duration\": 355000    }  },  \"playTime\": {    \"i64_\": 45000  }}```",
            "url": "https://blog.folf.fr/snippets/2026/03/16/naim-uniti/",
            "tags": ["audio","api","naim"],
            "date_published": "2026-04-22T14:16:25+00:00",
            "date_modified": "2026-04-27T08:19:13+00:00",
            "author": {
                "name": "Tristan BRINGUIER",
                "url": "https://blog.folf.fr/"
            }
        },
    
        
        
        {
            "id": "https://blog.folf.fr/snippets/2026/03/01/pipewire/",
            "title": "PipeWire Tips & Tricks",
            "summary": "Comment configurer convenablement son DAC pour de la hi-res avec un serveur de son PipeWire sous Linux.",
            "content_text": "## 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 = {  \t# Fréquence par défaut  \tdefault.clock.rate          = 384000  \t  \t# Autoriser PipeWire à basculer automatiquement sur ces fréquences sans rééchantillonner  \tdefault.clock.allowed-rates = [ 44100 48000 88200 96000 176400 192000 352800 384000 ]  \t  \t# Profondeur de bits maximale pour exploiter le DAC  \tdefault.audio.format        = \"S32_LE\"  \t  \t# Amélioration de la latence et réduction des craquements  \tdefault.clock.quantum       = 1024  \tdefault.clock.min-quantum   = 32  \tdefault.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 \"Momentary freq\" /proc/asound/card*/stream0  ```  - Après avoir lancé la lecture d'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_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 = {  \t# Fréquence par défaut  \tdefault.clock.rate          = 384000  \t  \t# Autoriser PipeWire à basculer automatiquement sur ces fréquences sans rééchantillonner  \tdefault.clock.allowed-rates = [ 44100 48000 88200 96000 176400 192000 352800 384000 ]  \t  \t# Profondeur de bits maximale pour exploiter le DAC  \tdefault.audio.format        = \"S32_LE\"  \t  \t# Amélioration de la latence et réduction des craquements  \tdefault.clock.quantum       = 1024  \tdefault.clock.min-quantum   = 32  \tdefault.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 \"Momentary freq\" /proc/asound/card*/stream0  ```  - Après avoir lancé la lecture d'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 !",
            "url": "https://blog.folf.fr/snippets/2026/03/01/pipewire/",
            "tags": ["linux","audio","pipewire"],
            "date_published": "2026-04-22T14:16:25+00:00",
            "date_modified": "2026-04-27T08:19:13+00:00",
            "author": {
                "name": "Tristan BRINGUIER",
                "url": "https://blog.folf.fr/"
            }
        },
    
        
        
        {
            "id": "https://blog.folf.fr/snippets/2026/03/01/linux-debian-proxmox/",
            "title": "Linux / Debian / Proxmox Tips & Tricks",
            "summary": "Quelques commandes que j'ai appris sur des systèmes Linux après plusieurs années d'usage.",
            "content_text": "## 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'obtenir les métadonnées d'un paquet.## GRUB- ```shell  /etc/default/grub    GRUB_CMDLINE_LINUX=\"net.ifnames=0 biosdevname=0\"  ```  - 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=\"console=tty0 console=ttyS0,115200n8\"  GRUB_TERMINAL=\"console serial\"  GRUB_SERIAL_COMMAND=\"serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1\"    update-grub  update-initramfs -u -k all    sudo systemctl enable serial-getty@ttyS0.service  ```  - Permet d'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=\"%F %T \"  export PROMPT_COMMAND=\"history -a; $PROMPT_COMMAND\"  shopt -s histappend  ```  - Permet de sauvegarder de manière illimitée l'historique bash.  - ```shell  grep -rnw '/path/où/chercher/' -e \"string\"  ```    - Permet de chercher une string de manière récursive dans un dossier voulu.  ## Proxmox- ```shell  bash -c \"$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/pve/kernel-clean.sh)\"  ```  - 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 \"/chemin/vers/image/disque\" --compact  ```  - Permet de compacter un fichier d'image disque- ```shell  zerofree -v /dev/sdaX  ```  - Permet de remplir de zéros les emplacements vides d'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'hôt.e    ```shell    systemctl status mon-service.service    journalctl -u mon-service.service -f    ```    - Permet d'approfondir pourquoi un service ne démarre pas en regardant l'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'agent SSH du client vers l'hôte pour transférer les clés SSH entre les deux.",
            "content_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'obtenir les métadonnées d'un paquet.## GRUB- ```shell  /etc/default/grub    GRUB_CMDLINE_LINUX=\"net.ifnames=0 biosdevname=0\"  ```  - 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=\"console=tty0 console=ttyS0,115200n8\"  GRUB_TERMINAL=\"console serial\"  GRUB_SERIAL_COMMAND=\"serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1\"    update-grub  update-initramfs -u -k all    sudo systemctl enable serial-getty@ttyS0.service  ```  - Permet d'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=\"%F %T \"  export PROMPT_COMMAND=\"history -a; $PROMPT_COMMAND\"  shopt -s histappend  ```  - Permet de sauvegarder de manière illimitée l'historique bash.  - ```shell  grep -rnw '/path/où/chercher/' -e \"string\"  ```    - Permet de chercher une string de manière récursive dans un dossier voulu.  ## Proxmox- ```shell  bash -c \"$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/pve/kernel-clean.sh)\"  ```  - 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 \"/chemin/vers/image/disque\" --compact  ```  - Permet de compacter un fichier d'image disque- ```shell  zerofree -v /dev/sdaX  ```  - Permet de remplir de zéros les emplacements vides d'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'hôt.e    ```shell    systemctl status mon-service.service    journalctl -u mon-service.service -f    ```    - Permet d'approfondir pourquoi un service ne démarre pas en regardant l'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'agent SSH du client vers l'hôte pour transférer les clés SSH entre les deux.",
            "url": "https://blog.folf.fr/snippets/2026/03/01/linux-debian-proxmox/",
            "tags": ["linux","debian","proxmox"],
            "date_published": "2026-04-22T14:16:25+00:00",
            "date_modified": "2026-04-27T08:19:13+00:00",
            "author": {
                "name": "Tristan BRINGUIER",
                "url": "https://blog.folf.fr/"
            }
        },
    
        
        
        {
            "id": "https://blog.folf.fr/snippets/2026/03/01/dell/",
            "title": "Dell Tips & Tricks",
            "summary": "Quelques commandes que j'ai appris avec les équipements Dell.",
            "content_text": "## 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_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.",
            "url": "https://blog.folf.fr/snippets/2026/03/01/dell/",
            "tags": ["dell","reseau","hardware"],
            "date_published": "2026-04-22T14:16:25+00:00",
            "date_modified": "2026-04-27T08:19:13+00:00",
            "author": {
                "name": "Tristan BRINGUIER",
                "url": "https://blog.folf.fr/"
            }
        },
    
        
        
        {
            "id": "https://blog.folf.fr/bunkerweb/",
            "title": "Mettre en place un reverse-proxy sécurisé grâce au WAF BunkerWeb",
            "summary": "Cette documentation guide pas à pas l’auto-hébergement d’un reverse-proxy robuste en s’appuyant sur BunkerWeb, un WAF open-source français..",
            "content_text": "## 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> [!NOTE]> **BunkerWeb peut s'exécuter sur n'importe quel environnement Docker.**> **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 🚀 |> [!NOTE]> **Pour le trafic réseau**, **pensez à autoriser les ports** **80/TCP**, **443/TCP** et **443/UDP**.> 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 'bw-apps' :                                        ###   - Créez-le avec : docker network create bw-apps                           ################################################################################################################# Variables globales ############################## Regroupées sous une ancre YAML (&bw-env) pour pouvoir être ré-utilisées## (« merge key »  [!WARNING]   > 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équate3. **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> [!NOTE]> **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).> [!TIP]> 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).> 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 & 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éploiementCliquez 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_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> [!NOTE]> **BunkerWeb peut s'exécuter sur n'importe quel environnement Docker.**> **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 🚀 |> [!NOTE]> **Pour le trafic réseau**, **pensez à autoriser les ports** **80/TCP**, **443/TCP** et **443/UDP**.> 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 'bw-apps' :                                        ###   - Créez-le avec : docker network create bw-apps                           ################################################################################################################# Variables globales ############################## Regroupées sous une ancre YAML (&bw-env) pour pouvoir être ré-utilisées## (« merge key » <<) dans les différents services.x-bw-env: &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: \"127.0.0.0/8 10.20.30.0/24\"  ## Chaîne de connexion à la base PostgreSQL (SQLAlchemy).  ## ➜ Changez le mot de passe.  DATABASE_URI: \"postgresql://bunkerweb:motdepasseachanger@bw-db:5432/db\"#################################################################################                                   Services                                #################################################################################services:  ###########################################################################  ## 1. Reverse-proxy / WAF                                                ##  ###########################################################################  bunkerweb:    image: bunkerity/bunkerweb:latest      ## Utilise la dernière image stable    ## ── Ports exposés ──────────────────────────────────────────────────────    ports:      - \"80:8080/tcp\"    ## HTTP  vers port interne 8080      - \"443:8443/tcp\"   ## HTTPS vers port interne 8443      - \"443:8443/udp\"   ## HTTP/3 (QUIC) sur le même port 8443 en UDP    ## ── Variables d’environnement ─────────────────────────────────────────    environment:      <<: *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: \"10m\"                 ## Rotation : 10 Mo par fichier        max-file: \"10\"                   ## Garde 10 fichiers  ###########################################################################  ## 2. Ordonnanceur (scheduler)                                           ##  ###########################################################################  bw-scheduler:    image: bunkerity/bunkerweb-scheduler:latest    environment:      <<: *bw-env      BUNKERWEB_INSTANCES: \"bunkerweb\"      SERVER_NAME: \"\"      MULTISITE: \"yes\"      UI_HOST: \"http://bw-ui:7000\"    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:      <<: *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: \"db\"      POSTGRES_USER: \"bunkerweb\"      ## ☠️ À CHANGER ABSOLUMENT AVANT PROD !      ##   ➜ Pensez aussi à mettre à jour DATABASE_URI plus haut.      POSTGRES_PASSWORD: \"motdepasseachanger\"    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 & 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'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** `\"motdepasseachanger\"` **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) :```shellsed -i -e \"s|motdepasseachanger|$(openssl rand -base64 32 | tr -dc 'A-Za-z0-9' | head -c32)|g\" -e '/^\\s*#/d' -e 's/\\s*#.*$//' compose.yaml``````shelldocker 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 web1. **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)   > [!WARNING]   > 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équate3. **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> [!NOTE]> **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).> [!TIP]> 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).> 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 & 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éploiementCliquez 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",
            "url": "https://blog.folf.fr/bunkerweb/",
            "tags": ["bunkerweb","waf","nginx","selfhosting","reverse-proxy"],
            "date_published": "2026-04-22T14:16:25+00:00",
            "date_modified": "2026-04-27T08:19:13+00:00",
            "author": {
                "name": "Tristan BRINGUIER",
                "url": "https://blog.folf.fr/"
            }
        },
    
        
        
        {
            "id": "https://blog.folf.fr/wireguard/",
            "title": "Avoir des adresses IPv4/IPv6 chez soi avec un tunnel Wireguard",
            "summary": "Comment j'ai réussi à monter des IP Failover chez moi !",
            "content_text": "# IntroductionJ'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'héberger **différents services** pour mes diverses activités d'**auto-hébergement**.Seulement, ne possédant qu'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'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'ayant trouvé aucune solution existante, j'ai bidouillé et mis en place la mienne.# Principe de fonctionnement![Comment fonctionne l'internet](/assets/contenu/img/posts/tunnel-wireguard-ip-homelab/doc-schema-hms.avif)# Le choix de l'hébergeurJ'ai choisi [**HostMyServers**](https://www.hostmyservers.fr/), un **hébergeur français** 🇫🇷 avec **plusieurs années d'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'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'est le **tarif des adresses IP supplémentaires**. Chez HMS, elles **coûtent 2€ à vie**.D'**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'adresses IP supplémentaire**Pour faire marcher cette documentation, il est nécessaire d'avoir plusieurs adresses IPv4 sur le VPS.**Depuis la rubrique \"**Configuration**\" sur votre VPS vous pouvez cliquer sur \"**Commander IP Supplémentaires**\" afin d'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'unité**. (les blocs ne sont pas assez intuitifs à mon goût dans l'espace client pour le moment)Une fois l'**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'adresse IP principale du VPS** est celle qui **possède** un **reverse DNS associée**.- **L'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.> [!WARNING]> Commandez raisonnablement des adresses IPv4, il n'y en a plus beaucoup, et il est inutile d'en claim si elles restent inutilisées.# Préparation du VPS**Cette partie de la documentation s'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'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'abord **préparer** **le VPS** en désinstallant **netplan** et réinstallant **systemd-networking**.J'ai déjà préparé un **script** qui fais tout cela **automatiquement**, il vous suffit d'**effectuer la commande ci-dessous** :```bashcurl -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** :```bashapt updateapt full-upgrade -yapt install wireguard-tools resolvconf iptables arping sudo bash curl arping wget -yapt autoremove -yreboot```Une fois notre VPS **redémarré**, nous pouvons **déployer le serveur Wireguard** :```bashcurl -O https://raw.githubusercontent.com/angristan/wireguard-install/master/wireguard-install.shchmod +x wireguard-install.shbash wireguard-install.sh```Un long **setup va démarrer**, nous pouvons **laisser les paramètres par défaut**.```plaintextWelcome to the wireguard installer!The git repository is available at: https://github.com/angristan/wireguard-installI 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.213Public interface: eth0wireguard interface name: wg0Server wireguard IPv4: 10.66.66.1Server wireguard IPv6: fd42:42:42::1Server wireguard port [1-65535]: 62052First DNS resolver to use for the clients: 1.1.1.1Second DNS resolver to use for the clients (optional): 1.0.0.1wireguard 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,::/0Okay, 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'appelle MaVM :```plaintextThe client name must consist of alphanumeric character(s). It may also include underscores or dashes and can't exceed 15 chars.Client name: MaVM```**On laisse** les adresses IP proposées **par défaut** :```plaintextClient wireguard IPv4: 10.66.66.2Client 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'avez qu'à faire cette étape une seule fois**.```bashnano /etc/wireguard/wg0.conf```Voici à quoi ressemble notre **fichier** wg0.conf **initial** :```ini[Interface]Address = 10.66.66.1/24,fd42:42:42::1/64ListenPort = 62052PrivateKey = qA0nlMcMHLUGLgbsQ7zsVlvg2NartzikMUMJRNwdeVs=PostUp = iptables -I INPUT -p udp --dport 62052 -j ACCEPTPostUp = iptables -I FORWARD -i eth0 -o wg0 -j ACCEPTPostUp = iptables -I FORWARD -i wg0 -j ACCEPTPostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADEPostUp = ip6tables -I FORWARD -i wg0 -j ACCEPTPostUp = ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADEPostDown = iptables -D INPUT -p udp --dport 62052 -j ACCEPTPostDown = iptables -D FORWARD -i eth0 -o wg0 -j ACCEPTPostDown = iptables -D FORWARD -i wg0 -j ACCEPTPostDown = iptables -t nat -D POSTROUTING -o eth0 -s 10.66.66.0/24 -j MASQUERADEPostDown = ip6tables -D FORWARD -i wg0 -j ACCEPTPostDown = 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** :```iniPostUp = 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 MASQUERADEPostDown = 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```> [!WARNING]> N'oubliez pas de remplacer `eth0` par le vrai nom de votre interface (cela peut changer en fonction de l'OS / provider) !Voici à quoi ressemble notre **fichier** de configuration **after modification** :```ini[Interface]Address = 10.66.66.1/24,fd42:42:42::1/64ListenPort = 62052PrivateKey = 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 ACCEPTPostDown = 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'ip forwarding** :```bashecho 'net.ipv4.ip_forward=1net.ipv4.conf.all.proxy_arp=1net.ipv6.conf.all.forwarding=1' | tee -a /etc/sysctl.conf```On peut ensuite **redémarrer** notre **VPS** **HMS** :```bashreboot```Nous pouvons maintenant **modifier la configuration serveur et client** pour **associer** l'**ip supplémentaire**.```bashnano /etc/wireguard/wg0.conf``````ini[Interface]Address = 10.66.66.1/24,fd42:42:42::1/64ListenPort = 62052PrivateKey = 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 ACCEPTPostDown = 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'**adresse ip supplémentaire**.```iniAllowedIPs = 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/64ListenPort = 62052PrivateKey = 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 ACCEPTPostDown = 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** :```bashnano wg0-client-MaVM.conf``````ini[Interface]PrivateKey = MM2OFVfYrJFtdAgebfPJL2hDtjaslufqoJ1yzvdN+X8=Address = 10.66.66.2/32,fd42:42:42::2/128DNS = 1.1.1.1,1.0.0.1[Peer]PublicKey = udEYVLpHnWb4o7kgjZ4pCnfUaVjqd9inXAUmak9mXxM=PresharedKey = t+rgwqN3j8LccHtgi7GULlwBrf8ghY8HAbZN6cagP8s=Endpoint = 146.19.168.213:62052AllowedIPs = 0.0.0.0/0,::/0```Il faut **remplacer l'adresse IP** **10.66.66.2** **par l'adresse ip supplémentaire** et également **rajouter la ligne** ci-dessous **en dessous de DNS** :```iniPostUp = 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/128DNS = 1.1.1.1,1.0.0.1PostUp = 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:62052AllowedIPs = 0.0.0.0/0,::/0```Une fois les **modifications apportées**, nous pouvons **relancer le serveur wireguard** pour **appliquer la configuration des clients** :```bashsystemctl restart wg-quick@wg0```Vous pouvez **vérifier l'état du serveur** avec les commandes```bashsystemctl status wg-quick@wg0wg 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'importe quelle plateforme** (Windows, Linux, Android, macOS, IOS et plein d'autres!)Voici les **commandes** **pour** **déployer le profil** **sur un linux** en base Debian :```bash# Installer wireguard, Resolvconf et IPTablesapt install wireguard-tools resolvconf iptables# Installer le profil Wireguard :nano /etc/wireguard/wg0.conf(puis coller le profil wireguard (wg0-client-) modifié à l'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 unip a# ou uncurl ifconfig.me```# Diagnostics**Si jamais le profil ne fonctionne pas**, **vérifiez que vous n'avez pas mélangé les adresses IPs** et **relisez la documentation**. Il peut arriver qu'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 :   ```         ```3. **Enregistrer et quitter** l'éditeur (`CTRL + X`, puis `Y`, puis `Entrée`).## Étape 2 : Configurer le script1. **Créer le script** ``arping-loop.sh`` dans ``/usr/local/bin`` et coller dedans :   ```bash   #!/bin/bash   while true; do       for arg in $( [!WARNING]   > N'oubliez pas de remplacer `eth0` par le vrai nom de votre interface (cela peut changer en fonction de l'OS / provider) !2. **Enregistrer et quitter** l'éditeur (`CTRL + X`, puis `Y`, puis `Entrée`).3. **Donner la permission** au script de s'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'é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 configuration1. **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'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 & Remerciements**Et voilà**, **vous avez maintenant des IP Failovers disponibles chez vous**, **protégées par Anti-DDOS**, **sur n'importe quel appareil !**Cette **astuce** m'a permis de franchir un **grand pas dans l'auto-hébergement**, que ce soit pour des **services pour moi** ou **pour les autres**, car elle m'offre la puissance d'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'**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'était pas tout à fait fini à l'é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'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'autres personnes qui m'ont envoyé un message sur Discord pour m'aider à améliorer cette documentation ou me remercier.## Si vous souhaitez approfondirIl est possible d'**implémenter différemment** ces **tunnels** **wireguard**, avec un **routeur** **centralisé** qui **distribue** ensuite **les IPs** **aux VMs**. Cela permet d'**é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'autres personnes souhaitent faire figurer leurs « forks » de cette documentation, n'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'aurais le temps de les écrire) :- Firewalling avec UFW- Routage bloc IPv6",
            "content_html": "# IntroductionJ'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'héberger **différents services** pour mes diverses activités d'**auto-hébergement**.Seulement, ne possédant qu'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'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'ayant trouvé aucune solution existante, j'ai bidouillé et mis en place la mienne.# Principe de fonctionnement![Comment fonctionne l'internet](/assets/contenu/img/posts/tunnel-wireguard-ip-homelab/doc-schema-hms.avif)# Le choix de l'hébergeurJ'ai choisi [**HostMyServers**](https://www.hostmyservers.fr/), un **hébergeur français** 🇫🇷 avec **plusieurs années d'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'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'est le **tarif des adresses IP supplémentaires**. Chez HMS, elles **coûtent 2€ à vie**.D'**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'adresses IP supplémentaire**Pour faire marcher cette documentation, il est nécessaire d'avoir plusieurs adresses IPv4 sur le VPS.**Depuis la rubrique \"**Configuration**\" sur votre VPS vous pouvez cliquer sur \"**Commander IP Supplémentaires**\" afin d'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'unité**. (les blocs ne sont pas assez intuitifs à mon goût dans l'espace client pour le moment)Une fois l'**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'adresse IP principale du VPS** est celle qui **possède** un **reverse DNS associée**.- **L'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.> [!WARNING]> Commandez raisonnablement des adresses IPv4, il n'y en a plus beaucoup, et il est inutile d'en claim si elles restent inutilisées.# Préparation du VPS**Cette partie de la documentation s'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'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'abord **préparer** **le VPS** en désinstallant **netplan** et réinstallant **systemd-networking**.J'ai déjà préparé un **script** qui fais tout cela **automatiquement**, il vous suffit d'**effectuer la commande ci-dessous** :```bashcurl -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** :```bashapt updateapt full-upgrade -yapt install wireguard-tools resolvconf iptables arping sudo bash curl arping wget -yapt autoremove -yreboot```Une fois notre VPS **redémarré**, nous pouvons **déployer le serveur Wireguard** :```bashcurl -O https://raw.githubusercontent.com/angristan/wireguard-install/master/wireguard-install.shchmod +x wireguard-install.shbash wireguard-install.sh```Un long **setup va démarrer**, nous pouvons **laisser les paramètres par défaut**.```plaintextWelcome to the wireguard installer!The git repository is available at: https://github.com/angristan/wireguard-installI 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.213Public interface: eth0wireguard interface name: wg0Server wireguard IPv4: 10.66.66.1Server wireguard IPv6: fd42:42:42::1Server wireguard port [1-65535]: 62052First DNS resolver to use for the clients: 1.1.1.1Second DNS resolver to use for the clients (optional): 1.0.0.1wireguard 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,::/0Okay, 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'appelle MaVM :```plaintextThe client name must consist of alphanumeric character(s). It may also include underscores or dashes and can't exceed 15 chars.Client name: MaVM```**On laisse** les adresses IP proposées **par défaut** :```plaintextClient wireguard IPv4: 10.66.66.2Client 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'avez qu'à faire cette étape une seule fois**.```bashnano /etc/wireguard/wg0.conf```Voici à quoi ressemble notre **fichier** wg0.conf **initial** :```ini[Interface]Address = 10.66.66.1/24,fd42:42:42::1/64ListenPort = 62052PrivateKey = qA0nlMcMHLUGLgbsQ7zsVlvg2NartzikMUMJRNwdeVs=PostUp = iptables -I INPUT -p udp --dport 62052 -j ACCEPTPostUp = iptables -I FORWARD -i eth0 -o wg0 -j ACCEPTPostUp = iptables -I FORWARD -i wg0 -j ACCEPTPostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADEPostUp = ip6tables -I FORWARD -i wg0 -j ACCEPTPostUp = ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADEPostDown = iptables -D INPUT -p udp --dport 62052 -j ACCEPTPostDown = iptables -D FORWARD -i eth0 -o wg0 -j ACCEPTPostDown = iptables -D FORWARD -i wg0 -j ACCEPTPostDown = iptables -t nat -D POSTROUTING -o eth0 -s 10.66.66.0/24 -j MASQUERADEPostDown = ip6tables -D FORWARD -i wg0 -j ACCEPTPostDown = 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** :```iniPostUp = 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 MASQUERADEPostDown = 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```> [!WARNING]> N'oubliez pas de remplacer `eth0` par le vrai nom de votre interface (cela peut changer en fonction de l'OS / provider) !Voici à quoi ressemble notre **fichier** de configuration **after modification** :```ini[Interface]Address = 10.66.66.1/24,fd42:42:42::1/64ListenPort = 62052PrivateKey = 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 ACCEPTPostDown = 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'ip forwarding** :```bashecho 'net.ipv4.ip_forward=1net.ipv4.conf.all.proxy_arp=1net.ipv6.conf.all.forwarding=1' | tee -a /etc/sysctl.conf```On peut ensuite **redémarrer** notre **VPS** **HMS** :```bashreboot```Nous pouvons maintenant **modifier la configuration serveur et client** pour **associer** l'**ip supplémentaire**.```bashnano /etc/wireguard/wg0.conf``````ini[Interface]Address = 10.66.66.1/24,fd42:42:42::1/64ListenPort = 62052PrivateKey = 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 ACCEPTPostDown = 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'**adresse ip supplémentaire**.```iniAllowedIPs = 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/64ListenPort = 62052PrivateKey = 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 ACCEPTPostDown = 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** :```bashnano wg0-client-MaVM.conf``````ini[Interface]PrivateKey = MM2OFVfYrJFtdAgebfPJL2hDtjaslufqoJ1yzvdN+X8=Address = 10.66.66.2/32,fd42:42:42::2/128DNS = 1.1.1.1,1.0.0.1[Peer]PublicKey = udEYVLpHnWb4o7kgjZ4pCnfUaVjqd9inXAUmak9mXxM=PresharedKey = t+rgwqN3j8LccHtgi7GULlwBrf8ghY8HAbZN6cagP8s=Endpoint = 146.19.168.213:62052AllowedIPs = 0.0.0.0/0,::/0```Il faut **remplacer l'adresse IP** **10.66.66.2** **par l'adresse ip supplémentaire** et également **rajouter la ligne** ci-dessous **en dessous de DNS** :```iniPostUp = 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/128DNS = 1.1.1.1,1.0.0.1PostUp = 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:62052AllowedIPs = 0.0.0.0/0,::/0```Une fois les **modifications apportées**, nous pouvons **relancer le serveur wireguard** pour **appliquer la configuration des clients** :```bashsystemctl restart wg-quick@wg0```Vous pouvez **vérifier l'état du serveur** avec les commandes```bashsystemctl status wg-quick@wg0wg 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'importe quelle plateforme** (Windows, Linux, Android, macOS, IOS et plein d'autres!)Voici les **commandes** **pour** **déployer le profil** **sur un linux** en base Debian :```bash# Installer wireguard, Resolvconf et IPTablesapt install wireguard-tools resolvconf iptables# Installer le profil Wireguard :nano /etc/wireguard/wg0.conf(puis coller le profil wireguard (wg0-client-) modifié à l'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 unip a# ou uncurl ifconfig.me```# Diagnostics**Si jamais le profil ne fonctionne pas**, **vérifiez que vous n'avez pas mélangé les adresses IPs** et **relisez la documentation**. Il peut arriver qu'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 :   ```   <ip-additionnelle1>   <ip-additionnelle2>   ```3. **Enregistrer et quitter** l'éditeur (`CTRL + X`, puis `Y`, puis `Entrée`).## Étape 2 : Configurer le script1. **Créer le script** ``arping-loop.sh`` dans ``/usr/local/bin`` et coller dedans :   ```bash   #!/bin/bash   while true; do       for arg in $(< /root/ips); do           arping -q -c1 -P $arg -S $arg -i eth0 &       done       sleep 1       wait   done   ```   > [!WARNING]   > N'oubliez pas de remplacer `eth0` par le vrai nom de votre interface (cela peut changer en fonction de l'OS / provider) !2. **Enregistrer et quitter** l'éditeur (`CTRL + X`, puis `Y`, puis `Entrée`).3. **Donner la permission** au script de s'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'é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 configuration1. **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'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 & Remerciements**Et voilà**, **vous avez maintenant des IP Failovers disponibles chez vous**, **protégées par Anti-DDOS**, **sur n'importe quel appareil !**Cette **astuce** m'a permis de franchir un **grand pas dans l'auto-hébergement**, que ce soit pour des **services pour moi** ou **pour les autres**, car elle m'offre la puissance d'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'**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'était pas tout à fait fini à l'é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'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'autres personnes qui m'ont envoyé un message sur Discord pour m'aider à améliorer cette documentation ou me remercier.## Si vous souhaitez approfondirIl est possible d'**implémenter différemment** ces **tunnels** **wireguard**, avec un **routeur** **centralisé** qui **distribue** ensuite **les IPs** **aux VMs**. Cela permet d'**é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'autres personnes souhaitent faire figurer leurs « forks » de cette documentation, n'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'aurais le temps de les écrire) :- Firewalling avec UFW- Routage bloc IPv6",
            "url": "https://blog.folf.fr/wireguard/",
            "tags": ["tunnel","hostmyservers","hms","ipfailover","ipfo","wireguard"],
            "date_published": "2026-04-22T14:16:25+00:00",
            "date_modified": "2026-05-06T08:26:45+00:00",
            "author": {
                "name": "Tristan BRINGUIER",
                "url": "https://blog.folf.fr/"
            }
        }
    
    ]
}
