Este es un problema viejo y aunque la solución puede encontrarse buscando por internet, quise tomarme unos minutos para escribir un breve post que habla del problema y como resolverlo.
Estoy seguro que a varios les ha pasado: tienes tu conmutador configurado perfectamente y todo marcha bien. De pronto, de la nada, tus extensiones internas se caen: no haces ni recibes llamadas. Revisas un poco y te das cuenta de que no tienes internet. ¿Pero para que necesito internet si mis extensiones son internas? ¿Qué tiene que ver una cosa con la otra? Es ahí donde entramos.
El problema radica en la manera en como Asterisk resuelve los dominios de las troncales SIP a donde necesita conectarse. El canal SIP utiliza un método de consulta de DNS síncrono, lo que quiere decir que cuando llega una petición de resolver un DNS (ej. siptrunk.alianza.com) el canal SIP le pregunta al servidor DNS, espera la respuesta, y cuando finalmente la obtiene continú con su siguiente petición SIP. En un mundo ideal esto no es problema, ya que la resolución por DNS es muy rápida y toma unos cuantos milisegundos, por lo que normalmente no la notamos. Pero… ¿qué ocurre cuando por alguna falla en internet, el servidor de DNS al que solemos apuntar se cae o simplemente no podemos acceder a él? Pues la respuesta es que esto provoca un efecto dominó en Asterisk que ocasiona que todo el canal SIP se caiga.
¿Cómo puede pasar esto?
Imagina el siguiente caso:
Juan quiere hacer una llamada a través de su troncal de pbx.micarrier.com, así que levanta su teléfono y llama al número deseado.
Asterisk recibe la petición de llamada y le manda a su DNS la solicitud de resoler pbx.micarrier.com, pero al utilizar paquetes por UDP, Asterisk no se da cuenta de que el equipo está offiline, así que le da un cierto tiempo de timeout a que el servidor responda.
Mientras que Asterisk espera a recibir la respuesta, Jorge desea hacer una llamada a través de pbx.miotrocarrier.com, pero aún no puede enviar la llamada porque Asterisk está ocupado con la petición anterior.
Para cuando Juan por fin recibe la respuesta de request timeout, Jorge ya lleva buen rato esperando a que su petición apenas comience, así que muy probablemente Jorge reciba un timeout pero a nivel de SIP, porque Asterisk se tardó mucho en responderle por estar ocupado en la petición de Juan.
Si a este escenario le agregan más usuarios y más carriers, el sistema se hace más complejo exponencialmente, ocasionando una serie de retrasos que eventualmebte tiran todo el servidor porque nada responde (todos se quedan esperando a todos y ninguna llamada logra salir).
Esto es un problema a nivel de código de Asterisk: si las peticiones fueran asíncronas la espera de uno no se convertiría en la espera del otro y todos serían felices. Pero como se menciona en los foros de desarrollo de Asterisk, esta es una funcionalidad que requiere mucho tiempo para ser resuelta, y que al menos en la versión 1.8.21.0, persiste.
¿Cómo lo resolvemos?
Hay algunas soluciones:
Editar manualmente el /etc/hosts y poner allí todos los dominios y direcciones IP que necesitemos. El problema es que esto no funciona para resolución inversa de DNS, así que tiene fallos. Otro problema es que tendríamos que agregar manualmente cada dominio, lo cual puede consumir mucho tiempo, además de que si el proveedor actualiza su IP, nuestra resolución fallaría.
Configurar en Asterisk las IPs fijas de cada carrier. Fácil de hacer pero de igual manera, es manual, así que nos exponemos a los problemas de tener que estar vigilando nuestro PBX constantemente.
La solución que mas predomina es la de instalar localmente (en el mismo servidor de Asterisk) un servicio de cache de DNS, como es el caso de bind. Esto hará que el equipo almacede de manera local la información de consulta frecuente para que en caso de fallos con el internet, Asterisk sobreviva del cache. Y es bastante fácil de hacer.
En CentOS/RedHat, por default el servicio no arranca automáticamente, así que debemos decirle a Linux que lo arranque cuando el sistema prenda.
chkconfig named on
También aprovechamos y lo arrancamos:
/etc/init.d/named start
Con esto el servicio de named ya está corriendo. Ahora le decimos a Linux que lo utilice. Editamos el archivo /etc/resolv.conf y nos aseguramos que solamente contenga una linea como la que sigue:
nameserver 127.0.0.1
Si usamos Elastix, hacer el cambio también desde la interfaz web. Abrimos el menu de System > Network y editamos la configuración para dejar únicamente un DNS:
De esta manera, obligamos a que use el local. Si el local falla, lo peor que pasa es que perdemos nuestra troncal, pero es mejor recibir una respuesta negativa del DNS a no recibir respuesta.
Podemos validar que todo está corriendo revisando que el puerto 53 esté ocupado por el servicio de named:
Y claro está, no puede faltar la super prueba del ping que muestre que los dominios resuelven correctamente:
[root@elastix ~]# ping asteriskmx.com
PING asteriskmx.com (216.93.172.112) 56(84) bytes of data.
64 bytes from 216.93.172.112.servepath.com (216.93.172.112): icmp_seq=1 ttl=53 time=74.6 ms
64 bytes from 216.93.172.112.servepath.com (216.93.172.112): icmp_seq=2 ttl=53 time=74.5 ms
64 bytes from 216.93.172.112.servepath.com (216.93.172.112): icmp_seq=3 ttl=53 time=74.9 ms
--- asteriskmx.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 74.563/74.723/74.912/0.265 ms
Hecho estos sencillos pasos, tu sistema estará preparado para caidas en el internet y tus troncales SIP no causarán que todo tu sistema se muera.
Solo una nota final: el servicio de named/bind al parecer vacia su cache cuando arranca. Esto quiere decir que si se va la luz y el internet al mismo tiempo, perderás la conectividad y todo se caerá (lo siento, no hay solución universal), pero en caso de que eso pase todo lo que necesitas hacer es detener el servicio y con esto tus DNS fallarán inmediatamente, con lo que te quedarás sin troncales SIP pero no si extensiones locales.
Este tutorial fue escrito por uno de los participantes de nuestro foro: navaismo.
El artículo original lo pueden encontrar aquí.
En algunas ocasiones nos vemos en la necesidad de crear un Cluster de alta disponibilidad para nuestros servicios de Asterisk. A continuación se describen los pasos necesarios para llevar esto acabo en nuestros servidores usando Asterisk y Mysql(por si queremos usar Asterisk Realtime Architechture).
Algunas indicaciones iniciales:
Estos pasos están basados en las instrucciones que brinda Digium y los tutoriales de DRBD para Mysql.
Este tutorial no esta hecho para hacer copy&paste.
El color verde indica que son pasos para realizar en ambos servidores.
El color Naranja indica que son pasos para realizar en el servidor primario.
El color Rojo indica que son pasos para realizar en el servidor secundario.
El Hostname del Servidor primario es «node1«.
El Hostname del Servidor secundario es «node2«.
La dirección IP del servidor primario es 10.0.1.51
La dirección IP del servidor secundario es 10.0.1.52
La dirección IP compartida del cluster y a la que deberán apuntar los servicios(como el registro de teléfonos, MySQL o apache) es 10.0.1.50.
La dirección IP del Gateway es 10.0.1.1.
Se puede adaptar fácilmente el Hardware Failover que provee Digium(rseries) y los servicios de Apache.
La Imagen anterior describe el funcionamiento del Cluster:
Escenario 1: El servidor primario esta activo y el secundario esta en modo pasivo esperando.
Escenario 2: El servidor Primario ha entrado en estado de falla(por conexión de RED o por reinicio o falla en el kernel), el servidor secundario entonces, se convierte en el servidor primario y es marcado como activo.
Escenario 3: El servidor secundario(antes primario) se ha recuperado de la falla y ha entrado en modo pasivo.
Escenario 4: El servidor primario(antes secundario) ha presentado falla y el servidor secundario(antes primario) es marcado como servidor primario nuevamente y entra en modo activo.
Paso 1 —- Realizar en Ambos Servidores:
Instala CentOS 5.X(Los agentes de recursos «ocf»de Digium no son compatibles con las versiones 6.X de CentOS). Escoger el modo de partición manual y dejar un espacio libre sin formateo ni nada, en este tutorial yo he dejado 5GB sin particionar. Este espacio será donde guardemos nuestros datos a replicar en el Cluster, así que deberán considerar cuanto espacio necesitaran para sus archivos y logs.
Paso 2 —- Realizar en Ambos Servidores:
Instala las dependencias para nuestros servidores. Primero añadiré el repositorio de rpmforge:
Selecciona el espacio libre y crea una nueva partición con todo el espacio libre usando los botones: New, Primary, Write. Al finalizar te preguntara si quieres efectuar los cambios, escribe la palabra: yes y da enter.
Cuando el proceso termine reinicia el servidor:
reboot
Una vez que el servidor haya arrancado de nuevo hay que limpiar la nueva partición usando el siguiente comando:
dd if=/dev/zero of=/dev/[hs]da[#] bs=1M; sync
Cambia /dev/[hs]da[#] por tu dispositivo que puede ser SDA3,HDA3 o SDB3 HDB3 etc. En este tutorial es HDA3.
Veras una salida similar cuando termine el proceso, dependiendo del tamaño de tu partición y de la velocidad de tus discos duros puede tomar minutos u horas.
Crea un nuevo directorio en /usr/src:
cd /usr/src/
mkdir asterisk
cd asterisk/
En el nuevo directorio descarga Asterisk y sus componentes:
Edita el archivo /etc/drbd.d/asterisk.res. Cambia astnode1 por el nombre el hostname del servidor primario, cambia astnode2 por el hostname del servidor secundario, cambia /dev/sda3 por la partición que creamos con el espacio libre(en este tutorial hda3). Cambia las IPs por las de tus servidores primarios y secundarios.Cambia el correo electrónico por el tuyo o el administrador del sistema en este tutorial el archivo quedo así:
resource asterisk {
handlers {
split-brain "/usr/lib/drbd/notify-split-brain.sh clusteradmin@example.com";
}
net {
after-sb-0pri discard-younger-primary;
after-sb-1pri discard-secondary;
after-sb-2pri disconnect;
}
on node1 {
device /dev/drbd0;
disk /dev/hda3;
address 10.0.1.51:7789;
meta-disk internal;
}
on node2 {
device /dev/drbd0;
disk /dev/hda3;
address 10.0.1.52:7789;
meta-disk internal;
}
}
Crea el Recurso llamado asterisk e inicia el servicio de DRDB:
drbdadm create-md asterisk
service drbd start
Paso 6—-Realizar solo en Servidor Primario.
A continuación crea el UUID llamado Asterisk, y formatea la partición que será usada por el cluster tipo: EXT3
Cambiate al directorio de rseries, marca el nodo como primario, monta la partición y ejecuta el script createlinks.sh:
cd /usr/src/asterisk/rseries-1.0.0
drbdadm primary asterisk
mount -t ext3 /dev/drbd0 /mnt/asterisk/
./createlinks.sh
Veras una salida como en la imagen anterior.
Cambiate al directorio de Asterisk, configura las mismas opciones que se configuraron en el servidor primario. Compilalo solo ejecutando make && make install. Desmonta la partición y marca el nodo como secundario.
cd ../certified-asterisk-1.8.11-cert9
contrib/scripts/get_mp3_source.sh
./configure && make menuselect
make && make install
umount /mnt/asterisk/
drbdadm secondary asterisk
Paso 10 —- Realizar en Ambos Servidores.
Edita el archivo /etc/corosync/corosync.conf. Cambia la opción bindnetaddr, y las opciones memberaddr. Para este tutorial el archivo quedo de la siguiente manera:
Inicia el servicio de Corosync y añade drbd y corosync al startup:
service corosync start
chkconfig drdb on
chkconfig corosync on
Verifica el estado del Cluster con el siguiente comando:
cat /proc/drbd
Veras una imagen como la siguiente:
Veras que se esta sincronizando la particion del cluster, también verás como Secondary/Secondary(no como en la imagen).
Si el proceso de sincronización reporta que tardará mucho tiempo puedes usar este comando para acelerar la velocidad de sincronización:
drbdsetup /dev/drbd0 syncer -r 250M
La velocidad máxima de sincronización dependerá de la velocidad de tus tarjetas de red así como la velocidad de escritura de tus discos duros. Para más información de como calcular la velocidad ve a este enlace.
Una vez que el estado sea UpToDate/UpToDate reinicia los servidores:
reboot
Paso 11—-Realizar solo en Servidor Primario.
Edita el siguiente codigo para que:
— node1 y node2. Sean los hostnames de tus servidores. En este ejemplo node1 y node2
— ip bajo ClusterIP. Sea la Ip de tu Cluster, la IP flotante. En este ejemplo 10.0.1.51
— cidr_mask bajo ClusterIP. Sea la mascara de tu red. en este ejemplo de 24bits(255.255.255.0)
– –host_list bajo GatewayStatus. Sea el gateway de tu red. en este ejemplo 10.0.1.1
node node1
node node2
primitive ClusterIP ocf:heartbeat:IPaddr2
params ip="10.0.1.50" cidr_netmask="24"
op monitor interval="5"
primitive drbd ocf:linbit:drbd
params drbd_resource="asterisk"
op monitor start-delay="10" interval="5"
primitive drbd_fs ocf:heartbeat:Filesystem
params device="/dev/drbd0" directory="/mnt/asterisk/" fstype="ext3"
primitive mysqld lsb:mysqld
primitive Asterisk ocf:Digium:asterisk
op monitor interval="5"
primitive GatewayStatus ocf:pacemaker:ping
params host_list="10.0.1.1" multiplier="100"
op monitor interval="5" timeout="10"
ms drbd_ms drbd
meta master-max="1" master-node-max="1" clone-max="2" clone-node-max="1" notify="true"
clone GatewayStatusClone GatewayStatus
location Asterisk-with-ping Asterisk
rule $id="Asterisk-with-ping-rule" -inf: not_defined pingd or pingd lte 0
group mysql drbd_fs ClusterIP mysqld
colocation mysql_on_drbd inf: mysql drbd_ms:Master
order mysql_after_drbd inf: drbd_ms:promote mysql:start
colocation Everything-with-Asterisk inf: ( drbd_ms:Master ) ( ClusterIP drbd_fs ) Asterisk
order Asterisk-after-Everything inf: ( drbd_ms:promote ) ( ClusterIP drbd_fs ) Asterisk:start
property $id="cib-bootstrap-options"
cluster-infrastructure="openais"
expected-quorum-votes="2"
stonith-enabled="false"
no-quorum-policy="ignore"
rsc_defaults $id="rsc-options"
resource-stickiness="99"
Una vez que has editado el archivo Cluster_Mysql_Asterisk.cfg, actualiza la configuración de pacemaker:
Si todo sale bien veras una salida como la siguiente y los servicios de MySQL y Asterisk se iniciaran en el nodo primario:
Para verificar que los servicios estén corriendo puedes revisar el estado del cluster con:
crm_mon
Y verás algo así:
Demostración:
El siguiente video muestra las pruebas del cluster. Asterisk esta configurado con «static realtime» obteniendo los datos de una base de datos de MySQL. Este tutorial no cubre la cofiguración de ARA(Asterisk Realtime Architechture).
Herramientas para diagnosticar fallas:
Puedes ejecutar el siguiente comando en el nodo secundario para verificar que la configuración de pacemaker se replico:
crm configure show
Para detener los servicios del cluster:
crm configure property stop-all-resources=true
Para borrar la configuracion del cluster:
crm configure erase
Verificar el estado del cluster:
crm_mon
Verificar el estado de la sincronización y los roles de los servidores:
El día de ayer publicamos un mini tutorial de como reiniciar masivamente todos los teléfonos Aastra de nuestra red. Hoy publicamos el equivalente aplicable para todos los teléfonos Cisco SPA (esto aplica también para la vieja gama de Linksys/Sipura).
El código es aún más sencillo que el de ayer:
[codesyntax lang=»php»]
#!/bin/bash
RED=192.168.1.1/24
echo "Escaneando $RED ..... "
for IP in `nmap -sP -v $RED | grep "appears to be up" | cut -d' ' -f 2`
do
wget -qT 1 --no-cache http://$IP/admin/reboot -O - > /dev/null
done
[/codesyntax]
Con un poco de ingenio, podemos mezclar ambos scripts para que en caso de tener mezcla de teléfonos, reiniciemos todo lo que nos encontremos.
Recientemente nos topamos con la necesidad de resetear cerca de 200 teléfonos Aastra en una misma red. Pudimos haber esperado a que los teléfonos comenzaran a registrarse solos, pero debido a que era un soporte de emergencia, utilizamos este script:
Lo que éste hace es escanear la red, abrir la interfaz web de todos los teléfonos, accesa con el usuario y contraseña default (admin/2222) y una vez adentro ingresa al menú Reset y posteriormente acciona el reseteo del teléfono. Para hacer uso de este script es necesario hacerlo ejecutable (chmod 755) y cambiar la variable de RED para que concida con la red que queremos resetear.
El eco en una señal de telefonía ocurre cuando tenemos 2 conductores a diferentes impedancias. El desacople de las mismas ocasiona que la señal se refleje y se perciba por nuestro cerebro como 2 señales diferentes. Si el eco es superior a 150ms, comienza a volverse molesto ya que como humanos nos distrae de la conversación que estamos teniendo.
En un sistema 100% VoIP el eco no existe. Definitivo: no existe. Sin embargo, dado que aún ocupamos medios analógicos para poder nosotros enviar o recibir el audio (micrófonos y altavoces), es en estos dispositivos donde el eco puede ocurrir. El punto más común donde se produce el eco es en el medio que ocupemos para conectarnos con medios 100% analógicos, como la línea telefónica, así que es responsabilidad de nuestras tarjetas o gateways, hacerse cargo de cancelar este eco, ya sea mediante hardware o software (recuerden que en VoIP, la voz al final son datos, y los datos pueden manipularse por software).
Para poder manipular el eco en Asterisk tenemos 2 opciones:
Hardware: es la más cara de las opciones, ya que nos exige comprar hardware dedicado a esta función. Sin embargo, es la de mejor rendimiento ya que libera al CPU de esta carga extra.
Software: justo lo contrario, es la opción más económica, pero depende del CPU para hacer el procesamiento.
Para opciones de hardware podemos comprar tarjetas que soporten esta característica. En tarjetas Sangoma podemos ir por los modelos que tengan la letra D (como la B600DE, A200DE, A101DE). El problema con estas tarjetas es que no son actualizables, es decir, no podemos comprar el módulo de cancelador de eco después. Las tarjetas Digium tienen la ventaja de que podemos adquirir el módulo de cancelador de eco por separado, asi nuestra inversión está asegurada.
En este artículo nos centraremos en las soluciones para software, ya que la mayoría de nosotros tiene equipos que no cuentan con el módulo en HW necesario para lograr esta función, y para hacerlo, primero haremos la instalación de OSLEC (Open Source Line Echo Canceller), la cual, tiene que ser compilada dentro de DAHDI.
Empezando con el trabajo: primero necesitamos conseguir el código fuente de DAHDI y también el código fuente de Wanpipe (los drivers de Sangoma que contienen la referencia a OSLEC).
cd /usr/src
wget http://downloads.asterisk.org/pub/telephony/dahdi-linux-complete/releases/dahdi-linux-complete-2.4.1.2+2.4.1.tar.gz
wget ftp://ftp.sangoma.com/linux/current_wanpipe/wanpipe-3.5.22.tgz
tar -zxf dahdi-linux-complete-2.4.1.2+2.4.1.tar.gz
tar -zxf wanpipe-3.5.22.tgz
Quizá se pregunten: ¿por qué descargar wanpipe si lo podemos conseguir en el código fuente de Linux? Simplemente porque wanpipe es más pequeño y tarda menos en descargarse.
Luego, creamos las carpetas necesarias dentro del código de DAHDI y copiamos la parte de OSLEC que necesitamos:
cd /usr/src/dahdi-linux-complete-2.4.1.2+2.4.1/linux/drivers
mkdir staging
cp -r /usr/src/wanpipe-3.5.22/OSLEC/echo staging
En este punto, hay 2 archivos que debemos de modificar:
El segundo archivo si tiene contenido. Buscamos un contenido similar a este:
# Archivo: /usr/src/dahdi-linux-complete-2.4.1.2+2.4.1/linux/drivers/dahdi/Kbuild
# Only enable this if you think you know what you're doing. This is not
# supported yet:
#obj-m += dahdi_echocan_oslec.o
#
# A quick and dirty way to build OSLEC, if you happened to place it
# yourself in the dahdi source tree. This is experimental. See README
# regarding OSLEC.
#obj-m += ../staging/echo/
Quitamos el comentario a las 2 lineas de código para dejarlo así:
# Archivo /usr/src/dahdi-linux-complete-2.4.1.2+2.4.1/linux/drivers/dahdi/Kbuild
# Only enable this if you think you know what you're doing. This is not
# supported yet:
obj-m += dahdi_echocan_oslec.o
#
# A quick and dirty way to build OSLEC, if you happened to place it
# yourself in the dahdi source tree. This is experimental. See README
# regarding OSLEC.
obj-m += ../staging/echo/
Procedemos a recompilar DAHDI desde nuestra carpeta /usr/src/dahdi-linux-complete-2.4.1.2+2.4.1
cd /usr/src/dahdi-linux-complete-2.4.1.2+2.4.1
make
make install
2 passos más: editamos /etc/dahdi/system.conf
#
# Archivo /etc/dahdi/system.conf
#
# Tomen en cuenta reemplazar sus canales por los de su equipo
# En este ejemplo tengo una tarjeta de 4 puertos FXO
fxsks=1-4
echocanceller=oslec,1-4
Si todo carga sin errores, ¡listo! tenemos habilitado el cancelador de eco OSLEC, que es considerablemente mejor contrarestando el eco que el default de MG2.
Estos pasos son bastante buenos para reducir el eco de nuestra línea, pero si aún así tenemos problemas, podemos usar fxotune para virtualmente, eliminar el eco remanente. Es muy sencillo de usar. El procedimiento sería el siguiente:
Detenemos Asterisk para que los canales DAHDI no estén en uso
Creamos el archivo /etc/fxotune.conf (se crea automáticamente usando el comando fxotune -i)
Cargamos los coeficientes encontrados cada vez que arranque el sistema
Reiniciamos Asterisk
Visto en código sería algo así:
/etc/init.d/asterisk stop
fxotune -i # Esto puede demorar algunos minutos
echo 'fxotune -s' >> /etc/rc.local
/etc/init.d/asterisk start
Nota final: El fxotune debe ser ejecutado cuando Asterisk NO está corriendo. En el ejemplo anterior, estoy agregando el fxotune -s al rc.local para que cargue en automático, pero esto hará que tras el re-arranque, se ejecute hasta después de que Asterisk ya inició (lo cual no está bien). Si queremos asegurarnos que cargue siempre, podemos agregar al rc.local las instrucciones para que Asterisk se detenga, se ejecute fxotune y luego re-arranque Asterisk. Hay muchas maneras de hacer esto, pero eso escapa a la intención de este artículo.
Siguiendo todos estos pasos, el eco debe quedar prácticamente eliminado. Hasta el momento he hecho instalaciones que han mantenido eco con uno de estos pasos, pero nunca alguno que haya persistido con los 2.
Este post realmente no tiene que ver con Asterisk, pero resolviendo una consulta que me hicieron, consideré que podría ser útil para aquel que se ha visto en la necesidad de acceder a una BD de MySQL de la cual no se tiene la contraseña de root.
Los pasos a seguir son bastante sencillos (hay que ejecutar los comandos con permisos de root de Linux):
Detenemos el servicio de MySQL
[codesyntax lang=»bash»]
/etc/init.d/mysql stop
[/codesyntax]
Iniciamos MySQL pero en modo sin privilegios
[codesyntax lang=»bash»]mysqld_safe –skip-grant-tables &[/codesyntax]
Hacemos un login a MySQL sin password
[codesyntax lang=»bash»]mysql -u root[/codesyntax]
Cambia el password (este query se ejecuta desde adentro de MySQL, al cual accedimos ya porque arrancamos sin contraseña).
[codesyntax lang=»sql»]UPDATE mysql.user set Password = PASSWORD(‘tunuevopass‘) WHERE User=’root’;[/codesyntax]
Salimos de SQL
[codesyntax lang=»sql»]exit;[/codesyntax]
Detenemos la sesión corriendo de MySQL
[codesyntax lang=»bash»]mysqladmin shutdown[/codesyntax]
Reiniciamos el servicio de MySQL
[codesyntax lang=»bash»]/etc/init.d/mysql restart[/codesyntax]
Al re-arrancar, ya debemos poder acceder a nuestro servicio MySQL con la nueva contraseña que definimos.
En ocasiones anteriores he hecho la mención de fail2ban, una herramienta escrita en Python que analiza logs del sistema y responde en caso de que ciertas condiciones se cumplan, por ejemplo, 5 intentos de contraseña SSH equivocada en un periodo de 10 minutos. Dada la proliferación de ataques a equipos Asterisk para tratar de hacer llamadas de larga distancia, tiene sentido que ocupemos esta herramienta para protegernos de los amantes de lo ajeno.
Ahora bien, ¿cómo configuramos esta herramienta para que nos evite los cargos de miles de dólares en llamadas fantasmas?
Primero, lo instalamos. En Debian podemos usar el mundialmente reconocido apt-get:
apt-get install fail2ban
O, si tenemos Centos, primero asegurémonos de que tengamos EPEL (un repositorio que nos da acceso a mucho software útil) y luego instalamos fail2ban:
El filtro a usar debe existir en /etc/fail2ban/filter.d/asterisk.conf
Cuando se active la regla, usaremos la acción iptables-allports, la cual bloquea a nivel de iptables. Nosotros le estamos indicando que cierre el acceso al puerto UDP 5060, y luego que haga uso de la acción sendmail-whois, la cual me enviaria a mi correo electrónico la notificación del bloqueo, además de enviarme información de whois de la IP que se bloqueó.
El archivo log a monitorear es el /var/log/asterisk/full (ojo, dependiendo de tu sistema, el log puede ser diferente, ajústalo acorde)
Se permiten un máximo de 5 fallos en 10 minutos antes de activar la protección. Es decir, se permiten un máximo de maxretry intentos en findtime segundos
Al activarse el bloqueo, se hará por 3 horas o bien, 10800 segundos (bantime)
Ya definido el jail, necesitamos crear el filtro que atrapará los ataques. Esto se define (de acuerdo a lo que especificamos arriba) en el /etc/fail2ban/filter.d/asterisk.conf (los valores con # son comentarios, solo se dejan por referencia)
[INCLUDES]
# Read common prefixes. If any customizations available -- read them from
# common.local
#before = common.conf
[Definition]
#_daemon = asterisk
# Option: failregex
# Notes.: regex to match the password failures messages in the logfile. The
# host must be matched by a group named "host". The tag "<HOST>" can
# be used for standard IP/hostname matching and is only an alias for
# (?:::f{4,6}:)?(?P<host>S+)
# Values: TEXT
#
failregex = Registration from '.*' failed for '<HOST>(:[0-9]{1,5})?' - Wrong password
Registration from '.*' failed for '<HOST>(:[0-9]{1,5})?' - No matching peer found
Registration from '.*' failed for '<HOST>(:[0-9]{1,5})?' - Device does not match ACL
Registration from '.*' failed for '<HOST>(:[0-9]{1,5})?' - Username/auth name mismatch
Registration from '.*' failed for '<HOST>(:[0-9]{1,5})?' - Peer is not supposed to register
NOTICE.* <HOST> failed to authenticate as '.*'$
NOTICE.* .*: No registration for peer '.*' (from <HOST>)
NOTICE.* .*: Host <HOST> failed MD5 authentication for '.*' (.*)
VERBOSE.* logger.c: -- .*IP/<HOST>-.* Playing 'ss-noservice' (language '.*')
# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.
# Values: TEXT
#
ignoreregex =
Se observa que estamos tratando de atrapar a los siguientes:
Usuarios que ingresan su contraeña SIP incorrectamente
Usuarios que intentan usar un usuario SIP que no existe
Usuarios que no cumplen con los parámetros permit y deny del sip.conf
Usuarios que su auth username no coincide con su username
Usuarios que tratan de registrarse con perfiles que son fijos (es decir, que no tienen host=dynamic)
Usuarios que no cumplen con los criterios de autenticación
Usuarios que marcan hacia números que no existen (esto es común en Elastix/FreePBX cuando deshabilitamos recibir llamdas anónimas)
Finalmente, solo nos queda activar el servicio. En Debian ya quedó instalado automáticamente, solo tenemos que arrancarlo:
/etc/init.d/fail2ban start
En CentOS, tenemos que habilitar el autoarranque para que inicie al arrancar el equipo:
chkconfig --add fail2ban
chkconfig fail2ban on
/etc/init.d/fail2ban start
Fail2ban es un excelente apoyo contra ataques que dejan registros en logs y no solo nos sirve para Asterisk, también para SMTP, SSH, HTTP o cualquier otra cosa que queramos monitorear. Esto, en conjunción con buenas prácticas de seguridad para Asterisk, nos darán un sistema más confiable y menos propenso a sufrir daños por parte de atacantes.
Muchas veces me han pregunado si Asterisk soporta MP3 como música en espera: la respuesta es si y no. Debo decir que si porque en efecto, con el módulo format_mp3 se pueden reproducir MP3, pero debo decir no porque solamente se soportan los de bitrate constante (y hoy en día, prácticamente todos son de bitrate variable, o VBR), además de que el consumo de CPU causado por el transcoding realmente puede afectar al sistema.
Entonces, ¿cómo podemos hacer para convertir nuestra colección favorita de audio MP3 a wav, gsm, ulaw o cualquier otro de los formatos que Asterisk soporte? El mecanismo es más sencillo de lo que se cree, siempre y cuando se tengan los conocimientos mínimos de Linux para hacerlo.
Si tu música origen es MP3, necesitas instalar SoX con soporte para MP3. Aquí un tutorial (en inglés) de como hacerlo. Si tienes Debian, es tan sencillo como usar:
[codesyntax lang=»bash»]
apt-get install sox libsox-fmt-mp3
[/codesyntax]
Si tu música ya está en un formato que Asterisk soporta (ej. wav mono a 16-bit 8khz), brinca al paso 3
Ya con el soporte para MP3, necesitas convertir tus MP3 a un formato inicial que Asterisk pueda usar. Te recomiendo que si usas Asterisk 1.8+, los conviertas a wav de 16khz. Para todo lo demás, usa wav de 8khz. Estos son los comandos que usarías (dentro de la carpeta donde están tus MP3):
[codesyntax lang=»bash»]
# Para Asterisk 1.8+
for i in `ls *.mp3`
do sox $i -r 16000 -c 1 -s -w `echo $i|cut -d. -f1`.wav
rename 's/.wav/.wav16/' *.wav
done
# Para Asterisk menor a 1.8
for i in `ls *.mp3`
do sox $i -r 8000 -c 1 -s -w `echo $i|cut -d. -f1`.wav
done
[/codesyntax]
Dependiendo de la versión que hayas usado, ahora debes tener una carpeta con archivos .wav o .wav16 (Asterisk 1.8 soporta wavs en wideband que se escuchan mucho mejor si tu teléfono soporta codecs HD, como el g722). Lo que necesitas hacer es convertir estos archivos wav al formato que tu quieres (ejemplo: gsm). Para este paso, te recomiendo hagas un script que te facilite la labor. Por ejemplo: convierte.sh
[codesyntax lang=»bash» tab_width=»3″ title=»convierte.sh»]
#!/bin/bash
for i in `find $1 -name "*.$2"`
do
j=`echo $i | cut -d . -f 1`
asterisk -rx "file convert $j.$2 $j.$3"
done
[/codesyntax]
No te olvides de darle permisos de ejecución al script con chmod 755 convierte.sh
El último paso es el más sencillo: invocar al recien creado script. Puedes ejecutarlo de la siguiente manera:
[codesyntax lang=»bash»]
./convierte.sh /var/lib/asterisk/moh wav gsm
[/codesyntax]
Lo argumentos que el script recibe son:
La carpeta donde se encuentran tus archivos (en formato wav)
El formato de los archivos iniciales (los que sox te entregó)
El formato de los archivos finales (gsm, ulaw, g722, ilbc, etc)
El resultado es que tendrás una carpeta con varios archivos (los originales MP3, los intermedios wav y los finales en el codec que escojas). Puedes convertir a cuantos codecs quieras siempre y cuando Asterisk los soporte.
Estos pasos también son válidos si tienes tus archivos de audio en un codec (en la carpeta /var/lib/asterisk/sounds) y quieres convertirlo a otro codec completamente diferente.
Una gran ventaja que tenemos en Linux es la facilidad de crear procesos automatizados que nos ayuden a ejecutar tareas cotidianas. Para nuestros usos comunes como administrador de equipos basados en Asterisk/Elastix/FreePBX, puede ser una labor cotidiana respaldar la configuración alojada en bases de datos de MySQL.
SSH nos permite ejecutar comandos en servidores Linux remotos y traernos el resultado al mismo tiempo, por lo que resulta ideal para realizar un respaldo en un equpo distante y almacenarlo en nuestro equipo Linux loca. El comando para hacerlo sería el siguiente (asumiendo que usamos la contraseña default de MySQL en nuestro equipo remoto):
Hay que tomar en cuenta que estamos asumiendo lo siguiente:
La IP de nuestro servidor remoto es 192.168.1.100. Hay que reemplazar esta por la IP real de nuestro equipo del que queramos copiar el respaldo
El password default del usuario root del MySQL remoto es eLaStIx.2oo7. Nuevamente, hay que reemplazar este por el correspondiente al servidor
Adaptando este comando podemos prácticamente hacer cualquier tipo de respaldo remoto. Si agregamos la conexión mediante llaves públicas y privadas, podemos dejar estas actividades programadas en el cron para no tener que estar proporcionando la contraseña de SSH cada vez que nos conectamos.