Defienda su servidor web contra ataques distribuidos de denegación de servicios (DDos)

En seguridad informática, rápidamente se hace evidente que prevenir ataques de computadora es mucho más desafiante que atacar computadoras. Un buen ejemplo de una técnica fácil para evitar que un sitio web funcione es un ataque distribuido de denegación de servicio (DDoS, por sus siglas en inglés) en el que una cantidad de computadoras comprometidas en Internet realizan solicitudes web (u otro protocolo) en un servidor deficiente. Si la página web solicitada es una que requiere mucho procesamiento del lado del servidor, la carga resultante de las solicitudes combinadas evita que el servidor web responda a solicitudes legítimas, negando así el servicio. Como Tech-Recipes.com fue objeto de un ataque de este tipo recientemente, sentimos que podría ser beneficioso para otros si describimos los pasos que tomamos en nuestra respuesta.


Nota: la siguiente información es relevante para los servidores basados ​​en UNIX que ejecutan Apache (aunque otras plataformas y software pueden ser aplicables). Un requisito previo para este enfoque requiere el uso de iptables, lo que probablemente signifique que necesita acceso de root al servidor, por lo que probablemente no le ayude si está usando un alojamiento compartido. ¡Lo siento! En este caso, lo mejor que puede hacer es ponerse en contacto con su ISP para obtener ayuda (buena suerte), ya que le interesa evitar grandes cargas en sus servidores compartidos, aunque es probable que deshabiliten temporalmente sus servicios de dominio, lo que definitivamente es No es la mejor solución desde su perspectiva.

Para minimizar el impacto de un ataque de denegación de servicio, debe conocer los problemas con su servidor web casi en tiempo real. Varios servicios de monitoreo del servidor están disponibles. Usamos tanto Pingdom como SiteUptime. Al usar estos servicios, recibimos notificaciones redundantes de cualquier interrupción del servicio enviada a nuestros teléfonos celulares a través de SMS y a varias direcciones de correo electrónico (ninguna de las cuales son manejadas por nuestros servidores monitoreados, por supuesto). Al usar estos servicios, se nos notifica dentro de un minuto de una solicitud fallida a nuestros servidores de producción.

Antes de implementar técnicas anti-DDoS específicas o buscar ayuda de un servicio de protección de DDos, es aconsejable asegurarse de que el problema sea realmente un ataque DDoS. Es posible que los servicios no respondan una solicitud por varios motivos, entre ellos, el ejecutable que ejecuta el servicio fallece de forma inesperada, el ISP que aloja el servidor y se produce una interrupción de la red, o algún otro problema de autocorrección en la matriz. Para determinar si la falla del servicio se debe a un DDoS y para recopilar la información necesaria para tomar medidas contra el ataque, primero debe investigar.

Necesita acceder a su registro de acceso, el archivo de registro que contiene una entrada de texto para cada solicitud realizada a su servidor web. Hay muchos lugares que este archivo puede ocultar y depende de la configuración de su servidor. En caso de duda, puede consultar la documentación del ISP (buscar el registro de acceso): puede acceder a los datos del registro a través de una consola web, pero es óptimo si tiene acceso de shell a su servidor. Si la ayuda en línea de su ISP no es tan útil para encontrar el registro de acceso, puede usar el comando de búsqueda UNIX.

Una vez que haya encontrado su registro de acceso, introduzca el directorio que contiene el registro y ejecute el comando tail en él con la opción -f:

cola -f acceso_log

El comando de cola solo mostrará las últimas 10 líneas del archivo especificado y luego se cerrará. La opción -f le indicará a tail que siga corriendo después de que se muestren las últimas 10 líneas y que siga mostrando las líneas subsiguientes que se agregan al archivo. Es probable que veas una serie de entradas. Si no ve ningún mensaje de registro después de los 10 predeterminados, o bien está mirando el archivo incorrecto o el servidor web está muerto o no ve ningún tráfico. Es posible que un servidor pueda alojar muchos sitios web y que cada uno tenga un archivo access_log separado, así que asegúrese de estar siguiendo el correcto. Si el servicio está muerto, resucítelo a través del mecanismo que sea apropiado. A partir de ahora, vamos a suponer que está viendo una tonelada de mensajes de registro de acceso que se ven muy similares (probablemente llegan a la misma URL) que no tienen una referencia válida o ninguna (si la referencia es slashdot.org o digg.com, bueno, entonces puede estar contento y triste de que el tráfico, aunque el servidor esté paralizado, sea legítimo) y tenga un montón de direcciones IP diferentes. Durante nuestro reciente asedio, hubo tantas solicitudes falsas que muy pocas solicitudes legítimas llegaron al archivo access_log. Aquí hay algunas líneas de nuestro access_log durante el ataque:

220.255.7.204 - - [07 / Jul / 2008: 19: 28: 18 -0700] "GET /modules.php?name=Forums&file=index HTTP / 1.1" 200 0 "-" "Mozilla / 4.0 (compatible; MSIE 6.0 "Windows NT 5.1; SV1; .NET CLR 1.1.4322)"

220.255.7.209 - - [07 / Jul / 2008: 19: 28: 18 -0700] “GET /modules.php?name=Forums&file=index HTTP / 1.1” 200 0 “-” “Mozilla / 4.0 (compatible; MSIE 6.0 ; Windows NT 5.1; SV1; .NET CLR 1.1.4322) ”

220.255.7.208 - - [07 / Jul / 2008: 19: 28: 18 -0700] “GET /modules.php?name=Forums&file=index HTTP / 1.1” 200 0 “-” “Mozilla / 4.0 (compatible; MSIE 6.0 ; Windows NT 5.1; SV1; .NET CLR 1.1.4322) ”

71.232.78.53 - - [07 / Jul / 2008: 19: 28: 19 -0700] “GET /modules.php?name=Forums&file=index HTTP / 1.1” 200 14313 “-” “Mozilla / 4.0 (compatible; MSIE 7.0 "Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)"

Si no está familiarizado con la estructura predeterminada de access_log de Apache, el primer valor es la dirección IP de origen de la solicitud, entonces la fecha y la hora de la solicitud están entre corchetes, y la primera cadena entre comillas dobles es la solicitud HTTP hecho. En nuestro ejemplo, la solicitud fue siempre la misma: "GET /modules.php?name=Forums&file=index HTTP / 1.1": una solicitud GET de la URL (/modules.php?….) Y el protocolo HTTP utilizado (1.1 ).La parte de la URL utilizada es importante ya que es lo único que podemos usar para identificar las direcciones IP ofensivas. La segunda cadena entre comillas es la URL de referencia, en nuestro caso no hay una, por lo que aparece como "-", lo que da crédito a la sospecha de que se trata de un ataque DDoS. La cadena restante describe la plataforma y el software que ha realizado la solicitud y no es muy significativo ni útil para nosotros, ya que se puede falsificar fácilmente.

Ahora que sabemos que hay un ataque DDoS en curso, necesitamos una lista de las direcciones IP involucradas en el ataque para bloquear sus solicitudes posteriores con iptables. En el ejemplo access_log anterior, sé que el componente de URL solicitado "/modules.php?name=Forums&file=index" se puede usar para buscar en access_log. ¿Porque contiene caracteres especiales como & y? Como la mayoría de los shells de UNIX interpretan como algo muy diferente, es una buena idea poner la cadena de búsqueda entre comillas dobles en todos los comandos que la usan. El siguiente comando capturará solo las líneas en access_log que coincidan con el componente de URL anterior y devolverá una lista de las direcciones IP que lo solicitaron y una cantidad de las veces que cada dirección IP realizó la solicitud, ordenada por la cuenta.

fgrep "/modules.php?name=Forums&file=index" access_log | corte -d \ -f1 | sort -n | uniq -c | ordenar -rn

El comando fgrep es un grep rápido que no busca expresiones regulares y puede atravesar enormes archivos de registro de manera mucho más eficiente. Si su sistema no lo tiene por alguna razón insondable, sustituya el antiguo grep del plan por fgrep. Sustituya el nombre de su registro de acceso si es diferente de access_log. Tenga en cuenta que hay dos espacios después de la barra diagonal inversa en la opción de corte -d \. Esta cadena de comandos extraerá las líneas coincidentes en access_log (fgrep), extraerá el primer campo separado por espacios (cortar), las ordenará numéricamente (sort -n), las agrupará para hacer una lista de direcciones IP únicas y contará las ocurrencias (uniq), y ordénelos numéricamente en orden inverso para que las direcciones IP con las cuentas más altas aparezcan primero. Aquí hay un ejemplo de la salida:

21889 71.232.78.53
17181 220.255.7.208
16162 220.255.7.209
16142 220.255.7.204

Es probable que vea dos grupos, algunas direcciones IP con un gran número (cientos, miles) de solicitudes y otras con solo unas pocas, quizás decenas de solicitudes. Al seleccionar el número de solicitudes que separa a los dos grupos, tenga cuidado ya que no desea bloquear solicitudes legítimas. Lo más probable es que cuando comience a bloquear las direcciones IP desde el principio de la lista, sabrá cuándo los números cambian y se convierten en valores aparentes legítimos, como un salto de varios cientos de visitas a unas pocas decenas de visitas. Si puede, copie la salida del comando anterior a alguna forma de editor de texto para tenerlo a mano. Una nota, si su access_log no se gira con frecuencia (su contenido se copia en otra ubicación y posiblemente se comprime), puede volverse enorme. Puede usar el comando tail de una manera diferente para hacer que este comando se ejecute más rápido, lo cual probablemente su servidor más apreciado: el comando "tail -10000 access_log" tomará las últimas 10,000 líneas de access_log y continuará procesándolas (puede cambiar 10000 a un número de su gusto):

cola -10000 access_log | fgrep "/modules.php?name=Forums&file=index" | corte -d \ -f1 | sort -n | uniq -c | ordenar -rn

Ahora que está armado con el conocimiento de qué direcciones IP necesita bloquear, es hora de establecer la ley de iptable. El sistema iptables puede realizar muchas operaciones diferentes y, afortunadamente para nosotros, bloquear una única dirección IP es una de las configuraciones más fáciles. Para bloquear todas las solicitudes de una dirección IP como 71.232.78.53, use el comando:

iptables -A ENTRADA -s 71.232.78.53 -j GOTAR

Si no ha iniciado sesión en el servidor como root, simplemente agregue un 'sudo' delante de este comando y proporcione su contraseña cuando se le solicite. Este comando agrega una regla temporal al sistema de iptables para eliminar todos los paquetes provenientes de la dirección IP especificada. Este efecto es temporal ya que no persistirá después de un reinicio. Si desea que estos cambios sean permanentes (probablemente no sea una gran idea, pero tampoco está mal, si planea reiniciar pronto para liberar cualquier memoria perdida), puede intentar ejecutar

/etc/init.d/iptables guardar

Este comando funcionará y le hará saber que funcionó, o se producirá un error. En este último caso, puede repetir los comandos de iptables, uno por cada dirección IP, para volver a bloquearlos.

Si tiene solicitudes provenientes de varias direcciones IP dentro de la misma subred, puede bloquear la subred con un comando de iptables. En nuestro caso, tuvimos un montón de direcciones IP de las solicitudes de envío de subred 220.255.7.0. En lugar de repetir el comando iptables un par de veces, la abreviatura de subred para el comando iptables hace que esta tarea sea mucho más sencilla:

iptables -A ENTRADA -s 220.255.7.0/24 -j GOTA

No bloquearía más de una subred de clase C a la vez, como se muestra arriba. Esencialmente, si ve un grupo de solicitudes de direcciones IP en las que los primeros tres números de la dirección IP son iguales, entonces todos están en la misma subred de clase C y puede bloquearlos todos usando los primeros tres números separados por períodos seguido por un .0 / 24 como el anterior.

Dado que un ataque DDoS puede estar en curso y más máquinas pueden participar en el ataque a lo largo del tiempo, puede valer la pena su esfuerzo para hacer un script rápido para bloquear una dirección IP simplemente. Escribí el siguiente script y lo coloqué en / usr / sbin / block

#! / bin / bash

iptables -A ENTRADA -s $ 1 -j DROP

Una vez que el archivo está en su lugar, hazlo ejecutable con chmod + x / usr / sbin / block y luego usarlo como:

bloque 71.232.78.53

Cada sistema es único, tiene diferentes aplicaciones y versiones de aplicaciones instaladas en diferentes lugares, por lo que su millaje puede variar con las instrucciones anteriores.