Guía técnica para capturar y controlar todo el tráfico destinado a hosts no declarados o rutas por defecto, tanto en HTTP como en HTTPS, con ejemplos de archivos de configuración listos para producción.
1. ¿Qué es un catch‑all en Nginx?
Un catch‑all es un bloque server
que actúa como destino por defecto cuando:
- El
Host
solicitado no coincide con ningúnserver_name
declarado. - El puerto solicitado no tiene un bloque más específico.
Su uso típico es:
- Redirigir tráfico desconocido hacia un dominio canónico.
- Responder con códigos de control (p. ej.,
444
para cortar conexiones indeseadas,404/410
). - Mostrar una página de mantenimiento o banner legal.
- Proteger el origin de un reverse proxy público.
Clave: se implementa con la directiva
default_server
en la escucha del puerto (listen
).
2. Diseño recomendado
- Separar HTTP y HTTPS: define un catch‑all para
:80
y otro para:443
con TLS. - Usar
server_name _;
: el guion bajo es un patrón que no coincidirá con dominios reales y documenta la intención. - Respuestas claras:
return
es preferible arewrite
cuando la lógica es simple. - Registro (logs) mínimo en el catch‑all para evitar ruido, con rotación y formato propio.
3. Estructura de ficheros
/etc/nginx/
├── nginx.conf
└── sites-available/
├── 00-catch-all-http.conf
├── 00-catch-all-https.conf
└── ... (otros sitios)
└── sites-enabled/ -> enlaces simbólicos
En distribuciones sin
sites-available/sites-enabled
(p. ej., Alpine por defecto), incluye los server blocks directamente ennginx.conf
o crea tu propia convención yinclude
.
4. Ejemplo: catch‑all HTTP (80)
Archivo: /etc/nginx/sites-available/00-catch-all-http.conf
server {
listen 80 default_server reuseport;
listen [::]:80 default_server;
server_name _;
# Opciones de seguridad y rendimiento mínimas
keepalive_timeout 10;
client_body_timeout 10;
client_header_timeout 10;
# Logs específicos y discretos
access_log /var/log/nginx/catch-all.access.log main if=$log_catch_all;
error_log /var/log/nginx/catch-all.error.log warn;
# Flag para reducir ruido en logs
set $log_catch_all 0;
# Política por defecto: redirigir todo a dominio canónico (HTTP -> HTTPS)
# Reemplaza ejemplo.com por tu dominio público
return 301 https://ejemplo.com$request_uri;
}
Notas:
default_server
garantiza que este bloque maneje cualquierHost
no declarado en :80.- Cambia la política si prefieres cerrar en lugar de redirigir (ver sección 6).
5. Ejemplo: catch‑all HTTPS (443) con TLS
Archivo: /etc/nginx/sites-available/00-catch-all-https.conf
server {
listen 443 ssl http2 default_server reuseport;
listen [::]:443 ssl http2 default_server;
server_name _;
# Certificado barajado por defecto (comodín o cert genérico). Puede ser un "dummy".
ssl_certificate /etc/nginx/ssl/catch-all/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/catch-all/privkey.pem;
# Perfil TLS razonable
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
# Logs discretos
access_log /var/log/nginx/catch-all-https.access.log main if=$log_catch_all;
error_log /var/log/nginx/catch-all-https.error.log warn;
set $log_catch_all 0;
# Política por defecto: redirigir a dominio canónico en HTTPS
return 308 https://ejemplo.com$request_uri;
}
Notas:
- En TLS, Nginx elige el default_server cuando no hay coincidencia SNI.
- Usa un certificado válido (comodín o SAN) si quieres evitar avisos del cliente cuando la conexión caiga aquí.
6. Políticas alternativas (sustituye return
del ejemplo)
6.1 Rechazar tráfico desconocido sin respuesta (desechar)
return 444; # Corta la conexión sin payload
6.2 Responder 404/410 (ocultar superficie)
return 404; # o 410 si quieres indicar recurso definitivamente inexistente
6.3 Página de mantenimiento simple
root /var/www/catch-all;
location = / {
try_files /index.html =503;
}
error_page 503 /maintenance.html;
location = /maintenance.html { internal; }
6.4 Bloquear por Source IP o ASN (ejemplo básico)
# Permite sólo una red interna (ej., para origins detrás de WAF)
allow 10.0.0.0/8;
deny all;
return 444;
7. Variables, mapas y formato de log para depurar Host desconocidos
Amplía nginx.conf
con un map
para activar logs sólo cuando el Host
no coincida con los tuyos.
Fragmento para http
en nginx.conf
:
http {
# ... otras directivas ...
# Enumera tus dominios "legítimos" para silenciar logs en ellos
map $host $log_catch_all {
default 1; # Log por defecto
ejemplo.com 0;
www.ejemplo.com 0;
api.ejemplo.com 0;
}
log_format main '$remote_addr - $host $request "$status" $body_bytes_sent "$http_referer" "$http_user_agent"';
# include de sitios
include /etc/nginx/sites-enabled/*.conf;
}
8. Activación, validación y recarga
# Crear enlaces simbólicos
ln -s /etc/nginx/sites-available/00-catch-all-http.conf /etc/nginx/sites-enabled/
ln -s /etc/nginx/sites-available/00-catch-all-https.conf /etc/nginx/sites-enabled/
# Validar sintaxis
ginx -t
# Recargar sin cortar conexiones
nginx -s reload
# o
systemctl reload nginx
9. Escenarios comunes y pitfalls
- Orden de evaluación: Nginx selecciona
server
por puerto y SNI; dentro de los candidatos, elige el más específico. Asegúrate de tenerdefault_server
sólo en tu catch‑all. - Certificado inválido en catch‑all: si devuelves 308/301 a dominio válido, los navegadores pueden mostrar aviso antes de seguir. Considera usar un comodín (p. ej.,
*.ejemplo.com
) o devolver444
en su lugar. - Bucles de redirección: valida que el dominio canónico no apunte a este server block.
- Proxy inverso/WAF delante: define allow/deny y cabeceras (
X-Forwarded-For
,Real-IP
) si tu catch‑all está expuesto al público. - Multitenant: si alojas muchos
server_name
, revisa periódicamente el log del catch‑all para detectar typos DNS o intentos maliciosos.
10. Variante: catch‑all como sinkhole anti‑escaneo
server {
listen 80 default_server;
server_name _;
add_header Connection close;
return 444;
}
Minimiza consumo y visibilidad; útil en origins no pensados para tráfico directo.
11. Variante: redirección canónica multi‑dominio
server {
listen 80 default_server;
server_name _;
# Si llega desde un conjunto de dominios antiguos, redirige a su equivalencia
if ($host ~* "^(old1\.com|old2\.net)$") { return 301 https://nuevo.com$request_uri; }
# Resto, 404
return 404;
}
12. Apéndice: plantilla completa combinada
# /etc/nginx/nginx.conf (extracto)
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events { worker_connections 4096; }
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
# Map para logging selectivo del catch‑all
map $host $log_catch_all {
default 1;
ejemplo.com 0;
www.ejemplo.com 0;
api.ejemplo.com 0;
}
log_format main '$remote_addr - [$time_local] "$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" host=$host';
include /etc/nginx/sites-enabled/*.conf;
}
# /etc/nginx/sites-available/00-catch-all-http.conf
server {
listen 80 default_server reuseport;
listen [::]:80 default_server;
server_name _;
access_log /var/log/nginx/catch-all.access.log main if=$log_catch_all;
error_log /var/log/nginx/catch-all.error.log warn;
return 301 https://ejemplo.com$request_uri;
}
# /etc/nginx/sites-available/00-catch-all-https.conf
server {
listen 443 ssl http2 default_server reuseport;
listen [::]:443 ssl http2 default_server;
server_name _;
ssl_certificate /etc/nginx/ssl/catch-all/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/catch-all/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
access_log /var/log/nginx/catch-all-https.access.log main if=$log_catch_all;
error_log /var/log/nginx/catch-all-https.error.log warn;
return 308 https://ejemplo.com$request_uri;
}
13. Verificación rápida
- Resolver un
Host
aleatorio a tu IP pública y ejecutar:curl -I http://IP --header 'Host: noexiste.tld' curl -I https://IP --header 'Host: noexiste.tld' -k
- Confirmar que responde según tu política (301/308/404/444).
Compartir: