Guía Paso a Paso: Búnker de Seguridad con Nginx y Docker

Nginx Docker Compose Backend API Ciberseguridad

Objetivo de esta guía: Documentar la arquitectura de defensa perimetral para aislar un backend del acceso público. Se aplican políticas de restricción máxima (Zero Trust y Mínimo Privilegio) limitando drásticamente el tamaño de las peticiones, mitigando ataques DDoS y auditando el tráfico mediante un proxy inverso Nginx contenedorizado.

1. Entendiendo la Arquitectura de Aislamiento

La seguridad real empieza por la arquitectura física de la red. En lugar de exponer la base de datos o la aplicación directamente a internet, creamos capas de protección sucesivas (Arquitectura de Defensa en Profundidad).

Concepto Clave: El Backend y la Base de Datos se ejecutan en una red privada virtual de Docker (secure_net). No tienen puertos expuestos al servidor físico host. El único que puede comunicarse con ellos es Nginx, y Nginx solo acepta peticiones que vengan del proxy principal (Apache) a nivel local.
graph LR User((App Frontend/Web)) -- HTTPS/443 --> Apache[Apache Reverse Proxy] subgraph "Servidor Host (Linux)" Apache -- 127.0.0.1:8081 --> Nginx[Docker Nginx :80] subgraph "Docker Network (secure_net)" Nginx -- Proxy Pass --> Backend[Docker Backend API :8080] Backend -- Internal --> DB[(Base de Datos :5432)] end end style Apache fill:#ffecb3,stroke:#fbc02d,stroke-width:2px style Nginx fill:#c8e6c9,stroke:#388e3c,stroke-width:2px style Backend fill:#ffcc80,stroke:#e65100,stroke-width:2px style DB fill:#bbdefb,stroke:#1976d2,stroke-width:2px

2. Aislamiento Físico (Docker Compose)

El primer paso es configurar nuestro entorno de contenedores para cortar el acceso directo al backend y establecer a Nginx como el único embudo de entrada.

📄 docker-compose.yml
services: api_backend: build: . container_name: app_backend restart: always # ELIMINADO: El bloque 'ports' se suprime para hacerlo invisible al exterior networks: - secure_net proxy_nginx: image: nginx:alpine container_name: app_nginx ports: # RESTRICCIÓN MÁXIMA: Nginx expone su puerto 80 SOLO al localhost (127.0.0.1) - "127.0.0.1:8081:80" volumes: - ./nginx.conf:/etc/nginx/nginx.conf:ro depends_on: - api_backend networks: - secure_net
Justificación de Seguridad: Al atar Nginx estrictamente a 127.0.0.1, bloqueamos por diseño que un atacante intente saltarse Apache escaneando o atacando la IP pública del servidor por el puerto 8081. Nginx será completamente sordo a peticiones externas no enrutadas.

3. Defensas Activas: Cortafuegos Restrictivo en Nginx

Asumiendo que todo tráfico entrante es potencialmente hostil, se configuran reglas en Nginx con umbrales extremadamente bajos, ajustados milimétricamente al uso real de la API.

📄 nginx.conf (Bloque http)
http { # 1. Ocultar huella del servidor a los atacantes (Evita perfilado de CVEs) server_tokens off; # 2. Zona de memoria para control estricto de IP (10MB) a un ritmo de 5 peticiones/seg limit_req_zone $binary_remote_addr zone=api_limit:10m rate=5r/s; upstream backend_servers { server api_backend:8080; } # ... }

3.1. Reglas de Protección (Bloque server)

Dentro del servidor Nginx, aplicamos barreras diseñadas para estrangular cargas maliciosas antes de que consuman ciclos de CPU o memoria en el Backend.
Json manda unos 3kb, con 56k se tiene un margen de seguridad amplio para cualquier petición legítima, pero se bloquea cualquier intento de subida de archivos o inyección de payloads gigantes.

📄 nginx.conf (Bloque server)
server { listen 80; # BARRERA 1: Bloqueo de Payloads Pesados (Restricción a 56 Kilobytes, o menos). client_max_body_size 56k; # BARRERA 2: Timeouts Anti-Zombies (Corte agresivo a 10s) client_body_timeout 10s; client_header_timeout 10s; send_timeout 10s; location / { # BARRERA 3: Ejecución implacable del Rate Limiting limit_req zone=api_limit burst=10 nodelay; proxy_pass http://backend_servers; } }

4. Auditoría y Trazabilidad (Logs)

Dado que la API opera detrás de múltiples proxies (Apache -> Nginx -> Docker), las IP entrantes se enmascaran como locales. Se implementa una trazabilidad absoluta para extraer el origen real del tráfico.

📄 nginx.conf (Cabeceras y Logs)
# 1. Formato personalizado para capturar la IP real y el Vector de Ataque log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; # 2. Aplicar la política de logs access_log /var/log/nginx/access.log main; location / { # 3. Inyectar la IP real a las cabeceras hacia el Backend proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://backend_servers; }

4.1. Comandos de Inspección (Respuesta a Incidentes)

Comandos operativos para auditar el sistema o reaccionar ante anomalías de tráfico.

# Monitorizar el tráfico en tiempo real atravesando las defensas
docker logs -f app_nginx
# Cazar IPs bloqueadas por el limitador de velocidad (Rate Limiting)
docker logs app_nginx | grep "limiting requests"
# Identificar intentos de inyección de payloads gigantes (>56KB)
docker logs app_nginx | grep "client intended to send too large body"