
Tableau de bord de pare-feu UFW multi-hôtes — explique les règles en langage clair, détecte les failles de sécurité et fournit des diagnostics de connexion
Tableau de bord de pare-feu UFW multi-hôtes. Se connecte aux hôtes Linux via SSH, analyse les règles de pare-feu et les ports en écoute, explique tout en langage clair et signale les failles de sécurité.

| Route | Description |
|---|---|
/ | Tableau de bord avec cartes hôtes, pastilles de services, compteurs de failles |
/host/{name} | Détail de l'hôte avec vue à onglets : règles expliquées, ports non couverts, ports en écoute, sortie brute |
/diagnose | Outil de diagnostic de connexion avec visualisation de la trace règle par règle |
/login | Authentification par session |
Browser --> Cloudflare Tunnel --> Reverse Proxy --> FencePost (:8890)
FastAPI container
|-- SSH --> Host 1 (ufw status, ss -tlnp)
|-- SSH --> Host 2
|-- SSH --> Host N
'-- POST --> Notification webhook
FencePost est en lecture seule -- il ne modifie jamais les règles de pare-feu, il se contente de les rapporter.
<user> ALL=(ALL) NOPASSWD: /usr/sbin/ufw status verbose, /usr/sbin/ufw status numbered, /usr/bin/ss -tlnp
git clone <repo-url> && cd fencepost
# Add your SSH key
cp ~/.ssh/your_key ssh/id_ed25519
chmod 600 ssh/id_ed25519
# Create your environment file from the template
cp .env.example .env
# Edit .env with real credentials
timezone: Australia/Melbourne
hosts:
- name: My Server
hostname: 192.168.1.10
ssh_user: deploy
ssh_port: 22
is_docker_host: false
networks:
"192.168.1.0/24": "LAN"
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
# Load env vars (bash/zsh)
export $(grep -v '^#' .env | xargs)
uvicorn app.main:app --reload --port 8890
Ouvrez http://localhost:8890.
Remarque : le mode local utilise la clé SSH au chemin spécifié dans config.yaml (ssh.key_path). Pour le développement local, vous voudrez peut-être le remplacer pour pointer vers votre ssh/id_ed25519 local :
ssh:
key_path: ssh/id_ed25519
timeout: 10
docker compose up -d --build
Ouvrez http://localhost:8890. Le conteneur lit les identifiants depuis .env automatiquement via compose.yaml.
| Section | Description |
|---|---|
timezone | Fuseau horaire IANA pour les horodatages affichés (par ex. Australia/Melbourne, UTC) |
hosts | Tableau des cibles SSH : name, hostname, ssh_user, ssh_port, is_docker_host |
ssh | key_path (chemin vers la clé privée) et timeout en secondes |
networks | Mappage CIDR-à-nom pour les VLAN -- utilisé dans les explications de règles et les diagnostics |
devices | IP nommées pour les boutons de sélection rapide de la page de diagnostic |
notifications | Webhook facultatif : url, channel (clé API définie via une variable d'environnement) |
| Variable | Défaut | Description |
|---|---|---|
FENCEPOST_USERNAME | admin | Nom d'utilisateur de connexion |
FENCEPOST_PASSWORD | fencepost | Mot de passe de connexion |
FENCEPOST_SECRET_KEY | change-me | Clé de signature des cookies de session |
FENCEPOST_CONFIG | config.yaml | Chemin vers le fichier de configuration |
NOTIFICATIONS_API_KEY | Jeton Bearer pour le webhook de notification |
Les identifiants sont stockés dans .env (ignoré par git) et référencés par compose.yaml. Ne committez jamais de secrets dans le dépôt.
app/
main.py # FastAPI routes and auth
models.py # HostFirewallState, UFWRule, ListeningPort dataclasses
parser.py # Parses ufw status and ss output
explainer.py # Translates rules to plain English
diagnose.py # Connection diagnostic engine
gap_detector.py # Finds uncovered listening ports
ssh_client.py # Paramiko wrapper, parallel host fetching
eventfeed.py # Change detection and webhook posting
templates/
base.html # Layout, CSS, navigation
overview.html # Host dashboard grid
host_detail.html # Per-host tabbed detail view
diagnose.html # Connection diagnostic form and results
login.html # Authentication page
config.yaml # Host definitions, VLANs, devices, timezone
compose.yaml # Docker Compose service definition
Dockerfile # Python 3.12 slim image
.env.example # Template for environment variables
ssh/ # SSH key directory (key not committed)
data/ # Runtime state (last_state.json, not committed)
config.yaml sous hosts:ssh-copy-id -i ssh/id_ed25519.pub user@host/etc/sudoers.d/fencepost sur l'hôte avec les règles NOPASSWD requisesdocker compose up -d --buildLorsqu'il est configuré dans config.yaml avec une variable d'environnement NOTIFICATIONS_API_KEY, FencePost publie les événements de changement à chaque actualisation du tableau de bord :
Les événements incluent des clés d'idempotence pour éviter les doublons.
MIT