resources/views/pages/frontend/docs/matriz-comunicaciones-firewall.md
Última modificación: 24 Oct, 2026

Matriz de Comunicaciones & Reglas de Firewall (UFW)

En una infraestructura distribuida de alta disponibilidad para Mañuti, la seguridad perimetral se rige bajo el principio estricto de Red Zero-Trust (Confianza Cero) y Mínimo Privilegio. Ningún nodo interno confía en el tráfico de la red local por el mero hecho de compartir el segmento Ethernet; cada host aísla su pila TCP/IP mediante UFW (Uncomplicated Firewall), permitiendo únicamente flujos punto a punto bidireccionalmente declarados.


1. Filosofía de Seguridad Perimetral: Red Zero-Trust

La topología distribuida de Mañuti divide los servidores físicos o virtuales en cuatro capas lógicas con políticas de descarte por defecto (Default Deny):

flowchart TD
    U(["INTERNET / CLIENTES EXTERNOS"])

    subgraph Capa1 ["1. CAPA DE ACCESO PÚBLICA (DMZ)"]
        LB["Load Balancer (Nginx / HAProxy)<br/>Única IP con cara a Internet"]
    end

    subgraph Capa2 ["2. CAPA DE APLICACIÓN"]
        WEB["Web-01 / Web-02 (PHP-FPM)"]
        WORKER["Worker (Horizon Daemons)"]
    end

    subgraph Capa3 ["3. CAPA TIEMPO REAL"]
        REVERB["Reverb (WebSockets)<br/>Puerto 8080 Interno"]
    end

    subgraph Capa4 ["4. CAPA DE PERSISTENCIA"]
        MARIADB[("MariaDB Clúster (3306)")]
        REDIS[("Redis Caché/Colas (6379)")]
        MONGO[("MongoDB Auditoría (27017)")]
    end

    subgraph Capa5 ["5. CAPA DE ALMACENAMIENTO"]
        MINIO[("MinIO S3 (9000/9001)")]
    end

    %% Conexiones desde el exterior
    U -->|"HTTPS (443) / HTTP (80)"| LB

    %% Conexiones desde el balanceador
    LB -->|"Red Privada LAN (Tráfico Balanceado)"| WEB
    LB -->|"Redirección WSS"| REVERB

    %% Conexiones desde la capa de aplicación hacia persistencia/almacenamiento
    WEB -->|"Consultas SQL / NoSQL"| MARIADB
    WEB -->|"Redis Caché/PubSub"| REDIS
    WEB --> MONGO
    WEB -->|"S3 PutObject"| MINIO

    WORKER --> MARIADB
    WORKER --> REDIS
    WORKER --> MONGO
    WORKER --> MINIO

    %% Conexiones desde la capa en tiempo real
    REVERB --> REDIS

Reglas de Oro de la Red:

  1. Denegación Implícita Universal: Todos los nodos inician con ufw default deny incoming. Si una conexión no está explícitamente autorizada con su IP de origen, el paquete se descarta de forma silenciosa (DROP).
  2. Invisibilidad de la Capa Web: Los servidores de aplicación (Web-01, Web-02) no tienen puertos públicos. Si un atacante intenta conectar a http://192.168.1.64:80 saltándose el balanceador, el firewall del host rechaza la conexión.
  3. Aislamiento de la Persistencia: MariaDB, MongoDB y Redis solo aceptan tráfico de las IPs de los servidores de aplicación y workers que ejecutan código PHP.

2. Matriz de Control de Acceso y Mapa de Puertos

A continuación se detalla la matriz maestra de interconexión.

Nota sobre el direccionamiento IP: Los parámetros 192.168.1.0/24 corresponden a la subred de demostración del clúster Bare-Metal. En entornos productivos, sustituya estos valores por las IPs estáticas de su VLAN privada o VPC.

Capa Nodo / Host IP Ilustrativa Servicio Puerto Origen Autorizado Justificación Operativa
Acceso Load Balancer (LB) 192.168.1.122 HTTP 80/tcp 0.0.0.0/0 (Anywhere) Recepción de tráfico web estándar y redirección a HTTPS.
HTTPS 443/tcp 0.0.0.0/0 (Anywhere) Terminación TLS/SSL para navegación web y túneles WSS.
SSH 22/tcp 192.168.1.0/24 (Admin) Gestión de infraestructura y despliegues desde el bastión.
Aplicación Web-01 192.168.1.64 HTTP 80/tcp 192.168.1.122 (Solo LB) Recepción de tráfico HTTP inverso balanceado desde Nginx.
SSH 22/tcp 192.168.1.0/24 Automatización de despliegues y administración remota.
Aplicación Web-02 192.168.1.130 HTTP 80/tcp 192.168.1.122 (Solo LB) Réplica idéntica sin estado para balanceo de carga.
SSH 22/tcp 192.168.1.0/24 Automatización de despliegues y administración remota.
Aplicación Worker (Horizon) 192.168.1.126 SSH 22/tcp 192.168.1.0/24 Administración. No recibe tráfico de red de usuarios.
Tiempo Real Realtime (Reverb) 192.168.1.127 WSS / API 8080/tcp 192.168.1.122 (LB) Túneles WebSocket de clientes derivados por Nginx.
HTTP API 8080/tcp 192.168.1.64 (Web-01) Emisión de eventos backend (API Push ShouldBroadcast).
HTTP API 8080/tcp 192.168.1.130 (Web-02) Emisión de eventos backend (API Push ShouldBroadcast).
HTTP API 8080/tcp 192.168.1.126 (Worker) Emisión de eventos desde jobs en segundo plano.
SSH 22/tcp 192.168.1.0/24 Administración y control de demonios.
Datos SQL (MariaDB) 192.168.1.123 MySQL 3306/tcp 192.168.1.64 (Web-01) Transacciones transaccionales y de identidad.
MySQL 3306/tcp 192.168.1.130 (Web-02) Transacciones transaccionales y de identidad.
MySQL 3306/tcp 192.168.1.126 (Worker) Procesamiento relacional asíncrono y lotes (job_batches).
SSH 22/tcp 192.168.1.0/24 Gestión DBA y respaldos.
Datos Caché (Redis) 192.168.1.124 Redis 6379/tcp 192.168.1.64 (Web-01) Sesiones de usuario (520 B) y caché de catálogos.
Redis 6379/tcp 192.168.1.130 (Web-02) Sesiones de usuario (520 B) y caché de catálogos.
Redis 6379/tcp 192.168.1.126 (Worker) Broker de transporte de colas (Horizon).
Redis 6379/tcp 192.168.1.127 (Reverb) Bus Pub/Sub para escalado de WebSockets.
SSH 22/tcp 192.168.1.0/24 Administración.
Datos NoSQL (MongoDB) 192.168.1.120 Mongo 27017/tcp 192.168.1.64 (Web-01) Escritura de logs forenses de auditoría en caliente.
Mongo 27017/tcp 192.168.1.130 (Web-02) Escritura de logs forenses de auditoría en caliente.
Mongo 27017/tcp 192.168.1.126 (Worker) Consumo y procesamiento forense por workers de Horizon.
SSH 22/tcp 192.168.1.0/24 Administración DBA.
Storage Object Storage (MinIO) 192.168.1.125 HTTP/S 80, 443/tcp 0.0.0.0/0 (Anywhere) Descargas públicas directas de avatares y mapas (CDN).
S3 API 9000/tcp 192.168.1.64 (Web-01) Subida interna de avatares (PutObject).
S3 API 9000/tcp 192.168.1.130 (Web-02) Subida interna de avatares (PutObject).
S3 API 9000/tcp 192.168.1.126 (Worker) Subida de exportaciones ARCO y diagramas SVG.
Consola 9001/tcp 192.168.1.0/24 Panel web administrativo de MinIO Console.
SSH 22/tcp 192.168.1.0/24 Administración.

3. Diagrama de Conectividad de Red y Flujos

flowchart TD
    UserClient(["Usuario / Internet"])

    subgraph CapaAcceso ["1. Capa de Acceso (Public Subnet)"]
        LB["Load Balancer (Nginx)<br>192.168.1.122"]
    end

    subgraph CapaApp ["2. Capa de Aplicación (Private Stateless)"]
        W1["Web-01<br>192.168.1.64"]
        W2["Web-02<br>192.168.1.130"]
        WORK["Worker (Horizon)<br>192.168.1.126"]
    end

    subgraph CapaRealtime ["3. Capa Tiempo Real"]
        RT["Reverb (WebSockets)<br>192.168.1.127"]
    end

    subgraph CapaDatos ["4. Capa de Datos (Private Stateful)"]
        DB[("MariaDB SQL<br>192.168.1.123")]
        REDIS[("Redis In-Memory<br>192.168.1.124")]
        MONGO[("MongoDB NoSQL<br>192.168.1.120")]
    end

    subgraph CapaStorage ["5. Capa Almacenamiento"]
        ST[("MinIO S3 Storage<br>192.168.1.125")]
    end

    %% Flujos Externos
    UserClient -->|"HTTPS:443 / HTTP:80"| LB
    UserClient -.->|"Descarga CDN (80/443)"| ST

    %% Balanceo HTTP
    LB -->|"TCP:80 (Proxy Pass)"| W1
    LB -->|"TCP:80 (Proxy Pass)"| W2
    LB -->|"TCP:8080 (WSS Tunnel /app)"| RT

    %% Tráfico hacia Realtime
    W1 -->|"HTTP API:8080 (Push Event)"| RT
    W2 -->|"HTTP API:8080 (Push Event)"| RT
    WORK -->|"HTTP API:8080 (Push Event)"| RT

    %% Conexiones de Datos SQL
    W1 -->|"TCP:3306"| DB
    W2 -->|"TCP:3306"| DB
    WORK -->|"TCP:3306"| DB

    %% Conexiones Redis
    W1 -->|"TCP:6379 (Session/Cache)"| REDIS
    W2 -->|"TCP:6379 (Session/Cache)"| REDIS
    WORK -->|"TCP:6379 (Queues)"| REDIS
    RT -->|"TCP:6379 (Pub/Sub)"| REDIS

    %% Conexiones NoSQL MongoDB
    W1 -->|"TCP:27017 (Audit)"| MONGO
    W2 -->|"TCP:27017 (Audit)"| MONGO
    WORK -->|"TCP:27017 (Audit)"| MONGO

    %% Conexiones MinIO S3
    W1 -->|"TCP:9000 (S3 PutObject)"| ST
    W2 -->|"TCP:9000 (S3 PutObject)"| ST
    WORK -->|"TCP:9000 (S3 PutObject)"| ST

4. Guía de Configuración Host por Host (UFW)

Para aplicar este blindaje en un despliegue Bare-Metal o máquinas virtuales Ubuntu 24.04, ejecute los bloques de comandos en sus nodos respectivos.

A. Política Base Inicial (Ejecutar en TODOS los nodos)

sudo ufw reset
sudo ufw default deny incoming
sudo ufw default allow outgoing
# Permitir SSH únicamente desde la red interna de administración
sudo ufw allow from 192.168.1.0/24 to any port 22 proto tcp comment 'Admin SSH'

B. Nodo 1: Load Balancer (192.168.1.122)

Es el único componente que expone puertos al mundo exterior:

sudo ufw allow 80/tcp comment 'HTTP Ingress'
sudo ufw allow 443/tcp comment 'HTTPS Ingress'
sudo ufw enable
sudo ufw status numbered

C. Nodos Web: Web-01 (.64) y Web-02 (.130)

Bloqueo de acceso directo. Solo atienden peticiones nacidas en la IP interna del Load Balancer:

sudo ufw allow from 192.168.1.122 to any port 80 proto tcp comment 'Trafico HTTP solo desde LB'
sudo ufw enable

D. Nodo Tiempo Real: Reverb (192.168.1.127)

Acepta dos fuentes de tráfico en el puerto 8080: el Load Balancer (clientes WebSocket) y los servidores de aplicación/worker (publicación de eventos backend):

# Tráfico de clientes web derivado por el Load Balancer
sudo ufw allow from 192.168.1.122 to any port 8080 proto tcp comment 'WSS Tunnel desde LB'

# API Push interna desde el clúster de aplicación
sudo ufw allow from 192.168.1.64 to any port 8080 proto tcp comment 'Push Event desde Web-01'
sudo ufw allow from 192.168.1.130 to any port 8080 proto tcp comment 'Push Event desde Web-02'
sudo ufw allow from 192.168.1.126 to any port 8080 proto tcp comment 'Push Event desde Worker'
sudo ufw enable

E. Nodo Base de Datos Relacional: MariaDB (192.168.1.123)

Atención: Asegúrese de configurar bind-address = 0.0.0.0 en /etc/mysql/mariadb.conf.d/50-server.cnf antes de activar el firewall.

sudo ufw allow from 192.168.1.64 to any port 3306 proto tcp comment 'SQL Web-01'
sudo ufw allow from 192.168.1.130 to any port 3306 proto tcp comment 'SQL Web-02'
sudo ufw allow from 192.168.1.126 to any port 3306 proto tcp comment 'SQL Worker Horizon'
sudo ufw enable

F. Nodo Caché y Sesiones: Redis (192.168.1.124)

Atención: Configure bind 0.0.0.0 y protected-mode yes en /etc/redis/redis.conf.

sudo ufw allow from 192.168.1.64 to any port 6379 proto tcp comment 'Redis Sesion Web-01'
sudo ufw allow from 192.168.1.130 to any port 6379 proto tcp comment 'Redis Sesion Web-02'
sudo ufw allow from 192.168.1.126 to any port 6379 proto tcp comment 'Redis Colas Worker'
sudo ufw allow from 192.168.1.127 to any port 6379 proto tcp comment 'Redis PubSub Reverb'
sudo ufw enable

G. Nodo NoSQL: MongoDB (192.168.1.120)

Atención: Configure net.bindIp: 0.0.0.0 en /etc/mongod.conf.

sudo ufw allow from 192.168.1.64 to any port 27017 proto tcp comment 'Mongo Audit Web-01'
sudo ufw allow from 192.168.1.130 to any port 27017 proto tcp comment 'Mongo Audit Web-02'
sudo ufw allow from 192.168.1.126 to any port 27017 proto tcp comment 'Mongo Audit Worker'
sudo ufw enable

H. Nodo Storage: MinIO S3 (192.168.1.125)

Expone la API interna para subidas autenticadas y la consola de administración en la LAN:

# Acceso público CDN para descarga de avatares y mapas vectoriales
sudo ufw allow 80/tcp comment 'MinIO CDN HTTP'
sudo ufw allow 443/tcp comment 'MinIO CDN HTTPS'

# API S3 Interna (PutObject / GetObject seguro)
sudo ufw allow from 192.168.1.64 to any port 9000 proto tcp comment 'MinIO API Web-01'
sudo ufw allow from 192.168.1.130 to any port 9000 proto tcp comment 'MinIO API Web-02'
sudo ufw allow from 192.168.1.126 to any port 9000 proto tcp comment 'MinIO API Worker'

# Consola Web Administrativa (Restringida a la Subred de Gestión)
sudo ufw allow from 192.168.1.0/24 to any port 9001 proto tcp comment 'MinIO Console LAN'
sudo ufw enable

I. Nodo Worker: Horizon (192.168.1.126)

Dado que Horizon es un consumidor pasivo (inicia sockets salientes hacia Redis, MariaDB, Mongo y MinIO pero no expone ningún puerto de escucha HTTP), su configuración perimetral es la más simple y segura:

# Solo SSH permitido
sudo ufw enable

5. El Flujo de Difusión WebSocket en Dos Fases

La separación de Reverb en un nodo dedicado genera una distinción arquitectónica entre la conexión persistente del cliente y la emisión de eventos del backend:

sequenceDiagram
    autonumber
    actor Cliente as Navegador Web
    participant LB as Load Balancer (.122)
    participant RT as Reverb Daemon (.127)
    participant W1 as Web-01 (.64)
    participant Redis as Redis Pub/Sub (.124)

    %% Fase 1
    Note over Cliente, RT: FASE 1: Conexión Persistente (El Túnel WSS)
    Cliente->>LB: GET /app/key (Upgrade: websocket) [Puerto 443]
    LB->>RT: Proxy Pass TCP:8080 (HTTP Upgrade)
    RT-->>LB: 101 Switching Protocols
    LB-->>Cliente: Conexión WebSocket Abierta (Túnel WSS Activo)

    %% Fase 2
    Note over Cliente, Redis: FASE 2: Disparo de Evento en Backend
    Cliente->>LB: POST /usuarios (Crear Usuario)
    LB->>W1: Proxy Pass HTTP:80
    W1->>W1: Procesa en MariaDB y despacha Evento
    W1->>RT: POST http://192.168.1.127:8080/apps/id/events (API Push)
    RT->>Redis: PUBLISH reverb-scaling (Payload JSON)
    Redis-->>RT: Mensaje distribuido a instancias suscritas
    RT-->>Cliente: Push Frame WebSocket (sessions.updated / audit.created)
  1. Fase 1 (El Túnel): El navegador del cliente abre un socket contra el Load Balancer (https://dominio.com/app). Nginx detecta el encabezado Upgrade: websocket y deriva el socket al puerto 8080 de Reverb. Los nodos Web desconocen esta conexión.
  2. Fase 2 (El Evento): Cuando ocurre una mutación en Web-01 (e.g. un operador desconecta a un usuario), el servidor web emite una llamada REST interna POST http://192.168.1.127:8080/apps/.../events. Reverb recibe el paquete, se coordina mediante Redis Pub/Sub y empuja el frame a través del túnel persistente establecido en la Fase 1 hacia el navegador.

6. Procedimientos de Diagnóstico y Mantenimiento

Inspección de Reglas Numeradas

sudo ufw status numbered

Eliminación Segura de una Regla Errónea

# Elimina la regla número 3 sin alterar las demás
sudo ufw delete 3
sudo ufw reload

Validación de Conectividad Inter-Nodo (Prueba de Socket)

Ejecute desde Web-01 para verificar que el puerto de base de datos está abierto en el nodo SQL:

nc -zv 192.168.1.123 3306
# Salida esperada: Connection to 192.168.1.123 3306 port [tcp/mysql] succeeded!

Enlaces Relacionados

Edita este documento en >> matriz-comunicaciones-firewall.md
← Volver a la Landing Page