Visualizador de ataques SSH/HTTP en tiempo real . Lee logs de SSH y Nginx, geolocaliza las IPs, las clasifica con MITRE ATT&CK y las pinta en un mapa mundial con arcos animados, particulas de datos y un dashboard estilo terminal retro-futurista.
Pensado para correr en cualquier VPS con un solo docker compose up.
- Mapa Leaflet oscuro con arcos animados desde el origen del ataque hasta tu VPS.
- Particulas de datos viajando por los arcos con fragmentos hex (
0xCAFE,SYN>>, etc). - Reticula del VPS con lineas de cruz, anillos rotativos y label
TARGET. - Cada IP atacante aparece como un punto pulsante del color de su tipo de ataque (rojo SSH, amarillo HTTP, azul visitas reales).
- Click en un punto -> callout estilo espia con linea de telemetria SVG animada, datos del subject (IP, origen, eventos, coordenadas) y boton
OPEN FULL DOSSIERque abre el drawer completo.
Todas las cards con tema Pip-Boy: bordes con corner brackets, headers flotantes, scanlines CRT, fuente VT323.
- Total counter con efecto de glitch ocasional (calavera ASCII y mensajes tipo
BREACH_DETECTED). - Attack patterns:
DICTIONARY_ATTACK,CREDENTIAL_STUFFING,PASSWORD_SPRAYING,SINGLE_PROBE. - Top origins por pais con barras animadas.
- IP addresses con tabs (ALL / SSH / HTTP / VISITS / RECENT). Click en cualquier IP abre el drawer.
- SSH targets: nube de tags con todos los usernames probados en rojo.
- HTTP routes: separados en
BOTS(probes a/wp-admin,/.git, etc) yREAL(rutas que tu app realmente sirve). - Recent events: ultimos 10 hits con timestamp, IP y tipo.
Cuando clickeas una IP (en el mapa, en la lista o en el feed):
- Header
THREAT DOSSIERcon badge SSH/HTTP/SSH+HTTP. - Subject identification: IP grande, geo, ASN/org, links a Shodan y AbuseIPDB.
- Threat assessment con
PipBoyMetersegmentado (20 bloques tipo barra de salud). - Vault stats: cards con esquinas L para total hits, SSH users, HTTP paths, req/min.
- AbuseIPDB intel con porcentaje de confianza y total de reportes.
- Classification: pattern + speed + KNOWN_THREAT badge si es notorio.
- MITRE ATT&CK badges con TTPs identificados.
- Tabs OVERVIEW (timeline + summary), SSH (todos los usernames probados), HTTP (rutas con status code y conteo).
Stream WebSocket con cada evento conforme entra: timestamp, IP, pais con flag, tipo, severidad. Filtros por SSH/HTTP/REAL.
GET /api/health— health check.GET /api/events?limit=— eventos crudos.GET /api/stats/{total,countries,ips,usernames,http-routes,patterns,asns,heatmap}?window=.GET /api/attacker/{ip}— perfil completo.GET /api/attackers?limit=&window=— ranking por threat score.GET /api/export/stix?window=— bundle STIX 2.1 descargable.GET /api/export/csv?window=— eventos en CSV.GET /api/export/report?window=— resumen ejecutivo JSON.
git clone <este-repo>
cd ssh-bot-rain-map
cp .env.example .env
# Edita .env (ver "Adaptar a tu entorno" abajo)
docker compose up -d --buildLuego abre:
- Dashboard:
http://localhost:3000(ohttp://<tu-vps-ip>:3000) - API:
http://localhost:8000/api/health
Si estas probando localmente y no tienes acceso a logs reales:
docker compose -f docker-compose.dev.yml up -d --build
# En otra terminal, genera trafico falso:
python scripts/fake_ssh_log.py --output ./logs/auth.log --rate 2.0El compose dev monta ./logs/auth.log en lugar de los logs del host.
Todo lo que probablemente quieras tocar.
| Variable | Default | Que cambiar y por que |
|---|---|---|
SSH_LOG_PATH |
/var/log/auth.log |
Obligatorio. Debian/Ubuntu usa auth.log, RHEL/CentOS/Fedora usa /var/log/secure. |
NGINX_LOG_PATH |
/var/log/nginx/access.log |
Opcional. Si no usas Nginx dejalo vacio o apunta a tu access log (Apache funciona si esta en formato combined). |
VPS_LAT |
40.4168 |
Obligatorio. Latitud de tu VPS — donde caera la "lluvia" de arcos. |
VPS_LON |
-3.7038 |
Obligatorio. Longitud de tu VPS. |
VPS_LABEL |
My VPS |
Texto que veras en el popup del marker del VPS. |
GEO_PROVIDER |
ip-api |
ip-api (gratis, 45 req/min) o ipinfo (mejor calidad, requiere token). |
IPINFO_TOKEN |
(vacio) | Solo si GEO_PROVIDER=ipinfo. Token gratis en ipinfo.io. |
ABUSEIPDB_API_KEY |
(vacio) | Opcional. Activa enriquecimiento de reputacion. Free tier: 1000 checks/dia. |
SHODAN_API_KEY |
(vacio) | Opcional. Datos extra de puertos/OS/vulns. |
MAX_EVENTS |
10000 |
Eventos en memoria (cola circular). Sube si tienes mucho trafico y quieres ventanas largas. |
GEO_CACHE_TTL |
86400 |
TTL del cache de geo en segundos (24h por defecto). |
ABUSE_CACHE_TTL |
86400 |
TTL del cache de AbuseIPDB. |
WS_BROADCAST_INTERVAL |
1.0 |
Cadencia de envio por WebSocket en segundos. Sube a 2.0 si tu CPU sufre. |
FRONTEND_PORT |
3000 |
Puerto del dashboard. Cambialo si ya tienes algo en 3000. |
BACKEND_PORT |
8000 |
Puerto del backend FastAPI. |
Importante si tienes Nginx sirviendo una web propia. Por defecto cualquier ruta no listada se marca como BOT_PROBE (amarillo). Para que tus rutas reales aparezcan en azul como visitas legitimas:
Edita frontend/src/config/knownRoutes.js y añade tus rutas:
export const KNOWN_ROUTES = [
'/',
'/about',
'/api/...',
// tus rutas aqui
]Si no sabes la lat/lon de tu servidor, usa curl ifconfig.co/json desde el VPS o consulta el panel de tu proveedor (Hetzner, DigitalOcean, OVH, etc).
Si despliegas frontend y backend en hosts separados (no recomendado para esta app, pero posible):
- Edita
frontend/src/hooks/useWebSocket.jspara apuntar al WS correcto (ws://tu-backend:8000/ws). - Edita
frontend/vite.config.js(proxy.target) para el modo dev. - En produccion el
nginx.confdel frontend asume backend en el servicio docker llamadobackend. Cambialo si tu setup es distinto.
Cambia FRONTEND_PORT y BACKEND_PORT en .env o edita los port mappings en docker-compose.yml. Por ejemplo:
frontend:
ports:
- "8080:80" # accede en :8080El backend lee el log montado como read-only. En la mayoria de distros auth.log pertenece a root:adm o root:syslog. Si el contenedor no puede leerlo:
sudo chmod o+r /var/log/auth.log
# o ajusta el user del contenedor en docker-compose.yml- Tema Pip-Boy: las variables CSS estan al inicio de
frontend/src/styles/app.css(--pip-green,--pip-amber,--pip-bg, etc). Cambialas para tener tu propia paleta. - Colores de tipos de ataque: definidos en
frontend/src/components/WorldMap.jsx(SSH_COLOR,HTTP_COLOR,VISITOR_COLOR). - Mensajes de glitch: edita
GLITCH_LINESenfrontend/src/components/StatsPanel.jsx.
SSH/Nginx log --tail-F--> FastAPI ingesta
|
+--> parser (regex) --> SSHEvent / HttpEvent
|
+--> geo enrichment (ip-api / ipinfo, cached)
|
+--> threat intel (AbuseIPDB, opcional, cached)
|
+--> analyzer (patterns + MITRE TTPs)
|
+--> EventStore (deque circular en memoria)
|
+--> WebSocket broadcast (1s) --> React UI
|
+--> REST API (stats, profile, export)
main.py— FastAPI, dos tasks asincronas:process_log_lines()yflush_loop().tail.py—async for line in tail_log(path), sobrevive a logrotate.parser.py— regex SSH + HTTP (Nginx combined).geo.py— geolocalizacion con cache TTL.threat_intel.py— AbuseIPDB con rate limit (1 req/s, 900/dia).analyzer.py— clasificador heuristico, MITRE ATT&CK, heatmap 7x24.stix_export.py— bundle STIX 2.1 sin dependencia externa.store.py—EventStorecon deque circular y dedupe por minuto.models.py— dataclassesSSHEvent,HttpEvent,GeoInfo.config.py— singletonsettingsque lee.env.
App.jsx— root, gestiona estado de eventos y drawer.components/WorldMap.jsx— Leaflet + canvas particles + IntelCallout (spy card con linea SVG).components/StatsPanel.jsx— stats tipo Pip-Boy con tabs y nube de tags.components/AttackerProfile.jsx— drawer 440px con dossier completo.components/EventFeed.jsx— feed scrolleable en vivo.components/Charts.jsx— timeline Recharts.components/HeatmapChart.jsx— grid 7x24 (dia x hora).components/ExportPanel.jsx— botones STIX / CSV / REPORT.components/MitreBadge.jsx— badge reutilizable de TTP.hooks/useWebSocket.js— gestion de conexion WS.config/knownRoutes.js— whitelist de rutas legitimas.styles/app.css— todo el tema Pip-Boy + animaciones.
tail -Fcon reintento automatico, sobrevive alogrotate.- Cache y rate limit para geo (45 req/min) y AbuseIPDB (1 req/s, 900/dia).
- Deduplicacion ligera (
ip:user:type:minute) para no inflar metricas. - Heuristica multi-factor combinando velocidad (rpm), patron, diversidad de usernames y reputacion externa.
- Volumen del log montado read-only en el contenedor.
- Sin DB: todo en memoria con deque acotado (no hay nada que limpiar al reiniciar).
# Health check
curl http://localhost:8000/api/health
# Logs en vivo
docker compose logs -f backend
docker compose logs -f frontend
# Datos crudos
curl http://localhost:8000/api/events?limit=20
curl http://localhost:8000/api/stats/total
# Reset (sin perder logs del host)
docker compose restart backend
# Rebuild despues de tocar codigo
docker compose up -d --buildNo veo eventos:
- ¿El contenedor lee el log?
docker compose exec backend cat $SSH_LOG_PATH | head(deberia funcionar). - ¿Hay actividad real? Genera con
python scripts/fake_ssh_log.py --output ./logs/auth.log --rate 2.0en modo dev. - ¿Las coordenadas del VPS son correctas? Si estan a
0,0el mapa centrara al medio del oceano.
Geo dice "Unknown":
- ip-api tiene rate limit. Espera o cambia a ipinfo con token.
- IPs privadas (
10.x,192.168.x) no se geolocalizan a proposito.
Frontend no conecta WS:
- Mira la consola del navegador. Si hay
404en/ws, revisa que el proxy de Vite o elnginx.confapunten al backend correcto.
- Persistencia opcional (SQLite/DuckDB) para historicos largos y replay.
- Multi-sensor: agregar varios VPS en un solo dashboard.
- Webhooks/Slack alerts en base a threat score.
- Modo claro (heretico pero por completitud).
- TLS/auth para exponer el dashboard publicamente.
MIT. Forkalo, adaptalo,.


