Reparar todas las tablas de MySQL en un sistema Vicidial

28 Nov

El domingo pasado recibí el correo de un cliente: su sistema de marcación predictiva con vicidial había tenido fallas eléctricas durante el fin de semana, ocasionando que las tablas de MySQL se corrompieran y que el sistema quedara inservible (al menos lo relacionado con la marcación predictiva).

Tras cerca de una hora reparé todas las tablas usando unos comandos simples como los que siguen:

/etc/init.d/mysql stop
cd /var/lib/mysql/asterisk
myisamchk -r *.MYI
/etc/init.d/mysql start

Sin embargo, me percaté que al hacer esto, estaba solo reparando las tablas una por una. El sistema tenía 4 núcleos, por lo que era posible hacer mucho más trabajo al mismo tiempo (4 tareas a la vez) en vez de ir una por una.

El sistema terminó de manera habitual tras el paso de 1 1/2 hrs. Para evitar que tanto tiempo se perdiera en nuevas ocasiones, decidí crear un script en bash que reparara todas las tablas de manera simultánea (limitándose a 1 proceso por cada núcleo del sistema), y me quedó el código así:

#!/bin/bash

# Editar estos valores:
## CORES 		debe ser igual al número de núcleos en el sistema 
##				(revisar el comando "cat /proc/cpuinfo")
## MYSQLDBDIR	debe ser igual a la carpeta de MySQL que contiene la BD
##				que debamos reparar (default: "/var/lib/mysql/asterisk")

CORES=4
MYSQLDBDIR=/var/lib/mysql/asterisk

# Enlistar los archivos
FILES=`ls $MYSQLDBDIR/*.MYI`
RUNS=0
for i in $FILES
do
	SALIR=0
	while [ $SALIR -eq 0 ]
	do
		# Obtener la cantidad de procesos en el sistema
		PROCS=`ps -eF|grep myisamchk|egrep -v "grep"|wc -l`

		# Ejecutamos el while los procesos activos sean menor a CORES
		if [ $CORES -gt $PROCS ]
		then
			echo `date +"%X"` Revisando/Reparando tabla $i
			myisamchk -r $i &
			# Descansamos 1 segundo
			sleep 1
			SALIR=1
		else
			# Esperamos 3 segundos
			sleep 3
		fi
	done

done

# Ya se terminaron de correr todas las instrucciones de reparación,
# pero existe la posibilidad de que algunas de ellas aún estén ejecutándose.
# Revisamos para ver si hay procesos corriendo y avisar al usuario
while [ $SALIR -eq 0 ]
do
	# Obtener la cantidad de procesos en el sistema
	PROCS=`ps -eF|grep myisamchk|egrep -v "grep"|wc -l`
	if [ $PROCS -gt 0 ]
	then
		echo `date +"%X"` Hay $PROCS procesos corriendo. Esperando 10s...
		sleep 10
	else
		echo "No hay procesos corriendo"
		SALIR=1
	fi
done
echo `date +"%X"` Fin. Ya puedes reiniciar MySQL

Los siguientes pasos son algo obvios:

  1. Hay que guardar este script como un archivo checar.sh
  2. Editamos el archivo y cambiamos el número de cores de nuestro sistema, así como la ubicación de la carpeta de MySQL que contiene los archivos de la BD
  3. Darle permisos de ejecución (chmod 755 checar.sh)
  4. Ejecutarlo: ./checar.sh
El script correrá varios procesos en paralelo para revisar cada uno una tabla. Mientras más núcleos tenga nuestro procesador, más rápido el script aprovechará los recursos para crear la reparación.
Espero les sirva.
¡Suerte!

 

Advertencia: Aunque este script puede ayudarnos a reparar nuestras tablas en caso de algún problema (falla eléctrica, corrupción del sistema de archivos, fallo en el disco duro, etc) no hay nada más seguro que respaldar nuestra información periódicamente. Siempre ten a la mano copias de seguridad de aquella información crítica, ya que no podemos hacernos responsables por la pérdida de información causada por el mal uso de las directivas que se muestran en este artículo. Úsalo bajo tu propio riesgo.

Distribución uniforme del consumo de llamadas entre líneas (AGI-PHP)

27 Nov

Tarde o temprano nos vemos en la necesidad de considerar el gasto individual de las lineas telefónicas conectadas a nuestro Asterisk y encontrar una forma en que las llamadas se distribuyan de forma uniforme entre las lineas, no es lo mismo que 90% de la llamadas al exterior se realicen por la primera linea desocupada a que en caso de tener 4 se repartan en un 25% entre ellas.

Debido a esta necesidad me vi en la necesidad de crear un script en AGI PHP que junto con el dialplan nos haga este trabajo:

Para llevar el contador de las llamadas haremos uso de la asteriskdb, la base de datos integrada en asterisk. Lo que haremos es establecer primero las familias y las llaves que llevaran los datos, usando los siguientes comandos desde adentro del Asterisk CLI (*CLI): Continue reading

Permitiendo llamadas no autenticadas del exterior (con restricciones)

26 Abr

Fuente: http://www.datacenta.com/Pictures/stop.jpg

En este blog y en muchos otros se ha discutido el uso de aplicaciones como fail2ban para impedir ataques de fuerza bruta combinado junto con iptablespara denegar el acceso a fuentes no autorizadas. Existe un caso especial que es cuando tenemos que aceptar las llamadas anónimas del exterior sin importar desde donde se originen, y ese es el caso del que voy a comentar a continuación.

Recibir llamadas anónimas no es malo, pero hay que saber lo que se hace y tomar las precauciones necesarias. Al permitir las llamadas entrantes desde cualquier fuente estamos permitiendo que cualquiera nos contacte via IP, para que así el interesado no tenga que paga costos de LD, ni tampoco tenga que hacer algún setup muy elaborado en su conmutador. Ofrecer un peer de autenticación a cada usuario sería un poco difícil, ya que lo que se espera de estos escenarios es que la comunicación sea en un solo sentido (de afuera nos marcan a nosotros hacia adentro) y también, buscas hacerla lo más fácil de marcar para el usuario final.

En nuestro caso, nosotros permitimos llamadas provenientes del exterior pero solo hacia nuestras extensiones internas. De esta manera, no hay costos relacionados con ataques porque las llamadas nunca vuelven a salir hacia la PSTN. Solo pueden comunicarse a nuestras extensiones internas y DIDs. El único problema, es que a veces los equipos que atacan piensan que al no negar las llamadas, vamos a permitirlas salir, así que nos mandan intentos de ataques de unas 40 llamadas simultáneas, lo que hace que nuestros teléfonos comiencen a sonar una y otra vez.

Para evitar que nuestro conmutador se atiborre de llamadas que no deseamos, pero que al mismo paso permita las llamadas que si queremos, debemos permitir lo siguiente desde nuestro GUI:

  • Permitir llamadas anónimas: si

Y luego hacemos esta combicación de plan de llamadas personalizado y fail2ban (estamos usando FreePBX). Dentro del archivo extensions_custom.conf ponemos:

[ext-did-post-custom]
exten => _X.,1,Macro(contador,${SIPCHANINFO(peerip)},3)
exten => _X.,n,Goto(ext-did-catchall,${EXTEN},1)

[macro-contador]
exten => s,1,GotoIf($[${GROUP_COUNT(${ARG1})}<=${ARG2}]?Permite)
exten => s,n,Noop(LLAMADAS EXCEDIDAS POR ${ARG1}. BLOQUEANDO)
exten => s,n,Congestion()
exten => s,n(Permite),Set(GROUP(${CDR(uniqueid)})=${ARG1})

Lo que estoy haciendo aquí es que siempre que reciba una llamada en mi FreePBX que no esté especificada hacia una extensión y/o DID que tenga dado de alta, el contexto [ext-did-post-custom] lo procesará y hará un análisis del número máximo de llamadas simultáneas que debe permitir.

  • Si se exceden 3 llamadas de acuerdo al ejemplo, debo cortar el paso y enviar un mensaje a consola que diga «LLAMADAS EXCEDIDAS»
  • Si no se excede, permito el paso enviando la llamada hacia la cláusula default [ext-did-catchall]
  • Si recibo llamadas desde una fuente «no autorizada» hacia un número que si existe en mi sistema, el contexto [ext-did] lo procesará de manera normal
  • Si el origen ya fuera autorizado, caerá en el contexto que sea que yo le haya especificado y hará caso omiso de esta configuración

Tras hacer la modificación correspondiente y recargar, el mensaje de «LLAMADAS EXCEDIDAS» ya aparece en mis logs. Ahora debo modificar mi fail2ban para que tome en cuenta este texto y bloquee a nivel de firewall a aquellos que nos manden llamadas en bruto.

Basándome en el artículo de fail2ban anterior que publicamos hace unos meses, modifico el /etc/fail2ban/filter.d/asterisk.conf para que quede así:

failregex = Registration from '.*' failed for '(:[0-9]{1,5})?' - Wrong password
Registration from '.*' failed for '(:[0-9]{1,5})?' - No matching peer found
Registration from '.*' failed for '(:[0-9]{1,5})?' - Device does not match ACL
Registration from '.*' failed for '(:[0-9]{1,5})?' - Username/auth name mismatch
Registration from '.*' failed for '(:[0-9]{1,5})?' - Peer is not supposed to register
LLAMADAS EXCEDIDAS DESDE (:[0-9]{1,5})?
NOTICE.* failed to authenticate as '.*'$
NOTICE.* .*: No registration for peer '.*' (from )
NOTICE.* .*: Host failed MD5 authentication for '.*' (.*)
VERBOSE.* logger.c: -- .*IP/-.* Playing 'ss-noservice' (language '.*')
LLAMADAS EXCEDIDAS POR

Si el fail2ban atrapa estas líneas, bloqueará al host por el tiempo que le hayamos especificado en el archivo jail.conf.

Debo destacar que este es un caso muy especial que pocos querrán utilizar, pero es bueno saber que se puede ser precavido y a la vez, flexible con el uso de tu conmutador. Dado que permitir llamadas anónimas expone tu conmutador, la responsabilidad de este código recae en quien lo usa, por lo que no debes aplicarlo si no estas seguro de que es lo que hará.

¡Suerte!

Explotando vulnerabilidades en teléfonos autenticados: Yealink

24 Abr

Actualización 30/julio/2013: Podemos confimar que al usar el firmware más reciente en este momento (9.70.0.140) la funcionalidad de marcación sin autenticación que provocaba este problema de seguridad viene desactivado, y es necesario configurar el teléfono con la IP autorizada que podrá hacer uso del API, por lo que este problema ya no existe. Sin embargo, nunca está de más asegurar su red y cambiar las contraseñas default del teléfono para impedir cualquier acceso no autorizado.

Yealink T20P: teléfono básico

Hace unos días recibí una llamada de uno de mis clientes. La historia comienza con una de las frases que menos me gusta escuchar en mi medio:

– Christian, ¿puedes venir? Nos hackearon el conmutador de la oficina…

Acudí en menos de una hora al sitio (yo no tenía acceso remoto y ni siquiera tenía conocimiento de este equipo) y me dí a la labor de revisar los logs para tratar de reconstruir el caso. Sin embargo, me encontré con lo siguiente:

  • El equipo tenía servicios de iptables y fail2ban protegiéndolo
  • Las contraseñas de SIP eran seguras
  • No se recibían conexiones ni por SIP ni por HTTPS del exterior
  • Todas las llamadas habían sido originadas desde una extensión
  • Apache no tenía registros de IPs externas, tampoco Asterisk.

Todo parecía indicar que hubiera sido un inside job, y en efecto (al menos parcialmente), así fue.

Por más que busqué no encontré señales de como había logrado entrar, pero las llamadas estaban en el CDR y en el gateway SIP que terminaba la comunicación. ¿Qué ocurrió entonces?

De pronto, el empleado al que pertenece el teléfono cuya cuenta SIP ocasionó todas las llamadas, exclamó lo siguiente:

– Mi teléfono ha estado raro. Varias veces en la mañana estuvo «marcando solo» y yo solamente escuchaba una grabación a veces de que la llamada no había podido ser completada

Momento… ¿marcando solo? ¿Desde cuando los teléfonos se marcan solos? Se trataba de un Yealink T20, el cual es un modelo extremadamente sencillo y económico. ¿Qué funcionalidad podría tener que hiciera que marcara solo?

La respuesta es: los Yealink ofrecen la posibilidad de marcación automática a través de una simple y sencilla petición HTTP que requiere autenticación, pero si nunca cambian la contraseña de usuario y administrador del teléfono (lo cual casi nadie hace), cualquiera puede hacer que el teléfono marque solo hacia cualquier destino.

Si tienen un teléfono Yealink consigo (cualquier modelo), prueben hacer esto en su casa/oficina:

Supongamos que la IP de nuestro Yealink sea 192.168.1.101. Asumimos que en nuestro Asterisk existe un plan de marcación que nos permite marcar larga distancia. Imaginemos el número 018881234567. Ahora bien, abran el siguiente URL en su navegador favorito (recuerden cambiar los valores según corresponda):

http://user:user@192.168.1.101/cgi-bin/ConfigManApp.com?Id=34&Command=1&Number=018881234567&Account=0

¿Y qué ocurre? Simple y sencillamente, su teléfono marcará por ustedes hacia el número indicado usando la primer cuenta que tengan configurado en él. Si Asterisk no los autentica a nivel de usuario, ustedes tienen un severo problema de seguridad ya que cualquier persona podría manipular su teléfono para marcar hacia donde le viniera en gana.

Y bien, ¿qué pasa si abren el URL repetidas ocasiones? Fácil. El teléfono marcará una y otra vez a ese número sin colgar las otras llamadas. De manera que un solo teléfono podría hacer 100 llamadas a Afghanistan, Sierra Leona o cualquier otro destino caro del mundo. Esto es muy fácil de lograr con un script en Linux que invoque al wget. Lo demostré en laboratorio y creanme, los resultados asustan.

Imaginen por un momento que alguien tuviera acceso a su red interna, pero no conoce las contraseñas de los teléfonos. Con este truco no es necesario saberlas, ya que el teléfono se encuentra ya autenticado en su red interna y por lo tanto, las llamadas saldrán aún si ustedes confían en que su firewall no recibirá conexiones del exterior.

Por tal motivo, si ustedes deciden abrir erróneamente los puertos en su firewall y exponen la configuración del teléfono, le están abriendo la puerta a alguien a que haga cientos de llamadas sin autorización. En la historia que les acabo de contar, alguien aprovechó esta vulnerabilidad e hizo más de 40,000 minutos de llamadas a los destinos más caros del mundo en tan solo 12 horas, y sin tener que usar su ancho de banda para generar esas llamadas.

Piénsenlo muy bien antes de que expongan equipos al internet. Hay un mundo peligroso allá afuera, y si no se protegen, más temprano que tarde acabarán siendo víctimas de la cyber delincuencia.

¡Suerte!

La importancia de una línea de código: como hacer debug a tu configuración de Asterisk

20 Mar

El fin de semana por la noche recibí una llamada de un cliente nuestro solicitando apoyo para revisar el estado de su E1. Al parecer habían estado con el servicio de telefonía caido todo ese día, y tras horas de conferencia con su carrier no habían podido encontrar la razón por la cual el servicio del E1 no levantaba. Asterisk podía hacer llamadas entre extensiones, pero no tenían comunicación con el exterior.

Por experiencia, mi primer acercamiento fue revisar el archivo chan_dahdi.conf, que es el responsable del E1. Lo abrí pero no noté nada fuera de lo normal, así que desde la consola de Asterisk procedí a descargarlo de memoria y cargarlo nuevamente, esperando que arrojara algo de información. El resultado fue algo como lo siguiente:

server1*CLI> module load chan_dahdi.so
[Mar 20 02:03:52]   == Registered application 'DAHDISendKeypadFacility'
[Mar 20 02:03:52]   == Registered application 'ZapSendKeypadFacility'
[Mar 20 02:03:52]   == Parsing '/etc/asterisk/chan_dahdi.conf': [Mar 20 02:03:52] Found
[Mar 20 02:03:52] WARNING[9583]: config.c:778 process_text_line: parse error: No category context for line 6 of /etc/asterisk/chan_dahdi.conf
[Mar 20 02:03:52] ERROR[9583]: chan_dahdi.c:12728 setup_dahdi: Unable to load chan_dahdi.conf
[Mar 20 02:03:52]   == Registered channel type 'DAHDI' (DAHDI Telephony Driver w/PRI)
[Mar 20 02:03:52]   == Manager registered action DAHDITransfer
[Mar 20 02:03:52]   == Manager registered action ZapTransfer
[Mar 20 02:03:52]   == Manager registered action DAHDIHangup
[Mar 20 02:03:52]   == Manager registered action ZapHangup
[Mar 20 02:03:52]   == Manager registered action DAHDIDialOffHook
[Mar 20 02:03:52]   == Manager registered action ZapDialOffHook
[Mar 20 02:03:52]   == Manager registered action DAHDIDNDon
[Mar 20 02:03:52]   == Manager registered action ZapDNDon
[Mar 20 02:03:52]   == Manager registered action DAHDIDNDoff
[Mar 20 02:03:52]   == Manager registered action ZapDNDoff
[Mar 20 02:03:52]   == Manager registered action DAHDIShowChannels
[Mar 20 02:03:52]   == Manager registered action ZapShowChannels
[Mar 20 02:03:52]   == Manager registered action DAHDIRestart
[Mar 20 02:03:52]   == Manager registered action ZapRestart
[Mar 20 02:03:52]  Loaded chan_dahdi.so => (DAHDI Telephony w/PRI)

De aquí lo que importa es la línea que nos da el error:

[Mar 20 02:03:52] WARNING[9583]: config.c:778 process_text_line: parse error: No category context for line 6 of /etc/asterisk/chan_dahdi.conf

Tras abrir el archivo chan_dahdi.conf nuevamente y prestar un poco más de atención, las primeras líneas indican lo siguiente:

;autogenerated by /usr/sbin/wancfg_dahdi do not hand edit
;autogenrated on 2011-10-11
;Dahdi Channels Configurations
;For detailed Dahdi options, view /etc/asterisk/chan_dahdi.conf.bak

language=es

[trunkgroups]

[channels]
context=default
usecallerid=yes
hidecallerid=no
callwaiting=yes
usecallingpres=yes
callwaitingcallerid=yes

Y aquí es donde tras poner atención, notamos que el error proviene de una sola línea de código, el language=es está fuera de cualquier contexto, y esto provoca un error de parsing al momento de cargar el módulo, lo que impide que el canal se cargue correctamente y por lo tanto, el E1 nunca levante.

Entonces, ¿Cuales son los pasos para hacer un debug correcto de la configuración de Asterisk?

Los sistemas informáticos, a diferencia de los seres vivos, no cambian por si solos. Si nuestro sistema estaba bien de principio y de pronto algo dejó de funcionar es porque algo cambió. Una manera sencilla de ver los archivos de configuración en el orden en que fueron recientemente modificados es usar el comando ls:

ls -lSt /etc/asterisk | head -n 20

Con este comando ordenaremos los archivos de configuración de más reciente a menos reciente, mostrando solo los últimos 20 modificados. De ahí, podemos ir retrocediendo en nuestros pasos hasta que demos con la línea de código que alteramos y el sistema se restituya tras recargar el módulo o reiniciar Asterisk.

Si tenemos localizado el archivo con el problema, pero no sabemos exactamente en que línea está, el CLI de Asterisk puede resultar muy útil. Solo debemos asegurarnos que el log de eventos se arroja a consola editando el archivo /etc/asterisk/logger.conf

#/etc/asterisk/logger.conf
[general]

[logfiles]
console => warning,error,notice,debug
full => notice,warning,error,verbose

Como se aprecia en el archivo, estamos diciéndole a Asterisk que envie a consola toda la información relacionada con eventos warning, error, notice y debug (nota: el debug arroja MUCHA información, si hemos resuelto el problema lo recomendable es retirarlo del archivo hasta la siguiente vez que lo ocupemos). Recuerden que después de modificarlo deben recargar el logger dentro del Asterisk CLI

*CLI> logger reload

Y por último pueden descargar/cargar el módulo que da problemas en memoria. Este es un ejemplo del módulo de SIP:

amx*CLI> module unload chan_sip.so
Unloaded chan_sip.so
== Unregistered channel type 'SIP'
== Unregistered custom function SIPCHANINFO
== Unregistered custom function SIPPEER
== Unregistered custom function SIP_HEADER
== Unregistered custom function CHECKSIPDOMAIN
== Unregistered application 'SIPDtmfMode'
== Unregistered application 'SIPAddHeader'
== Unregistered application 'SIPRemoveHeader'
== Unregistered RTP glue 'SIP'
== Manager unregistered action SIPpeers
== Manager unregistered action SIPshowpeer
== Manager unregistered action SIPqualifypeer
== Manager unregistered action SIPshowregistry
== Manager unregistered action SIPnotify
amx*CLI> module load chan_sip.so
Loaded chan_sip.so
SIP channel loading...
== Parsing '/etc/asterisk/sip.conf': == Found
== Parsing '/etc/asterisk/sip_general_additional.conf': == Found
== Parsing '/etc/asterisk/sip_general_custom.conf': == Found
== Parsing '/etc/asterisk/sip_nat.conf': == Found
== Parsing '/etc/asterisk/sip_registrations_custom.conf': == Found
== Parsing '/etc/asterisk/sip_registrations.conf': == Found
== Parsing '/etc/asterisk/sip_custom.conf': == Found
== Parsing '/etc/asterisk/sip_additional.conf': == Found
== Parsing '/etc/asterisk/sip_custom_post.conf': == Found
== Parsing '/etc/asterisk/users.conf': == Found
[2012-03-20 01:48:54] WARNING[4896]: chan_sip.c:28479 reload_config: No valid transports available, falling back to 'udp
'.
== SIP Listening on 0.0.0.0:5060
== Using SIP TOS bits 96
== Using SIP CoS mark 4

En este otro ejemplo puede notarse como el módulo SIP arroja un WARNING. Eso es un típico caso de que algo en mi configuración no está 100% bien, por lo que conviene revisarlo.

Este paso de quitar/cargar el módulo en memoria resulta muy adecuado porque la información que arroja ese módulo no se pierde entre toda la demás al momento de hacer un reload. Fíjense en los detalles y pregúntense que quiso decir el CLI cuando les dió un warning o error. Los mensajes suelen ser bastante explícitos, solo depende de ustedes interpretarlos.

¡Suerte!

Modelo de seguridad en Asterisk (parte 3 de 3)

8 Mar

Fuente: http://static.internetblog.org.uk/files/manjail.jpg


Llegamos al final de nuestras entregas discutiendo el modelo de seguridad de Asterisk. En la primera parte discutimos sobre la seguridad antes de llegar al conmutador, normalmente a cargo del firewall de nuestro acceso a internet. En la segunda partehablamos sobre como autenticar a los usuarios para permitirles acceder a nuestro sistema. En esta tercera entrega hablaremos sobre como limitar las características de los usuarios que ya se encuentran autenticados dentro de Asterisk.

Seguridad de operación

Existen errores en versiones anteriores de algunas interfases gráficas (léase: Elastix) que nos permitían leer la lista completa de extensiones del conmutador y sus contraseñas aún si el usuario no pasaba la autenticación de administrador. Esto quiere decir que a pesar de cerrar nuestra interfaz administrativa y que nadie pueda modificarla, al tener los usuario/contraseñas podría tomar un teléfono, registrarlo con estos datos y empezar a hacer llamadas. Peor aún: podría vender estos datos para que algún tercero haga llamadas ilegalmente desde nuestro equipo. Asumiendo que ya cometimos los errores de las otras 2 etapas, ¿cómo podemos evitar (o al menos reducir) el daño inminente?

El primer paso, es limitar los accesos de las extensiones de acuerdo a lo que deban hacer. Por ejemplo, es probable que la recepcionista necesite poder llamara a locales, LD y celulares. Sin embargo, ¿por qué la extensión que está en la cafetería tendría la necesidad de marcar hacia afuera? Limitar esto es muy sencillo haciendo uso de contextos:

[codesyntax lang=»bash» title=»extensions.conf»]

[internas]
exten => _XXXX,1,Dial(SIP/${EXTEN})

[locales]
include => internas
exten => _ZXXXXXXX,1,Dial(DAHDI/g0/${EXTEN})

[largadistancia]
include => locales
exten => _01NXXXXXXXXX,1,Dial(DAHDI/g0/${EXTEN})

[/codesyntax]

En este ejemplo, tenemos 3 contextos: [internas], [locales] y [largadistancia]. Cada uno incluye al anterior y además, agrega un grado más de permisos. La idea es que al configurar cada usuario SIP/IAX de nuestro sistema, limitemos los accesos que cada uno tenga, sabiendo que cada uno solo puede marcar estrictamente a lo que nosotros le permitimos, además de tener la facilidad de que al conceder un permiso superior, daremos acceso a lo anterior.

Es altamente recomendable que si no hacemos llamadas internacionales, entonces… ¡no las habilitemos! Si sabemos que nuestros negocios se centran en territorio nacional y quizá llamadas a EUA/Canadá, limitemos agregando el _001NXXXXXXXXX, pero no agreguemos algo tan general como permitir _00., que estaríamos dándole la oportunidad al atacante de que use el mundo entero. Recuerden que limitar las posibilidades improbables reduce el probable riesgo.

Una manera mucho más elegante sería hacer uso de Realtime para que al marcar, se consulte la BD para determinar si tenemos permisos de marcar a ese destino o no, y en base a eso reaccionar. Dado que Realtime es un poco más avanzado, lo veremos más adelante en otro artículo.

El segundo paso consistiría en poner limitantes no al teléfono sino a la persona. La manera de hacer esto sería obligar a quien marca a proporcionarnos un código que le autorice a marcar a ese destino. Si alguien puede marcar por nuestro sistema, al menos obliguemoslo a que se sepa las contraseñas de los usuarios. Usando el mismo ejemplo anterior, lo podríamos hacer así:

[codesyntax lang=»php» title=»extensions.conf»]

[internas]
exten => _XXXX,1,Dial(SIP/${EXTEN})

[locales]
include => internas
exten => _ZXXXXXXX,1,Macro(salida,DAHDI/g0/${EXTEN})

[largadistancia]
include => locales
exten => _01NXXXXXXXXX,1,Macro(salida,DAHDI/g0/${EXTEN})

[macro-salida]
exten => s,1,Authenticate(/etc/asterisk/pinset)
exten => s,n,Dial(${ARG1} )
exten => s,n,Hangup

[/codesyntax]

En el ejemplo de arriba estamos introduciendo un nuevo elemento, un macro que nos permitirá hacer 2 pasos en uno solo: la autenticación y luego la marcación. De acuerdo al ejemplo, cualquiera podria marcar extensiones locales sin restriccion (al final de cuentas, son gratis). Sin embargo, si trata de marcar a llamadas locales o larga distancia se le pedirá al usuario que ingrese un código (el cual estaría escrito dentro del archivo /etc/asterisk/pinset). Si el usuario no proporciona la contraseña correcta, la llamada termina.

Los 2 esquemas que hemos mencionado (contextos y contraseñas) deberían impedir que algo malo pase. Sin embargo, si en el peor de los casos alguien logra penetrar todo lo anterior, limitemos la cantidad de daño recibido. ¿Cómo? Limitando la cantidad de llamadas simultáneas que puede hacer. Este paso es sumamente importante ya que, para empezar, nadie tiene por que poder hacer 20 llamadas simultáneas, ¿o si?

Para hacer esto, reaprovechemos el ejemplo anterior:

[codesyntax lang=»php» title=»extensions.conf»]

[internas]
exten => _XXXX,1,Dial(SIP/${EXTEN})

[locales]
include => internas
exten => _ZXXXXXXX,1,Macro(salida,DAHDI/g0/${EXTEN},2)

[largadistancia]
include => locales
exten => _01NXXXXXXXXX,1,Macro(salida,DAHDI/g0/${EXTEN},1)

[macro-salida]
exten => s,1,GotoIf($[${GROUP_COUNT(${CALLERID(num)})}>=${ARG2}]?Permite)
exten => s,n,Congestion()
exten => s,n(Permite),Set(GROUP(${CDR(uniqueid)})=${CALLERID(num)})
exten => s,n,Authenticate(/etc/asterisk/pinset)

exten => s,n,Dial(${ARG1} )
exten => s,n,Hangup

[/codesyntax]

Notarán que el macro se ha hecho bastante más complejo. Hay una buena razón para esto:

Hemos agregado al Macro la posibilidad de determinar cuantas llamadas simultáneas activas tiene un usuario en un momento dado, y si se excede de esta cantidad, corta la llamada.

Observen esta línea:

[codesyntax lang=»php»]

exten => _ZXXXXXXX,1,Macro(salida,DAHDI/g0/${EXTEN},2)

[/codesyntax]

El 2 que está al final de la línea es la cantidad máxima de llamadas a ese tipo de destino que estamos permitiendo. En el ejemplo anterior, permitimos que alguien marque hasta 2 llamadas locales al mismo tiempo, pero solo puede marcar a una LD. No sería muy difícil seguir este patrón para limitar el acceso internacional, pero eso se los dejo a ustedes para que practiquen.

 

Conclusiones

Si sumamos todas las barreras que hemos puesto con estos 3 niveles de seguridad, al final obtenemos:

  • Cerrar el acceso por firewall externo a nuestro conmutador
  • Detener el acceso al conmutador por firewall interno (iptables)
  • Acortar el rango de IPs desde las que pueden registrarse los usuarios SIP/IAX
  • Bloquear a aquellos usuarios que intenten fuerza bruta contra nosotros
  • Activar solo el plan de llamadas  necesario
  • Restringir  al usuario dependiendo de si sabe la contraseña correcta para el destino o no
  • Reducir la cantidad de llamadas simultáneas que el usuario puede hacer

Lo mejor de estas reglas es que son acumulables. Mientras más de ellas usemos lograremos un conmutador más y más seguro. Inclusive si consideramos que llevar a cabo todas resulta difícil, aplicar tantas como se pueda nos garantizará que estaremos restringiendo la posibilidad de que algo salga mal.

Créanme: vale más invertir tiempo en tomar en cuenta estos pasos en lugar de tener que pagar la cuenta final.

¡Suerte!

Evaluación del Grandstream GXV3175

7 Mar

El día de ayer recibimos un producto que había querido evaluar desde hace algunos días, y se trata del teléfono estrella de la gama alta de teléfonos que promueve Grandstream: el GXV3175 que ofrece soporte para videollamadas y una amplia pantalla touchscreen.

El teléfono aún en su caja

La primera impresión tras recibir la caja es que se trata de un producto orientado no al profesional, sino al consumidor. Las descripciones, imágenes e inclusive el tipo de empaque deja en claro que lo que el teléfono promueve son toda la gama de funcionalidades extras de un teléfono que está orientado al mercado de alto nivel adquisitivo.

El precio de venta público de este teléfono en México es elevado, siendo de alrededor de $480 USD + IVA (unos $6,240 pesos mexicanos). Por un precio así, lo que uno está esperando es prácticamente todo: video, audio, alta calidad de fabricación, funcionalidades extra, expandibilidad, aplicaciones y cualquier medio de interconexión que pueda haber. Por tal motivo, haremos mención de los pros y los contras que $480 USD te pueden comprar.

 

Contenidos

El teléfono trae consigo todos los componentes necesarios para funcionar out-of-the-box, que son:

Contenido de la caja

  • Auricular
  • Cable de red
  • Eliminador de corriente (12 V)
  • Base de escritorio
  • Soporte para pared
  • Cable de A/V para conectarlo a una televisión
  • Manuales
  • Toalla de limpieza
El teléfono soporta PoE, por lo que tener un eliminador de corriente es un buen extra aunque claro está, para el precio debería traer su propio eliminador. Los cables de A/V también son un plus al no tener que adquirirlos como un extra.

 

Fabricación

El GXV3175 está hecho totalmente de plástico, salvo el espacio de la pantalla LCD que actúa como touchscreen. Debo ser honesto: el plástico con el que está hecho la unidad es un plástico negro mate que se siente ligeramente poroso, casi como si fuera pasta. Este sentimiento al tacto es compartido por los otros teléfonos de gama inferior de Grandstream, por lo que en esta ocasión esperábamos que fuera un poco diferente. Buscábamos sentir un material de mayor calidad para un teléfono de este precio. (nota: no pensamos someter la unidad a pruebas de resistencia física, por lo que la sensación de tener un material barato es solo nuestra percepción, no indicamos que el proceso de manufactura sea, efectivamente, malo)

La base del teléfono se siente pesada, sinónimo inequívoco de toda la circuitería que se necesita para darle vida a la pantalla LCD (la cual se lleva todo el show). Al ser totalmente touchscreen el teléfono no posee botones físicos, y cuenta con un único botón de «Home» situado en la parte inferior central de la base, justo debajo del LCD. La forma y diseño de este botón no hacen sino hacernos sentir que es un diseño copiado del iPhone/iPad de Apple.

El auricular, por otro lado, es bastante ligero. Carece del peso que muchas personas buscan al momento de comprar un teléfono de gama alta. Dado que es la única parte física del teléfono que puede sostenerse (no hay botones, solo superficie touch), nos deja con la sensación de que algo le faltó al aparato, algo que nos hiciera sentir que al menos compramos su peso.

Un punto a favor del teléfono son los puertos de expansión. En uno de los costados ofrece posibilidad de conectar 2 USBs, 1 tarjeta SD, 1 puerto para audífonos/manos libres (jack 2.5 mm) y 1 puerto para A/V (para poder proyectar hacia la televisión).

Puertos de expansión

En la parte posterior el teléfono cuenta con lo habitual: 2 puertos de red (hacia el ruteador y como puente hacia la PC) y el puerto del handset.

Parte trasera del teléfono

Dependiendo de donde se coloque la base, el teléfono ofrece dos niveles de altura, lo que permite ajustar el ángulo de la pantalla para mayor comodidad.

Dado que la pantalla es una touch screen resistiva, el teléfono viene con un stylus (que se almacena dentro de la unidad en la esquina superior derecha, viéndolo de frente)  que nos hace sentir de vuelta en los tiempos de la Palm. Si bien no es necesaria en la mayoría de los casos, acceder a ciertos botones en algunos momentos resulta más cómoda con la pluma. Sin embargo, tener que usar un aditamento adicional para utilizar nuestro teléfono no es lo más cómodo del mundo.

Por último, en la parte frontal superior el teléfono cuenta con un pequeño switch que nos permite ajustar el ángulo de la video cámara integrada al teléfono.

 

Características

La más obvia de todas es la pantalla LCD de 800×480, la cual actua como teclado y es el único medio para introducir información al teléfono sin usar la interfaz web. La pantalla viene de la mano de la cámara de video integrada, la cual es configurable tanto en codecs como en resolución y FPS que deseamos enviar. Los puertos de expansión ya mencionados le permiten conectar un manos libres tipo celular, por lo que aquellas diademas con conector RJ9 quedan fuera de consideración.

El teléfono soporta Wifi (802.11b/g/n) lo cual es una buena característica, pero que se anula inmediatamente si queremos hacer uso del PoE (¿qué sentido conectar por WiFi si necesitamos un cable de red para la corriente?). Otro punto en contra es que el teléfono carece de Bluetooth, por lo que no es posible hacer pairing de tu manos libres BT como otros teléfonos de gama alta (tales como el Aastra 6739i o el Cisco SPA525G).

Otra característica importante y que hasta el momento solo he visto en los teléfonos Yealink es el soporte para Open VPN. Para quien no lo sabe, OpenVPN es una solución gratuita en software que te permite crear VPNs en capa SSL. La gran ventaja de hacer esto en un teléfono, es que puedes encriptar el tráfico VoIP (tanto el SIP como el RTP) y con eso tener comunicación segura por todo el medio de la VPN. Otra ventaja es que al encriptar el tráfico, es imposible para los ruteadores intermedios saber que contiene, así que contra aquellos proveedores de internet que bloquean el tráfico VoIP, esta funcionalidad puede ser muy útil.

El punto fuerte del teléfono son las aplicaciones: es casi como si tuviéramos una tablet con handset integrado. La gama de servicios de redes sociales o consultas web es relativamente amplia, y superior a las que vienen de fábrica con otros teléfonos. Una aplicación muy importante que echamos de menos y que otros teléfonos de Grandstream tienen, es la integración con Skype. Si este teléfono pudiera hacer uso de esa red y enviar video a través de ella, tendríamos definitivamente un ganador aquí. Es una sorpresa que teléfonos inferiores tengan esta característica mientras que este no.

Uso del sistema

Al conectar el teléfono al PoE inmediatamente este arrancará con la pantalla de bienvenida de Grandstream y empezará a cargar su sistema. A nuestro parecer el re-arranque del teléfono es bastante lento (2 minutos aproximadamente), pero en parte resulta entendible porque la interfaz gráfica no es tan sencilla. Tras encender el teléfono por primera vez nos guiará por un wizard de configuración de primera ocasión, con lo que podremos guiar al teléfono para configurar la hora por NTP y configurar también nuestra primer cuenta SIP.

Configuración inicial de la primer cuenta SIP

Tras configurar la primer cuenta, el teléfono cargará y estará listo para hacer llamadas.

El GUI del teléfono está bastante bien hecho. En apariencia se asemeja a una interfaz modificada de Android 3.0 (para tablets), ya que ofrece la posibilidad de colocar widgets, tener múltiples escritorios para guardar y desplegar información en ellos y claro está, acceder a aplicaciones como Facebook, Twitter, Google Voice, feeds RSS y hasta Youtube. Con todas estas características se nos puede olvidar que el teléfono también hace llamadas.

La interfaz aunque se asemeja  a otras, tiene su estilo propio. Para empezar a hacer una llamada tienes una de dos opciones: presionar el botón de «Phone» en la parte inferior derecha o presionar el widget que contiene el nombre de la cuenta que configuraste. Tener que presionar algo antes de empezar a marcar resulta un tanto frustrante, pero es un sacrificio necesario para poder aprovechar la pantalla LCD para desplegar información de otros temas mientras que el teléfono no se está usando.

El sistema posee varias aplicaciones instaladas (en este momento desconozco si es posible agregarle más). Entre las que están disponibles vienen la integración con Google Calendar, Google Voice, Twitter, Facebook, feeds RSS, tipos de cambio, indicadores de la bolsa de valores, clima y algunas otras. Aunque al principio parecen muy llamativas, interactuar con muchas de ellas resulta complicado por el teclado de la pantalla touchscreen. Es bueno para ingresar texto corto, pero a veces hasta escribir un pequeño tweet de 140 caracteres resulta complicado usando el teléfono.

La estabilidad del sistema diría que está a un 80%. La respuesta de ingreso de órdenes del usuario no es inmediata (se siente a veces un tanto lenta la interfaz) y en ocasiones, el sistema se congeló al acceder a la aplicación de FB (la pantalla literalmente se congeló, aunque fue posible reiniciar el teléfono desde la interfaz web)

 

Configuración del teléfono

Como ya es costumbre, la configuración principal se hace mediante una interfaz web, la cual debo agregar esta muy por encima de las anteriores interfaces de Grandstream.

Podemos configurar hasta 3 cuentas SIP diferentes (algo bajo para este tipo de teléfonos), y en cada cuenta podemos ajustar parámetros individuales como codecs, ringtones, direcciones de proxy y otras. Aparte de las 3 cuentas podemos configurar detalles de las aplicaciones individuales, además de poder hacer uso de la red por WiFi (algo inútil a mi gusto si es que queremos aprovechar el PoE).

Todo cambio requiere de un reinicio del teléfono para poder aplicarlo, aunque al menos tienes la opción de decidir en que momento quieres reiniciar (no es tan severo como Polycom). Dado el largo tiempo de carga del teléfono (2+ minutos), es preferible hacer todos los cambios de una vez antes de enviar reiniciar el equipo.

Casi todas las opciones del teléfono son configurables mediante el GUI del touchscreen, pero ingresar valores en el teclado virtual no es tan sencillo como se cree. Hay que recordar que la pantalla es resistiva, por lo que es necesario hacer cierta presión al momento de teclear algo, además de que los sensores no son tan exactos como los de una pantalla capacitiva (como la de la mayoría de los celulares con touchscreen).

 

Operación

Dado que el estado estándar del teléfono es mostrar los widgets del escritorio, necesitas presionar el botón de phone antes de que puedas hacer una llamada. Dentro del panel de marcación debes escoger que línea (cuenta SIP) quieres usar, además de que al momento de enviar la marcación debes decir si es una llamada con o sin video (aunque puedes solicitar el video estando ya a mitad de la llamada).

La interacción con el teléfono puede requerir un poco de paciencia. Al no tener botones físicos debemos esperar a que el sistema procese nuestros comandos por touchscreen. Si a esto le agregamos errores de detección, tenemos un sistema que aunque muy bonito, nos obliga a ir lento para que detecte correctamente lo que estamos tratando de decirle.

La calidad del video es buena, pero sin llegar a lo expectacular. Quizá el mayor problema sea el tipo de pantalla, ya que al ser resistiva necesita no tener un recubrimiento de vidrio, lo cual le habría dado mejor apariencia a la pantalla y por consecuente, una mejor apreciación del video.

El manos libres (speaker) se escucha bastante bien, aunque la cancelación de ruido del teléfono es, para lo que cuesta, pobre. En nuestras pruebas el altavoz de un Yealink T38G resultó muy superior en términos de no retroalimentar el audio nuevamente por el micrófono, de manera que este teléfono se escucha muy bien, pero a quien le llamemos por el manos libres no opinará lo mismo.

 

Conclusiones

El GXV3175 es un buen teléfono, pero no para su precio. Por $480 USD esperamos lo mejor de lo mejor, y aunque la idea de las aplicaciones en el teléfono y el tamaño de la pantalla son puntos muy buenos de entrada, la operabilidad con la interfaz gráfica deja mucho que desear. La falta de Skype y Bluetooth con características básicas para este rango, y nos resulta inadmisible que Grandstream (teniendo ya teléfonos con soporte de Skype), decida dejar este fuera del juego. Esperemos y esto se corrija con una actualización del firmware futura, pero por este momento, no tenemos el soporte para el mismo.

La fabricación definitivamente no está al nivel de la de teléfonos como Cisco o Polycom e inclusive, nos atrevemos a decir que está aún por debajo de la de Yealink. El hecho de tener siquiera que incluir un stylus nos hace pensar que el fabricante pensó en posibles problemas con el touchscreen y decidió incorporarlo. Parece una solución rápida a un problema inevitable, pero prefirieron optar por ese camino.

Al final, el teléfono se siente como una tablet más que como un teléfono. Su potencial de aplicaciones es muy bueno, pero la a veces lentitud de respuesta puede desesperar al momento de hacer cualquier otra cosa que no sean llamadas. Creo que el procesador les quedó corto para lo que al final desearon que hiciera.

Definitivamente, este es un teléfono orientado para el entusiaste, más alla que para el alto ejecutivo. Características más conservadoras (pero mayor calidad) de otros fabricantes serán preferidas por encima de este equipo. La participación de Grandstream en el alto mercado es buena, pero se quedó a varios metros de hacer un home run con este producto. Esperamos que con el continuo avance al firmware que ha puesto la compañía en los últimos años, logren pulir los detalles que este teléfono tiene, para así acercarlo un paso más a la gloria.

Esta es la primera de varias futuras reseñas que planeamos publicar en nuestro blog. La idea es ofrecerle a nuestros visitantes una percepción objetiva de los equipos que evaluamos para ayudarlos a saber si el producto cumple con sus expectativas antes de comprar. Como siempre, los invitamos a compartir sus opiniones dejándonos comentarios al término del artículo

Modelo de seguridad en Asterisk (parte 2 de 3)

6 Mar

El día de ayer publicamos la primera de esta serie de entregas que buscan concientizar sobre los 3 diferentes niveldes de seguridad en un conmutador IP como lo es Asterisk. Discutimos sobre la seguridad de acceso al sistema, que es la primer barrera contra la quenos anfrentamos al acceder al equipo. Para esta entrega hablaremos del segundo nivel de seguridad, es decir: los atacantes ya pueden llegar hasta el equipo, ¿cómo podemos defendernos de lo que nos pueden hacer?

Seguridad de autenticación

Como mencioné en el párrafo anterior, esta es la segunda capa de protección contra atacantes externos: ya penetraron nuestra red, ya pueden «ver» nuestro conmutador. ¿Quiere eso decir que estamos a su merced? Obviamente no, pero debemos tener algunos aspectos muy importantes en cuenta para que esto no nos pase. De entre los puntos a mencionar, resaltemos estos:

  • Listas de acceso para usuarios SIP/IAX
  • Contraseñas SIP/IAX seguras
  • Defensa contra fuerza bruta

Listas de acceso

Esta es, sin duda, la característica mas evitada en seguridad de Asterisk: configurar listas de acceso que hagan una coincidencia con los dispositivos que deben/pueden registrarse en nuestro sistema, limitando el acceso a ciertas extensiones desde ciertas IPs.

Por ejemplo: si nuestra red interna está en el segmento 192.168.1.0/24, ¿por qué razón habríamos de permitir que la extensión que pertenece a la sala de juntas se registre desde la IP 189.200.45.13? Las listas de acceso nos permiten restringir desde que IP puede un dispositivo registrarse o hacer llamadas con nosotros. Esta es la única manera que tienen de hacer que solo ciertas extensiones puedan ser usadas desde afuera de nuestra red (usuarios móviles), mientras que el resto no (usuarios locales)

Las listas de acceso en Asterisk se configuran usando los campos de permit y deny dentro ya sea de la sección [general] o bien dentro de la configuración de cada usuario (esto aplica para sip.conf y para iax.conf). Tomen en cuenta que el orden si importa y que la metodología default es un permit any. Esto quiere decir que si no negamos la autenticación, se le permite el paso a todo. Observen el siguiente ejemplo:

[codesyntax lang=»ini»]

[100]
username=100
type=friend
context=default
secret=aBcDeF12345!
deny=0.0.0.0/0.0.0.0
permit=192.168.1.1/255.255.255.0

[/codesyntax]

 

En este ejemplo, la regla de deny=0.0.0.0/0.0.0.0 está negando el paso a todo, ya continuación el permit=192.168.1.1/255.255.255.0 está permitiendo el paso solamente a aquellos dispositivos que se encuentren dentro de la red 192.168.1.x. Tengan mucho cuidado ya que si invertimos el orden de declaración:

[codesyntax lang=»ini»]

[100]
username=100
type=friend
context=default
secret=aBcDeF12345!
permit=192.168.1.1/255.255.255.0
deny=0.0.0.0/0.0.0.0
[/codesyntax]

Al final, el deny (que es lo último declarado) prevalecerá, y dado que 0.0.0.0/0.0.0.0 hace match con todo, estamos negando el paso a todos (haciendo que la extensión no sirva).

También pueden usar la notación CIDR, por lo que pueden declarar un rango de red como 192.168.1.1/24 y es igual que 192.168.1.1/255.255.255.0.

Recuerden que al declarar el permit/deny dentro de [general] están habilitando esa regla para todos, pero si solo colocan reglas de permit individuales dentro de cada usuario, abrirán ese usuario solamente. Esta es la única manera que tendrán de permitir el acceso remoto a usuarios SIP/IAX específicos, negando la posibilidad a todos los demás. Esto resulta muy conveniente porque no exponen todas sus extensiones, sino solo las estrictamente necesarias.

Al tener que descuidar y permitir el paso a ciertos usuarios, deben asegurarse de que las contraseñas de aquellos usuarios a los que les permiten acceder desde el exterior son suficientemente seguras, y de ahí viene el siguiente punto.

 

Contraseñas SIP/IAX seguras

Un motivo que muchos administradores tienen para dejar contraseñas inseguras es por facilitarse la labor al momento de configurar sus dispositivos SIP. Lo que muchas personas desconocen es que las contraseñas SIP/IAX se hicieron para tener que teclearlas una única vez, y esto es cuando configuramos el dispositivo (de hecho, si hacemos la configuración por provisionamiento TFTP nunca tendremos que teclearlas, pero ese es material para otro artículo). Si la contraseña solo deble escribirse o copiarse una única vez, entonces no existe razón para aprovechar y echarle un poco más de tiempo en usar contraseñas que sean tan seguras que un sistema de fuerza bruta no pueda romper.

Existen muchos mecanismos sencillos para generar contraseñas aleatorias. Quizá uno disponible que cualquier sistema con Linux tendría (con el paquete de openssl instalado):

[codesyntax lang=»bash» title=»Desde el Linux CLI:»]

# Esto generará 20 contraseñas aleatorias de 12 caracteres
for i in {1..20}; do openssl rand -base64 12; done

[/codesyntax]

Podemos fácilmente cambiar el 20 por cualquier otro número y generar un pool de contraseñas aleatorias que podemos ocupar para nuestras extensiones, asegurándonos con esto de que nuestras contraseñas sean totalmente seguras.

También tomemos en cuenta peores casos: si no colocamos una contraseña en una cuenta IAX estaremos abriendo la posibilidad de que cualquier entidad que llegue a nuestro equipo aún y si no proporciona contraseña sea autenticado inmediatamente. Esto es por la propiedad de IAX que se basa totalmente en la contraseña para realizar la autenticación de un dispositivo. Si no llenamos este campo, cualquiera se podrá autenticar como tal, aún y sin proporcionar ningún dato.

El hecho de tener contraseñas seguras impedirá que los atacantes entren a nuestro sistema. Sin embargo, no impedirá que lo intenten. Aquí está la última parte de este rompecabezas:

 

Defensa contra fuerza bruta

Es un hecho: si nuestro equipo debe estar expuesto porque nuestros usuarios así lo requieren, entonces tarde o temprano será atacado. El ataque puede verse en la forma de cientos de intentos de registro que intentarán adivinar nuestra contraseña segura definida en el punto anterior. A pesar de que sabemos que nunca la encontrarán, tantos cientos (o miles) de intentos pueden generar un ataque DoS en nuestro conmutador. ¿Cómo defendernos ante esto?

La respuesta es un sencillo (pero eficiente) programa llamado fail2ban. El fail2ban es una herramienta que analiza logs de intentos de ataque y bloquea selectivamente por iptables a la IP que origina estos ataques. Es como traer la seguridad de acceso cuando alguien ya entró a nuestro equipo pero se delató proporcionando contraseñas equivocadas. Veanlo como el personal de seguridad que te saca del lugar por comportarte mal, permitiéndote bloquearlo a nivel de firewall por unos minutos, horas o de manera permanente, todo depende de como lo configures.

Si estás interesado en ver como puedes configurar fail2ban y los filtros que puedes aplicar, puedes consultar el artículo que escribí hace unos meses.

 

Con esto cubrimos el segundo nivel en esta serie de entregas. En la siguiente discutiremos sobre la manera en como autenticar no a los dispositivos, sino a los usuarios, que son los últimos elementos en la cadena de seguridad de nuestro sistema.

¡Suerte!

Modelo de seguridad en Asterisk (parte 1 de 3)

5 Mar

Fuente: http://upload.wikimedia.org/wikipedia/commons/5/5b/Firewall.png

Desafortunadamente y como hemos comentado en otros posts, la seguridad en Asterisk es algo que se ha visto sobrevalorado por la sencillez y rapidez que trae el dejar un sistema que funciona en unas cuantas horas a partir de una distribución todo integrado, pero que es inseguro por descuidos del administrador.

¿Cómo puede alcanzarse la seguridad al 100% del conmutador? La respuesta es no se puede. Sin embargo, lo que si podemos hacer es llevar nuestro sistema a un nivel de seguridad que haga que aquel que intente penetrarlo sin autorización tenga que invertir más tiempo del que está dispuesto a ceder.

Para explicar mejor esto, definiremos el modelo de seguridad de Asterisk en 3 niveles:

  1. Seguridad externa (acceso al sistema)
  2. Seguridad de autenticación
  3. Seguridad de operación

Seguridad externa

Todo acceso al sistema desde fuentes externas (WAN) debe estar restringido a través de un firewall. Idealmente, usaríamos un firewall en hardware, pero si nuestro proveedor nos entrega una IP directa y la configuramos en nuestro equipo, podemos hacer uso de iptables.

Cuando decidimos que puertos abrir en nuestro firewall, debemos hacernos las siguientes preguntas:

  • ¿Habrá extensiones externas?
  • ¿Habrá alguna administración externa del conmutador?
  • ¿Existe algún proceso externo que controle el conmutador (manager interface)?

El tema de las extensiones externas es delicado, ya que es una parte fundamental de las ventajas de Asterisk pero al mismo tiempo es lo que permite el mal uso del conmutador. Si no pensamos tener extensiones externas, los puertos UDP 5060 y 4569 (SIP e IAX) deben estar cerrados. Si no abrimos los puertos, nadie ajeno al sistema, aún sabiendo las contraseñas de las extensiones podrá hacer llamadas. Al cerrar los puertos, cortamos el cable de acceso, y nada puede pasar. Es por eso que esta es la parte más importante de seguridad del sistema.

Si nos encontramos bajo el escenario que debemos tener extensiones externas, tenemos que asegurarnos que el nivel de seguridad secundario sea bueno, ya que al conceder acceso a entidades externas, debemos dejar la responsabilidad de la seguridad a las capas interiores. De esto nos encargaremos en la parte 2 de este artículo.

Nota: Al momento de hacer un register hacia una entidad SIP/IAX2 externa estaremos abriendo una sesión a través del firewall, lo que permitiría a esta entidad enviarnos llamadas a pesar de que el firewall esté cerrado. Hay que tomar esto en cuenta pues si alguien tuviera acceso administrativo a nuestro equipo podria generar un register hacia su propio conmutador y con ello, enviarnos llamadas en sentido inverso. El caso es muy raro, pero puede ocurrir. Ténganlo en cuenta.

Si necesitamos contar con administración remota del equipo debemos decidir correctamente que tipo de seguridad proveer. Si utilizamos alguna interfaz gráfica como FreePBX nunca, pero nunca debemos abrir el puerto HTTPS (TCP 443). Abrir el puerto 443 permitiria que cualquier vulnerabilidad de nuestra web, ya sea por FreePBX, Webmin, phpMyAdmin o cualquier otra interfaz que nos exponga contra atacantes externos.

Sobre este punto debo decir que dadas múltiples vulnerabilidades que han sido encontradas en interfaces gráficas, ningún administrador que considere su trabajo digno dejaría expuesto el puerto de HTTPS. Si acaso se necesita (para la administración), lo correcto es usar un túnel SSH o mejor aún, una conexión por VPN (sobre este último punto, si creamos una VPN podríamos no tener que abrir ni un solo puerto entrante en el firewall, por lo que este resultaría el caso más seguro de todos).

Por último, si tuviéramos necesidad de controlar Asterisk a través del Manager Interface (AMI), es necesario saber que toda la comunicación por este puerto siempre viaja sin encriptación, por lo que si alguien intercepta los paquetes del AMI podría fácilmente controlar completamente nuestro conmutador, creando extensiones o solicitando llamadas de la nada. El puerto que se ocupa para esta comunicación es el 5038 TCP y por lo tanto, nunca deberíamos dejarlo expuesto en nuestro firewall.

 

Este es el final de la primera de tres entregas sobre el modelo de seguridad de Asterisk. En las siguientes 2 partes haremos mención de como configurar ACLs dentro de Asterisk para asegurar el acceso, así como las opciones que debemos tomar en cuenta al momento de generar contraseñas seguras para acceso a nuestros usuarios SIP/IAX.

Recuerden que también pueden dejarnos sus comentarios a través de Twitter o Facebook.

¡Suerte!

El carrier no siempre tiene la razón

1 Mar

(por cuestiones de confidencialidad no puedo revelar nombres, pero esta historia aplica en general)

Desde el pasado noviembre recibí una llamada de uno de mis clientes indicándome que su equipo Elastix muy frecuentemente le daba el ya conocido mensaje «todos los circuitos se encuentran ocupados«. Su enlace con la PSTN era a través de un enlace digital E1 ISDN.  Pensé que algo estaría mal con la configuración del equipo, así que decidí acceder a la consola para ver que era lo que lo ocasionaba.

Intentó varias llamadas a un mismo número: todas fallaron. Mi creencia fue pensar que Elastix estaba mal interpretando el código Q.931 que el carrier entregaba de vuelta tras el resultado de la llamada. Para quienes no saben, el Q.931 es el protocolo estándar de la ITU para la señalización de control de conexión en ISDN (en otras palabras, es el responsable de indicar el estado de una llamada generada a través de un E1 ISDN). Por default, Elastix interpreta prácticamente todo con la misma respuesta de «todos los circuitos se encuentran ocupados», por lo que a pesar de que la razón de terminado de la llamada sea una congestión del carrier o bien que el número marcado no existe, siempre obtenemos la misma respuesta.

Implementé la solución de uno de mis post anteriores esperando que eso resolviera el problema y el cliente se enterara de cual era la verdadera razón para la desconexión. Poco tiempo paso cuando mi cliente me indicó que no hubo cambio, sino que todo continuó exactamente igual que al principio (mismo mensaje para todos los casos). Esto me extrañó dado que esta solución ha sido exitosa en muchos casos e inclusive, otras empresas lo han sugerido a sus clientes para resolver problemas con el servicio recibido por otros carriers, por lo que tuve que indagar más para encontrar la causa del problema.

Tras analizar los logs, encontré cientos de registros como este:

[Feb 9 08:34:03] VERBOSE[10458] pbx.c:     -- Executing [continue@macro-dialout-trunk:3] NoOp("SIP/31163-00002883", "TRUNK Dial failed due to CONGESTION HANGUPCAUSE: 31 - failing through to other trunks") in new stack
[Feb 9 08:36:42] VERBOSE[10472] pbx.c:     -- Executing [continue@macro-dialout-trunk:3] NoOp("SIP/31142-0000288d", "TRUNK Dial failed due to CONGESTION HANGUPCAUSE: 31 - failing through to other trunks") in new stack
[Feb 9 08:42:10] VERBOSE[10499] pbx.c:     -- Executing [continue@macro-dialout-trunk:3] NoOp("SIP/31161-00002897", "TRUNK Dial failed due to CONGESTION HANGUPCAUSE: 31 - failing through to other trunks") in new stack
[Feb 9 08:44:45] VERBOSE[10512] pbx.c:     -- Executing [continue@macro-dialout-trunk:3] NoOp("SIP/31131-0000289c", "TRUNK Dial failed due to CONGESTION HANGUPCAUSE: 31 - failing through to other trunks") in new stack
[Feb 9 08:49:55] VERBOSE[10523] pbx.c:     -- Executing [continue@macro-dialout-trunk:3] NoOp("SIP/31112-0000289f", "TRUNK Dial failed due to CONGESTION HANGUPCAUSE: 31 - failing through to other trunks") in new stack

Aquí se aprecia que el código de terminación de la llamada fue el 31. Si buscamos en Google encontraremos que el código 31 dice «Normal, unspecified», significando que la llamada terminó por causas normales que no fueron especificadas. Esto es normal de vez en cuando, pero tener tantos intentos fallidos en el mismo intervalo de tiempo me hizo investigar más.

Encontré los números que se marcaban y tomé mi línea analógica convencional y marqué a ellos. Los resultados fueron diferentes para los diferentes números:

  • «El número que marcó está fuera de servicio»
  • «El número que marcó está suspendido»
  • «El número que marcó no existe»
  • «El número celular que usted marcó no está disponible o se encuentra fuera del área de servicio»

Entonces no era problema que todos los canales estuvieran ocupados, sino que el carrier NO estaba regresándonos la causa correcta de terminación de la llamada para cada caso específico. Esto es sumamente importante, ya que en base al código de error obtenido sabes como debes retroalimentar a los usuarios para que reintenten pasados unos minutos o bien, que dejen de intentar llamar a un número imposible de localizar.

A pesar que trates de explicarle esto a los clientes, muchos no entienden que las líneas digitales se basan en códigos de error y no en grabaciones que escuchan en su línea al momento de marcar. Decir que todos los circuitos están ocupados normalmente es asociado con problemas de capacidad (piensan que hacen demasiadas llamadas simultáneas) o con un problema del conmutador, y acaban echándote la culpa a ti como proveedor del mismo.

Como el problema escalaba de lo que éramos capaces de ofrecer (ya que el enlace es provisto por el carrier, no por nosotros) no nos quedó de otra que levantar la incidencia. Esto fue desde noviembre 2011. Múltiples pruebas se tuvieron que hacer para demostrar a los ingenieros de soporte del carrier que el problema no venía del conmutador, sino de su enlace (o bien, de la interconexión de ellos con el destino al que se estaba marcando).

Tras 3 meses de idas y vueltas, reportes enviados y pruebas fallidas, antier me reportaron que por fin pudieron cumplirse pruebas exitosas del proyecto. El problema radicó en la interconexión entre carriers, no en la conexión de Asterisk.

Los ingenieros de soporte nos hicieron notar que gracias a la insistencia de nuestra parte el problema pudo detectarse e inclusive, se corrigió para todos los usuarios del mismo tipo de servicio. Inclusive la retroalimentación fue que muchos proveedores de conmutadores de telefonía convencional disfrazan los códigos de error recibidos para otorgarle al usuario respuestas aceptables en los problemas de los enlaces digitales. Sin embargo, Asterisk es de los pocos conmutadores con acceso total a la información (sin restricciones), por lo que pudimos meternos a hacer un debug intensivo del medio y pudimos refutar al carrier que el problema no venía de nuestro lado.

Sin acceso a la información que Asterisk entrega, nunca hubiéramos tenido las pruebas para acusar a quien tuvo la verdadera culpa del problema y hoy, seguiríamos igual que al principio.

Creo que la moraleja de esta historia es: nunca asuman que el proveedor grande siempre tiene la razón. Consigan pruebas, experimenten y evalúen sus resultados. Es muy probable que ustedes sean quienes puedan salir victoriosos de la contienda, solo infórmense bien de lo que ustedes saben que deberían estar recibiendo.

¡Suerte!