Pangolin est une solution open-source de tunneling et de reverse proxy auto-hébergée, développée par Fossorial. Elle permet d’exposer des services internes sur Internet de façon sécurisée, sans avoir besoin d’ouvrir de ports sur votre réseau local. Pensez à Cloudflare Tunnel, mais que vous hébergez vous-même.
Dans ce guide, nous allons installer Pangolin sur un serveur Debian 12 (Bookworm), le configurer, puis le sécuriser avec un pare-feu ufw.
Architecture de Pangolin
Pangolin repose sur deux composants principaux :
- Pangolin Server — le serveur central, hébergé sur une VPS publique, qui gère les tunnels, l’authentification et le routage HTTP/HTTPS.
- Newt — le client léger, installé sur chaque machine interne à exposer. Il établit un tunnel WireGuard chiffré vers le serveur Pangolin.
Le trafic entrant arrive sur le serveur Pangolin → est routé via le tunnel Newt → arrive sur votre service interne. Zéro port ouvert côté LAN.
Prérequis
- Un serveur Debian 12 avec une IP publique (VPS, bare-metal…)
- Un nom de domaine pointant vers ce serveur (ex :
tunnel.mondomaine.fr) - Accès root ou sudo
- Docker et Docker Compose installés
- Ports 80, 443 et 51820/UDP accessibles
1 — Installation de Docker sur Debian
Si Docker n’est pas encore présent, installez-le depuis le dépôt officiel :
# Dépendances
apt update && apt install -y ca-certificates curl gnupg
# Clé GPG officielle Docker
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg \
| gpg --dearmor -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg
# Dépôt Docker
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/debian $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
| tee /etc/apt/sources.list.d/docker.list
# Installation
apt update && apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
Vérifiez l’installation :
docker version
docker compose version
2 — Déploiement de Pangolin via Docker Compose
Créez le répertoire de travail :
mkdir -p /opt/pangolin && cd /opt/pangolin
Créez le fichier docker-compose.yml contenant les trois services : Pangolin, Gerbil (gestion WireGuard) et Traefik (reverse proxy HTTPS) :
cat << 'EOF' > docker-compose.yml
services:
pangolin:
image: fosrl/pangolin:latest
container_name: pangolin
restart: unless-stopped
volumes:
- ./config:/app/config
- ./data:/app/data
ports:
- "127.0.0.1:3001:3001" # Dashboard — local uniquement
networks:
- pangolin_net
gerbil:
image: fosrl/gerbil:latest
container_name: gerbil
restart: unless-stopped
depends_on:
- pangolin
cap_add:
- NET_ADMIN
- SYS_MODULE
sysctls:
- net.ipv4.ip_forward=1
- net.ipv6.conf.all.forwarding=1
volumes:
- /lib/modules:/lib/modules:ro
ports:
- "51820:51820/udp" # WireGuard
networks:
- pangolin_net
traefik:
image: traefik:v3.1
container_name: traefik
restart: unless-stopped
command:
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.letsencrypt.acme.tlschallenge=true"
- "--certificatesresolvers.letsencrypt.acme.email=admin@mondomaine.fr"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./letsencrypt:/letsencrypt
networks:
- pangolin_net
networks:
pangolin_net:
driver: bridge
EOF
Créez ensuite le fichier de configuration principal config/config.yml :
mkdir -p config
cat << 'EOF' > config/config.yml
app:
dashboard_url: "https://tunnel.mondomaine.fr"
log_level: "info"
domains:
base_domain: "tunnel.mondomaine.fr"
server:
external_port: 443
internal_port: 3001
secret: "CHANGEZ_CE_SECRET_PAR_UNE_VALEUR_ALEATOIRE"
gerbil:
start_port: 51820
base_endpoint: "tunnel.mondomaine.fr"
block_size: 24
rate_limit:
enabled: true
window_minutes: 1
max_requests: 100
EOF
Démarrez la stack :
docker compose up -d
docker compose logs -f pangolin
3 — Première connexion au dashboard
Ouvrez votre navigateur sur https://tunnel.mondomaine.fr. Lors du premier accès, Pangolin vous invite à créer le compte administrateur.
Une fois connecté, le dashboard affiche la liste des organisations, des sites et des ressources exposées.
Créer un site et connecter Newt
Dans le dashboard, créez un Site, puis un tunnel Newt. Pangolin génère la commande Docker à exécuter sur votre machine interne :
# Sur la machine interne à exposer
docker run -d \
--name newt \
--restart unless-stopped \
--cap-add NET_ADMIN \
fosrl/newt:latest \
--id <VOTRE_SITE_ID> \
--secret <VOTRE_SITE_SECRET> \
--endpoint tunnel.mondomaine.fr
4 — Sécurisation et pare-feu
Un reverse proxy exposé sur Internet est une cible privilégiée. Voici les mesures essentielles à mettre en place sur votre serveur Debian.
4.1 — Pare-feu avec UFW
Installez et activez ufw en n’autorisant que les ports strictement nécessaires :
apt install -y ufw
# Politique par défaut : tout bloquer en entrée
ufw default deny incoming
ufw default allow outgoing
# SSH — adaptez le port si nécessaire
ufw allow 22/tcp comment "SSH"
# HTTP et HTTPS pour Traefik
ufw allow 80/tcp comment "HTTP redirect"
ufw allow 443/tcp comment "HTTPS Traefik"
# WireGuard pour les tunnels Newt
ufw allow 51820/udp comment "WireGuard Pangolin"
# Activation
ufw enable
ufw status verbose
Attention avec Docker : Docker modifie directement les règles iptables et peut contourner UFW. Pour forcer Docker à respecter UFW, ajoutez dans /etc/docker/daemon.json :
{
"iptables": false
}
Puis gérez les règles Docker manuellement via la chaîne DOCKER-USER :
# Autoriser uniquement le trafic entrant sur les ports publiés
iptables -I DOCKER-USER -i eth0 -p tcp --dport 3001 -j DROP
iptables -I DOCKER-USER -i lo -j ACCEPT
4.2 — Restriction de l’accès au dashboard
Le dashboard Pangolin (port 3001) ne doit jamais être exposé directement sur Internet. Dans le docker-compose.yml, le port est déjà lié à 127.0.0.1 uniquement. Vérifiez :
# Ce port NE doit PAS écouter sur 0.0.0.0
ss -tlnp | grep 3001
# Résultat attendu : 127.0.0.1:3001
Pour y accéder à distance, utilisez un tunnel SSH local :
# Depuis votre poste local
ssh -L 3001:localhost:3001 user@tunnel.mondomaine.fr
# Puis ouvrez http://localhost:3001 dans votre navigateur
4.3 — Blocage des tentatives de bruteforce avec Fail2ban
Installez Fail2ban pour bloquer automatiquement les IP qui multiplient les échecs d’authentification :
apt install -y fail2ban
# Filtre pour les échecs d'authentification Pangolin
cat << 'EOF' > /etc/fail2ban/filter.d/pangolin-auth.conf
[Definition]
failregex = .*authentication failed.*ip=<HOST>
.*invalid credentials.*ip=<HOST>
ignoreregex =
EOF
# Jail Fail2ban
cat << 'EOF' > /etc/fail2ban/jail.d/pangolin.conf
[pangolin-auth]
enabled = true
port = 443
filter = pangolin-auth
logpath = /opt/pangolin/data/logs/pangolin.log
maxretry = 5
bantime = 3600
findtime = 600
EOF
systemctl restart fail2ban
fail2ban-client status pangolin-auth
4.4 — Mises à jour automatiques avec Watchtower
Ajoutez Watchtower dans votre docker-compose.yml pour maintenir les images à jour automatiquement :
watchtower:
image: containrrr/watchtower
container_name: watchtower
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
command: --schedule "0 0 4 * * *" --cleanup
# Mise à jour quotidienne à 4h du matin
4.5 — Récapitulatif des mesures de sécurité
| Mesure | Outil | Priorité |
|---|---|---|
| Pare-feu entrant restrictif | UFW / iptables | ✅ Obligatoire |
| Dashboard non exposé publiquement | Docker port binding (127.0.0.1) | ✅ Obligatoire |
| HTTPS avec certificat Let’s Encrypt | Traefik ACME | ✅ Obligatoire |
| Blocage bruteforce | Fail2ban | ⚠️ Fortement recommandé |
| MFA sur le dashboard | Pangolin (intégré) | ⚠️ Fortement recommandé |
| Mises à jour automatiques | Watchtower | 🔵 Recommandé |
| Audit des logs | Logwatch / journalctl | 🔵 Recommandé |
Conclusion
Pangolin est une excellente alternative auto-hébergée à Cloudflare Tunnel. Combiné à Traefik pour le TLS automatique et Newt pour les tunnels WireGuard, il offre une solution robuste pour exposer vos services internes sans ouvrir votre réseau local. En ajoutant UFW, Fail2ban et une politique de mises à jour régulières, vous réduisez la surface d’attaque au minimum.
Le code source est disponible sur GitHub (fosrl/pangolin) et la documentation officielle sur docs.fossorial.io.
Des questions ou retours d’expérience ? N’hésitez pas à laisser un commentaire ci-dessous.
