Plan2026/05-decision-seguridad.md

848 lines
34 KiB
Markdown

# Decision: Capa de seguridad (punto 2)
## Contexto
Este servidor fue comprometido con un credential stealer via PAM que opero 4 dias sin ser detectado. Tenemos firewall bien configurado (policy DROP, SSH por IP, bloqueo de mineria) y aun asi entraron. La capa de seguridad debe cubrir lo que el firewall no puede: **detectar amenazas que ya estan dentro**.
4 subcapas:
- 2.1 Deteccion de intrusiones y file integrity
- 2.2 Escaneo de vulnerabilidades
- 2.3 Gestion de secretos
- 2.4 Acceso y autenticacion
---
## 2.1 Deteccion de intrusiones y file integrity
### La pregunta: Wazuh, AIDE, o auditd?
No son excluyentes. Hacen cosas diferentes:
| Herramienta | Que hace | Analogia |
|-------------|----------|----------|
| **auditd** | Registra eventos del kernel: quien abrio/modifico/creo que fichero, que proceso hizo que syscall | La camara de seguridad |
| **AIDE** | Genera baseline de checksums y alerta si algo cambia | La foto del "antes" para comparar |
| **Wazuh** | HIDS completo: analiza logs + file integrity + rootkit detection + vulnerability detection + compliance + respuesta activa | El guardia de seguridad con camaras, alarmas y protocolo |
### Opcion A: Wazuh (RECOMENDADA)
#### Que es
Plataforma de seguridad open source (fork de OSSEC). Incluye:
- **HIDS**: deteccion de intrusiones basada en host
- **FIM**: file integrity monitoring (incluye lo que hace AIDE)
- **Rootkit detection**: busca artefactos conocidos de rootkits
- **Log analysis**: analiza auth.log, syslog, etc. con reglas de correlacion
- **Vulnerability detection**: escanea paquetes instalados contra bases de CVE
- **Active response**: puede bloquear IPs, matar procesos, ejecutar acciones automaticas
- **Compliance**: reportes CIS, PCI-DSS, GDPR
- **Dashboard**: Kibana/OpenSearch integrado, o Grafana via plugin
#### Que habria detectado en este incidente
| Evento | Regla Wazuh | Tiempo de deteccion |
|--------|-------------|-------------------|
| Creacion de `/usr/bin/login.sh` | FIM: fichero nuevo en directorio monitorizado | **Segundos** |
| Modificacion de `/etc/pam.d/common-auth` | FIM: cambio en fichero critico | **Segundos** |
| Creacion de `/etc/ld.so.preload` | FIM + rootkit check | **Segundos** |
| Creacion de `/usr/local/sbin/env/` | FIM: directorio nuevo en ruta de sistema | **Segundos** |
| Conexion saliente a 91.208.162.132:10480 | Log analysis de firewall + active response | **Minutos** |
| Exfiltracion de credenciales via curl | Log analysis / network anomaly | **Minutos** |
**Conclusion: el incidente habria durado minutos, no 4 dias.**
#### Arquitectura
```
┌─────────────────────────────┐
│ Wazuh Manager │
│ (servidor central) │
│ │
│ - Recibe eventos de agentes │
│ - Evalua reglas │
│ - Genera alertas │
│ - Vulnerability scanner │
│ │
│ Wazuh Dashboard │
│ (o Grafana via plugin) │
└──────────┬──────────────────┘
┌────────────────┼────────────────────┐
│ │ │
┌────────▼────────┐ ┌────▼──────────┐ ┌──────▼───────┐
│ Wazuh Agent │ │ Wazuh Agent │ │ Wazuh Agent │
│ (PBS server 1) │ │ (PBS server 2│ │ (PVE node) │
│ │ │ )│ │ │
│ - FIM │ │ - FIM │ │ - FIM │
│ - Log analysis │ │ - Log anal. │ │ - Log anal. │
│ - Rootkit det. │ │ - Rootkit │ │ - Rootkit │
│ - Vuln scan │ │ - Vuln scan │ │ - Vuln scan │
└────────────────┘ └──────────────┘ └──────────────┘
```
#### Configuracion FIM para PBS/Proxmox
```xml
<!-- /var/ossec/etc/ossec.conf (en el agente) -->
<syscheck>
<!-- Frecuencia de escaneo: cada 5 minutos para criticos -->
<frequency>300</frequency>
<!-- FICHEROS CRITICOS - Alerta inmediata en tiempo real -->
<directories check_all="yes" realtime="yes" report_changes="yes">
/etc/pam.d
</directories>
<directories check_all="yes" realtime="yes" report_changes="yes">
/etc/ssh
</directories>
<directories check_all="yes" realtime="yes">
/etc/ld.so.preload
</directories>
<directories check_all="yes" realtime="yes">
/root/.ssh/authorized_keys
</directories>
<directories check_all="yes" realtime="yes">
/etc/sudoers,/etc/sudoers.d
</directories>
<directories check_all="yes" realtime="yes">
/etc/cron.d,/etc/crontab
</directories>
<directories check_all="yes" realtime="yes">
/etc/systemd/system
</directories>
<!-- BINARIOS DE SISTEMA - Detectar modificaciones/adiciones -->
<directories check_all="yes" realtime="yes">
/usr/bin,/usr/sbin,/usr/local/bin,/usr/local/sbin
</directories>
<!-- CONFIGURACION PROXMOX/PBS -->
<directories check_all="yes" realtime="yes">
/etc/proxmox-backup
</directories>
<directories check_all="yes">
/etc/pve
</directories>
<!-- Ignorar ficheros que cambian legitimamente -->
<ignore>/etc/pve/authkey.pub</ignore>
<ignore>/etc/pve/authkey.pub.old</ignore>
<ignore>/etc/pve/priv/authkey.key</ignore>
<ignore>/etc/proxmox-backup/shadow.json</ignore>
<ignore type="sregex">/etc/proxmox-backup/.*.cfg</ignore>
<ignore>/etc/zfs/zpool.cache</ignore>
</syscheck>
<!-- Rootkit detection -->
<rootcheck>
<rootkit_files>/var/ossec/etc/shared/rootkit_files.txt</rootkit_files>
<rootkit_trojans>/var/ossec/etc/shared/rootkit_trojans.txt</rootkit_trojans>
<system_audit>/var/ossec/etc/shared/system_audit_rcl.txt</system_audit>
<frequency>3600</frequency>
</rootcheck>
```
#### Reglas custom para este tipo de ataque
```xml
<!-- /var/ossec/etc/rules/local_rules.xml (en el manager) -->
<group name="custom_pbs_security">
<!-- Detectar pam_exec añadido (el vector exacto de este incidente) -->
<rule id="100001" level="15">
<if_sid>550</if_sid>
<match>pam.d</match>
<description>Fichero PAM modificado - posible backdoor</description>
</rule>
<!-- Detectar ld.so.preload creado o modificado -->
<rule id="100002" level="15">
<if_sid>554</if_sid>
<match>ld.so.preload</match>
<description>ld.so.preload creado/modificado - posible rootkit</description>
</rule>
<!-- Nuevo fichero en /usr/bin que no es de un paquete -->
<rule id="100003" level="12">
<if_sid>554</if_sid>
<match>/usr/bin/|/usr/sbin/</match>
<description>Nuevo fichero en directorio de sistema</description>
</rule>
<!-- Detectar curl a IPs externas desde scripts de sistema -->
<rule id="100004" level="10">
<if_sid>530</if_sid>
<match>curl.*--max-time|nohup.*curl</match>
<description>Ejecucion sospechosa de curl con nohup</description>
</rule>
</group>
```
#### Integracion con el stack existente
**Opcion 1: Wazuh Dashboard (OpenSearch)**
- Dashboard propio de Wazuh con todos los modulos
- Requiere OpenSearch (fork Elasticsearch) + 4GB RAM extra
- Mejor experiencia para analisis de seguridad dedicado
**Opcion 2: Wazuh + Grafana (via plugin o Loki)**
- Wazuh envia alertas a Loki -> Grafana las muestra junto con metricas y logs
- No necesita OpenSearch (ahorra 4GB RAM)
- Un solo panel para todo, pero pierde dashboards especializados de Wazuh
**Recomendacion**: empezar con **Opcion 1** (Wazuh Dashboard completo). La seguridad merece su propio panel especializado. Las alertas criticas se reenvian a Telegram/email igual que el resto.
#### Recursos
| Componente | CPU | RAM | Disco |
|-----------|-----|-----|-------|
| Wazuh Manager + Dashboard (OpenSearch) | 4 vCPU | 12 GB | 100 GB |
| Wazuh Agent (por servidor) | <0.1 | 50-100 MB | 100 MB |
**VM dedicada recomendada**: no compartir con la VM de monitoring (VictoriaMetrics/Loki/Grafana). Si Wazuh detecta un problema, debe estar en infra separada.
#### Despliegue
```bash
# Manager (VM dedicada)
curl -sO https://packages.wazuh.com/4.9/wazuh-install.sh
bash wazuh-install.sh -a # instalacion all-in-one
# Agent (en cada servidor, via Ansible)
apt-get install wazuh-agent
# Configurar manager IP y registrar
```
### Opcion B: AIDE + auditd (ligero, sin servidor central)
#### Cuando tiene sentido
- Si no quereis/podeis mantener un Wazuh Manager
- Como complemento a Wazuh (belt and suspenders)
- Para servidores aislados sin conectividad al manager
#### AIDE (file integrity)
```bash
# Instalar y generar baseline
apt install aide
aide --init
mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db
# Check diario via cron
0 5 * * * /usr/bin/aide --check | mail -s "AIDE $(hostname)" seguridad@empresa.com
# Tras cambios legitimos, regenerar baseline
aide --update
```
Configuracion para PBS:
```
# /etc/aide/aide.conf.d/99_pbs_custom.conf
/etc/pam.d Full
/etc/ssh Full
/etc/ld.so.preload Full
/usr/bin Full
/usr/sbin Full
/usr/local/bin Full
/usr/local/sbin Full
/root/.ssh Full
/etc/cron.d Full
/etc/systemd/system Full
```
#### auditd (registro de eventos)
```bash
# /etc/audit/rules.d/pbs-security.rules
# Monitorizar cambios en PAM
-w /etc/pam.d/ -p wa -k pam_changes
# Monitorizar ld.so.preload
-w /etc/ld.so.preload -p wa -k ld_preload
# Monitorizar SSH config
-w /etc/ssh/ -p wa -k ssh_changes
# Monitorizar authorized_keys
-w /root/.ssh/authorized_keys -p wa -k ssh_keys
# Monitorizar crontabs
-w /etc/crontab -p wa -k cron_changes
-w /etc/cron.d/ -p wa -k cron_changes
-w /var/spool/cron/ -p wa -k cron_changes
# Monitorizar creacion de ficheros en /usr/bin
-w /usr/bin/ -p wa -k system_binaries
-w /usr/sbin/ -p wa -k system_binaries
-w /usr/local/bin/ -p wa -k local_binaries
-w /usr/local/sbin/ -p wa -k local_binaries
# Monitorizar sudoers
-w /etc/sudoers -p wa -k sudoers
-w /etc/sudoers.d/ -p wa -k sudoers
# Monitorizar systemd
-w /etc/systemd/system/ -p wa -k systemd_changes
# Monitorizar ejecucion de herramientas sospechosas
-a always,exit -F arch=b64 -S execve -F path=/usr/bin/curl -k suspicious_exec
-a always,exit -F arch=b64 -S execve -F path=/usr/bin/wget -k suspicious_exec
-a always,exit -F arch=b64 -S execve -F path=/usr/bin/base64 -k suspicious_exec
```
#### Limitaciones sin Wazuh
- auditd registra pero **no alerta** (hay que leer los logs o enviarlos a Loki)
- AIDE detecta cambios pero **solo en el check programado** (no real-time)
- No hay correlacion de eventos entre servidores
- No hay vulnerability scanning
- No hay active response
### Opcion C: Lynis (auditoria puntual, no monitoring continuo)
#### Que es
Script de auditoria de seguridad que escanea el sistema y da puntuacion con recomendaciones. No es un agente permanente.
#### Uso
```bash
apt install lynis
lynis audit system
```
#### Donde encaja
- Ejecutar tras el despliegue inicial de cada servidor (baseline)
- Ejecutar periodicamente (mensual) para verificar drift
- Generar informe de hardening pendiente
- **No reemplaza** ni a Wazuh ni a auditd, es complementario
### Comparativa 2.1
| Aspecto | Wazuh | AIDE + auditd | Lynis |
|---------|-------|--------------|-------|
| Deteccion real-time | Si (FIM + log analysis) | auditd si, AIDE no | No (puntual) |
| File integrity | Si (integrado) | AIDE (cron) | Check puntual |
| Rootkit detection | Si | No | Basico |
| Vulnerability scan | Si | No | Basico |
| Log analysis | Si (reglas de correlacion) | Hay que leer logs | No |
| Active response | Si (bloquear IP, matar proceso) | No | No |
| Alertas | Si (email, Telegram, webhook) | Manual (cron + mail) | Informe |
| Servidor central | Si (Manager) | No | No |
| RAM por servidor | 50-100 MB | 10-20 MB | Solo durante scan |
| Complejidad | Media-alta | Baja | Nula |
### DECISION 2.1 (confirmada)
**Wazuh como pilar principal** + **auditd como complemento** en todos los servidores + **Lynis** como check puntual post-despliegue.
- Wazuh: deteccion continua, alertas, correlacion, vulnerability scanning
- auditd: registro granular de quien hizo que (forensics, compliance)
- Lynis: auditoria de hardening tras cada despliegue y revision trimestral
**Visualizacion**: Wazuh Dashboard propio (OpenSearch). La seguridad merece su panel especializado con modulos dedicados (FIM, rootkits, vulnerabilidades, compliance). Al no tener experiencia previa en HIDS, los dashboards especializados aceleran el aprendizaje. Alertas criticas se reenvian a Telegram/email igualmente.
**Lynis como checklist**: se ejecuta en 4 momentos:
1. Instalacion nueva (baseline)
2. Post-hardening (verificar que Ansible aplico todo)
3. Revision periodica trimestral (detectar drift)
4. Post-incidente (evaluar estado tras limpieza)
**Overhead por servidor**: 50-100MB RAM del agente Wazuh. Perfectamente asumible en servidores de 32-256GB (pasa completamente desapercibido).
**Recursos VM Wazuh**: 4 vCPU, 12 GB RAM (8 Manager + 4 Dashboard/OpenSearch), 100 GB disco. VM dedicada separada de monitoring.
---
## 2.2 Escaneo de vulnerabilidades
### Que necesitamos
Dos tipos de escaneo:
| Tipo | Que busca | Desde donde |
|------|-----------|-------------|
| **Interno (host)** | Paquetes con CVEs, configuraciones debiles | Dentro de cada servidor |
| **Externo (red)** | Puertos abiertos, servicios expuestos, CVEs accesibles | Desde fuera del servidor |
### Escaneo interno: ya cubierto por Wazuh
Wazuh incluye vulnerability detection que escanea los paquetes instalados contra bases de CVE (NVD, Debian Security). Si hemos desplegado Wazuh, esto ya esta cubierto.
### Escaneo externo: OpenVAS/Greenbone
| Herramienta | Que hace | Recursos |
|-------------|----------|----------|
| **OpenVAS/Greenbone** | Escaner de vulnerabilidades de red. Escanea puertos, servicios, prueba CVEs conocidos. | VM dedicada: 4 vCPU, 8 GB RAM, 20 GB disco |
**Frecuencia**: scan semanal o tras cambios significativos. No mantener scaneando continuamente (consume muchos recursos y puede afectar servicios).
**Alternativa ligera**: **Nuclei** (escaner basado en templates, mucho mas ligero que OpenVAS). Ideal para servicios web (paneles Proxmox, PBS GUI, PowerDNS Admin).
### Escaneo de contenedores: Trivy
Para la VM del DNS y cualquier otra VM con Docker:
```bash
# Escanear imagenes en uso
trivy image powerdns/pdns-auth
trivy image mariadb:latest
trivy image traefik:latest
# Escanear docker-compose
trivy config /opt/30-powerdns/docker-compose.yml
# Escanear filesystem de la VM
trivy fs --scanners vuln,misconfig /
```
**Frecuencia**: tras cada `docker pull` o actualizacion de imagenes.
### Modelo de responsabilidad: VMs Linux vs Windows
| Tipo | Quien gestiona | Que hacemos nosotros |
|------|----------------|---------------------|
| **Hosts Proxmox/PBS** | Nosotros | Wazuh agent + todo el stack de seguridad |
| **VMs Linux** | Nosotros (mayoria) | Wazuh agent + auditd + hardening |
| **VMs Windows** | El cliente | Solo monitoring externo |
Para VMs Windows de clientes (IaaS):
- **Monitorizar desde fuera**: Uptime Kuma (disponibilidad), trafico anomalo desde el host (mineria, C2, DDoS)
- **NO instalar agentes dentro**, NO gestionar parches, NO escanear vulnerabilidades
- Si la VM "se desmadra", tenemos visibilidad de red/recursos para orientar al cliente
### DECISION 2.2 (confirmada)
| Herramienta | Ambito | Frecuencia | Prioridad |
|-------------|--------|------------|-----------|
| **Wazuh vuln detection** | Paquetes en hosts + VMs Linux gestionadas | Continuo (ya viene con Wazuh) | Fase 1 (gratis, ya incluido) |
| **Trivy** | Imagenes Docker en VMs | Tras updates de imagenes | Fase 2 |
| **Nuclei** | Servicios web expuestos (PBS:8007, PVE:8006, paneles) | Semanal (programado en Semaphore) | Fase 2 (mes 2-3) |
| **OpenVAS** | ~~Escaneo de red completo~~ | ~~Mensual~~ | **Aparcado** salvo requisitos de compliance (ISO 27001, PCI-DSS) |
| **VMs Windows** | Solo monitoring externo (red, disponibilidad) | Continuo desde el host | Siempre |
OpenVAS descartado por ahora: con Wazuh + Nuclei cubrimos el 90%. OpenVAS requiere VM dedicada (4 vCPU, 8GB RAM) y solo aporta valor marginal sin compliance obligatorio.
---
## 2.3 Gestion de secretos e identidad
### El problema real
En este entorno encontramos:
- Contraseñas en docker-compose.yml en texto plano (`PDNS_API_KEY=secret`, `MYSQL_ROOT_PASSWORD`)
- Contraseña de PBS en scripts (`modificar.sh` recibe password como argumento)
- API tokens en ficheros de configuracion
- Password de root capturada y enviada al atacante
- ~50 contraseñas distintas para diferentes servicios, compartidas por chat
### Dos estrategias complementarias
No basta con custodiar secretos (guardarlos bien). Tambien hay que **reducir la cantidad de secretos** (SSO):
| Estrategia | Que hace | Herramienta |
|------------|----------|-------------|
| **Custodiar secretos** | Guardar 50 contraseñas de forma segura | Vaultwarden |
| **Reducir secretos** | Tener 1 login con MFA que abre todo (SSO) | **Authentik** |
### Authentik: Identity Provider centralizado
**Que es**: Identity Provider open source (SSO, SAML, OAuth2, OIDC, LDAP provider). UI moderna e intuitiva.
**Por que Authentik y no Keycloak/Authelia**:
| Aspecto | Authentik | Keycloak | Authelia |
|---------|-----------|----------|----------|
| UI | Moderna, intuitiva | Funcional pero anticuada | Minima (solo login) |
| LDAP provider | Si (emite LDAP) | Si | No |
| Proxy de autenticacion | Si (protege apps sin SSO nativo) | No nativo | Si (es su funcion) |
| MFA integrado | TOTP, WebAuthn, Duo | TOTP, WebAuthn | TOTP, WebAuthn |
| Flows personalizables | Si (drag & drop) | Si (mas complejo) | No |
| Recursos | 2 vCPU, 2 GB RAM | 2 vCPU, 4 GB RAM | 1 vCPU, 512 MB RAM |
| Comunidad | Creciente, muy activa | Grande, madura | Pequeña |
**Que servicios se ponen detras de Authentik (SSO)**:
| Servicio | Soporte SSO | Como |
|----------|-------------|------|
| **Proxmox VE** | OpenID Connect (nativo desde PVE 7) | Configuracion directa |
| **Proxmox Backup Server** | OpenID Connect (nativo) | Configuracion directa |
| **Grafana** | OAuth2/OIDC nativo | Configuracion directa |
| **Netbox** | OAuth2/OIDC nativo | Plugin SSO |
| **Forgejo** | OAuth2/OIDC nativo | Configuracion directa |
| **Semaphore** | OIDC nativo | Configuracion directa |
| **Wazuh Dashboard** | SAML/OpenID | Configuracion en OpenSearch |
| **Vaultwarden** | SSO nativo (v1.29+) | Configuracion directa |
| **PowerDNS Admin** | OAuth2 nativo | Configuracion directa |
| **n8n** | OAuth2 nativo | Configuracion directa |
| **Uptime Kuma** | No nativo | Authentik proxy delante |
| **phpMyAdmin** | No nativo | Authentik proxy delante |
**Impacto**: un tecnico, una cuenta, un MFA, acceso a todo. Baja de la empresa = desactivar 1 cuenta, no 50.
### Evolucion de la gestion de secretos
```
FASE 0 (actual):
50 contraseñas distintas → en la cabeza, en un .txt, en Telegram
FASE 1 (dia 1 - Vaultwarden + .env):
50 contraseñas distintas → custodiadas en Vaultwarden
Secretos en docker-compose → ficheros .env con chmod 600
FASE 2 (dia 1 - Authentik):
1 cuenta Authentik con MFA → abre PVE, PBS, Grafana, Netbox,
Forgejo, Semaphore, Wazuh...
~10 contraseñas residuales → custodiadas en Vaultwarden
(APIs, root de emergencia, clientes)
FASE 3 (mes 6+ - HashiCorp Vault):
Authentik → humanos
Vault → maquinas (Ansible, CI/CD, API tokens con rotacion)
Vaultwarden → secretos residuales del equipo
```
### Orden de despliegue critico
**Authentik debe desplegarse ANTES que los demas servicios** en el servidor nuevo. Si no, cada servicio nace con contraseña local y hay que reconfigurarlo despues.
Orden correcto:
```
Dia 1: Forgejo (git) → para versionar todo desde el minuto 0
Dia 1: Authentik → para que todo lo siguiente ya nazca con SSO
Dia 1: Vaultwarden → con SSO de Authentik
Dia 2: Wazuh Manager → con SSO
Dia 2: VictoriaMetrics + Grafana → con SSO
Dia 3: Loki + Alloy
Dia 3: Netbox → con SSO
Dia 4: Semaphore → con SSO
... Todo nace autenticado contra Authentik
```
### Vaultwarden (gestor de contraseñas para el equipo)
**Que es**: fork self-hosted de Bitwarden. Gestor de contraseñas para equipos.
**Que resuelve**:
- Contraseñas residuales (APIs, root de emergencia, credenciales de clientes)
- Generacion de contraseñas fuertes
- Audit log de quien accedio a que secreto
- Eliminacion de contraseñas en chats/post-its
**Despliegue**: un contenedor Docker, 256MB RAM, 1GB disco.
```yaml
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: unless-stopped
volumes:
- ./data:/data
environment:
- ADMIN_TOKEN=${ADMIN_TOKEN}
- SIGNUPS_ALLOWED=false
```
### HashiCorp Vault (secretos para automatizacion) - MES 6+
**Cuando implementar**: cuando Ansible este en produccion y la automatizacion lo justifique. No antes.
**Que resuelve**:
- Secretos en docker-compose.yml referencia a Vault
- Passwords en playbooks Ansible lee de Vault
- API tokens rotacion automatica
- Certificados PKI interna
### DECISION 2.3 (confirmada)
| Fase | Herramienta | Que cubre | Esfuerzo |
|------|-------------|-----------|----------|
| **Dia 1** | **Vaultwarden** | Custodiar contraseñas del equipo | 30 min |
| **Dia 1** | **Ficheros .env** (chmod 600) | Sacar secretos de docker-compose | 1h |
| **Dia 1** | **Authentik** | SSO + MFA centralizado para todos los paneles | 1-2 dias |
| **Mes 6+** | **HashiCorp Vault** | Secretos para automatizacion (Ansible, CI/CD) | 1 semana |
Recursos Authentik: 2 vCPU, 2 GB RAM, 20 GB disco (contenedor Docker o VM ligera).
---
## 2.4 Acceso y autenticacion
### El problema real
- SSH con password habilitado (cloud-init lo reactivo)
- Solo clave SSH de `david@ansible` como acceso
- Sin MFA
- Sin registro centralizado de quien accede a que servidor
- Sin grabacion de sesiones SSH (no hay audit de que hizo cada tecnico)
- PBS:8007 abierto a internet con autenticacion basica
### Paneles web: ya cubierto por Authentik (2.3)
Con Authentik desplegado, todos los paneles web (PVE, PBS, Grafana, Netbox, Forgejo, Wazuh, etc.) tienen SSO + MFA centralizado. No hace falta configurar TOTP por separado en cada panel.
### SSH: Bastion host con grabacion de sesiones
#### Por que bastion y no Teleport
Se evaluo Teleport pero se descarto por:
- **Licencia AGPL con riesgo** de features migrando a enterprise (patron HashiCorp)
- **Cliente propietario** (`tsh`): no es SSH estandar, requiere instalar software en cada maquina de tecnico
- **Complejidad adicional** para Ansible (requiere configurar proxy SSH especial)
El bastion SSH usa **SSH estandar** (OpenSSH `ProxyJump`, disponible desde 2016):
| Cliente | Soporte ProxyJump (-J) |
|---------|----------------------|
| Linux (OpenSSH) | Si, nativo |
| macOS Terminal / iTerm | Si, nativo |
| Windows 10/11 (OpenSSH) | Si, preinstalado |
| MobaXterm | Si |
| WinSCP | Si (transferencia de ficheros) |
| Ansible | Si (`ansible_ssh_common_args`) |
| PuTTY | No directo (config propia, pero casi nadie lo usa ya) |
#### Como funciona
```
┌──────────┐ ┌─────────────────────────────┐ ┌──────────────┐
│ Tecnico │────▶│ BASTION (VM pequeña) │────▶│ Servidor PBS │
│ │ │ │ └──────────────┘
│ ssh -J │ │ - ForceCommand graba sesion │────▶│ Servidor PVE │
│ bastion │ │ (script/asciinema) │ └──────────────┘
│ servidor │ │ - Grabacion → Loki │────▶│ Servidor DNS │
│ │ │ - Audit log completo │ └──────────────┘
└──────────┘ │ - Solo IP permitida en │
│ firewalls de servidores │
└─────────────────────────────┘
```
Los servidores destino **solo aceptan SSH desde el bastion**:
```bash
# Firewall de cada servidor de produccion (via Ansible)
iptables -A INPUT -p tcp --dport 22 -s IP_BASTION -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j DROP
```
No hay forma de saltarse el bastion.
#### Configuracion del tecnico (una sola vez)
```
# ~/.ssh/config del tecnico
Host bastion
HostName bastion.empresa.local
User david
IdentityFile ~/.ssh/id_ed25519
Host *.infra
ProxyJump bastion
User root
IdentityFile ~/.ssh/id_ed25519
```
Uso diario (nada cambia):
```bash
# SSH normal, transparente, el tecnico ni nota el bastion:
ssh servidor-pbs.infra
ssh servidor-pve.infra
scp fichero.tar.gz servidor-pbs.infra:/tmp/
# Ansible tambien funciona sin cambios:
ansible all -m ping
ansible-playbook -i inventory/netbox.yml playbooks/hardening.yml
```
#### Grabacion de sesiones
El bastion usa `ForceCommand` en sshd_config para grabar cada sesion con `script` o `asciinema`:
- Cada sesion se guarda con: fecha, usuario, servidor destino, duracion
- Se puede reproducir con `scriptreplay` o `asciinema play`
- Los logs van a Loki para busqueda centralizada
- No es un video bonito como Teleport, pero es texto completo con replay y timing
#### Recursos
VM bastion: 1 vCPU, 1 GB RAM, 20 GB disco. Minima.
### Hardening SSH (Ansible playbook, dia 1)
Cada servidor nuevo nace con este hardening aplicado automaticamente:
```yaml
# Hardening SSH base
- PasswordAuthentication: "no"
- KbdInteractiveAuthentication: "no"
- PermitRootLogin: "prohibit-password" # solo clave
- MaxAuthTries: 3
- LoginGraceTime: 30
- AllowUsers: "root david" # solo usuarios conocidos
# Neutralizar cloud-init SSH override
- /etc/cloud/cloud.cfg.d/99-ssh-hardening.cfg: "ssh_pwauth: false"
# Firewall: SSH solo desde bastion
- iptables: -A INPUT -p tcp --dport 22 -s IP_BASTION -j ACCEPT
# Fail2ban
- Instalar y configurar con ban de 1h tras 5 intentos
```
### Fail2ban (dia 1)
```ini
# /etc/fail2ban/jail.d/custom.conf
[sshd]
enabled = true
port = ssh
filter = sshd
maxretry = 5
findtime = 600
bantime = 3600
action = %(action_mwl)s
[proxmox]
enabled = true
port = 8006
filter = proxmox
maxretry = 5
bantime = 3600
```
### CrowdSec (semana 2)
**Que es**: IPS colaborativo open source. Analiza logs, detecta ataques, y comparte IPs maliciosas con la comunidad.
**Diferencia con Fail2ban**:
- Fail2ban: reactivo, local, solo tu ves tus ataques
- CrowdSec: proactivo, colaborativo, bloqueas IPs que atacan a otros antes de que te ataquen a ti
**Complementa** a Fail2ban, no lo reemplaza.
```bash
curl -s https://install.crowdsec.net | bash
cscli collections install crowdsecurity/sshd
cscli collections install crowdsecurity/linux
```
### Flujo de acceso completo para un tecnico
```
Tecnico quiere acceder a:
Panel PVE/PBS/Grafana/Netbox/Wazuh/Forgejo:
→ Authentik SSO → MFA → acceso
→ 1 cuenta, 1 password, 1 TOTP
SSH a un servidor:
→ ssh servidor.infra (transparente, pasa por bastion)
→ Clave SSH (sin password)
→ Bastion graba toda la sesion
→ Fail2ban + CrowdSec protegen
→ auditd registra todo dentro del servidor
→ Wazuh alerta si algo raro
Secreto de un cliente:
→ Vaultwarden (SSO via Authentik) → buscar → copiar
→ Audit log de quien accedio
```
### DECISION 2.4 (confirmada)
| Fase | Accion | Herramienta |
|------|--------|-------------|
| **Dia 1** | SSO + MFA para todos los paneles web | Authentik |
| **Dia 1** | Bastion SSH con grabacion de sesiones | VM bastion + asciinema |
| **Dia 1** | Hardening SSH en cada servidor nuevo | Ansible playbook |
| **Dia 1** | Fail2ban en cada servidor nuevo | Ansible playbook |
| **Cada servidor nuevo** | Firewall: SSH solo desde bastion | Ansible playbook |
| **Semana 2** | CrowdSec en servidores expuestos | Ansible playbook |
---
## Resumen Capa 2 completa (DECISIONES FINALES)
```
┌─────────────────────────────────────────────────────┐
│ CAPA 2: SEGURIDAD │
├─────────────────────────────────────────────────────┤
│ │
│ 2.1 DETECCION │
│ ┌───────────────────────────────────┐ │
│ │ Wazuh Manager + Dashboard │ │
│ │ (VM dedicada, 4vCPU, 12GB RAM) │ │
│ │ - FIM (file integrity real-time) │ │
│ │ - Log analysis + correlacion │ │
│ │ - Rootkit detection │ │
│ │ - Vulnerability detection │ │
│ │ - Active response │ │
│ │ + auditd en cada servidor │ │
│ │ + Lynis post-despliegue/trimest. │ │
│ └───────────────────────────────────┘ │
│ │
│ 2.2 VULNERABILIDADES │
│ ┌───────────────────────────────────┐ │
│ │ Wazuh vuln detection (continuo) │ │
│ │ Trivy (contenedores Docker) │ │
│ │ Nuclei (servicios web, semanal) │ │
│ │ OpenVAS: DESCARTADO (salvo │ │
│ │ compliance futuro) │ │
│ │ VMs Windows: solo monitoring │ │
│ │ externo (red/disp.) │ │
│ └───────────────────────────────────┘ │
│ │
│ 2.3 SECRETOS E IDENTIDAD │
│ ┌───────────────────────────────────┐ │
│ │ Authentik (SSO + MFA, dia 1) │ │
│ │ - PVE, PBS, Grafana, Netbox, │ │
│ │ Forgejo, Semaphore, Wazuh, │ │
│ │ Vaultwarden, PowerDNS Admin │ │
│ │ Vaultwarden (secretos residuales)│ │
│ │ .env con permisos 600 (interim) │ │
│ │ HashiCorp Vault (mes 6+) │ │
│ └───────────────────────────────────┘ │
│ │
│ 2.4 ACCESO │
│ ┌───────────────────────────────────┐ │
│ │ Bastion SSH con grabacion │ │
│ │ (SSH estandar, ProxyJump -J) │ │
│ │ Hardening SSH (Ansible, dia 1) │ │
│ │ Fail2ban (dia 1) │ │
│ │ CrowdSec (semana 2) │ │
│ │ Teleport: DESCARTADO │ │
│ │ (AGPL, cliente propietario) │ │
│ └───────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────┘
Recursos Capa 2:
- VM Wazuh: 4 vCPU, 12 GB RAM, 100 GB disco
- VM Bastion: 1 vCPU, 1 GB RAM, 20 GB disco
- Authentik: 2 vCPU, 2 GB RAM, 20 GB disco (contenedor)
- Vaultwarden: contenedor Docker, 256 MB RAM
- Wazuh agent por servidor: 50-100 MB RAM
- CrowdSec por servidor: ~50 MB RAM
- Fail2ban por servidor: ~30 MB RAM
- auditd: ya instalado, 0 extra
```
---
## Prioridades de despliegue Capa 2
Contexto: se monta un servidor nuevo desde cero. La infra existente esta cerrada y se migrara progresivamente. Cada servicio nuevo nace ya con SSO, monitoring y seguridad desde el minuto 0.
| Prioridad | Que | Esfuerzo | Impacto |
|-----------|-----|----------|---------|
| **Dia 1** | Authentik (SSO + MFA) | 1-2h | Todo lo que se despliegue despues ya nace con SSO |
| **Dia 1** | Vaultwarden (con SSO) | 30min | Secretos custodiados desde el dia 1 |
| **Dia 1** | Bastion SSH + grabacion | 2h | Toda sesion SSH queda registrada |
| **Dia 1** | Hardening SSH + Fail2ban (Ansible) | 2h | Cierra la puerta principal |
| **Semana 1** | Wazuh Manager + Dashboard (con SSO) | 1 dia | Deteccion de intrusiones activa |
| **Semana 1** | Wazuh agents en servidores criticos | 2h | FIM + rootkit detection |
| **Semana 2** | auditd en todos los servidores (Ansible) | 2h | Registro forense completo |
| **Semana 2** | CrowdSec en servidores con puertos publicos | 2h | Inteligencia de amenazas colaborativa |
| **Mes 1** | Wazuh agents en todos los servidores | 1 dia | Cobertura completa |
| **Mes 1** | Lynis baseline en todos los servidores | 2h | Hardening score por servidor |
| **Mes 2** | Trivy en VMs con Docker | 2h | Vulnerabilidades en contenedores |
| **Mes 2-3** | Nuclei scans semanales | 2h | Vulnerabilidades en servicios web |
| **Mes 6+** | HashiCorp Vault | 1 semana | Secretos automatizados |