# nginx como proxy inverso endurecido (80/443) — 2026

Entrada única a Internet que solo hace de proxy inverso hacia máquinas internas.

## Estructura

```
nginx/
  nginx.conf                       -> /etc/nginx/nginx.conf
  snippets/tls.conf                -> TLS 1.2/1.3, sin tickets, sin 0-RTT
  snippets/proxy.conf              -> cabeceras hacia backend, anti-spoofing, httpoxy
  snippets/security-headers.conf   -> HSTS, nosniff, X-Frame, COOP/CORP...
  snippets/cloudflare-realip.conf  -> solo si vas detrás de CDN
  sites-enabled/00-default.conf    -> descarta Host/SNI desconocidos (444 / reject_handshake)
  sites-enabled/app.ejemplo.com.conf -> plantilla por servicio
system/
  99-nginx-proxy.sysctl.conf       -> /etc/sysctl.d/   (SYN flood, anti-spoofing)
  nftables.conf                    -> /etc/nftables.conf (policy drop, límite por IP)
  fail2ban-nginx.local             -> /etc/fail2ban/jail.d/nginx.local
  nginx-systemd-override.conf      -> /etc/systemd/system/nginx.service.d/override.conf
```

## Instalación

1. **Versión de nginx**: usa el repositorio oficial de nginx.org (stable 1.30.x o mainline 1.31.x, siempre la última).
   Los paquetes de muchas distros van muy por detrás y en 2026 se han publicado varios CVEs
   (rewrite, proxy HTTP/2, map con regex, SSI, slice, HTTP/3...). Requiere >= 1.25.1 por `http2 on;`.
2. Copia los archivos, edita `app.ejemplo.com.conf` (dominio, IPs de backend, IPs de admin).
3. **Antes de nftables**: pon tu IP en `admin_v4` o perderás SSH.
4. Aplica:
   ```bash
   sysctl --system
   nft -c -f /etc/nftables.conf && systemctl enable --now nftables
   nginx -t && systemctl reload nginx
   systemctl daemon-reload && systemctl restart nginx    # tras el override de systemd
   systemctl enable --now fail2ban
   ```
5. Certificados: `certbot certonly --webroot -w /var/www/acme -d app.ejemplo.com`
   (o el módulo oficial `nginx-acme`). Prefiere certificados ECDSA.

## En los backends (igual de importante)

- Firewall: que **solo** acepten conexiones desde la IP interna del proxy.
- Confiar en `X-Forwarded-For` / `X-Real-IP` únicamente si viene del proxy.
- Si la red entre proxy y backend no es de confianza: TLS al backend (bloque comentado en la plantilla).

## Qué cubre y qué no

| Amenaza | Cubierto por |
|---|---|
| Slowloris / slow POST | timeouts cortos, `reset_timedout_connection`, buffering |
| Fuerza bruta en login/API | `limit_req` zona `req_auth` + fail2ban |
| Flood L7 de una IP | `limit_req`, `limit_conn`, nftables (conn nuevas y simultáneas) |
| SYN flood | syncookies, backlog |
| HTTP/2 Rapid Reset | `http2_max_concurrent_streams`, nginx actualizado |
| Escaneo por IP / Host falso / SNI | default servers con 444 y `ssl_reject_handshake` |
| Spoofing de IP vía X-Forwarded-For | se sobrescribe con `$remote_addr` |
| Request smuggling | nginx normaliza y re-emite la petición; límites de cabecera |
| Fingerprinting | `server_tokens off`, `proxy_hide_header` |
| Downgrade TLS | solo TLS 1.2/1.3 AEAD, HSTS |
| Escalada si nginx cae | sandbox systemd, worker sin privilegios |
| **DDoS volumétrico (Gbps)** | **NO**: necesitas CDN/anti-DDoS delante (Cloudflare, proveedor) |
| **Ataques a la lógica de la app (SQLi, XSS...)** | **NO**: añade WAF (ModSecurity v3 + OWASP CRS 4, o CrowdSec AppSec / BunkerWeb) |

## Comprobaciones rápidas

```bash
nginx -t
curl -I -H 'Host: inventado.com' http://TU_IP/           # debe cerrar la conexión
curl -X TRACE https://app.ejemplo.com/ -o /dev/null -w '%{http_code}\n'   # 405
curl https://app.ejemplo.com/.env -o /dev/null -w '%{http_code}\n'        # 404
testssl.sh app.ejemplo.com                                # o SSL Labs
```

## Mantenimiento

- Suscríbete a las noticias de seguridad de nginx.org y actualiza en cuanto salga una versión.
- Revisa `/var/log/nginx/error.log` para 429 legítimos y ajusta `rate`/`burst` según tu tráfico.
- Si usas CDN: actualiza los rangos de `cloudflare-realip.conf` y limita 80/443 a esos rangos en nftables.
- HTTP/3 (QUIC) desactivado a propósito: actívalo solo si lo necesitas y con nginx al día.
