Problema
En entornos auto‑hosted es habitual exponer un reverse proxy (Nginx, Caddy, HAProxy, etc.) que recibe tráfico de todo internet. Los crawlers de IA, los bots de búsqueda y los rangos de IP de los proveedores cloud aparecen constantemente en los logs y pueden consumir recursos o generar falsos positivos en WAFs. Mantener listas manuales de “no permitir” o “permitir” es una tarea que se vuelve insostenible: los proveedores añaden o retiran bloques cada pocos días, y los CI/CD de terceros (CircleCI, TeamCity…) también usan rangos dinámicos. El síntoma típico es un aumento inesperado de errores 403/404, saturación de logs y, a veces, bloqueos de servicios legítimos porque la lista está desactualizada.
Causa
- Actualizaciones frecuentes de rangos IP – AWS, GCP, Azure, DigitalOcean, Cloudflare y otros publican sus CIDR cada 24‑48 h. Los scripts caseros que descargan un archivo estático quedan obsoletos rápidamente.
- Falta de normalización – Cada proveedor entrega los datos en formatos diferentes (JSON, CSV, texto plano). Unirlos manualmente genera errores de sintaxis y duplicados.
- Integración manual en firewalls – Copiar y pegar listas en archivos de configuración de Nginx o iptables implica reinicios innecesarios y riesgo de errores de orden.
- Ausencia de fallback offline – Cuando la red falla, los sistemas que dependen de una consulta HTTP a la lista remota dejan de bloquear correctamente.
- Escalabilidad de lookups – Consultas por cada IP del log usando
grepoawkson lentas; los firewalls modernos (iptables/ipset, nftables) pueden manejar millones de entradas, pero requieren una carga previa eficiente.
Solución
Una arquitectura reutilizable se basa en tres capas:
- Fuente de datos automatizada – Un repositorio que, mediante GitHub Actions, descarga los rangos de cada proveedor, los convierte a un formato unificado (plain‑text v4/v6, JSON, CSV) y genera archivos de configuración listos para Nginx, iptables/ipset, nftables, HAProxy, Caddy y UFW.
- Librerías de lookup – Un módulo Go y otro JavaScript/TypeScript que cargan los CIDR en estructuras radix‑tree. Permiten consultas sub‑microsegundo, funcionan offline y pueden usarse dentro de scripts de auditoría o de generación de reglas dinámicas.
- Generador de reglas – Un script que, a partir de los archivos de la fuente, crea los conjuntos (
ipsetonft set) y los incluye en la configuración del firewall o del proxy sin necesidad de reiniciar todo el servicio. El proceso se puede programar concrono con el mismo workflow de CI.
Paso a paso práctico
- Clonar el repositorio – El proyecto mantiene una rama
maincon los archivos actualizados. - Seleccionar el bundle – Los bundles predefinidos (
all-clouds,all-ai-crawlers,all-ci) ya vienen mergeados y deduplicados. - Generar ipset – El script
generate_ipset.shcrea un conjunto llamadocloud_ipsy lo rellena con los CIDR del bundle elegido. - Incluir en Nginx – En la sección
httpse añadeinclude /etc/nginx/conf.d/deny_clouds.conf;donde el archivo contienedenypor cada rango. - Actualizar automáticamente – Un cron que ejecuta
git pull && ./generate_ipset.sh && systemctl reload nginxgarantiza que la lista nunca quede obsoleta. - Uso de la librería Go – En aplicaciones que necesiten decidir en tiempo real si una IP pertenece a un cloud, basta con importar
github.com/rezmoss/cloudipdby llamar aLookup(ip). - Uso de la librería JS – En entornos Node o navegadores,
import { lookup } from "cloudipdb"permite validar IPs sin depender de la red.
Cuándo aplicar esta solución
- Entornos con tráfico mixto (público + interno) donde los bots representan más del 5 % del total de peticiones.
- Servicios críticos detrás de un reverse proxy que no pueden permitirse downtime por listas de bloqueo desactualizadas.
- Equipos que gestionan varios proveedores cloud y necesitan una única fuente de verdad para reglas de firewall.
- CI/CD que requieren salida a internet y deben ser whitelistados sin abrir todo el rango 0.0.0.0/0.
No es necesario cuando:
- El número de IPs a bloquear es estático y bajo (menos de 100 rangos).
- Se usa un WAF SaaS que ya provee actualizaciones automáticas de listas de bots.
Código
# Clonar el repositorio oficial
git clone https://github.com/rezmoss/cloud-provider-ip-addresses.git
cd cloud-provider-ip-addresses
# Elegir el bundle que se va a usar (ejemplo: all-ai-crawlers)
BUNDLE=all-ai-crawlers
# Generar ipset llamado cloud_ips
./generate_ipset.sh $BUNDLE cloud_ips
# Verificar que el set contiene los CIDR esperados
ipset list cloud_ips | wc -l
# Recargar nginx (o cualquier otro servicio) sin reiniciar
systemctl reload nginx
Verificación
- Comprobar la existencia del set –
ipset list cloud_ipsdebe mostrar cientos de CIDR sin errores de sintaxis. - Test de bloqueo – Desde una máquina con una IP que pertenezca al bundle, intentar acceder al endpoint protegido; debería recibir
403 Forbidden. - Log de Nginx – Buscar la cadena
403y confirmar que la razón esdenypor una IP del set. - Actualización automática – Simular una nueva ejecución del workflow (por ejemplo, modificando un archivo en el repo) y observar que
git pulltrae cambios y quesystemctl reload nginxse ejecuta sin interrupciones.
Notas adicionales
- Persistencia de ipset – En distribuciones que no guardan los sets al reboot, añadir
ipset save > /etc/ipset.confy cargarlo enrc.localo mediante un servicio systemd. - Rendimiento – Un set de 2 M+ IPs consume ~150 MiB RAM; asegúrese de que el host tenga suficiente memoria antes de cargar todos los rangos simultáneamente.
- Fallback offline – Las librerías Go/JS incluyen un archivo
fallback.datcon los CIDR más comunes; es útil cuando la red está caída pero se necesita seguir bloqueando. - Extensión a IPv6 – El mismo proceso funciona para IPv6, solo hay que usar
generate_ipset.sh $BUNDLE cloud_ips_v6y habilitarip6tablesonftcon la familiainet. - Auditoría periódica – Ejecutar
radix_lookup.py access.logpermite identificar rápidamente qué rangos aparecen con mayor frecuencia y ajustar los bundles (por ejemplo, crear uncustom-blocklist).
Con esta arquitectura se elimina la carga manual de listas, se garantiza que los firewalls y reverse proxies siempre trabajen con datos frescos y se consigue una solución que se adapta tanto a entornos Linux tradicionales como a pipelines de CI que requieren salida a la nube.