Introducción
Los servicios autoalojados expuestos a través de un proxy inverso inevitablemente atraen escáneres automáticos que buscan configuraciones erróneas, paneles de administración y puntos finales vulnerables. En este artículo, muestro cómo convertir los registros rutinarios de acceso Traefik en un control defensivo activo usando Elastic Security y Cloudflare.
Yo uso un ES| ya de uso Regla de detección QL para identificar el comportamiento de detección y difusión del servidor sitio web. Cuando se detectan patrones de sondeo sospechosos, un flujo de trabajo automatizado bloquea inmediatamente la IP fuente problemática en el borde mediante la API de Cloudflare. Lo mejor de esta configuración es que escala sin esfuerzo. Construyendo esta tubería de respuesta una vez para la detección de fuzzing, puedo anexar exactamente la misma acción de bloque a cualquier otra regla de Elastic, como las que capturan inyecciones SQL o intentos de inclusión de archivos. Esto transforma una tubería básica de tala en una defensa perimetral altamente adaptable.
Antecedentes y panorama de amenazas
Mi configuración de homelab emplea Proxmox VE para contenedores y máquinas virtuales. Yo uso un proxy inverso de Traebik, protegido con Authelia para autenticación, para permitir acceso externo sin necesidad de VPN. Cloudflare, con el proxy activado, gestiona el DNS.
Para quienes no estén familiarizados con esta pila específica, Traefik actúa como la puerta principal de la cadena. Cuando llega una solicitud sitio web a través de Cloudflare, Traefik enruta dinámicamente el tráfico al contenedor interno correcto mientras gestiona certificados SSL para mantener las conexiones cifradas. Sin embargo, antes de que cualquier tráfico llegue realmente a esas aplicaciones de backend, es interceptado por Authelia. Aprovechando la función de autenticación directa de Traefik, Authelia aplica el inicio de sesión único (SSO) y la autenticación multifactor en todos los ámbitos. Esto significa que los escáneres automáticos y los atacantes ni siquiera pueden acceder a las pantallas de inicio de sesión de mis servicios internos sin pasar por ese portal seguro inicial.
Para mantener la visibilidad y la seguridad, inierto estos registros de acceso de Traefik en Elastic usando la integración oficial. Durante la monitorización rutinaria, observé numerosos códigos de respuesta HTTP 404 originados en las mismas direcciones IP de origen en estos registros.
Este patrón sugiere un posible sondeo o fuzzing del tráfico de servidores sitio web que apunte a vulnerabilidades en aplicaciones que en realidad no se usan en mi red. Ejemplos de estos caminos dirigidos incluyen /wp-includes/mani., /wp-content/plugins/all-in-one-wp-security-and-firewall/templates.php, /archive.phpy /wp-admin/includes/header.php.
Filosofía de diseño: ¿por qué no Fail2Ban?
Una pregunta común en la comunidad de homelab es por qué no usar simplemente herramientas locales como Fail2Ban o CrowdSec directamente en el servidor Traefik. Aunque son herramientas excelentes, orquestar la respuesta a través de Elastic Security y trasladar el bloque a Cloudflare ofrece dos grandes beneficios. Eliminar tráfico malicioso en el borde de Cloudflare ahorra ancho de banda local y mantiene los escáneres fuera de la red doméstica por completo. Además, orquestar la respuesta a través de Elastic nos da un único panel de cristal para toda la monitorización de seguridad.
Estrategia de detección e implementación
Para identificar eficazmente el reconocimiento malicioso, nuestra estrategia se basa en analizar la frecuencia de los códigos de respuesta HTTP a nivel de proxy. Específicamente, buscamos un alto volumen de errores de 404 (No Encontrados) generados por una única IP de origen en una ventana de tiempo corta, un indicador tradicional de difusión de directorios o escaneo de vulnerabilidades.
Aunque Elastic Security proporciona reglas robustas y listas para la detección para este escenario exacto, estas reglas requieren datos ECS (Esquema Común Elástico) correctamente normalizados para funcionar correctamente. Por tanto, detectar y mitigar estos escaneos requiere un flujo coordinado. Para que esto funcione, necesitamos ingerir los registros de Traefik, parchear el campo de host.name faltante usando una tubería personalizada y apuntar la regla de detección a nuestros datos.
Lógica de umbral y ajuste
Nuestra estrategia de detección se aleja de la simple coincidencia de cadenas, basar en umbrales estadísticos. La regla monitoriza específicamente los recursos denegados o inexistentes representados por códigos HTTP 403 y 404 respuesta y agrega esta actividad mediante la IP de origen original.
Este comportamiento está regulado por la última sentencia where en la consulta. Por defecto, una alerta solo se activa si una IP de origen produce más de 500 errores a lo largo de 250 rutas URI distintas durante la ventana de sondeo. Este umbral de doble capa está diseñado para eliminar falsos positivos, cerciorando que un solo recurso roto no active un bloqueo, mientras identifica scripts automáticos que pasan por listas de palabras en directorios.
En un entorno de homelab pequeño o equipos pequeños, estos valores por defecto suelen ser demasiado permisivos. Como el tráfico externo legítimo no tiene motivo para afectar paneles de administración inexistentes en mi red, ajusté la sensibilidad para detectar esfuerzos de reconocimiento más furtivo a tiempo. Modifiqué la lógica para que se activara cuando event_count > 100 y url_original_count_distinct > 50.
Para entornos de producción donde las aplicaciones generan naturalmente mayores volúmenes de error, podrías considerar aumentar estos valores o agregar un ES|QL where not cláusula para excluir enlaces rotos conocidos. Por último, empleo un filtro where source.ip not in (...) para cerciorarme de que las herramientas de seguridad autorizadas o los escáneres de vulnerabilidades personales no sean bloqueados accidentalmente por el flujo de trabajo automatizado.
Ingesta de los registros de acceso Traefik
Para integrar los registros de acceso de Traefik al clúster, usé la integración predeterminada de Traefik. El Agente Elastic recopila registros de los servidores Traefik. Esta integración escribe los registros ingeridos en el flujo de datos logs-traefik.access-default .
Construcción de una canalización de ingesta personalizada
El campo host.name es crucial para la regla de detección que uso, pero la integración predeterminada con Traefik no lo muebla. Por lo tanto, se requiere una pipeline de ingesta personalizada para agregar este campo. Como la integración con Traefik emplea un flujo de archivos en el servidor Traebik, puedo copiar el valor del campo de agent.name existente para llenar host.name.
Yo uso específicamente la logs-traefik.access@custom pipeline en lugar de modificar la principal. Las integraciones elásticas están diseñadas para recoger y ejecutar automáticamente estas @custom tuberías justo al final de su flujo de procesamiento. Más importante aún, las pipelines predeterminadas se sobreescribir por completo cada vez que actualizo una integración. Almacenar mi lógica en la tubería personalizada cerciora que mis mapeos de campos realmente sobrevivan a la siguiente actualización. La llamada a la API necesaria para crear esta canalización puede ejecutar en la consola de Dev Tools:
PUT _ingest/pipeline/logs-traefik.access@custom
{
"description": "copy the agent.name field to the host.name field",
"processors": [
{
"set": {
"field": "host.name",
"value": "{{{agent.name}}}",
"override": false,
"ignore_empty_value": true,
"ignore_failure": true
}
}
]
}
Respuesta automatizada mediante flujo de trabajo de Cloudflare
Para pasar de la detección a la defensa activa, implementamos un flujo de trabajo que cubre la brecha entre nuestras alertas Elastic y el borde de Cloudflare. La lógica está diseñada para ser eficiente: en lugar de crear una nueva regla de firewall para cada alerta, que rápidamente alcanzaría los límites de Cloudflare, el flujo de trabajo primero recupera la lista de bloqueo existente. Luego agrega dinámicamente la nueva IP fuente problemática a esa lista antes de enviar la actualización de nuevo a la API de Cloudflare. Una vez cerciorado el borde, el flujo de trabajo termina reconociendo la alerta en Elastic, cerrando efectivamente el bucle del incidente.
Requisitos previos y alcance del token
Este proceso requiere tanto una clave API como el ID de Zona para la configuración de Cloudflare. El token de la API debe poseer privilegios de "Zone WAF edit" para permitir la creación de la regla. Al generar este token en el panel de Cloudflare, emplea la opción "Crear token personalizado" y establece las licencias estrictamente a Zone -> Zone WAF -> Edit.
Una vez configurado el flujo de trabajo, debe asignar como una acción a la regla de detección de "Descubrimiento o Fuzzing de Actividad de Descubrimiento de Servidor Sitio web".
Con los requisitos previos establecido, vamos a repasar paso a paso cómo construimos el flujo de trabajo.
Configuración del flujo de trabajo y disparadores
Primero, definimos los metadatos básicos. Este flujo de trabajo bloquea las direcciones IP que aparecen en las alertas de la actividad de descubrimiento o fuzzing del servidor sitio web. El flujo de trabajo está habilitado y tiene un tiempo de espera de 30 segundos para la solicitud de la API. En este caso, se basa en una alerta, por lo que se ejecuta automáticamente cuando se activa una alerta de seguridad.
# =========================================================================
# Workflow: Block IP at Cloudflare test
# Category: security/response
# =========================================================================
version: '1'
name: Block IP at Cloudflare
enabled: true
triggers:
- type: alert
Constantes y autenticación
Esta sección contiene las variables para la autenticación. Recuerda sustituir las cadenas de marcador por tu token real de la API y el ID de la zona.
consts:
cloudflare_api: "<cloudflare API>"
cloudflare_zone: "<cloudflare ZONE>"
Paso 1: Recuperar la lista de bloqueo actual
La secuencia comprueba si la regla de firewall ya existe. El flujo de trabajo realiza una solicitud HTTP GET para recuperar la regla de bloqueo IP existente.
steps:
- name: cloudflare_current_block
type: http
with:
url: "https://api.cloudflare.com/client/v4/zones/{{consts.cloudflare_zone}}/rulesets/phases/http_request_firewall_custom/entrypoint"
headers:
Authorization: Bearer {{consts.cloudflare_api}}
method: GET
on-failure:
continue: true
Paso 2: Actualizar o crear la regla del firewall
Si existe, la regla se agrega junto con la dirección IP; de lo contrario, la regla se crea. El flujo de trabajo identifica si la descripción de "bloque de escaneo del servidor sitio web" está presente. Si es así, agrega la nueva dirección IP a la lista actual de direcciones IP bloqueadas mediante una solicitud PUT. Si no, se reduce a crear una nueva regla.
- name: cloudflare_block
type: if
condition: 'steps.cloudflare_current_block.output.data.result.rules[0].description == "webserver scanning block"'
steps:
- name: ip-block-cloudflare_add
type: http
with:
url: "https://api.cloudflare.com/client/v4/zones/{{consts.cloudflare_zone}}/rulesets/phases/http_request_firewall_custom/entrypoint"
method: PUT
headers:
Authorization: Bearer {{consts.cloudflare_api}}
timeout: 30s
body: '{ "rules": [ { "description": "webserver scanning block", "expression": "{{steps.cloudflare_current_block.output.data.result.rules[0].expression}} or (ip.src eq {{event.alerts[0].source.ip}})", "action": "block" } ]}'
else:
- name: ip-block-cloudflare_new
type: http
with:
url: "https://api.cloudflare.com/client/v4/zones/{{consts.cloudflare_zone}}/rulesets/phases/http_request_firewall_custom/entrypoint"
method: PUT
headers:
Authorization: Bearer {{consts.cloudflare_api}}
timeout: 30s
body: '{ "rules":[ { "description": "webserver scanning block", "expression": "(ip.src eq {{event.alerts[0].source.ip}})", "action": "block" } ]}'
on-failure:
continue: true
Paso 3: Reconocer la alerta
Entonces la alerta es reconocida. Este paso emplea la acción kibana.SetAlertsStatus para cerrar automáticamente la alerta en Elastic Security.
- name: update_alert_status
type: kibana.SetAlertsStatus
with:
status: "acknowledged"
signal_ids: ["{{event.alerts[0]._id}}"]
Paso 4: Anexar el flujo de trabajo a la regla
Con el flujo de trabajo completamente desarrollado, el paso final es anexarlo a la regla de detección para que se dispare automáticamente. En la configuración de la regla de Elastic Security para la regla "Descubrimiento de servidor sitio web o actividad de fuzzing", navego a la pestaña de acciones de la regla y agrego una nueva acción. Desde el desplegable del conector, simplemente selecciono el flujo de trabajo de Cloudflare que acabo de crear.
Nota sobre los límites de WAF
Como este flujo de trabajo concatena direcciones IP usando una sentencia or (or (ip.src eq <IP>)), ten en cuenta que Cloudflare tiene un límite de caracteres para expresiones WAF personalizadas (normalmente 4096 caracteres en niveles estándar). En entornos muy específicos, esta cadena puede llegar al límite. Para homelabs y equipos pequeños, eliminar manualmente esta regla WAF ocasionalmente sirve como un resetear saludable.
Pruebas y validación
Para verificar que la tubería funciona de extremo a extremo, podemos generar algo de ruido con una herramienta estándar de fuzzing. Puedes simular un ataque de escaneo contra tu propio homelab usando una herramienta de fuzzing como ffuf o gobuster.
Haz un escaneo rápido en un directorio inexistente en tu dominio público de Traefik:
ffuf -u https://your-domain.com/FUZZ -w /path/to/wordlist.txt
Una vez que la simulación está en marcha, podemos observar la cadena de defensa automatizada en acción. Los errores de 404 aparecen casi inmediatamente en la logs-traefik.access-default flujo de datos. Durante el intervalo de votación, el ES|La regla QL identifica el patrón y genera una nueva alerta en la página de Alertas de Seguridad Elastic. A partir de ahí, el flujo de trabajo toma el control: cambia el estado de alerta a "reconocido" y empuja el bloque IP a nuestra regla WAF de Cloudflare, neutralizando efectivamente el escáner en el borde antes de que pueda continuar su reconocimiento.
Puedes confirmar que el bloqueo fue exitoso consultando tu panel de Cloudflare en Security -> WAF -> Custom rules. (Nota: Cerciórate de eliminar tu IP de la regla de Cloudflare después para no quedarte bloqueado.)
Ampliación de la defensa
Lo bueno de esta configuración es que nuestro flujo de trabajo en Cloudflare no se limita solo a la detección de fuzzing. Una vez construida la automatización, podemos anexarla a cualquier regla Elastic que marque tráfico proxy sospechoso. Por ejemplo, podemos vincular esta misma acción de respuesta exacta a reglas listas para usar que apuntan a exploits específicos de aplicaciones, como la Actividad Local de Inclusión de Archivos en el Servidor Sitio web, la Actividad Potencial de Inclusión Remota de Archivos del Servidor Sitio web para eliminar al atacante inmediatamente. También se combina perfectamente con el Posible Pico en los Registros de Errores del Servidor Sitio web y el Agente de Usuario Sitio web Inusual para detectar scrapers mal configurados y ruido de red más amplio. Construimos la fontanería una vez, y de repente todo el perímetro se vuelve más inteligente.
Conclusión
Conectar Traefik y Cloudflare a Elastic Security es una excelente forma de convertir los registros básicos de acceso en una defensa activa. Los entornos de homelab están constantemente bombardeados por escáneres automáticos en busca de frutos fáciles. Este flujo de trabajo automatizado no solo bloquea a los atacantes en el borde, sino que también reduce la fatiga de alertas al reconocer automáticamente los incidentes. Es un ejemplo práctico de cómo la orquestación y respuesta de seguridad pueden ahorrar tiempo mientras mejoran significativamente tu postura de seguridad.