Deteniendo un SIP flood con OpenSIPS y el módulo pike

Esta semana mientras miraba algo en uno de nuestros servidores me di cuenta de que estábamos siendo «atacados» mediante SIP flooding. Lo pongo entre comillas porque no era un ataque suficientemente significativo como para que el servicio se viera afectado, así que decidí aprovechar la ocasión para experimentar un poco y encontrar la manera de evitar éste tipo de ataques.

Como he dicho el ataque no era gran cosa: un montón de REGISTER que ni siquiera intentaban averiguar passwords. El problema de éste tipo de ataques es que pueden dejar nuestro sistema fuera de combate si los recursos no se liberan demasiado rápido. Los descriptores de fichero asignados a un proceso no son ilimitados (aunque ulimit -n diga lo contrario) y si se acaban no podremos hacer casi nada. Por otro lado, si la aplicación que está sufriendo el ataque consume el 100% de la CPU también estaremos afectando a otros procesos del sistema.

En estos casos un IDS como Snort puede ayudarnos, pero ya que se trata de OpenSIPS vamos a utilizar el módulo pike ya que viene incluido y así no necesitamos añadir un elemento más a nuestra infraestructura.

El módulo pike no bloquea el ataque de por si. Es capaz de detectarlo y de darnos las herramientas necesarias para actuar ente un ataque. Podéis ver toda la documentación del módulo, yo aquí comentaré los parámetros más relevantes:

  • sampling_time_unit: Indica el número de segundos que componen una muestra. A priori puede parecer algo abstracto, cobra sentido en combinación con el siguiente parámetro.
  • reqs_density_per_unit: Indica el número de mensajes permitidos en un sampling_time_unit, de manera que al sobrepasar éste número se ‘bloqueará’ la IP que esté originando el tráfico.
  • remove_latency: Indica el tiempo que tendremos una IP marcada como ‘bloqueada’.

Todas las unidades de tiempo se indican en segundos.

Una vez tenemos el módulo configurado vamos a utilizar la función pike_check_req() para detectar el flooding y actuar en consecuencia. Un ejemplo con un poco de pseudocódigo:

modparam("pike", "sampling_time_unit", 2)
modparam("pike", "reqs_density_per_unit", 30)
modparam("pike", "remove_latency", 120)
...
...
if (!(FROM_SELF || FROM_TRUSTED)) {
if (!pike_check_req()) {
exit;
}
}
...
...

Como se puede ver lo que haremos al detectar el flood es llamar a la función exit, para dejar de procesar los requests y liberar los recursos lo antes posible.

Alguno ya se habrá dado cuenta de que en realidad no estamos deteniendo el ataque… veamos como se podría hacer 🙂

El módulo pike nos generará unas bonitas entradas en syslog:

Jun 14 11:32:39 node03 /usr/sbin/opensips[12654]: PIKE - BLOCKing ip 1.2.3.4, node=0xaf793a68
Jun 14 14:15:43 node03 /usr/sbin/opensips[12659]: PIKE - UNBLOCKing node 0xaf793a68
Jun 14 14:15:45 node03 /usr/sbin/opensips[12623]: PIKE - BLOCKing ip 1.2.3.4, node=0xaf793axx
Jun 14 14:34:25 node03 /usr/sbin/opensips[12659]: PIKE - UNBLOCKing node 0xaf793axx
Jun 14 14:34:27 node03 /usr/sbin/opensips[12646]: PIKE - BLOCKing ip 1.2.3.4, node=0xaf793axx
Jun 14 15:35:39 node03 /usr/sbin/opensips[12659]: PIKE - UNBLOCKing node 0xaf793axx

Todo lo que tendremos que hacer es detectar estos mensajes con Rsyslog (por ejemplo) y añadir temporalmente una regla de iptables para bloquear el tráfico.

Ala, ya tenéis deberes 😉

4005407576_a1e671452d_m

3 thoughts on “Deteniendo un SIP flood con OpenSIPS y el módulo pike

  1. ante todo, gracias por tu blog, para los que recien comenzamos en este mundo de opensips es de mucha utilidad. Mi pregunta es … tomar el log que emite pike y aplicarle Fail2ban seria una buena opcion ????

  2. Claro 😉 pike bloquea el trafico en OpenSIPS, mientras que si usas su output junto a fail2ban lo bloqueas a un nivel más bajo y el impacto del ataque será menor.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *