📊 LAB : Cartographie Réseau et IPAM avec Scanopy
_____
/ ___|
\ `--. ___ __ _ _ __ ___ _ __ _ _
`--. \/ __/ _` | '_ \ / _ \| '_ \| | | |
/\__/ / (_| (_| | | | | (_) | |_) | |_| |
\____/ \___\__,_|_| |_|\___/| .__/ \__, |
| | __/ |
|_| |___/
Rôle : Administrateur Réseau / Ingénieur DevOps
Mission : Déployer Scanopy, une solution de cartographie réseau distribuée qui agit comme un annuaire IPAM dynamique. Contrairement à un simple scanner, Scanopy s'appuie sur une architecture décentralisée (un serveur central + des démons déportés) pour scanner simultanément plusieurs sous-réseaux isolés (VLANs, DMZ, LAN physique). Il utilise des requêtes de Niveau 2 (ARP) et Niveau 3/4 (ICMP, TCP, UDP, SNMP) pour découvrir les équipements, identifier les ports ouverts, et construire une topologie visuelle interactive.
L'intérêt technique 🎯
- Visibilité Couche 2 (ARP) : Déployer des démons locaux sur chaque sous-réseau permet de récupérer les adresses MAC et de détecter les hôtes furtifs qui bloquent le ping (ICMP), chose impossible au travers d'un routeur.
- Architecture Zero Trust : Le serveur central est isolé en DMZ. Les sondes communiquent avec lui via un modèle Polling (ce sont les sondes qui initient la connexion, le serveur n'ouvre aucun flux vers l'extérieur) en utilisant des jetons d'authentification uniques (API Tokens).
- Sécurité par Design (Moindre Privilège) : Abandon du mode Docker privilégié (
privileged: true) au profit d'une élévation de privilèges granulaire via lesLinux Capabilities(NET_RAW,NET_ADMIN).
🛠️ Architecture du Lab
- Environnement : Serveur Proxmox VE
- Serveur Central (UI + API + DB) : VM Docker (Debian 13)
- IP :
10.0.0.20(Zone DMZ, survmbr2) - Port d'écoute API/Web :
60072TCP
- IP :
- Sonde Locale (DMZ) : Conteneur Docker sur la même VM (
10.0.0.20), chargé de scanner la zone10.0.0.0/24 - Sonde Déportée (LAN) : Conteneur LXC (Debian 13) dédié au scan du réseau physique
- IP :
192.168.1.243(Zone LAN, survmbr0)
- IP :
- Routeur / Pare-feu : pfSense (
192.168.1.251côté WAN)
1️⃣ Installation du Serveur Central (Docker Compose)
Le serveur central et sa base de données sont déployés via Docker Compose sur la VM 10.0.0.20. Le fichier intègre également une sonde locale pour scanner la DMZ.
nano docker-compose.yml
⚠️ Sécurité : Le bloc
daemonofficiel utiliseprivileged: true, qui donne un accès complet au noyau de la VM hôte. On le remplace par lescap_addstrictement nécessaires pour forger des trames réseau.
name: scanopy
services:
# --- BASE DE DONNÉES ---
postgres:
image: postgres:17-alpine
environment:
POSTGRES_DB: scanopy
POSTGRES_USER: postgres
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-<MOT_DE_PASSE>}
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
networks:
- scanopy
# --- SERVEUR CENTRAL ---
server:
image: ghcr.io/scanopy/scanopy/server:latest
ports:
- "60072:60072"
environment:
SCANOPY_LOG_LEVEL: ${SCANOPY_LOG_LEVEL:-info}
SCANOPY_DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD:-<MOT_DE_PASSE>}@postgres:5432/scanopy
SCANOPY_WEB_EXTERNAL_PATH: /app/static
SCANOPY_PUBLIC_URL: ${SCANOPY_PUBLIC_URL:-http://10.0.0.20:60072}
SCANOPY_INTEGRATED_DAEMON_URL: http://host.docker.internal:60073
volumes:
- ./data:/data
extra_hosts:
- "host.docker.internal:host-gateway"
depends_on:
postgres:
condition: service_healthy
restart: unless-stopped
networks:
- scanopy
# --- SONDE LOCALE (DMZ) ---
daemon:
image: ghcr.io/scanopy/scanopy/daemon:latest
container_name: scanopy-daemon
network_mode: host # Obligatoire pour le scan ARP (couche 2)
cap_add: # Moindre Privilège : remplace "privileged: true"
- NET_RAW # Forger des paquets bruts (ARP, ICMP)
- NET_ADMIN # Modifier les interfaces réseau
restart: unless-stopped
environment:
SCANOPY_LOG_LEVEL: ${SCANOPY_LOG_LEVEL:-info}
SCANOPY_SERVER_URL: http://127.0.0.1:60072
volumes:
- daemon-config:/root/.config/daemon
- /var/run/docker.sock:/var/run/docker.sock:ro # Lecture seule des conteneurs
volumes:
postgres_data:
daemon-config:
networks:
scanopy:
driver: bridge
Démarrage de l'infrastructure :
docker compose up -d
L'interface Web est accessible sur http://10.0.0.20:60072.
2️⃣ Configuration IPAM (Interface Web)
Avant de déployer une sonde sur un autre sous-réseau, il faut déclarer ce réseau dans l'application pour générer une identité sécurisée.
- Création du Réseau Logique : Networks > Add Network → Nom :
Network LAN - Création du Sous-réseau : Subnets > Add Subnet → Type :
LAN, CIDR :192.168.1.0/24, Parent :Network LAN - Génération de l'Identité du Démon : Daemons > Create a daemon → Réseau
Network LAN, Nom :scanopy-daemon-network-lan- Copier la commande d'installation, le Token API et l'ID réseau.
3️⃣ Déploiement de la Sonde Déportée (LXC)
Création d'un conteneur LXC Debian 13 non privilégié sur Proxmox :
CPU : 1 Cœur | RAM : 512 Mo | Disque : 2 Go
Réseau : vmbr0 | IP : 192.168.1.243/24 | Gateway : 192.168.1.254
A. Routage inter-zones (LAN → DMZ)
La sonde LAN (192.168.1.0/24) doit contacter le serveur en DMZ (10.0.0.0/24). La box domestique ne gère pas le routage interne — on configure un routage statique local (host-based routing) via pfSense.
nano /etc/network/interfaces
auto eth0
iface eth0 inet static
address 192.168.1.243/24
gateway 192.168.1.254
# Route statique : trafic DMZ via pfSense
up ip route add 10.0.0.0/24 via 192.168.1.251
Redémarrer le conteneur ou injecter à chaud : ip route add 10.0.0.0/24 via 192.168.1.251.
Règle de pare-feu pfSense : Firewall > Rules > WAN
| Paramètre | Valeur |
|---|---|
| Action | Pass |
| Protocol | TCP |
| Source | 192.168.1.243 |
| Destination | 10.0.0.20 |
| Port | 60072 |
B. Installation et Configuration du Service Systemd
# Installation des pré-requis
apt update && apt install -y curl sudo
# Lancement du script officiel (remplacer localhost par l'IP DMZ)
bash -c "$(curl -fsSL https://raw.githubusercontent.com/scanopy/scanopy/refs/heads/main/install.sh)" \
&& sudo scanopy-daemon \
--server-url http://10.0.0.20:60072 \
--network-id <VOTRE_ID> \
--daemon-api-key <VOTRE_TOKEN> \
--user-id <VOTRE_USER_ID> \
--name scanopy-daemon-network-lan \
--mode daemon_poll
⚠️ Le script installe le binaire mais les variables d'environnement peuvent être perdues au redémarrage. Configurer le fichier Systemd en dur pour la fiabilisation.
nano /etc/systemd/system/scanopy-daemon.service
[Unit]
Description=Scanopy Network Discovery Daemon
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/scanopy-daemon \
--server-url http://10.0.0.20:60072 \
--network-id <VOTRE_ID> \
--daemon-api-key <VOTRE_TOKEN> \
--user-id <VOTRE_USER_ID> \
--name scanopy-daemon-network-lan \
--mode daemon_poll
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
⚠️ La syntaxe du mode exige
daemon_poll(underscore) et nonDaemonPoll.
systemctl daemon-reload
systemctl enable --now scanopy-daemon
journalctl -fu scanopy-daemon
Le message Connected to server dans les journaux confirme que le routage, le pare-feu et l'authentification sont fonctionnels. La découverte réseau démarre automatiquement sur l'interface web.



Topologie

📋 Résumé
- Service : Scanopy — cartographie réseau distribuée et IPAM
- Serveur : Docker Compose sur VM
10.0.0.20:60072(DMZ) - Sonde DMZ : conteneur Docker en
network_mode: hostaveccap_add(pas deprivileged) - Sonde LAN : LXC
192.168.1.243avec routage statique vers la DMZ via pfSense - Protocoles : ARP (L2), ICMP/TCP/UDP (L3/L4), SNMP
- Sécurité : tokens API uniques, modèle polling (sonde → serveur), moindre privilège (capabilities)
📚 Références
- GitHub Scanopy : https://github.com/scanopy/scanopy
- Documentation Officielle : https://scanopy.net/docs/