
Panel de control de firewall UFW multihost — explica las reglas en inglés sencillo, detecta brechas de seguridad y proporciona diagnósticos de conexión
Panel de control de firewall UFW para múltiples hosts. Se conecta a hosts Linux por SSH, analiza las reglas de firewall y los puertos en escucha, explica todo en lenguaje sencillo y señala brechas de seguridad.

| Ruta | Descripción |
|---|---|
/ |
Navegador --> Túnel Cloudflare --> Proxy Inverso --> FencePost (:8890)
Contenedor FastAPI
|-- SSH --> Host 1 (ufw status, ss -tlnp)
|-- SSH --> Host 2
|-- SSH --> Host N
'-- POST --> Webhook de notificaciones
FencePost es solo lectura — nunca modifica las reglas del firewall, solo informa sobre ellas.
<usuario> ALL=(ALL) NOPASSWD: /usr/sbin/ufw status verbose, /usr/sbin/ufw status numbered, /usr/bin/ss -tlnp
git clone <url-del-repositorio> && cd fencepost
# Añade tu clave SSH
cp ~/.ssh/tu_clave ssh/id_ed25519
chmod 600 ssh/id_ed25519
# Crea tu archivo de entorno a partir de la plantilla
cp .env.example .env
# Edita .env con las credenciales reales
timezone: Australia/Melbourne
hosts:
- name: Mi servidor
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
# Cargar variables de entorno (bash/zsh)
export $(grep -v '^#' .env | xargs)
uvicorn app.main:app --reload --port 8890
Abrir http://localhost:8890.
Nota: el modo local utiliza la clave SSH en la ruta especificada en config.yaml (ssh.key_path). Para desarrollo local, quizás quieras sobrescribir esto para apuntar a tu ssh/id_ed25519 local:
ssh:
key_path: ssh/id_ed25519
timeout: 10
docker compose up -d --build
Abrir http://localhost:8890. El contenedor lee las credenciales de .env automáticamente a través de compose.yaml.
Las credenciales se almacenan en .env (gitignorado) y son referenciadas por compose.yaml. Nunca confirmes secretos en el repositorio.
app/
main.py # Rutas y autenticación de FastAPI
models.py # Dataclasses HostFirewallState, UFWRule, ListeningPort
parser.py # Analiza la salida de ufw status y ss
explainer.py # Traduce reglas a lenguaje sencillo
diagnose.py # Motor de diagnóstico de conexiones
gap_detector.py # Encuentra puertos en escucha sin cubrir
ssh_client.py # Envoltorio de Paramiko, obtención paralela de hosts
eventfeed.py # Detección de cambios y publicación en webhook
templates/
base.html # Diseño, CSS, navegación
overview.html # Cuadrícula del panel de hosts
host_detail.html # Vista detallada por host con pestañas
diagnose.html # Formulario de diagnóstico de conexión y resultados
login.html # Página de autenticación
config.yaml # Definiciones de host, VLANs, dispositivos, zona horaria
compose.yaml # Definición del servicio Docker Compose
Dockerfile # Imagen slim de Python 3.12
.env.example # Plantilla para variables de entorno
ssh/ # Directorio de claves SSH (la clave no está confirmada)
data/ # Estado en tiempo de ejecución (last_state.json, no confirmado)
config.yaml bajo hosts:ssh-copy-id -i ssh/id_ed25519.pub usuario@host/etc/sudoers.d/fencepost en el host con las reglas NOPASSWD requeridasdocker compose up -d --buildCuando está configurado en config.yaml con una variable de entorno NOTIFICATIONS_API_KEY, FencePost publica eventos de cambio en cada actualización del panel:
Los eventos incluyen claves de idempotencia para evitar duplicados.
MIT
| Panel de control general con tarjetas de host, píldoras de servicio, contadores de brechas |
/host/{nombre} | Detalle del host con vista de pestañas: reglas explicadas, puertos descubiertos, puertos en escucha, salida sin procesar |
/diagnosticar | Herramienta de diagnóstico de conexión con visualización de rastreo regla por regla |
/iniciar-sesion | Autenticación basada en sesión |
| Sección | Propósito |
|---|
timezone | Zona horaria IANA para las marcas de tiempo mostradas (ej. Australia/Melbourne, UTC) |
hosts | Array de destinos SSH: name, hostname, ssh_user, ssh_port, is_docker_host |
ssh | key_path (ruta a la clave privada) y timeout en segundos |
networks | Mapeo de CIDR a nombre para VLANs — usado en explicaciones de reglas y diagnósticos |
devices | IPs con nombre para los botones de selección rápida de la página de diagnóstico |
notifications | Webhook opcional: url, channel (clave API se establece mediante variable de entorno) |
| Variable | Predeterminado | Descripción |
|---|
FENCEPOST_USERNAME | admin | Nombre de usuario para inicio de sesión |
FENCEPOST_PASSWORD | fencepost | Contraseña de inicio de sesión |
FENCEPOST_SECRET_KEY | change-me | Clave de firma de cookies de sesión |
FENCEPOST_CONFIG | config.yaml | Ruta al archivo de configuración |
NOTIFICATIONS_API_KEY | Token Bearer para el webhook de notificaciones |