# =====================================================================
#  /etc/nginx/nginx.conf  —  Proxy inverso endurecido (solo 80/443)
#  Probado con nginx 1.30.x stable / 1.31.x mainline (2026)
# =====================================================================

user  www-data;                 # en RHEL/Alma/Rocky: nginx
worker_processes  auto;
worker_rlimit_nofile  65535;
pid   /run/nginx.pid;
error_log  /var/log/nginx/error.log warn;

# Carga SOLO los módulos que uses. En 2026 hubo CVEs en ssi, slice, mp4,
# dav, charset, scgi/uwsgi y http3: si no los necesitas, no los cargues/compiles.
include /etc/nginx/modules-enabled/*.conf;

events {
    worker_connections  8192;
    multi_accept        on;
}

http {
    # ---------- Básico / fingerprinting ----------
    server_tokens  off;               # oculta versión en cabecera Server y páginas de error
    include        /etc/nginx/mime.types;
    default_type   application/octet-stream;

    sendfile     on;
    tcp_nopush   on;
    tcp_nodelay  on;

    # ---------- Anti-Slowloris / slow-POST ----------
    client_header_timeout   10s;
    client_body_timeout     10s;
    send_timeout            10s;
    keepalive_timeout       15s;
    keepalive_requests      1000;
    reset_timedout_connection on;     # libera memoria de conexiones colgadas

    # ---------- Límites de tamaño (anti buffer abuse / smuggling) ----------
    client_header_buffer_size    1k;
    large_client_header_buffers  4 8k;   # cabeceras > 8k => 400
    client_body_buffer_size      128k;
    client_max_body_size         10m;    # súbelo solo en el location que lo necesite

    # ---------- HTTP/2 (mitigación "Rapid Reset" y similares) ----------
    http2_max_concurrent_streams 64;

    # ---------- TLS global ----------
    include /etc/nginx/snippets/tls.conf;

    # ---------- IP real si vas detrás de CDN (Cloudflare, etc.) ----------
    # Si NO usas CDN, deja esto comentado (si no, cualquiera podría falsear su IP).
    # include /etc/nginx/snippets/cloudflare-realip.conf;

    # ---------- Lista blanca para rate limit (monitorización, oficinas) ----------
    geo $limit_exempt {
        default        0;
        127.0.0.1/32   1;
        # 10.0.0.0/8   1;   # tu red interna / health checks
    }
    map $limit_exempt $limit_key {
        0  $binary_remote_addr;
        1  "";                   # clave vacía = no se cuenta
    }

    # ---------- Zonas de rate limiting / conexiones ----------
    limit_req_zone  $limit_key zone=req_general:20m rate=20r/s;
    limit_req_zone  $limit_key zone=req_auth:10m    rate=10r/m;   # login, reset password, API keys
    limit_conn_zone $limit_key zone=conn_ip:20m;
    limit_req_status   429;
    limit_conn_status  429;
    limit_req_log_level  warn;
    limit_conn_log_level warn;

    # ---------- Métodos permitidos (sin regex a propósito) ----------
    map $request_method $bad_method {
        default  1;
        GET      0;
        HEAD     0;
        POST     0;
        PUT      0;
        PATCH    0;
        DELETE   0;
        OPTIONS  0;
    }

    # ---------- WebSocket + keepalive a upstream ----------
    map $http_upgrade $connection_upgrade {
        default  upgrade;
        ""       "";             # vacío => permite keepalive hacia el backend
    }

    # ---------- Logs (formato compatible con fail2ban + métricas) ----------
    log_format proxy '$remote_addr - $remote_user [$time_local] "$request" '
                     '$status $body_bytes_sent "$http_referer" "$http_user_agent" '
                     'host="$host" rt=$request_time uct=$upstream_connect_time '
                     'urt=$upstream_response_time up="$upstream_addr" tls=$ssl_protocol';
    access_log  /var/log/nginx/access.log proxy buffer=64k flush=5s;

    # ---------- Proxy: valores por defecto (sobrescribibles por location) ----------
    proxy_connect_timeout   5s;
    proxy_send_timeout      30s;
    proxy_read_timeout      60s;
    proxy_buffering         on;      # protege a los backends de clientes lentos
    proxy_request_buffering on;
    proxy_buffer_size       16k;
    proxy_buffers           16 16k;
    proxy_busy_buffers_size 32k;
    proxy_next_upstream         error timeout http_502 http_503;   # POST no se reintenta
    proxy_next_upstream_tries   2;
    proxy_next_upstream_timeout 10s;
    proxy_redirect          off;

    # ---------- Compresión ----------
    # Desactivada en el proxy a propósito (riesgo BREACH con respuestas que llevan
    # tokens/CSRF). Deja que cada backend decida qué comprime.
    gzip off;

    include /etc/nginx/sites-enabled/*.conf;
}
