Proteger una web en Nginx contra ataques de fuerza bruta: rate limiting

Uno de los peligros que corren las páginas web es el ataque por fuerza bruta, y los ataque DDOS. Básicamente son muchas peticiones a la web por segundo, lo que bloquea los procesadores y “tira” la web (no se pueden procesar más peticiones y el servidor se cuelga). Evidentemente tenemos que proteger nuestra web de estos ataques.

Cloudflare tiene unas protecciones mínimas para evitar estos ataques, pero en los modos gratis y Pro hemos hecho pruebas y no son muy efectivos (en modo alto, no se en modo ataque). Tenemos que pensar en Cloudflare como una capa más de seguridad, pero no algo 100% efectivo.

Así que nos queda proteger el servidor, hoy os contamos cómo hacerlo con Nginx.

Nginx tiene una directiva llamada limit_req_zone , que se puede usar junto con  limit_req para controlar el número de peticiones. Para comprenderlo podemos usar la analogía de un cubo de agua con agujeros. Si no tuviera agujeros y sigue llegando agua, el cubo rebosará (servidor caído). Si ponemos agujeros, podremos seguir metiendo agua sin que el servidor rebose, hasta un límite (donde ya rebosará). El agua que sale de los agujeros es la información que meteremos en los buffers. El agua que rebosa son las peticiones que no se atenderán, pero serán menos que sin agujeros. Esto nos permite controlar un poco ataques.

Para configurar este parámetro hay que hacer lo siguiente:

En el fichero de configuración tienes que añadir una línea como esta, configurando la zona y los límites. Juega con esos límites, sobre todo la última parte que son las peticiones por segundo. Puedes dejarlo en 10 o ponerlo en 1. Por defecto empieza en 10 y prueba. El nombre de la zona (mylimit) podemos cambiarlo también.

limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;

Esta línea la puedes añadir tanto en el fichero de configuración del sitio, como en el directorio conf.d en un fichero llamado limits.conf.

Después en el fichero de configuración del sitio (sites-enabled) tenemos que aplicar ese límite con limit_req donde queramos (por ejemplo un wp-admin de wordpress en este caso).

server { 
  location /wp-admin/ 
     { limit_req zone=mylimit;
} }

También podemos ponerlo sólo para un tipo de ficheros:

location ~ \.php$ {
limit_req zone=one burst=5 nodelay;}

 

Con esto al reinciar Nginx (prueba la configuración primero) deberías poder hacer pruebas de muchas llamadas al servidor y no debería haber problemas. Cualquier exceso o se guardará en la cola o no se procesará, sin tirar el servidor.

Más información aquí.