# Sustituir el “Catch-All” de Nginx por un sitio con dominio técnico y Let’s Encrypt que siempre devuelva 404

- Link: https://binariocero.com/linux/sustituir-el-catch-all-de-nginx-por-un-sitio-con-dominio-tecnico-y-lets-encrypt-que-siempre-devuelva-404
- Published: 2025-08-18T20:09:22+02:00
- Author: Juan José Fernández Durán

![Loading](https://binariocero.com/wp-content/plugins/page-views-count/ajax-loader-
2x.gif)

Este artículo explica cómo reemplazar un _catch-all_ genérico en Nginx por un “sitio
sumidero” (_blackhole_) con un **dominio técnico propio**, certificado **Let’s Encrypt**,
marcado como **default_server**, y que **responda 404** a cualquier petición que
no coincida con tus _server\_name_ reales. Es útil para evitar servir por error 
uno de tus sitios ante hosts desconocidos o mal configurados.

## Objetivo

 * Tener un **subdominio técnico** (p. ej. `blackhole.tudominio.com`) apuntando 
   al proxy Nginx.
 * Emitir un **certificado válido** para ese subdominio con Let’s Encrypt.
 * Definir dos _server blocks_ (HTTP y HTTPS) con `default_server`.
 * Permitir sólo el **ACME challenge** y devolver **404** para todo lo demás.

> Usa un dominio/subdominio real que controles. Let’s Encrypt no emitirá certificados
> para dominios inexistentes.

## Prerrequisitos

 * DNS: `A`/`AAAA` de `blackhole.tudominio.com` al Nginx.
 * Puertos 80/443 abiertos al Nginx.
 * Acceso root o sudo.
 * Nginx instalado.
 * **Certbot** (o tu cliente ACME preferido). Ejemplos con _webroot_.

## 1. Preparar el _webroot_ para ACME

    ```wp-block-code
    sudo mkdir -p /var/www/acme-challenge
    sudo chown -R www-data:www-data /var/www/acme-challenge   # usa 'nginx:nginx' en CentOS/RHEL
    ```

## 2. Crear el bloque HTTP por defecto (80)

Archivo (Debian/Ubuntu): `/etc/nginx/sites-available/00-default-404.conf`
(CentOS/
RHEL): `/etc/nginx/conf.d/00-default-404.conf`

    ```wp-block-code
    server {
        listen 80 default_server;
        listen [::]:80 default_server;
        # Acepta cualquier Host; declaramos también el técnico
        server_name blackhole.tudominio.com;

        access_log /var/log/nginx/blackhole.access.log;
        error_log  /var/log/nginx/blackhole.error.log warn;
        server_tokens off;

        # Permitir sólo el ACME HTTP-01 (Este bloque es opcional)
        location ^~ /.well-known/acme-challenge/ {
            root /var/www/acme-challenge;
            default_type "text/plain";
            try_files $uri =404;
        }

        # Todo lo demás => 404
        location / {
            return 404;
        }
    }
    ```

Activa el sitio (Debian/Ubuntu):

    ```wp-block-code
    sudo ln -s /etc/nginx/sites-available/00-default-404.conf /etc/nginx/sites-enabled/
    sudo nginx -t && sudo systemctl reload nginx
    ```

## 3. Emitir el certificado Let’s Encrypt

Con **webroot**:

    ```wp-block-code
    sudo certbot certonly \
      --webroot -w /var/www/acme-challenge \
      -d blackhole.tudominio.com \
      --agree-tos -m admin@tudominio.com --no-eff-email
    ```

(En distros con _snap_: `sudo snap install certbot --classic` y usar `certbot` igual
que arriba).

Comprueba que se hayan creado los ficheros en:
`/etc/letsencrypt/live/blackhole.
tudominio.com/`

## 4. Crear el bloque HTTPS por defecto (443)

Añade al mismo archivo de antes (o a otro, a tu gusto):

    ```wp-block-code
    server {
        listen 443 ssl http2 default_server;
        listen [::]:443 ssl http2 default_server;
        server_name blackhole.tudominio.com;

        # Rutas del certificado emitido
        ssl_certificate     /etc/letsencrypt/live/blackhole.tudominio.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/blackhole.tudominio.com/privkey.pem;

        # Mínimos sensatos
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_prefer_server_ciphers on;

        # Cabeceras básicas de endurecimiento
        add_header X-Content-Type-Options nosniff always;
        add_header X-Frame-Options DENY always;
        add_header Referrer-Policy no-referrer always;

        # Responder SIEMPRE 404
        location / {
            return 404;
        }
    }
    ```

Valida y recarga:

    ```wp-block-code
    sudo nginx -t && sudo systemctl reload nginx
    ```

## 5. Renovación automática

`certbot` instala _systemd timers_ o _cron_. Verifica con:

    ```wp-block-code
    sudo certbot renew --dry-run
    ```

## 6. Pruebas rápidas

 * HTTP (host inventado):

    ```wp-block-code
    curl -i -H "Host: noexiste.tudominio.com" http://TU_IP
    ```

Debe devolver `HTTP/1.1 404 Not Found`.

 * HTTPS (SNI apuntando a un host inventado):

    ```wp-block-code
    curl -i --resolve noexiste.tudominio.com:443:TU_IP https://noexiste.tudominio.com/
    ```

Debe negociar TLS con el cert de `blackhole.tudominio.com` y responder `404`.

## Notas y buenas prácticas

 * **No uses HSTS** en el “blackhole”; no aporta y puede anclar políticas innecesarias.
 * Si el ruido en logs es alto, puedes **desactivar el access_log**: 
   `access_log
   off;`
 * Si necesitas “cortar” conexiones en lugar de 404, existe `return 444;`, pero 
   aquí mantenemos **404** como pediste.
 * El orden de los archivos en `sites-enabled` no afecta a la selección por `default_server`;
   lo importante es el flag en `listen`.

## Resultado

Con estos pasos, tu Nginx tiene un **default_server** limpio, con **certificado 
Let’s Encrypt** y que **siempre responde 404**, evitando servir contenido accidental
a hosts desconocidos y manteniendo un _handshake_ TLS válido para clientes que lleguen
por HTTPS.
