Al publicar servicios en Internet, nos exponemos a todo tipo de amenazas, desde Bots y Web Crawlers hasta intentos de ataques con intenciones diversas (desde obtener nuestros datos con llamadas GET a nuestras APIs, hasta denegaciones de servicio de todo tipo). Tenemos muchas maneras de protegernos en función de la situación concreta (ej: autenticación, uso de CDNs, uso de WAF, etc). En este Post vamos a ver varios Plugins de Kong que también nos pueden ayudar, y la forma de configurarlos utilizando Konga: Bot Detection, Request Size Limiting, Proxy Cache, IP Restrictions, Rate Limiting, y Response Rate Limiting
Continuando con la serie de Posts acerca de Kong, en esta ocasión vamos a ver los principales Plugins de Seguridad y Control de Tráfico, que ayudan a proporcionar mayor estabilidad y seguridad a nuestras APIs, explicando el cometido de cada uno, la forma de configurarlo utilizando Konga, y cómo probarlo con un curl.
Si quieres seguir este Post paso a paso, te recomiendo que te apoyes en el Docker Compose que compartí en GitHub (GitHub – ElWillieES – kong-docker-lab) y que revises los anteriores Post, al menos el primero (Introducción a Kong Gateway y Kong Dashboard) que además de hacer una introducción a Kong, también explica el Docker Compose compartido en GitHub.
Si has seguido los anteriores Posts haciendo los diferentes laboratorios, para hacer los ejercicios de este Post, deberías deshabilitar todos los Plugins de los laboratorios anteriores.
Dicho esto, comenzamos.
Plugin Bot Detection
Permite filtrar por el contenido del encabezado HTTP user-agent, con el fin de detectar y bloquear Bots de Internet que puedan estar intentando acceder a nuestros contenidos, para lo cual:
- Incluye un conjunto de reglas predefinidas para bloquear según el contenido del user-agent.
- Complementando el punto anterior, permite además hacer un whitelist y blacklist personalizado del encabezado user-agent.
Para más información acerca del Plugin de Bot Detection: Kong – Plugin – Bot Detection
Para probarlo, vamos a añadir el Plugin de Bot Detection a nivel global, utilizando Konga.
En la siguiente pantalla, podemos especificar las expresiones de allow y deny (whitelist y blacklist) que deseemos, para complementar la configuración de reglas predefinidas del plugin. En nuestro caso a modo de ejemplo, vamos a añadir una expresión para denegar el acceso a través de curl, aprovechando que curl informa el encabezado de user-agent resultando fácil de filtrar con este Plugin.
Para probarlo, es suficiente con ejecutar un par de comandos curl como el siguiente, uno antes de aplicar el Bot Detection y otro después:
curl -i --location 'http://localhost:8000/service-c'
En la siguiente pantalla capturada, vemos cómo antes de aplicar el Bot Detection se permitía la petición del curl, y como después es rechazada (Forbidden). También vemos el valor del encabezado user-agent.
Como siguiente prueba, podemos quitar la expresión que añadimos en la blacklist para bloquear el curl, y así dejar sólo las reglas predefinidas que proporciona este filtro.
Para seguidamente, intentar acceder simulando ser un Bot, por ejemplo especificando la palabra «spider» en el encabezado de user-agent, y comprobar como la petición el bloqueada (403 Forbidden).
Plugin Request Size Limiting
Permite bloquear aquellas peticiones en las que el tamaño del body supere un umbral determinado. Este Plugin es fundamental (es un MUST), más aún en el caso de APIs públicas para protegernos de posibles ataques de denegación de servicio. Para más información acerca del Plugin de Request Size Limiting: Kong – Plugin – Request Size Limiting
Para probarlo, vamos a añadir el Plugin de Request Size Limiting a un servicio (Servicio A de nuestro Docker Compose), utilizando Konga.
En la siguiente pantalla hay varias opciones que podemos configurar. En nuestro caso de ejemplo, con especificar que deseamos limitar a 2 MB las peticiones, es suficiente. Click Add Plugin para continuar.
Para probarlo, podemos lanzar dos comandos curl como los siguientes, uno que no exceda el umbral que hemos configurado, y otro que lo exceda, para así ver que una petición finaliza OK (HTTP 200) mientras que la otra no (HTTP 413).
curl -i --location --request GET 'http://localhost:8000/service-a' \
--form 'test-file=@"/mnt/c/temp/pdf-90kb.pdf"'
curl -i --location --request GET 'http://localhost:8000/service-a' \
--form 'test-file=@"/mnt/c/temp/pdf-7mb.pdf"'
A continuación se muestra la ejecucion de ambos comandos, y su resultado.
También podríamos probarlo de forma rápida y sencilla con Postman, con el mismo resultado.
Plugin Proxy Cache
Proporciona un Caché por tiempo definido (ttl) de las respuestas HTTP, en función del verbo/método, API, path, y querystring, evitando que la petición baje al origen (a la propia API), resultando apropiado para llamadas que son costosas. Es decir, si la llamada a cierta API tarda 5 seg, si pudiéramos cachearla, la primera invocación tardaría 5 seg, mientras que la siguiente sería inmediata al resolverse desde la caché de Kong ahorrando los recursos de procesamiento de la misma.
Podemos añadir el Plugin de Proxy Cache a nivel global, de Service, de Route, o asociarlo a un Consumidor concreto, y por supuesto, podemos instanciar el Pluign múltiples veces, en función de lo que necesitemos.
Para más información acerca del Plugin de Proxy Cache: Kong – Plugin – Proxy Cache
Para probarlo, vamos a añadir el Plugin de Proxy Cache a un servicio (Servicio B de nuestro Docker Compose), utilizando Konga.
En la siguiente pantalla hay varias opciones que podemos configurar. En nuestro caso de ejemplo, con especificar strategy memory, es suficiente. Click Add Plugin para continuar.
Para probarlo, es suficiente con ejecutar de forma sucesiva, varios comandos curl como el siguiente:
curl -i --location 'http://localhost:8000/service-b'
A continuación se muestra un ejemplo de dos llamadas idénticas:
- La primera produce un Miss al no encontrarse en caché
- La segunda produce un Hit, pudiendo resolverse desde caché (no baja a origen)
Si hiciéramos más llamadas idénticas, se resolverían igualmente desde caché, sin embargo, si cambiase el verbo, el path, o la querystring (por ejemplo), se tratarían como llamadas diferentes a efectos de caché, ya que se almacenarían en Keys diferentes.
Este Plugin también proporciona métodos para Purgar la Caché, algo muy necesario, como ocurre con las CDNs. Por ejemplo, podemos purgar toda la caché con el siguiente comando.
curl -i -X DELETE --location 'http://localhost:8001/proxy-cache/'
A continuación se muestra un ejemplo, de Hit en la caché, la ejecución del purgado de la caché, y cómo la siguiente petición después del purgado genera un Miss (en lugar de Hit) como consecuencia del purgado.
Plugin IP Restrictions
Permite configurar IPs o rangos de IPs (en notación CIDR) que sean permitidas (whitelist) o denegadas (blacklist). Está bien y es muy útil, aunque la pena es que no permita geobloqueo. Para más información acerca del Plugin de IP Restrictions: Kong – Plugin – IP Restrictions
Su configuración es muy sencilla, a continuación se muestra un ejemplo de configuración utilizando Konga, donde se restringe tanto a una IP como a un rango de IPs mediante su notación CIDR.
Plugin Rate Limiting (Limit/Quota)
Permite controlar el número de peticiones HTTP entrantes que llegan a nuestras APIs en un periodo de tiempo determinado (segundos, minutos, horas, días, meses, ó incluso años) a través de Kong, pudiendo establecer quotas de uso personalizadas a nuestros Consumidores (no sólo limitar el tráfico), mostrando un mensaje de error en caso de exceder el límite configurado (HTTP 429 Too Many Requests). Para ello, este Plugin necesita contar las peticiones entrantes (pudiendo apoyarse en la base de datos de Kong o en un Redis adicional), y tomar decisiones (permitir o bloquear) en función de los umbrales que le configuremos. Para más información acerca del Plugin de Rate Limiting: Kong – Plugin – Rate Limiting
Para probarlo, vamos a añadir el Plugin de Rate Limiting a un servicio (Servicio C de nuestro Docker Compose), utilizando Konga.
La siguiente pantalla es importante, ya que podemos configurar varias cosas. A continuación explicamos algunas:
- Podemos especificar a qué Consumidor aplica la configuración de Rate Limit. Si no se especifica este valor, aplicará a todos los consumidores, pero además podemos instanciar múltiples veces el Plugin con configuraciones distintas para consumidor, de tal modo que podamos establer una Quota de uso para los usuarios «Standard» y otra para los usuarios «Premium», con el fin de monetizar nuestras APIs.
- Podemos especificar varios rates (peticiones por segundo, minuto, hora, día, mes, y año), que se aplicarán de forma simultánea. Por ejemplo:
- Podemos tener un rate de 5 peticiones/min y a la vez de 3.000 peticiones/día, para los Consumidores Standard
- Podemos tener un rate de 30 peticiones/min y a la vez de 20.000 peticiones/día, para los Consumidores Premium
- Podemos especificar usar una política local (no usa base de datos), cluster (usa la base de datos de Kong, si es Postgres, pues ese), o Redis (usar un servidor Redis externo, para no penalizar la base de datos y mejorar el rendimiento, al ser Redis una base de datos NoSQL en memoria).
- En el caso de utilizar Redis, podemos especificar sus datos de conexión: host, port, user/password, ssl, etc. Hay que tener en cuenta, que si deseamos utilizar Redis Sentinel, sólo lo podremos hacer con Kong Enterprise (la versión de pago).
En nuestro caso particular (para este ejemplo) sólo nos interesa especificar que deseamos un rate de 5 peticiones por minuto dejando el resto de opciones por defecto (se aplicará a todos los consumidores), tal y como se muestra en la siguiente pantalla.
Para probarlo, es suficiente con ejecutar de forma sucesiva, varios comandos curl como el siguiente:
curl -i --location 'http://localhost:8000/service-c'
A continuación se muestra un ejemplo de la respuesta tras haber excedido el límite: obtenemos un mensaje de error 429 (Too Many Requests) y vemos cómo nos informa a través de encabezados, que está configurado Rate Limit y que intentemos de nuevo en 37 segundos.
Si quisiéramos, podríamos configurar la autenticación (ej: Basic Auth) y añadir otra instancia del Plugin Rate Limiting especificando un consumidor (ej: willie) y un rate diferente (ej: 10 peticiones/min), y comprobar llamando con curl, que las llamadas autenticadas como el consumidor willie disfrutan de un rate o quota mayor.
Plugin Response Rate Limiting (Limit/Quota)
Permite controlar el número de peticiones HTTP entrantes que llegan a nuestras APIs en un periodo de tiempo determinado (segundos, minutos, horas, días, meses, ó incluso años) a través de Kong, pudiendo establecer quotas de uso a nuestros Consumidores (no sólo limitar el tráfico), mostrando un mensaje de error en caso de exceder el límite configurado (HTTP 429 Too Many Requests).
A diferencia del anterior Plugin de Rate Limiting en el que especificábamos unos límites de forma estática, el Plugin Response Rate Limiting permite ajustar los límites de forma dinámica en base a las respuestas que recibe del origen (upstream) según el valor del encabezado x-kong-limit, permitiendo aumentar o disminuir los límites a lo largo del tiempo.
Implica implementar alguna lógica para poder devolver este encabezado correctamente, en base al auto-escalado de la plataforma o de cualquier otro factor, y es un poco más complicado de administrar. Para más información acerca del Plugin de Rate Limiting: Kong – Plugin – Response Rate Limiting
A continuación se muestra la pantalla de configuración del Plugin Response Rate Limiting en Konga, a modo ilustrativo, que junto a la documentación del producto, transmite una idea de las posibilidades y configuración de este Plugin.
Despedida y Cierre
Hasta aquí llega este Post sobre Kong, donde hemos podido ver varios Plugins de Kong relacionados con la Seguridad y el Control de Tráfico (algunos de los cuales son muy necesarios), explicando su funcionamiento, su configuración mediante Konga, probándolos mediante comandos curl, y utilizando el Docker Compose compartido en GitHub para quienes deseen seguir este laboratorio paso a paso: GitHub – ElWillieES – kong-docker-lab
Poco más por hoy, como siempre confío que la lectura resulte de interés.