Guía Paso a Paso: Búnker de Seguridad Perimetral con Nginx y Docker
Nginx
Docker Compose
Backend API
Ciberseguridad
Objetivo de esta guía: Documentar el diseño de un "Búnker de Seguridad" perimetral para aislar un backend API de acceso público. Aplicamos los principios de Defensa en Profundidad (Zero Trust) y Mínimo Privilegio, restringiendo el tamaño máximo de los cuerpos de petición, mitigando ataques de denegación de servicio (DDoS/Slowloris) y garantizando la trazabilidad forense de logs mediante Nginx.
1. Arquitectura de Aislamiento en Profundidad (Zero Trust)
En la ingeniería de seguridad de infraestructura, exponer una base de datos relacional o una aplicación Java directamente a internet representa un riesgo inaceptable. Los escáneres automatizados detectan constantemente puertos abiertos (como el 8080 o 5432) intentando explotar vulnerabilidades conocidas (CVEs) o lanzar ataques de fuerza bruta.
Para mitigar este vector de ataque, aplicamos una arquitectura de Defensa en Profundidad. La base de datos y la API backend se ejecutan completamente "sordas" e invisibles al exterior dentro de una red privada virtual de Docker (secure_net). Nginx se sitúa en la frontera como un embudo de seguridad, filtrando cada petición antes de transmitirla a los contenedores internos.
Aislamiento Físico Garantizado: El backend y la base de datos PostgreSQL carecen de mapeo de puertos hacia la máquina host. Únicamente el contenedor de Nginx puede comunicarse con ellos por la red interna de Docker, y Nginx solo acepta conexiones locales originadas por el proxy Apache principal.
graph LR
User((Cliente Web / App)) -- HTTPS/443 --> Apache[Apache Reverse Proxy]
subgraph "Servidor Host (Linux)"
Apache -- 127.0.0.1:8081 --> Nginx[Docker Nginx :80]
subgraph "Red Privada Docker (secure_net)"
Nginx -- Proxy Pass interno --> Backend[Docker Backend API :8080]
Backend -- Red interna --> DB[(Base de Datos PostgreSQL :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 mediante Docker Compose
Configuramos la infraestructura de contenedores de modo que la directiva ports sea suprimida por completo en el servicio del backend. Al eliminar el binding de puertos, Docker no crea ninguna interfaz de escucha en la máquina física para ese contenedor, volviéndolo inaccesible ante escaneos de IP pública.
El contenedor proxy_nginx expone su puerto 80 amarrado estrictamente a la interfaz de bucle local 127.0.0.1:8081, lo que impide que atacantes externos intenten saltarse la primera capa de cortafuegos conectándose directamente a la IP pública por el puerto 8081.
services:
api_backend:
build: .
container_name: app_backend
restart: always
# AISLAMIENTO TOTAL: Se elimina 'ports' para hacerlo invisible en la máquina host
networks:
- secure_net
proxy_nginx:
image: nginx:alpine
container_name: app_nginx
ports:
# RESTRICCIÓN PERIMETRAL: Expuesto SOLO al bucle local 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
networks:
secure_net:
driver: bridge
Justificación de Diseño: Si un atacante ejecuta un escaneo masivo de puertos (ej. nmap) sobre la IP pública del servidor, Nginx permanecerá totalmente invisible porque sólo responde a llamadas originadas internamente dentro del propio servidor host.
3. Defensas Activas: Cortafuegos de Aplicación en Nginx
Partiendo del principio de Zero Trust (Confianza Cero), asumimos que cualquier tráfico entrante es potencialmente malicioso. Por ello, configuramos en Nginx políticas de estrangulamiento de peticiones y restricciones de tamaño basadas en el perfil de uso real de la API.
http {
# 1. Ocultar la versión de Nginx en las cabeceras HTTP (Dificulta el perfilado de vulnerabilidades CVE)
server_tokens off;
# 2. Asignar 10MB de RAM para rastrear IPs y limitar el tráfico a un máximo de 5 peticiones por segundo
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 Anti-Exploit (Bloque Server)
Dentro de la configuración del servidor virtual de Nginx, aplicamos barreras diseñadas para descartar cargas maliciosas en la capa de red antes de que lleguen a consumir memoria o hilos de procesamiento en la aplicación Spring Boot.
Un Payload JSON legítimo emitido por una caja registradora Novapay ocupa entre 2KB y 4KB. Al establecer un límite de 56KB, proporcionamos un margen de tolerancia amplio para peticiones legítimas mientras bloqueamos de inmediato (devuelviendo HTTP 413 Payload Too Large) cualquier intento de inyección de binarios o ataques de desbordamiento de búfer.
server {
listen 80;
# BARRERA 1: Límite estricto de tamaño de cuerpo (56 Kilobytes máximo)
client_max_body_size 56k;
# BARRERA 2: Timeouts defensivos contra ataques Slowloris (Corte a 10s)
client_body_timeout 10s;
client_header_timeout 10s;
send_timeout 10s;
location / {
# BARRERA 3: Aplicar Rate Limiting (Permite ráfaga puntual de 10 peticiones sin retardo)
limit_req zone=api_limit burst=10 nodelay;
proxy_pass http://backend_servers;
}
}
- Límite Restrictivo de 56KB: Diseñado específicamente para APIs REST. Evita que un atacante sature la memoria RAM del servidor enviando ficheros gigantescos o archivos maliciosos.
- Timeouts Agresivos (10s): Neutralizan ataques tipo Slowloris, en los cuales los clientes abren conexiones y envían datos byte a byte a velocidad extremadamente lenta para agotar la tabla de sockets del servidor.
- Rate Limiting (Rate=5r/s, Burst=10 nodelay): Permite ráfagas normales de uso de la aplicación, pero bloquea con código HTTP 503 cualquier script que intente realizar ataques de fuerza bruta.
4. Auditoría Forense y Trazabilidad de IPs en Logs
Debido a que la petición atraviesa múltiples capas de proxies (Cliente → Apache → Nginx → Backend Java), por defecto la IP origen que registraría el backend sería 127.0.0.1. Para mantener una trazabilidad forense completa en caso de incidente de seguridad, Nginx captura e inyecta las cabeceras HTTP X-Real-IP y X-Forwarded-For.
# Formato de log personalizado para capturar IP cliente real y User-Agent
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
location / {
# Propagar la IP pública original hacia los contenedores de la red interna
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 Operativos de Inspección de Incidentes
Comandos de terminal para auditar en tiempo real las peticiones bloqueadas por las defensas perimetrales de Nginx:
docker logs -f app_nginx
docker logs app_nginx | grep "limiting requests"
docker logs app_nginx | grep "client intended to send too large body"