Protección DDOS cloudflare. Protege el acceso directo a tu servidor con headers ocultos

Los ataques DDOS o los robots automatizados buscando «robar» información de grandes sitios (sin pretender un DDOS aunque lo puedan causar) siempre han sido un problema desde que existe la WWW pero en los últimos años está tomando un papel muy relevante. Los proveedores de servicios proxy con millones de ips disponibles a precios muy competitivos hacen que cualquiera, sin ser un hacker con infinidad de ordenadores comprometidos a su disposición, puedan disfrutar de un pool de ips importante y pueden causar un verdadero problema a cualquier servidor web.

En uno de los proyectos en los que estoy involucrado he tenido que desarrollar un robot para scrapear google shopping, amazon y cientos de otros E-commerce. Igualmente como administrador de sistemas para otros clientes he tenido que enfrentarme a la forma de parar los rastreos y ataques DDOS, así que conozco perfectamente ambas caras de la moneda y los retos que implica en cada caso. Y la verdad es divertido, el juego del ratón y el gato.

Existen infinidad de medidas, desde honeypots, retos javascript, limitación de solicitudes por ip o rango de ips, bloqueos de listas negras de ips, análisis de tráfico y bloqueo selectivo según su tipo, lógica de bloqueo por patrón de comportamiento en la aplicación, cookies secretas y un infinito etc. con los que tendrán que lidiar ambos jugadores de la partida y obviamente todo ello eleva el coste del mantenimiento del sito, sus recursos y los recursos y tiempo necesario por el atacante.

Generalmente siempre soy partidario de implementar todos los servicios y herramientas de manera autónoma, desde mi propio servidor y sin depender de terceros. Pero en este caso, dado la magnitud del problema y de la eventual necesidad de grandes recursos es interesante valerse de empresas especializadas en este cometido tales como CloudFlare o Sucuri estando el primero mas especializado en una protección DDOS y optimización de red y el segundo en protección WAF, ambos finalmente confluyen en sus servicios pero eso daría para otro post. En este nos centraremos en el uso de CloudFlare (en adelante CF) y su protección DDOS.

Entre las múltiples funcionalidades interesantes de CF está el grado de seguridad y protección del sitio, pasando desde nulo, bajo hasta modo «I’m under Attack!». Este último es muy efectivo utilizando un reto javascript con cookies sin interacción por parte del usuario, se que esto podría hacerlo yo mismo en mi servidor pero los programadores de robots saben estudiar incluso los retos javascript y saltárselos con lo que sería un trabajo de nunca acabar así que por el precio de CF (incluso la versión gratuita incluye esta funcionalidad) compensa y ellos se encargan con su gran infraestructura y recursos de hacer muy difícil la tarea de saltarse las medidas a los robots.

Lamentablemente (recordad el juego del gato y el ratón) hecha la ley hecha la trampa y la forma mas sencilla de evitar esta protección junto con las múltiples medidas de seguridad que implementa CF es simplemente saltarlo. Y suele ser bastante sencillo, existen múltiples métodos con los que averiguar la ip real en la que está alojado el servidor web original sin protección de CF y una vez teniendo la ip puedes configurar los robots para que la utilicen directamente ignorando las ips proxy que ofrece el DNS de CF. En un mundo ideal se podrían buscar formas de hacer encontrar la ip real muy difícil pero requeriría de un esfuerzo y cautela continuo de todo el equipo, tanto de sistemas como de desarrollo y los segundos suelen prestar poca atención a problemas de ips, procolos y seguridad así que en la medida de lo posible, como responsables de sistema es interesante poder contar con métodos para remediar la posibilidad que un atacante conozca la ip real.

Recientemente CF ha anunciado la posibilidad de modificar y añadir headers concretos a la solicitud que envían sus proxys hacia nuestro servidor. Antes podía hacerse, pero era necesario programar los «workers» de CF, ahora es mucho mas sencillo (https://blog.cloudflare.com/transform-http-request-headers/). Esta sencilla herramienta abre un amplio mundo de posibilidades.

La forma mas sencilla de evitar el acceso directo al servidor web sería bloquear a nivel IP cualquier ip que quiera acceder a los puertos 80 y 443 que no sean del rango de ips de CF (https://www.cloudflare.com/ips/). El problema de esta solución es que si tienes varios dominios alojados en un mismo servidor/ip y no todos los dominios están protegidos por CF entonces no puedes bloquear por ip. Igualmente, aunque el rango de ips de CF no cambia demasiado a menudo, obliga a estar pendiente de cualquier actualización en su rango de ips para adaptarlo a las reglas de tu cortafuegos.

Así que necesitamos un método mas fácil de mantener y útil para un sistema mas complejo. Y aquí entran en juego los headers personalizados de CF. La ideas es simple, crear un header con un valor clave y verificar en el servidor si este header ha sido enviado en la solicitud, si el header no se ha enviado entonces podemos estar seguro que la conexión es directa sin pasar por CF. En principio, el header sería muy difícil de encontrar, solo lo conoce quien lo ha configurado, el servidor web y CF. Para llegar a encontrar el header oculto sería necesario llegar a hackear el servidor web y ejecutar algún script en él que mostrara los headers enviados en la solicitud a través de CF, algo posible pero aún en ese caso el atacante tendría que saber qué esta buscando y qué método está utilizando el servidor para denegar los accesos directos. ¿ Qué no es perfecto el método ? seguro, pero es una parte mas en el juego del gato y el ratón. La protección anti DDOS va mucho mas allá pero no es el objetivo de este post un análisis completo de todas las técnicas posibles.

Como ejemplo concreto os detallo como aplicar el filtro del header en el servidor nginx, de camino podemos aprovechar para añadir mas verificaciones de headers como la geolocalización de CF (geolocalización pro gratis).

Para verificar el header oculto, basta con añadir en la sección «server» de nginx lo siguiente (obviamente antes has tenido que crear dicho header en CF como se explica en el enlace que os dejé):

if ($http_customheader != 'TOKENSECRETO') { return 511; }

Y así de sencillo, cualquier solicitud directa que llegue al servidor sin especificar el customheader con el valor TOKENSECRETO recibirá de regalo un bonito error 511. Como valor de retorno puedes elegir el que mas te apetezca siguiendo criterios lógicos (no se te ocurra hacer un return 200). En este caso he utilizado el 511 (Network Authentication Required) para así tener constancia en los logs de los intentos de accesos directos que ha habido a modo informativo (siempre hay que tener un ojo en los logs).

Otra verificación interesante sería el control de acceso por país. Unos de mis clientes estaba sufriendo infinidad de ataque de prácticamente todos los países del mundo (parte del juego DDOS) pero su mercado potencial era de solo unos pocos países así que gracias al header de geolocalización de CF más el bloqueo de acceso directo lo tienes fácil:

Añadimos en el bloque http de nginx:

map $http_cf_ipcountry $countryok {
default "0";
"FR" "1";
"ES" "1";
"DE" "1";
"BE" "1";
"US" "1";
}

Añadimos en el bloque server de nginx:

if ($countryok != '1') { return 511; }

Como veis utilizo el header cf_ipcountry para obtener el código ISO del pais y verificar si está en la lista de permitidos.

La posibilidades son infinitas, solo tienes que aplicar la imaginación.

Espero que os sirva de ayuda y si necesitáis asesoramiento técnico para implementar protecciones DDOS puedo ofreceros como servicio mis años de experiencia en este campo.