Asterisk 11.X v. 1.2 “Las comunicaciones más allá del presente” CentOS 6.6 64Bit Asterisk 11.17.1 DAHDI 2.10.0.1 Mayo 2015
By
VozToVoice
www.voztovoice.org
Convenciones tipográficas. Negrita = comandos que el usuario tiene que teclear en la consola de Linux NegritaCursiva: Lineas que hay que añadir/modificar en los archivos de configuración Nombreprograma = Indica el nombre de un programa o librería Cursiva: respuesta del servidor Linux a los comandos enviados CLI> indica que se está trabajando en la consola de Asterisk mysql> indica que se está trabajando en la consola del cliente MySQL
Si encuentran alguna incorrección o errata pueden escribir al autor:
[email protected]
i
Este documento se publica bajo la GNU Free Documentation License, versión 1.3 o sucesivas, publicadas por la Free Software Foundation. Está permitido copiar, distribuir y/o modificar este documento bajo los términos indicados en la licencia. Una copia integral de la licencia es presente en la apéndice B de este libro.
Copyright (C)
2014-2018
Andrea Sannucci
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
ii
INDICE Capitulo I - Instalación de Asterisk ….......................................................................................... 1 1.1 Preparación del VPS 1.2 SSH y clave RSA 1.2.1 Clave RSA en Windows 1.2.2 Clave RSA en Linux 1.2.3 Configuración servidor SSH 1.3 Utilidades, librerías, dependencias 1.4 DAHDI 1.5 LibPRI 1.6 Res_fax, GoogleTalk, LibiCAL y SRTP 1.7 Instalación de Asterisk
1 9 9 13 14 18 22 24 24 30
Capitulo II - Configuración inicial de Asterisk ......................................................................... 40 2.1 Instalar y configurar un cortafuego 2.2 Carpetas y archivos 2.3 asterisk.conf 2.4 modules.conf 2.5 Música en espera y MP3 2.6 El comando asterisk 2.7 Preparación del dialplan – extensions.conf
40 44 46 48 50 53 55
Capitulo III – Protocolo SIP y archivo sip.conf.......................................................................... 62 3.1 sip.conf 3.2 Directmedia 3.3 Contraseñas seguras 3.4 Ngrep 3.5 SoftPhone X-Lite y REGISTER 3.6 Softphone 3CX 3.7 Llamadas entre extensiones 3.8 SIP INVITE y CANCEL 3.9 Los codecs 3.9.1 Negociación de codecs en Asterisk
64 81 82 83 84 89 91 92 95 97
Capitulo IV – Protocolo IAX2 – iax.conf ................................................................................. 102 4.1 iax.conf 4.2 Softphone Zoiper
102 107 iii
Capitulo V - GoogleTalk – motif.conf xmpp.conf................................................................... 114 5.1 xmpp.conf y motif.conf 5.2 Google Voice 5.3 Aplicación JabberSend 5.4 La función JABBER_RECEIVE
115 123 125 126
Capitulo VI - Asterisk y la red PSTN........................................................................................ 130 6.1 Tarjeta Digium TDM410 con 4 puertos FXO 6.1.1 OSLEC 6.2 Tarjeta Digium TDM410 con 2 puertos FXS 6.3 Tarjeta Digium TE120P 6.4 Wanpipe 6.5 DAHDI_GENCONF 6.6 Linksys SPA3102 – Gateway FXO/FXS
131 135 140 141 147 148 149
Capitulo VII - Dialplan – Configuración avanzada.................................................................. 160 7.1 Las Variables 7.2 Pattern Matching 7.3 La aplicación Echo 7.4 El contexto Subscribe 7.4.1 Monitoreo de las extensiones remotas con Corosync 7.5 Las Subrutinas 7.6 Autenticar las Llamadas Salientes con la aplicación Authenticate 7.7 Limitar llamadas salientes: funciones GROUP y GROUP_COUNT 7.8 Los mensajes instantáneos entre extensiones 7.9 WebRTC (Comunicación en tiempo real vía Web) 7.9.1 JSSIP 7.9.2 SIPML5
160 164 165 165 169 176 178 182 188 196 200 204
Capitulo VIII - IVR …................................................................................................................. 209 8.1 Grabación de las locuciones 8.2 Configuración numero geográfico 8.3 Creación del IVR 8.4 IVR “Clásico” 8.5 Horario Apertura/Cierre
209 211 212 216 217
Capitulo IX - Funcionalidades avanzadas de Asterisk – features.conf ................................... 224 9.1 features.conf
224 iv
9.2 Callgroup y Pickupgroup 9.2.1 namedcallgroup y namedpickupgroup 9.3 Aplicación Dial y features.conf 9.4 Las aplicaciones Park y ParkAndAnnounce 9.5 La aplicación FollowMe (Sígueme)
236 238 239 244 247
Capitulo X - Asterisk y los calendarios ….................................................................................. 255 10.1 calendar.conf 10.2 CALENDAR_BUSY 10.3 CALENDAR_EVENT 10.4 CALENDAR_QUERY y CALENDAR_QUERY_RESULT 10.5 CALENDAR_WRITE 10.6 Enviar las notificaciones de los calendarios a números fijos/celulares
256 268 270 272 275 279
Capitulo XI - CCSS (Call Completion Supplementary System) – Rellamada …................... 283 11.1 Configuración del CCSS 11.2 CCSS 1ª Prueba 11.3 CCSS 2ª Prueba 11.4 CCSS 3ª Prueba
283 286 287 288
Capitulo XII – Asterisk Realtime............................................................................................... 291 12.1 Realtime estático 12.2 Realtime dinámico 12.2.1 Extensiones SIP en Realtime 12.2.2 Extensiones IAX en Realtime 12.2.3 Dialplan en Realtime dinámico
291 298 298 307 311
Capitulo XIII – IVR avanzados – func_odbc.conf ........... ....................................................... 316 13.1 Empleados 13.2 Encuesta 13.3 Bolsa de minutos 13.4 Consultas con respuestas múltiples
316 321 323 325
Capitulo XIV - Buzón de voz – voicemail.conf........................................................................ 329 14.1 voicemail.conf 14.2 Mensajes de voz en una base de datos
329 341 v
14.3 Buzones de voz en una base de datos
344
Capitulo XV - Las conferencias audio ...................................................................................
349
15.1 meetme.conf 15.2 Aplicación ConfBridge 15.2.1 La función CONFBRIDGE 15.3 Meetme en Realtime Dinámico 15.4 Aplicación Page
349 354 370 371 374
Capitulo XVI - Distribución automática de llamadas – Colas de espera …........................... 378 16.1 Los agentes 16.2 Las colas de espera – queue.conf 16.3 Agentes dinámicos 16.4 Estadísticas de las colas 16.5 Colas, agentes y estadísticas en Realtime dinámico 16.6 La aplicación Chan_Spy
378 381 392 395 398 405
Capitulo XVII - Asterisk y los FAX …........................................................................................ 411 17.1 IAXmodem 17.2 Hylafax 17.3 Protocolo T38 17.3.1 Aplicación ReceiveFax 17.3.2 Applicación SendFax
411 415 437 442 444
Capitulo XVIII - Conexiones entre servidores Asterisk …....................................................... 448 18.1 Conectar dos servidores Asterisk con el protocolo SIP 18.2 Conectar dos servidores Asterisk con el protocolo IAX2 18.3 El protocolo DUNDi 18.4 Conectar dos servidores Asterisk con OpenVPN 18.5 Conectar dos Servidores Asterisk con TLS y SRTP
448 451 453 464 482
Capitulo XIX – AMI y AGI …............................................................................................
490
19.1 AMI (Asterisk Manager Interface) 19.2 AGI (Asterisk Gateway Interface) 19.3 Las variantes AGI
490 499 505 vi
19.3.1 EAGI 19.3.2 FastAGI 19.3.3 Async AGI
506 507 508
Capitulo XX - Los registros en Asterisk …................................................................................. 513 20.1 CDR (Call Detail Record) 20.1.1 cdr.conf 20.1.2 cdr_manager.conf 20.1.3 CDR adaptive 20.2 CEL (Channel Event Logging) 20.3 Logger.conf 20.3.1 Debug
513 515 518 519 524 531 535
Capitulo XXI - Seguridad en Asterisk …................................................................................... 539 21.1 Reglas de oro 21.2 Fail2ban 21.3 Bloquear IP por países
539 539 542
Capitulo XXII - Monitorear Asterisk ….....................................................................................549 22.1 Monit 22.2 SNMP 22.3 Nagios 22.3.1 NDOutils 22.3.2 PNP4NAGIOS 22.4 Monitoreo calidad llamadas 22.4.1 Monitoreo calidad llamadas desde la consola de Asterisk 22.4.2 Monitoreo calidad de las llamadas con pre-dial handlers y hangup-handlers 22.4.3 Monitoreo calidad llamadas con VoIPMonitor 22.5 CDR-STATS
549 555 558 569 571 576 576 577 582 585
Capitulo XXIII - Conectar un Softphone (Blink) de forma segura: SIP TLS y SRTP …...... 594 23.1 Creación de los certificados 23.2 Configuración Softphone Blink
594 598
Capitulo XXIV - Openfire y Asterisk …..................................................................................... 603
vii
24.1 Instalación de Openfire 24.2 Instalar el Plugin SIPPhone en Openfire 24.3 El Plugin Asterisk-IM 24.4 Asterisk como cliente en Openfire 24.5 Conectar dos servidores Openfire 24.6 Openfire Connection Manager
603 611 614 618 622 626
Capitulo XXV - Asterisk y alta disponibilidad ......................................................................... 632 25.1 Replicación MySQL Master-Slave 25.2 Replicación MySQL Master-Master 25.3 DRBD - Raid1 vía TCP 25.4 Heartbeat
632 639 649 658
Capitulo XXVI - Asterisk GUI …............................................................................................. 664 Capitulo XXVII – FreePBX …................................................................................................... 670 Apéndice A – Instalar CentOS 6.4 en una maquina virtual con VirtualBox
677
Apéndice B – Licencia GNU FDL
698
viii
Introducción versión 1.0 Esta el primera versión dedicada a la rama 11.X de Asterisk. La verdad es que Asterisk ha crecido mucho y en esta versión se empiezan a ver los frutos. Entre las nuevas y interesantes funcionalidades disponibles, podemos destacar por lo menos seis: •
La aplicación Confbridge que en la versión 11 ha sido ampliada y ahora tiene su propio archivo de configuración con muchas funcionalidades interesantes. Esto vuelve un poco obsoleta la aplicación Meetme y por consecuencias la obligación de instalar DAHDI para poder utilizar las conferencias audio.
•
El nuevo canal Chan_motif que repiensa totalmente la forma de conectarse a servidores Jabber y a los servicios de Google (Gtalk y GoogleVoce). La única nota doliente es que a partir de mayo 2014, Google abandonará por completo el soporte del protocolo XMPP.
•
El nuevo modulo res_corosync que permite compartir el estado de las extensiones entre distintos servidores Asterisk
•
La nueva funcionalidad que permite a Asterisk actuar como Gateway T38 para el envío y recepción de FAX utilizando este protocolo.
•
El envío y recepción de mensajes instantáneos entre las extensiones configuradas.
•
La implementación del protocolo WebRTC 1 que según muchos “gurús” del VoIP, representa una revolución en la forma de comunicar.
El pasaje de la escritura del libro de la versión 1.8.X a la versión 11.X no ha sido fácil. Está siempre en acecho el olvidarse de tratar partes importantes y/o omitir configuraciones que puedan ser muy útiles a la hora de implementar una solución basada en esta ultima versión. Espero que este libro esté a la altura de sus expectativas y los invito a enviar sus consejos, propuestas, correcciones, al siguiente correo electrónico:
[email protected] ¡Hasta pronto!
Introducción versión 1.1 Se ha actualizado el libro a las ultimas versiones disponibles de DAHDI, Asterisk, Kernel. Se ha añadido el soporte DTLS a WebRTC (ahora obligatorio en Chrome y Firefox). Se ha rescrito parte del párrafo dedicado a los mensajes instantáneos ya que la ultima versión de Xlite no funciona más con Asterisk. Se ha testado nuevamente el soporte TLS y SRTP con el cliente Blink y confirmo que 1 http://es.wikipedia.org/wiki/WebRTC
ix
funciona perfectamente. Creo que es todo. ¡Hasta pronto!
x
Introducción versión 1.2 En esta versión más que nada se han actualizado todos los programas utilizados a las ultimas versiones disponibles. Se han corregido, como siempre, más errores de ortografía y de sintaxis. En la próxima versión se tiene planeado añadir nuevos parrafos (LDAP, Servidor XMPP Ejabber). ¡Hasta Pronto!
Capitulo I Instalación de Asterisk Asterisk es el programa Open Source más reconocido para implementar una PBX. Para una lista completa de las funcionalidades brindadas, visiten la página de los desarrolladores. Entre ellas: • • • • • • • • • •
Registro (Log) de llamadas Grabación de llamadas Desvío de llamadas Trasferencia de llamadas Conferencias audio Música en espera Gestión de colas (call center) Soporte para tarjetas y Gateway FXO, FXS, digitales y celulares IVR Buzón de voz
Este libro abarca la instalación de Asterisk en un VPS (Servidor Virtual Privado) remoto y es valida para cualquier Servidor Linux CentOS. Con el VPS remoto la ventaja es tener una PBX siempre activa, independiente de la banda ancha disponible en la casa/oficina y evita tener una computadora dedicada y siempre encendida. En este caso, considerando la relación calidad/precio, se ha optado por los VPS de la empresa Linode. Para aquellos que quieran trabajar con un servidor local, en la apéndice A es presente una guía para la instalación de CentOS en VirtualBox. 1.1
Preparación del VPS
Los VPS de Linode, utilizan como sistema de virtualización Xen y vienen con un Kernel personalizado. Para poder trabajar con el ultimo Kernel disponible de la versión de CentOS instalada, se modificará la configuración del servidor, instalando el sistema de arranque GRUB y luego iniciando el servidor con la opción pv-grub-x86_64 configurada. De esta forma el servidor se iniciará con el Kernel configurado en el archivo menu.lst que habrá que crear. Una vez creada una cuenta en Linode, se accede a la pagina de administración y se adquiere un nuevo VPS:
Se selecciona el tamaño de la RAM del VPS (1024) y el centro de datos que lo hospedará (Dallas). Se confirma la compra presionando el botón “Add This Linode!”.
En la nueva pagina se selecciona el enlace que sigue (el numero es único por cada Linode):
En la nueva ventana que aparece se selecciona el siguiente enlace:
2
se configuran algunos parámetros (distribución Linux, Memoria disco, swap y contraseña del usuario root. En el disco duro se deja espacio para la creación de dos particiones que luego se utilizarán para la configuración de alta disponibilidad:
Se presiona el botón “Deploy”. Luego con el espacio libre que queda en el disco duro, se crean dos nuevas particiones:
Se crea la primera partición de 1000 Mb que es donde se guardarán los datos de alta disponibilidad:
3
y la segunda para los meta-datos del programa DRDB que se utilizará para el alta disponibilidad:
El resultado final:
Una vez que el sistema haya terminado la configuración, ya se puede iniciar el servidor presionando el botón “Boot”:
4
Como se puede ver en la imagen, el Kernel que se instala es la versión “Latest 64 bit (3.19.1-x86_64linode53). De esta versión no hay las fuentes disponibles y eso imposibilita la instalación de DAHDI y, en general, de todos los programas que se instalan como módulos del Kernel. Por eso en los próximos párrafos se verá como instalar en el servidor Linode la ultima versión disponible del Kernel Linux y el sistema de arranque GRUB. Una vez que el servidor esté corriendo, como indicado en la imagen que sigue, que aparece en el lado derecho de la pagina de administración de Linode, se puede acceder al servidor con el programa PuTTy (un cliente SSH):
Para conocer la dirección IP del servidor Linode, se entra en la siguiente pagina, donde aparecen todos los datos de configuración de red relativos al VPS:
Se descarga el programa PuTTy para Windows desde esta pagina: http://the.earth.li/~sgtatham/putty/latest/x86/putty.exe
5
Una vez descargado se ejecuta. Aparecerá la siguiente ventana:
En “Host Name (or IP address) se pone la dirección IP del servidor Linode, en “Port” 22 y en “Saved Sessions” un nombre que identifique la conexión al VPS. Terminada la configuración se presiona el botón “Save” y luego el botón “Open” que aparece más abajo. Se abrirá una nueva ventana donde en “login as” hay que poner root y en “password” la contraseña que se ha escogido al momento de la instalación del sistema operativo. Si se está utilizando Linux se abre una ventana terminal y para conectarse al servidor remoto se ejecuta el siguiente comando: ssh root@IPLinode El resultado será:
La primera cosa que hay que hacer es actualizar el sistema: yum update -y De esta forma actualizará la versión 6.5 64bit de CentOS con los últimos paquetes disponibles. Para corroborarlo: cat /etc/redhat-release CentOS release 6.6 (Final) 6
Luego se instala el ultimo Kernel Linux disponible y el sistema de arranque GRUB: yum install kernel grub -y Se averigua la versión del Kernel que se ha instalado: rpm -q kernel kernel-2.6.32-504.12.2.el6.x86_64 y con esos datos se configura GRUB. Si la versión del Kernel cambia, modificar las lineas según la nueva versión: nano /boot/grub/grub.conf #boot=/dev/xvda default=0 timeout=5 title CentOS (2.6.32-504.12.2.el6.x86_64) root (hd0) kernel /boot/vmlinuz-2.6.32-504.12.2.el6.x86_64 root=/dev/xvda initrd /boot/initramfs-2.6.32-504.12.2.el6.x86_64.img Se guardan las modificaciones y se crea un enlace simbólico al archivo menu.lst que será leido por pvgrub: ln -s /boot/grub/grub.conf /boot/grub/menu.lst El paso a seguir es modificar la configuración del servidor Linode. Desde la pagina de administración se selecciona el enlace que aparece en la imagen:
En la nueva pagina se modifican los parámetros como indicado en las dos siguientes imágenes:
7
En Boot Settings – Kernel se selecciona “pv-grub-x86_64”
En Block Device Assignment, se configuran las dos particiones que se han creado anteriormente para la alta disponibilidad:
8
En Filesystem/Boot Helpers se modifican las dos opciones indicadas en la imagen. Para terminar se guardan los cambios presionando el botón “Save Changes”. Se regresará a la pagina principal del servidor Linode y de ahí se reinicia:
Para averiguar que efectivamente el sistema se reinicia utilizando el Kernel Linux instalado y el gestor de arranque GRUB, en la pagina de Linode se entra en el menú “Remote access” y luego se sigue el enlace “Launch Lish Ajax Console” che permite acceder al servidor desde una consola local. Se abrirá una nueva ventana y después de unos segundos aparecerá esta imagen:
1.2 SSH y clave RSA RSA es un sistema criptográfico de clave publica che permite la configuración de conexiones seguras. Para crear la clave RSA hay que descargar el programa PuTTygen (para Windows). 1.2.1 Clave RSA en Windows Para crear la clave RSA se descarga el programa PuTTygen: http://the.earth.li/~sgtatham/putty/latest/x86/puttygen.exe Se ejecuta:
9
En “Number of bits in a generated key” se pone 2048 y luego se presiona el botón “Generate”. Para la creación de la clave se necesita generar una serie aleatoria de números y esto se realiza moviendo el ratón en el cuadro que aparece bajo la linea “Key”:
Hay que seguir moviendo el ratón hasta que la barra que aparece no llegue al final de la linea. Terminada la operación se tendrá disponible la clave RSA (publica y privada): 10
IMPORTANTE: para aumentar la seguridad de la clave privada, se puede asociar una contraseña. La contraseña se escribe en la casilla “Key passphrase” y se repite en “Confirm passphrase”. Se guarda la clave privada en una carpeta del ordenador local presionando el botón “Save private key”(en este caso se nombra claveprivada):
Para continuar se selecciona todo el texto que aparece en la imagen que sigue, se presiona el botón derecho del ratón y se escoge en el menú “copiar”:
11
El texto copiado es la clave publica. Se accede nuevamente con PuTTy al servidor remoto y se sigue este procedimiento para utilizar la clave publica; se crea la carpeta ssh: mkdir .ssh se permite el acceso a la carpeta creada solamente al usuario root: chmod 700 .ssh se entra en la carpeta: cd .ssh se crea el archivo authorized_keys que es donde el sistema buscará las claves RSA publicas del sistema (en este caso para el usuario root): nano authorized_keys se pega el contenido copiado desde PuTTygen que debe quedar todo en la misma linea:
12
Se guarda el archivo presionando las teclas CTRL-X. Se asigna al archivo recién creado los permisos de lectura y escritura solamente para el usuario root: chmod 600 /root/.ssh/authorized_keys Ya se puede continuar con la configuración del servidor SSH (párrafo 1.2.3). 1.2.2 Clave RSA en Linux Se accede al servidor Linux LOCAL como usuario root y e la ventana terminal se escribe: cd /root mkdir .ssh se permite el acceso a la carpeta creada solamente al usuario root: chmod 700 .ssh se entra en la carpeta: cd .ssh Se crea la clave RSA ssh-keygen -t rsa Enter file in which to save the key (/root/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /root/.ssh/id_rsa. Your public key has been saved in /root/.ssh/id_rsa.pub. The key fingerprint is: 2e:86:eb:d0:8e:2d:49:1f:0e:83:a8:b2:45:e7:2b:26 root@li215-240 The key's randomart image is: +--[ RSA 2048]----+ |... . S | |o.++.. . | |..o*+.o . | |E.==o+ . | 13
|o+.+* | +-----------------+ [root@li215-240 .ssh]# ls -l total 8 -rw------- 1 root root 1675 Mar 11 20:06 id_rsa -rw-r--r-- 1 root root 396 Mar 11 20:06 id_rsa.pub Cuando el sistema lo solicita (lineas en negrita), se puede configurar la clave con una contraseña. Se crearán dos archivos: • •
id_rsa que contiene la clave privada id_rsa.pub que contiene la clave publica
El segundo archivo se copia en el servidor Linode remoto: scp id_rsa.pub root@IPservidorremoto:/tmp Con este comando se copia la clave publica en la carpeta /tmp del servidor remoto. Luego se añade la clave al archivo authorized_keys en la carpeta /root/.ssh cat /tmp/id_rsa.pub >> /root/.ssh/authorized_keys Se borra la clave publica: rm /tmp/id_rsa.pub y se cambian los permisos del archivo authorized_keys: chmod 600 /root/.ssh/authorized_keys Ya se puede continuar con la configuración del servidor SSH (párrafo 1.2.3). 1.2.3 Configuración servidor SSH Terminada la operación de creación y configuración de las claves RSA, hay que modificar algunos parámetros del servidor SSH para permitir el acceso al VPS solamente al usuario root si se autentica con la clave RSA; además, para aumentar la seguridad, se cambia el puerto predefinido para el acceso SSH (22 TCP), escogiendo otro (15000 TCP). Esto se realiza modificando el archivo de configuración del servidor SSH: nano /etc/ssh/sshd_config Se buscan estas lineas (para buscar un texto con el editor nano hay que presionar la tecla CTRL junto a la tecla W):
14
#Port 22 #RSAAuthentication yes PasswordAuthentication yes y se modifican para que queden: Port 15000 RSAAuthentication yes PasswordAuthentication no Se guardan los cambios y se reinicia el servidor SSH: /etc/init.d/sshd restart Se abre otra instancia del cliente SSH:
Se pone la IP del servidor Linode, come puerto el 15000 y se asigna un nuevo nombre a esta nueva conexión.
15
En la barra de la izquierda se busca el menú “SSH”, luego “Auth” y se presiona el botón “Browse”. Se busca la clave privada en la carpeta donde se ha guardado anteriormente y se selecciona. Se vuelve al menú Session (en la izquierda) y se guarda esta nueva configuración presionando el botón “Save”. Ahora hay dos sesiones disponibles en el cliente SSH: Linode y Linode2. Para acceder al servidor Linux se escoge la sesión Linode2, botón “Load” y luego botón “Open”. Debe aparecer esta ventana:
Una vez que se haya escrito el nombre de usuario root en “login as:”, automáticamente el cliente se conectará al servidor autenticándose con la clave RSA creada. Para conectarse desde el servidor Linux LOCAL: ssh -p 15000 root@localhost Para terminar la configuración del VPS, se modifica la hora predefinida del servidor: rm /etc/localtime rm: remove regular file `/etc/localtime'? Y 16
Se crea un enlace simbólico a la hora de Colombia (personalizar): ln -s /usr/share/zoneinfo/America/Bogota /etc/localtime se averigua que la hora sea exacta con el comando: date Fri Sep 5 09:46:36 COT 2014 Para que la hora se actualice de manera automática se instala el servidor NTP (Network Time Protocol): yum install ntp -y Se configura para que se inicie automáticamente al arrancar el servidor Linux: chkconfig ntpd on y se inicia: service ntpd start Starting ntpd:
[ OK ]
Para modificar el idioma predefinido (ingles) y ponerlo en español (de Colombia): nano /etc/sysconfig/i18n se modifica esta linea: LANG="en_US.UTF-8" para que quede (personalizar): LANG="es_CO.iso88591" Para activar el nuevo idioma basta salir y volver a entrar al servidor con PuTTy. Se revisa que Selinux esté desactivado: nano /etc/selinux/config averiguando que los dos parámetros que aparecen tengan el valor que sigue: SELINUX=disabled SELINUXTYPE=targeted
17
Se guardan los cambios. Como la IP publica viene asignada a través de un servidor DHCP y esto puede causar problemas si hay modificaciones en la configuración del servidor por parte de Linode, es buena practica configurar directamente la IP publica sin apoyarse a dicho servidor. Para realizar este cambio, se modifica el siguiente archivo: nano /etc/sysconfig/network-scripts/ifcfg-eth0 Se comenta el contenido previo y se añaden las siguiente lineas de forma que el archivo quede: #DEVICE="eth0" #BOOTPROTO="dhcp" #IPV6INIT="yes" #IPV6_AUTOCONF="yes" #ONBOOT="yes" #TYPE="Ethernet" DEVICE=eth0 BOOTPROTO=none IPV6INIT="no" IPV6_AUTOCONF="no" ONBOOT=yes IPADDR=173.255.194.236 NETMASK=255.255.255.0 GATEWAY=173.255.194.1 173.255.194.236 es la IP publica del servidor Linode (personalizar). Se guardan los cambios y se reinicia el sistema: reboot 1.3 Utilidades, librerías, dependencias Antes de la compilación de Asterisk, se instalarán una serie de librerías y dependencias que permitirán obtener la instalación de la mayoría de los módulos de la PBX. Se empieza con Vorbis que es una librería para la compresión/descompresión audio: yum install libvorbis libvorbis-devel vorbis-tools libogg libogg-devel -y se sigue con CURL que es un cliente que permite recibir o enviar archivos utilizando los protocolos HTTP, HTTPS, FTP, GOPHER, DICT, TELNET: yum install curl curl-devel libidn-devel -y se instalan todas las librerías y dependencias que se necesitan para compilar las fuentes: 18
yum install gcc ncurses-devel make gcc-c++ compat-libtermcap zlib-devel libtool bison-devel \ bison openssl-devel bzip2-devel wget newt-devel subversion flex gtk2-devel -y a seguir para crear y gestionar las bases de datos, MySQL: yum install mysql mysql-server mysql-devel -y Si en lugar de MySQL se quiere utilizar POSTGRESQL: yum install postgresql postgresql-devel postgresql-docs postgresql-libs postgresql-odbc postgresql-server -y
UNIXODBC que es la implementación Linux de los API ODBC que permiten conectarse a muchos sistemas de gestión de base de datos (ej: MySQL): yum install unixODBC unixODBC-devel mysql-connector-odbc libtool-ltdl-devel -y Como la base de datos interna de Asterisk se basa en SQLite, se instala el paquete del programa y el paquete de desarrollo: yum install sqlite sqlite-devel -y Se instala FESTIVAL, que es un sistema de text to speech (disponible en español): yum install festival festival-devel hispavoces-pal-diphone hispavoces-sfl-diphone -y Para las librerías de pjproject incluidas en Asterisk 11.X, se instala libuuid: yum install libuuid libuuid-devel uuid uuid-devel -y Una vez terminada esta parte se empieza a instalar una serie de programas desde las fuentes; En teoría algunos de estos programas se podrían instalar como paquetes desde los repositorios de CentOS pero la idea es ver como se instalan los programas desde las fuentes para tener algo de practica. El primero es SPEEX que es un programa para la compresión audio específicamente diseñado para la voz. IMPORTANTE: Para todos los programas que se instalan desde las fuentes, antes de descargarlos, averiguar si hay una versión más reciente disponible. cd /usr/src wget http://downloads.xiph.org/releases/speex/speex-1.2rc1.tar.gz tar -xf speex-1.2rc1.tar.gz cd speex-1.2rc1 ./configure --prefix=/usr --libdir=/usr/lib64/ 19
make make install Se continua con LAME que se utiliza para codificar/decodificar archivos audio en formato MP3: cd /usr/src wget http://ufpr.dl.sourceforge.net/sourceforge/lame/lame-3.99.5.tar.gz tar -xf lame-3.99.5.tar.gz cd lame-3.99.5 ./configure --prefix=/usr --libdir=/usr/lib64/ make make install LIBMAD que es un MPEG audio decodificador de alta calidad: cd /usr/src wget http://prdownloads.sourceforge.net/mad/libmad-0.15.1b.tar.gz tar -xf libmad-0.15.1b.tar.gz cd libmad-0.15.1b ./configure --prefix=/usr --libdir=/usr/lib64/ Para que la compilación tenga éxito hay que modificar una linea del Makefile: nano +129 Makefile CFLAGS = -Wall -g -O -fforce-mem -fforce-addr -fthread-jumps -fcse-follow-jumps -fcse-skipblocks -fexpensive-optimizations -fregmove -fschedule-insns2 para que quede: CFLAGS = -Wall -g -O -fforce-addr -fthread-jumps -fcse-follow-jumps -fcse-skip-blocks -fexpensive-optimizations -fregmove -fschedule-insns2 Se guardan los cambios y se continua con la compilación e instalación: make make install WAVPACK es un compresor audio de alto rendimiento sin perdida de calidad: 20
cd /usr/src wget http://www.wavpack.com/wavpack-4.70.0.tar.bz2 tar -xf wavpack-4.70.0.tar.bz2 cd wavpack-4.70.0 ./configure --prefix=/usr --libdir=/usr/lib64/ make make install Se termina con SOX que es un programa que permite la manipulación de archivos audio y la posibilidad de pasarlos de un formato a otro: cd /usr/src wget http://downloads.sourceforge.net/project/sox/sox/14.4.2/sox-14.4.2.tar.gz tar -xf sox-14.4.2.tar.gz cd sox-14.4.2 ./configure --prefix=/usr --libdir=/usr/lib64/ Al finalizar el configure aparecerá esta tabla donde se encontrarán todos los formatos audio que se podrán manipular con SOX:
21
Se termina con la compilación e instalación: make make install 1.4 DAHDI El paquete DADHI (Digium Asterisk Hardware Device Interface) permite cargar los drivers y configurar distintos tipos de tarjetas en Asterisk (analógicas, digitales, RDSI/ISDN, cancelador de ECHO). Asterisk además se apoya en DAHDI para las conferencias audio (modulo app_meetme) y el trunking IAX2 (tema tratado en la configuración del archivo iax.conf). Aunque su instalación ya no es indispensable, para las conferencias audio existe la aplicación ConfBridge que es mucho más completa, se instalará para tener todos los módulos disponibles. Se instala el paquete de desarrollo del Kernel: yum install kernel-devel -y Se continua con la ultima versión disponible de DAHDI-Linux: cd /usr/src wget http://downloads.asterisk.org/pub/telephony/dahdi-linux/dahdi-linux-current.tar.gz 22
tar -xf dahdi-linux-current.tar.gz cd dahdi-linux-2.10.0.1 make make install Se termina con la ultima versión disponible de DAHDI-Tools: cd /usr/src wget http://downloads.asterisk.org/pub/telephony/dahdi-tools/dahdi-tools-current.tar.gz tar -xf dahdi-tools-current.tar.gz cd dahdi-tools-2.10.0.1 ./configure make make install make config Ya se puede iniciar DAHDI: /etc/init.d/dahdi start Loading DAHDI hardware modules: wct4xxp: wcte43x: wcte12xp: wcte13xp: wct1xxp: wcte11xp: wctdm24xxp: wcaxx: wcfxo: wctdm: wcb4xxp: wctc4xxp: xpp_usb: Running dahdi_cfg:
[ OK ] [ OK ] [ OK ] [ OK ] [ OK ] [ OK ] [ OK ] [ OK ] [ OK ] [ OK ] [ OK ] [ OK ] [ OK ] [ OK ]
En el caso del servidor Linode, como no se va a instalar ningún tipo de tarjeta, es buena practica no cargar todos los driver de DAHDI al momento de su arranque para ahorrar recursos de sistema. Esto se realiza modificando este archivo:
23
nano /etc/dahdi/modules y se añade el carácter # a todas las lineas que no lo tienen. Se guardan las modificaciones y se reinicia DAHDI: service dahdi restart Unloading DAHDI hardware modules: done Loading DAHDI hardware modules: Running dahdi_cfg:
[ OK ]
1.5 LIBPRI En el caso que se quiera instalar tarjetas digitales en el servidor Asterisk (E1, T1, ISDN), después de instalar DAHDI, hay que instalar la librería libpri cd /usr/src wget http://downloads.asterisk.org/pub/telephony/libpri/libpri-1.4.14.tar.gz se descomprime: tar -xf libpri-1.4.14.tar.gz se entra en la carpeta: cd libpri-1.4.14 se compila y se instala: make make install 1.6 Res_fax, XMPP, LibiCAL y SRTP En este párrafo se verá como instalar SpanDSP, un procesador de señales digitales que en Asterisk permite la instalación del modulo res_fax para la recepción y envío de FAX, y IKSEMEL que permite implementar el protocolo XMPP en Asterisk y de esta forma conectarse a GoogleTalk y/o a cualquier servidor de tipo XMPP (otro ejemplo es Openfire): Para SpanDSP se necesita instalar primero las librerías libtiff y libxml2: yum install libtiff libtiff-devel libxml2 libxml2-devel -y se continua con SpanDSP: 24
cd /usr/src wget http://www.soft-switch.org/downloads/spandsp/spandsp-0.0.6pre21.tgz tar -xf spandsp-0.0.6pre21.tgz cd spandsp-0.0.6 ./configure --prefix=/usr --libdir=/usr/lib64/ make make install El protocolo XMPP permite conexione seguras entre cliente y servidor utilizando el protocolo TLS; para ese efecto se instala, antes de IKSEMEL, las relativas librerías: yum install gnutls gnutls-devel gnutls-utils -y se continua con IKSEMEL: cd /usr/src wget http://iksemel.googlecode.com/files/iksemel-1.4.tar.gz tar -xf iksemel-1.4.tar.gz cd iksemel-1.4 ./configure --prefix=/usr --libdir=/usr/lib64/ make antes de la instalación se ejecuta un test para averiguar que la compilación haya tenido éxito: make check PASS: tst-ikstack PASS: tst-iks PASS: tst-sax PASS: tst-dom PASS: tst-sha PASS: tst-md5 PASS: tst-filter PASS: tst-jid ================== All 8 tests passed ================== Ya que todo está bien, se puede instalar: 25
make install Antes de la instalación de Asterisk, se termina la preparación del sistema con unos programas más. Primero un servidor de correo electrónico, SENDMAIL: yum install sendmail sendmail-devel sendmail-cf -y Se remueve el servidor de correo electrónico predefinido POSTFIX: service postfix stop yum remove postfix -y Se configura Sendmail para que se inicie en automático: chkconfig sendmail on Al alquilar el servidor Linode, cada usuario tiene asignado un sub-dominio que se puede utilizar para la configuración del sistema. Este dato aparece en la pagina de administración de Linode, bajo el menú “Remote Access”
En este caso el sub-dominio asignado es li204-236.members.linode.com . Ese nombre se pone en la configuración de red del servidor de la siguiente forma: nano /etc/sysconfig/network se modifica la linea HOSTNAME de modo que quede: HOSTNAME=li204-236.members.linode.com
26
Se guardan los cambios y se reinicia el servicio de red: service network restart El sub-dominio se utilizará también para el envío de los correos electrónicos. Por defecto el servidor de correo electrónico escucha solamente en la puerto TCP 25 local. Para que sea alcanzable también desde remoto hay que abrir el archivo de configuración de Sendmail: nano /etc/mail/sendmail.mc se busca esta linea: DAEMON_OPTIONS(`Port=smtp,Addr=127.0.0.1, Name=MTA')dnl y se modifica como sigue: DAEMON_OPTIONS(`Port=smtp,, Name=MTA')dnl se guardan los cambios y se vuelve a compilar la configuración de Sendmail: make -C /etc/mail se reinicia el servidor de correo: /etc/init.d/sendmail start Si en Windows se tiene instalado el programa Telnet, para realizar la prueba de conexión al servidor de correo electrónico desde remoto, se abre una ventana terminal y se escribe: C:\> telnet -a IPLinode 25 En lugar de IPLinode se pone la IP del servidor Linode. El resultado:
OpenLDAP es la versión open source del protocolo Lightweight Directory Access. Normalmente se utiliza para crear un directorio de usuarios que puede ser consultado y/o modificado desde remoto. Muchos programas implementan la posibilidad de conectarse a un servidor OpenLDAP y Asterisk, desde la versión 1.6.X, presenta esta posibilidad: yum install compat-openldap openldap openldap-clients openldap-devel openldap-servers -y SNMP es el Protocolo Simple de Administración de Red y sirve para controlar y monitorear el 27
desempeño del servidor Linux. En Asterisk permite monitorear, entre otras cosas, los canales y las llamadas. Se utilizará junto a NAGIOS para monitorear el servidor Asterisk y enviar avisos cuando se verifique algún tipo de problema: yum install net-snmp net-snmp-devel net-snmp-libs net-snmp-utils -y Para poder compartir el estado de extensiones entre servidores Asterisk, se instala COROSYNC: yum install corosync corosynclib corosynclib-devel -y En Asterisk existe la posibilidad de guardar los registros de las llamadas en un servidor RADIUS a través de un cliente RADIUS que hay que instalar. En este caso se instala desde las fuentes: cd /usr/src wget http://colocrossing.dl.sourceforge.net/project/radiusclient-ng.berlios/radiusclient-ng-0.5.6.tar.gz
tar -xf radiusclient-ng-0.5.6.tar.gz cd radiusclient-ng-0.5.6 ./configure --prefix=/usr --libdir=/usr/lib64 make make install Se continua la preparación del servidor con la instalación del lenguaje de programación LUA que permite escribir el dialplan (o plan de marcado) utilizando este lenguaje. Al terminar la instalación de Asterisk se encontrará un archivo de ejemplo en la carpeta /etc/asterisk. En este caso se instala desde las fuentes. Primero unas dependencias: yum install readline-devel -y luego el programa: cd /usr/src wget http://www.lua.org/ftp/lua-5.1.5.tar.gz tar -xf lua-5.1.5.tar.gz cd lua-5.1.5 Se modifica el archivo Makefile para que el programa se instale por defecto en la carpeta /usr: nano Makefile se modifica esta linea: 28
INSTALL_TOP= /usr/local para que quede: INSTALL_TOP= /usr Para la versión CentOS de 64bit hay que modificar también este archivo: nano src/Makefile cambiar esta linea: CFLAGS= -O2 -Wall $(MYCFLAGS) para que quede: CFLAGS= -O2 -Wall -fPIC $(MYCFLAGS) Se guardan los cambios, se compila e instala: make linux make install Para terminar se compilan los paquetes que permiten utilizar las funcionalidades calendario de Asterisk. Primero LIBICAL que permite la implementación del protocolo iCalendar (RFC5546) a través del modulo res_calendar: cd /usr/src wget http://downloads.sourceforge.net/project/freeassociation/libical/libical-1.0/libical-1.0.tar.gz
tar -xf libical-1.0.tar.gz cd libical-1.0 ./autogen.sh --prefix=/usr --libdir=/usr/lib64 make make install Luego NEON que es una librería que permite la implementación del protocolo WebDAV en Asterisk: cd /usr/src wget http://www.webdav.org/neon/neon-0.30.0.tar.gz tar -xf neon-0.30.0.tar.gz 29
cd neon-0.30.0 ./configure --prefix=/usr --libdir=/usr/lib64 make make install Por ultimo la librería LIBSRTP que permite implementar el cifrado del flujo media en Asterisk a través del protocolo SRTP (RFC3711). De esta librería se instalará un fork que ha aumentado las opciones disponibles y mejorado el cifrado de audio. Como las fuentes están disponibles en Github, para descargarlas se utilizará el programa GIT que hay que instalar: yum install git words -y Luego se descargan las fuentes: cd /usr/src git clone https://github.com/cisco/libsrtp libsrtp Se entra en la carpeta creada: cd libsrtp Se compila e instala: ./configure --prefix=/usr CFLAGS=-fPIC --libdir=/usr/lib64 make make runtest make install 1.7 Instalación de Asterisk Terminada la preparación del servidor, se inicia con la instalación de Asterisk. Se descarga la ultima versión 11.X disponible: cd /usr/src wget http://downloads.asterisk.org/pub/telephony/asterisk/asterisk-11.17.1.tar.gz tar -xf asterisk-11.17.1.tar.gz cd asterisk-11.17.1 ./configure --libdir=/usr/lib64 make menuselect 30
Desde la versión 1.8.X lo que antes era un paquete a parte (asterisk-addons) ahora es presente en el paquete principal de Asterisk. Como se puede notar, los módulos relacionados con MySQL (menos res_mysql) son “deprecated” y muy probablemente en las futuras versiones serán eliminados. Se entra en el menú “Add-ons” y se activan los paquetes que siguen:
Desde la versión 11.X, la aplicación MeetMe (conferencias audio) está desactivada. Asegurarse seleccionarla para que el modulo sea compilado (menú izquierdo Applications):
El menú “Channel Event Logging” que como se verá más adelante, permite complementar el CDR (call detail record) con nuevas informaciones relacionadas con las llamadas:
Para ambientes virtualizados, en “Compiler Flags” se deselecciona el parámetro “Build Native”:
En “Resource modules” se controla que los módulos relacionados con las funciones calendario y cifrado del flujo media estén activados: 31
Se seleccionan todos los módulos en el menú “Utilities” y “AGI Samples”:
En “Core Sound Packages” se seleccionan todos los paquetes disponibles:
32
En “Music On Hold File Packages” se hace lo mismo:
Como se hace lo mismo en “Extra Sound Packages”:
33
Se guarda la configuración presionando la tecla tabulador hasta posicionarse sobre “Save & Exit”. Se termina con la compilación e instalación: make Si a lo largo de la compilación aparece este error: make[1]: *** [format_mp3.o] Error 1 make: *** [addons] Error 2 se continua con: contrib/scripts/get_mp3_source.sh y luego otra vez el make: make se instala Asterisk: make install se instalan los archivos de configuración predefinidos: make samples se configura el script de arranque de Asterisk: make config
34
Terminada la instalación, se procede a la configuración de MySQL para crear la base de datos y la tabla donde se guardarán los registros de las llamadas. /etc/init.d/mysqld start se configura para que arranque en automático: chkconfig mysqld on y se crea una contraseña para el usuario root de MySQL (sesamo): IMPORTANTE: para un sistema en producción utilizar siempre contraseñas fuertes mysqladmin -u root password sesamo Para asegurar el servidor MySQL se ejecuta el programa: mysql_secure_installation Se contestan las preguntas somo sigue: Enter current password for root (enter for none): sesamo OK, successfully used password, moving on... Change the root password? [Y/n] n ... skipping. Remove anonymous users? [Y/n] y ... Success! Disallow root login remotely? [Y/n] y ... Success! Remove test database and access to it? [Y/n] y - Dropping test database... Reload privilege tables now? [Y/n] y ... Success! Cleaning up... All done! If you've completed all of the above steps, your MySQL installation should now be secure. Thanks for using MySQL! 35
Se configura la zona horaria en MySQL: mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -psesamo mysql Warning: Unable to load '/usr/share/zoneinfo/iso3166.tab' as time zone. Skipping it. Warning: Unable to load '/usr/share/zoneinfo/zone.tab' as time zone. Skipping it. nano /etc/my.cnf Bajo la etiqueta [mysqld] se añade (personalizar): default-time-zone = America/Bogota Se reinicia el servidor MySQL: service mysqld restart Se crea la base de datos para guardar los registros de las llamadas. Se entra en el cliente de MySQL: mysql -u root -psesamo se crea la base de datos asteriskcdr: mysql> create database asteriskcdr; se selecciona: mysql> use asteriskcdr se crea la tabla cdr (copiando y pegando las lineas que siguen): mysql> CREATE TABLE cdr ( calldate datetime NOT NULL default '0000-00-00 00:00:00', clid varchar(80) NOT NULL default '', src varchar(80) NOT NULL default '', dst varchar(80) NOT NULL default '', dcontext varchar(80) NOT NULL default '', channel varchar(80) NOT NULL default '', dstchannel varchar(80) NOT NULL default '', lastapp varchar(80) NOT NULL default '', lastdata varchar(80) NOT NULL default '', duration int(11) NOT NULL default '0', billsec int(11) NOT NULL default '0', disposition varchar(45) NOT NULL default '', amaflags int(11) NOT NULL default '0', accountcode varchar(20) NOT NULL default '', peeraccount varchar(20) NOT NULL default '', 36
uniqueid varchar(32) NOT NULL default '', linkedid varchar(80) NOT NULL default '', userfield varchar(255) NOT NULL default '', KEY callerid (clid) ); Desde la versión 1.8 de Asterisk se han añadido dos nuevos campos a la tabla CDR: • •
linkedid peeraccount
que permiten tener informaciones más detalladas de cada llamada. Se otorgan los permisos de acceso a la base de datos creada al usuario asterisk, desde local: mysql> GRANT ALL PRIVILEGES ON asteriskcdr.* TO 'asterisk'@'localhost' IDENTIFIED BY 'sesamo'; SOLAMENTE si se necesita desde remoto: mysql> GRANT ALL PRIVILEGES ON asteriskcdr.* TO 'asterisk'@'%' IDENTIFIED BY 'sesamo'; se actualizan los permisos: mysql> flush privileges; se sale del cliente: mysql> quit En Asterisk la conexión a la base de datos y la tabla de los registros de las llamadas, se configura en el archivo cdr_mysql.conf. Se renombra el predefinido: mv /etc/asterisk/cdr_mysql.conf /etc/asterisk/cdr_mysql.conf.old se crea uno nuevo: nano /etc/asterisk/cdr_mysql.conf se añaden las siguientes lineas: [global] hostname=localhost dbname=asteriskcdr table=cdr 37
password=sesamo user=asterisk port=3306 sock=/var/lib/mysql/mysql.sock Los datos: 1. [global] – etiqueta inicial del bloque 2. hostname - nombre de dominio o IP del servidor MySQL 3. dbname - nombre de la base de datos 4. table - nombre de la tabla 5. password - contraseña del usuario que tiene los permisos para acceder a la base de datos 6. user - nombre del usuario que tiene los permisos para acceder a la base de datos 7. port – puerto donde MySQL recibirá las conexiones (predefinido 3306) 8. sock – archivo que se crea (socket) cuando se inicia MySQL y que se necesita indicar para una correcta conexión cuando en hostname se configura como valor “localhost” Se guardan los cambios y se inicia Asterisk: /etc/init.d/asterisk start se averigua que esté corriendo: /etc/init.d/asterisk status asterisk (pid 2403) is running... se entra en la consola: asterisk -rvvvvvvvvvvvvvvvv se controla que la conexión a la base de datos esté funcionando: CLI> cdr mysql status Connected to asteriskcdr@localhost, port 3306 using table cdr for 59 seconds. Wrote 0 records since last restart. Se sale de la consola: CLI> quit Executing last minute cleanups Todos los registros de la actividad de Asterisk se guardarán en /var/log/asterisk/messages. En ese archivo estarán presentes una serie de errores que se irán corrigiendo a lo largo del libro.
38
Capitulo II Configuración inicial de Asterisk 2.1 Instalar y configurar un cortafuegos Para proteger el servidor Linux de accesos no autorizados hay que instalar un firewall (cortafuegos) y abrir los puertos que Asterisk necesita para aceptar conexiones externas. Esta es la parte más delicada de la configuración del servidor porque es donde se definen los puertos y los servicios que son accesibles desde Internet. En el caso del VPS Linode se instalará y Configurará IPtables. Si Asterisk se encuentra instalado en un computador local conectado a Internet a través de un router hay dos opciones: • •
Abrir los puertos desde la pagina de administración del router. Configurar en el router una DMZ que apunte a la IP local del servidor donde está instalado Asterisk y luego gestionar los puertos directamente con IPtables en el servidor Linux
Para instalar iptables: yum install iptables -y Iptables se encarga de gestionar todos los paquetes que entren y salgan del servidor Linux. Para eso utiliza tres tipos de tablas: •
la tabla filter donde pasan todos los paquetes en entrada y salida. La tabla filter acepta tres tipos de opciones (cadenas) • INPUT para los paquetes en entrada • OUTPUT para los paquetes en salida • FORWARD para redireccionar los paquetes
• •
la tabla NAT se utiliza para rescribir las direcciones o los puertos de los paquetes la tabla MANGLE se utiliza para modificar algunos parámetros de los paquetes (un ejemplo es marcar los paquetes para que sean procesados y enviados con una prioridad más alta)
Las reglas se definen una por linea y serán procesadas por iptables siguiendo la misma secuencia. Cuando no se especifica diversamente, todas las reglas aplicarán a la tabla filter: Se acepta todo el trafico en entrada con destino la interfaz lookpack iptables -A INPUT -i lo -j ACCEPT Se rechaza (REJECT) todo el trafico entrante destinado a las IP 127.0.0.0/127.255.255.255 menos los paquetes para la interfaz -lo
iptables -A INPUT ! -i lo -d 127.0.0.0/8 -j REJECT Se aceptan todos los paquetes en entrada de conexiones ya establecidas, o relacionados con conexiones establecidas. Véase protocolo TCP iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT Se dejan pasar todos los paquetes salientes. iptables -A OUTPUT -j ACCEPT Se deja pasar todo el trafico en entrada para el protocolo SSH (puerto 15000 TCP) iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 15000 -j ACCEPT Se deja pasar todo el trafico en entrada destinado al puerto udp 4569 (protocolo IAX2) iptables -A INPUT -p udp --dport 4569 -j ACCEPT Se bloquea el trafico sobre el puerto 5060 procedente de los más conocidos programas de escaneo de servidores SIP utilizados para ataques y fraudes de llamadas: iptables -A INPUT -p udp -m udp --dport 5060 -m string --string "friendly-scanner" --algo bm -j DROP
iptables -A INPUT -p udp -m udp --dport 5060 -m string --string "sipcli" --algo bm -j DROP iptables -A INPUT -p udp -m udp --dport 5060 -m string --string "VaxSIPUserAgent/3.0" --algo bm -j DROP
iptables -A INPUT -p udp -m udp --dport 5060 -m string --string "sipvicious" --algo bm -j DROP Se deja pasar todo el trafico en entrada destinado al puerto udp 5060 (protocolo SIP) iptables -A INPUT -p udp --dport 5060 -j ACCEPT Se deja pasar todo el trafico en entrada destinado al puerto tcp 5060 (protocolo SIP sobre TCP) iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 5060 -j ACCEPT Se deja pasar todo el trafico en entrada destinado a los puertos udp que van de 10000 a 20000 (protocolo RTP) iptables -A INPUT -p udp --dport 10000:20000 -j ACCEPT Se dejan pasar las solicitudes de ping iptables -A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT
41
A este punto, ya que se han definido los puertos base que se necesitan abiertos, se bloquea todo el trafico restante. iptables -A INPUT -j REJECT iptables -A FORWARD -j REJECT Se averigua el estado de las reglas definidas con el comando: iptables -L Aparecerá: Chain INPUT (policy ACCEPT) target prot opt source destination ACCEPT all -- anywhere anywhere REJECT all -- anywhere loopback/8 ACCEPT all -- anywhere anywhere ACCEPT tcp -- anywhere anywhere ACCEPT udp -- anywhere anywhere DROP udp -- anywhere anywhere ALGO name bm TO 65535 DROP udp -- anywhere anywhere bm TO 65535 DROP udp -- anywhere anywhere "VaxSIPUserAgent/3.0" ALGO name bm TO 65535 DROP udp -- anywhere anywhere name bm TO 65535 ACCEPT udp -- anywhere anywhere ACCEPT tcp -- anywhere anywhere ACCEPT udp -- anywhere anywhere ACCEPT icmp -- anywhere anywhere REJECT all -- anywhere anywhere
udp dpt:sip state NEW tcp dpt:sip udp dpts:ndmp:dnp icmp echo-request reject-with icmp-port-unreachable
Chain FORWARD (policy ACCEPT) target prot opt source destination REJECT all -- anywhere anywhere
reject-with icmp-port-unreachable
reject-with icmp-port-unreachable state RELATED,ESTABLISHED state NEW tcp dpt:hydap udp dpt:iax udp dpt:sip STRING match "friendly-scanner" udp dpt:sip STRING match "sipcli" ALGO name udp dpt:sip STRING match udp dpt:sip STRING match "sipvicious" ALGO
Chain OUTPUT (policy ACCEPT) target prot opt source destination ACCEPT all -- anywhere anywhere Para guardar los cambios: service iptables save Saving firewall rules to /etc/sysconfig/iptables:
[ OK ]
Se inicia el servicio: 42
service iptables start Para iniciar iptables automáticamente: chkconfig iptables on Para terminar hay que configurar Asterisk para que use los puertos UDP desde 10000 hasta 20000 para el protocolo RTP (es el que se encarga, una vez establecida la conexión entre dos canales, del flujo audio/vídeo) Se renombra el archivo predefinido: mv /etc/asterisk/rtp.conf /etc/asterisk/rtp.conf.old Se crea uno nuevo: nano /etc/asterisk/rtp.conf Se copian las siguientes lineas: [general] rtpstart=10000 rtpend=20000 rtpchecksums=no dtmftimeout=3000 rtcpinterval=5000 strictrtp=yes icesupport=yes Los datos: • • • • • • • •
[general] – etiqueta inicial del archivo de configuración rtpstart – puerto inicial para el trafico RTP rtpend – puerto final para el trafico RTP rtpchecksums – Activar o no la suma de verificación en los paquetes RTP dtmftimeout – la cantidad de tiempo (en mili segundos) que un tono DTMF sin marcador de fin tiene los permisos para continuar en el trafico RTP mili segundos entre cada reporte del protocolo RTCP (protocolo che se utiliza para controlar el flujo RTP strictrtp – Lo paquetes que no proceden del mismo flujo RTP utilizado en la conexión serán eliminados icesupport – se activa el soporte para el protocolo ICE (RFC5245).
Se guardan los cambios efectuados y se recarga la configuración de Asterisk: 43
/etc/init.d/asterisk reload 2.2 Carpetas y archivos Al terminar la instalación de Asterisk unas cuantas carpetas nuevas serán creadas. /etc/asterisk Contiene todos los archivos de configuración de Asterisk. /usr/lib64/asterisk/modules Contiene todos los módulos compilados y utilizables en Asterisk. /var/lib/asterisk Que a su vez contiene las siguientes carpetas: agi-bin/ donde se guardan los script AGI. documentation/ contiene la documentación utilizada por la consola de Asterisk firmware/ Donde se guardan los firmware de las tarjetas en uso. images/ Donde las aplicaciones irán a buscar las imágenes cuando se comuniquen con teléfonos que soportan esta función. keys/ Donde se guardan las claves publicas y privadas que Asterisk necesita para autenticarse con otros servidores o servicios (Ej: DUNDi, IAX2). moh/ La música en espera que viene con la instalación de Asterisk (no mp3). phoneprov/ 44
donde se guardan los archivos de configuración de los teléfonos que se quiere aprovisionar directamente desde Asterisk sounds/ Contiene todas las locuciones que se pueden utilizar en el plan de marcado (dialplan). static-http/ donde se encuentran algunos programas para interactuar con Asterisk desde un navegador Web /var/spool/asterisk Que contiene: dictate/ Donde se guardarán los archivos audio creados con la aplicación Dictate(). meetme/ Donde se guardarán las grabaciones de las conferencias. monitor/ donde se guardarán los archivos audio de las grabaciones de las llamadas outgoing/ Donde hay que mover los archivos de llamadas (call files). system/ Carpeta para archivos temporales creados por la aplicación System(). tmp/ Carpeta donde se guardan los archivos temporales creados por algunas aplicaciones (Ej. buzón de voz). voicemail/ Donde se guardarán los archivos audio de los mensajes de voz dejados en el buzón de voz y los mensajes audio personalizados de cada usuario. /var/run/asterisk
45
Contiene la ID del proceso de Asterisk cuando esté corriendo. /var/log/asterisk Donde se guardarán todos los registros de Asterisk (errores, mensajes, llamadas y eventos, debug). De revisar cuando se tengan problemas con Asterisk. 2.3 asterisk.conf En el archivo asterisk.conf, que se encuentra en la carpeta /etc/asterisk, se puede modificar la configuración general de Asterisk. Se divide en cuatro bloques: • • • •
un bloque donde se definen las carpetas de trabajo de Asterisk un bloque donde se definen distintas opciones del funcionamiento de Asterisk un bloque donde se definen los permisos para el socket de Asterisk un bloque donde se define el tipo de comportamiento que debe tener Asterisk para determinadas aplicaciones (dialplan, AGI, Realtime).
[directories](!) astetcdir => /etc/asterisk astmoddir => /usr/lib64/asterisk/modules astvarlibdir => /var/lib/asterisk astdbdir => /var/lib/asterisk astkeydir => /var/lib/asterisk astdatadir => /var/lib/asterisk astagidir => /var/lib/asterisk/agi-bin astspooldir => /var/spool/asterisk astrundir => /var/run/asterisk astlogdir => /var/log/asterisk astsbindir => /usr/sbin El Bloque [directories] es donde se pueden cambiar las carpetas de configuración de Asterisk. El valor (!) después de la etiqueta [directories] indica que el bloque esta comentado (no será leído por Asterisk). [options] ;verbose = 3 ;debug = 3 ;alwaysfork = yes ;nofork = yes ;quiet = yes ;timestamp = yes ;execincludes = yes ;console = yes ;highpriority = ye ;initcrypto = yes 46
;nocolor = yes ;dontwarn = yes ;dumpcore = yes ;languageprefix = yes ;internal_timing = yes ;systemname = my_system_name ;autosystemname = yes ;mindtmfduration = 80 ;maxcalls = 10 ;maxload = 0.9 ;maxfiles = 1000 ;minmemfree = 1 ;cache_record_files = yes ;record_cache_dir = /tmp ;transmit_silence_during_record = yes ;transmit_silence = yes ;transcode_via_sln = yes ;runuser = asterisk ;rungroup = asterisk ;lightbackground = yes ;forceblackbackground = yes ;defaultlanguage = en ;documentation_language = en_US ;hideconnect = yes ;lockconfdir = no ;stdexten = gosub ;live_dangerously = no El Bloque [options] permite modificar algunas opciones de Asterisk. Por defecto todas las opciones están comentadas (no aplican). Algunos ejemplos: • • • • •
si se quiere quitar los colores en la consola de Asterisk, se quita el punto y coma de la linea nocolors=yes Si el sistema donde está instalado Asterisk no puede cursar más de 30 llamadas, se pone maxcalls = 30 y se quita el punto y coma delante de la linea si se quiere que al alcanzar un consumo del 0,9 (90%) de la CPU del servidor, no se curse más llamadas, se quita el punto y coma delante de maxload = 0.9 si en lugar del usuario y grupo root, se quiere que Asterisk arranque con usuario y grupo asterisk (que hay que crear) se quita el punto y coma delante de runuser = asterisk y rungroup = asterisk si se utiliza un servidor dedicado para la base de datos y todos los registros de llamadas de distintos servidores Asterisk se guardan en ese servidor, no hay forma de saber de cual servidor es un determinado registro. Para que esto sea posible, en cada servidor Asterisk hay que configurar el parámetro systemname con un valor que identifique el servidor Asterisk. De esta forma en los registros de llamadas se podrá saber en cual PBX se originó la llamada.
47
;[files] ;astctlpermissions = 0660 ;astctlowner = root ;astctlgroup = apache ;astctl = asterisk.ctl El Bloque [files] es donde se definen permisos, usuarios y nombre del socket de Asterisk. [compat] pbx_realtime=1.6 res_agi=1.6 app_set=1.6 El Bloque [compat] es donde se puede cambiar el comportamiento de Asterisk para el dialplan, el AGI y el Realtime (temas que serán abordados en lo próximos capítulos). En las versiones anteriores a la 1.8 y 1.6 cuando se definían las opciones de una aplicación, se separaban con un pipe | Desde la versión 1.6 hay que sostituir el pipe con una coma. Si se quiere que Asterisk interprete correctamente los pipe hay que modificar las tres lineas de la siguiente forma: [compat] pbx_realtime=1.4 res_agi=1.4 app_set=1.4 En este caso se deja la configuración predefinida. 2.4 modules.conf Cuando se instala Asterisk, todos los módulos se guardan en la carpeta /usr/lib64/asterisk/modules. Por defecto cuando se inicia Asterisk, todos los módulos serán cargados. Este comportamiento se debe a la configuración predefinida del archivo modules.conf. Si se abre este archivo, después de la etiqueta [modules] se encontrará el parámetro: autoload=yes que significa que todos los módulos compilados se cargarán al iniciar Asterisk. Otra forma de cargar los módulos podría ser poner ese parámetro en no y luego en el mismo archivo utilizar el parámetro load para cargar los módulos uno a uno. En el mismo archivo encontramos el parámetro preload. Este parámetro se utiliza para cargar un modulo antes de todos los demás. Como se verá más adelante, en el caso de los módulos relacionados con ODBC, hay que utilizar este parámetro para cargar estos modulo por primeros. Es muy probable que a lo largo de la configuración de Asterisk, no se necesite utilizar algunos módulos y es una buena practica desactivarlos de forma que no se carguen al iniciar Asterisk. En este modo se reduce la memoria y los recursos utilizados por la PBX. 48
Un ejemplo puede ser el canal Skinny que se utiliza en los teléfonos de marca CISCO. Si no se va a utilizar este protocolo, es mejor desactivarlo en el archivo modules.conf. Esto se realiza utilizando el parámetro noload. Se abre el archivo modules.conf: nano /etc/asterisk/modules.conf y al final se añade la siguiente linea: noload => chan_skinny.so Se guardan los cambios y se reinicia Asterisk: service asterisk restart Se entra en la consola de Asterisk: asterisk -rvvvvvvvvvvvvvv y con el comando: CLI> module show like chan se verán todos los canales disponibles: Module Description Use Count app_chanisavail.so Check channel availability 0 app_channelredirect.so Redirects a given channel to a dialplan 0 app_chanspy.so Listen to the audio of an active channel 0 app_dumpchan.so Dump Info About The Calling Channel 0 chan_agent.so Agent Proxy Channel 0 chan_bridge.so Bridge Interaction Channel 0 chan_dahdi.so DAHDI Telephony Driver w/PRI 0 chan_iax2.so Inter Asterisk eXchange (Ver 2) 0 chan_local.so Local Proxy Channel (Note: used internal 0 chan_mgcp.so Media Gateway Control Protocol (MGCP) 0 chan_motif.so Motif Jingle Channel Driver 0 chan_multicast_rtp.so Multicast RTP Paging Channel 0 chan_oss.so OSS Console Channel Driver 0 chan_phone.so Linux Telephony API Support 0 chan_sip.so Session Initiation Protocol (SIP) 0 chan_unistim.so UNISTIM Protocol (USTM) 0 func_channel.so Channel information dialplan functions 0 res_calendar_exchange.so Asterisk MS Exchange Calendar Integratio 0 18 modules loaded El canal chan_skinny no aparece porque se ha configurado para que no se cargue. Si en un determinado 49
momento se quiere cargar un modulo que ha sido configurado para no cargarse al iniciar Asterisk, se utiliza el comando: CLI> module load chan_skinny.so Loaded chan_skinny.so [Apr 6 11:26:34] NOTICE[1726]: chan_skinny.c:7736 config_load: Configuring skinny from skinny.conf == Parsing '/etc/asterisk/skinny.conf': Found == Skinny listening on 0.0.0.0:2000 == Registered channel type 'Skinny' (Skinny Client Control Protocol (Skinny)) == Registered RTP glue 'Skinny' == Manager registered action SKINNYdevices == Manager registered action SKINNYshowdevice == Manager registered action SKINNYlines == Manager registered action SKINNYshowline Loaded chan_skinny.so => (Skinny Client Control Protocol (Skinny)) El modulo cargado de esta forma quedará activo hasta el siguiente reinicio de Asterisk. Se sale de la consola: CLI> quit 2.5 Música en espera y MP3 Una de las funcionalidades de Asterisk es la música en espera. En muchos servicios de asistencia al cliente es típico escucharla mientras se espera que algún operador nos atienda. En este párrafo se mostrará la configuración de la música en espera con archivos MP3. Primero se crea la carpeta donde guardar los archivos MP3: mkdir /var/lib/asterisk/mohmp3 Se descarga un archivo mp3 en la carpeta creada. cd /var/lib/asterisk/mohmp3 wget http://www.voztovoice.org/tmp/fresas.mp3 Informaciones sobre el archivo (utilizando SoX): sox --i fresas.mp3
50
Terminada la descarga del fichero MP3, el paso que sigue es configurar el archivo musiconhold.conf, utilizado para este tipo de configuración. Se modifica de la siguiente manera: nano /etc/asterisk/musiconhold.conf Se añaden las siguientes líneas al final del archivo: [mp3] mode=files directory=/var/lib/asterisk/mohmp3 random=yes • • • •
[mp3] – Nombre de la nueva clase de música en espera mode= files – la nueva clase utilizará archivos audio directory=/var/lib/asterisk/mohmp3 – los archivos se encontrarán en la carpeta indicada en el parametro directory random=yes – los archivos audio se utilizarán de forma aleatoria
Se accede a la consola de Asterisk: asterisk -rvvvvvvvvvvvvv Se escribe: CLI> moh reload para recargar la configuración de la música en espera. CLI> moh show classes Para ver las clases de música en espera configuradas. Aparecerá: Class: default localhosMode: files localhosDirectory: /var/lib/asterisk/moh 51
Class: mp3 Mode: files Directory: /var/lib/asterisk/mohmp3 CLI> quit Cuando se utilizan archivos MP3 para la música en espera, hay que tener en cuenta que el sistema necesitará utilizar bastante recursos de la CPU. Esto porque los archivo MP3 tendrán que ser convertidos en el formato audio requerido por el canal que está accediendo al servicio. Considerando que los teléfonos IP no tienen un sistema de audio de alta calidad se puede bajar la frecuencia de muestreo de los archivos MP3 sin perder en calidad del audio escuchado. El programa que permite este tipo de operación es el mismo SOX. sox fresas.mp3 -V -r 22050 -c 1 fresas1.mp3 • • •
-c 1 se pasa el archivo de estéreo a mono (un canal). -r 22050 frecuencia de muestreo de 44100 H/z a 22050 Hz. archivo1.mp3 – nombre del archivo resultado de la conversión.
Usando la opción -V aparecerá en la pantalla todo el proceso:
Se borra el archivo original: rm fresas.mp3 52
rm: remove regular file `fresas.mp3'? Y Para probar la nueva configuración se necesita crear una extensión en el archivo extensions.conf (el dialplan o plan de marcado) que se verá más adelante. IMPORTANTE: cada vez que se modifican o añaden nuevos archivos en la carpeta hay que recargar la configuración de la música en espera o reiniciar Asterisk: /etc/init.d/asterisk restart Para luego averiguar que efectivamente el archivo mp3 esté presente en la lista de archivos para la música en espera [mp3] asterisk -rvvvvvvvvvvvvvvv CLI> moh show files Class: default File: /var/lib/asterisk/moh/macroform-the_simplicity File: /var/lib/asterisk/moh/manolo_camp-morning_coffee File: /var/lib/asterisk/moh/macroform-robot_dity File: /var/lib/asterisk/moh/reno_project-system File: /var/lib/asterisk/moh/macroform-cold_day Class: mp3 File: /var/lib/asterisk/mohmp3/fresas1 2.6 El comando asterisk Como se ha visto anteriormente, para entrar en la consola de Asterisk, se ha utilizado el comando: asterisk -rvvvvvvvvvvvvvvvvvvvvv La opción -r significa que la conexión se realiza a un instancia de Asterisk que ya está corriendo, el numero de v presentes después de la r, indica el grado de detalle que se quiere tener en la consola. Para una lista de los comando disponibles: asterisk -h Asterisk 11.17.1, Copyright (C) 1999 - 2013, Digium, Inc. and others. Usage: asterisk [OPTIONS] Valid Options: -V Display version number and exit -C
Use an alternate configuration file -G Run as a group other than the caller -U Run as a user other than the caller -c Provide console CLI -d Enable extra debugging 53
-f Do not fork -F Always fork -g Dump core in case of a crash -h This help screen -i Initialize crypto keys at startup -L Limit the maximum load average before rejecting new calls -M Limit the maximum number of calls to the specified value -m Mute debugging and console output on the console -n Disable console colorization -p Run as pseudo-realtime thread -q Quiet mode (suppress output) -r Connect to Asterisk on this machine -R Same as -r, except attempt to reconnect if disconnected -s Connect to Asterisk via socket (only valid with -r) -t Record soundfiles in /var/tmp and move them where they belong after they are done -T Display the time in [Mmm dd hh:mm:ss] format for each line of output to the CLI -v Increase verbosity (multiple v's = more verbose) -x Execute command (implies -r) -X Execute includes by default (allows #exec in asterisk.conf) -W Adjust terminal colors to compensate for a light background Si se quiere ver la versión de Asterisk: asterisk -V Asterisk 11.17.1 Si se quiere iniciar Asterisk directamente sin utilizar el script de arranque, primero se para el servicio: service asterisk stop y luego de utiliza la opción -c asterisk -cvvvvvvvvvvvvvvvvvvvvv para salir de la consola y terminar el programa: CLI> core stop now Algunas de las opciones disponibles, se verán a lo largo del curso. Para terminar se reinicia el Asterisk: service asterisk start En la carpeta /etc/asterisk donde se encuentran los archivo de configuración de la PBX, se encuentran tres archivos relacionados con la consola de Asterisk:
54
• • •
cli_aliases.conf: permite crear alias de los comandos de la consola de Asterisk facilitando su utilizo cli.conf: permite configurar el debug y el nivel de verbosidad predefinido cuando se accede a la consola de Asterisk cli_permissions.conf: permite crear permisos diferenciados para los distintos usuarios/grupos presentes en el servidor Linux. De esta forma, por ejemplo, algunos usuarios tendrán acceso solamente a los comandos relacionados con el protocolo SIP, otros a los comandos relacionados con el dialplan, etcetera.
2.7 Preparación del dialplan – extensions.conf El archivo de configuración de Asterisk extensions.conf es donde se define el dialplan (plan de marcado) de la centralita. Todas las llamadas entrantes y salientes se procesan en este archivo. Para que Asterisk sepa come tratarlas se definen contextos, extensiones y prioridades. Más adelante se verá como se crea un contexto y dentro del contexto las extensiones y las prioridades. Una pequeña paréntesis. En el lenguaje común, la extensión es el numero de teléfono interno de una oficina o de un determinado servicio con el que se quiere comunicar. En el caso de Asterisk, la extensión es también una serie de números y/o letras que definen un bloque del dialplan dentro del cual se ejecutan aplicaciones o funciones de la PBX. El dialplan se puede escribir también en lenguaje AEL y LUA. Como en este libro no se van a utilizar es mejor desactivar los respectivos módulos: nano /etc/asterisk/modules.conf al final del archivo se añade: noload => pbx_ael.so noload => pbx_lua.so Se guardan los cambios y se reinicia Asterisk: service asterisk restart En este párrafo se presentará la configuración base del archivo para luego enriquecerlo a lo largo del libro. Este archivo se divide en tres bloques: • • •
Parte general Parte dedicada a las variables globales el dialplan
En la columna descripción, en negrita, el valor asociado al parámetro. Al final del modulo, la configuración completa del archivo.
55
Parámetro
Descripción
[general]
etiqueta que da inicio a la parte general
static
no=cuando se modifica una extensión en el dialplan el modulo pbx_config reescribirá este archivo y se perderán todos los comentarios presentes. yes=el modulo pbx_config no actualiza automáticamente el dialplan
writeprotect
si writeprotect=no y static=yes y se guarda la configuración del dialplan con el comando “dialplan save” se perderán todos los comentarios presentes en el archivo. si writeprotect=yes no se perderán los comentarios y se desactiva el comando “dialplan save”
autofallthrough
yes=si una llamada, por cualquier motivo, se sale del dialplan será terminada
extenpatternmatchnew
yes=mejora la velocidad de procesamiento del dialplan para contextos con un numero elevado de extensiones.
clearglobalvars
no=si se recarga el dialplan, las variables globales mantendrán su valor definido yes=si se recarga el dialplan, las variables globales serán reajustadas y asociadas nuevamente
[globals]
desde esta etiqueta empieza la definición de las variables globales.
1000
se asocia a la variable 1000 un valor. En este caso SIP/1000
voztovoice
se asocia a la variable voztovoice el valor SIP/voztovoice
marko
se asocia a IAX2/marko
la
variable
marko
el
valor
Terminada la configuración general y globals se empieza a construir el dialplan. Para iniciar se crearan dos contexto: internas y externas. En uno se definirá la parte accesible a todas las extensiones y en el otro la parte dedicada a las llamadas salientes. De esta forma se podrá controlar quienes tienen acceso y a que. Cada contexto se compone de extensiones y cada extensión de prioridades. Un primero ejemplo: [internas] se define el contexto internas exten => 123,1,Answer 56
el comando exten => es para definir una extensión. 123 es la extensión, 1 es la prioridad y Answer es la aplicación que se utilizará. En este caso Answer contesta la llamada La segunda linea: exten => 123,2,Playback(hello-world) la extensión es la misma, la prioridad es la numero 2 y en este caso la aplicación es Playback cuya función es enviar el audio de una locución al canal que está llamando La tercera linea: exten => 123,3,Hangup la extensión es siempre la misma, la prioridad es la numero 3 y la aplicación es Hangup que lo que hace es terminar la llamada. Con este primer ejemplo ya se puede empezar a entender como funciona el dialplan. Desde una extensión conectada a Asterisk se marca 123 y si esa extensión tiene acceso al contexto internas, se ejecutará la primera linea, luego la segunda y por ultimo la tercera. Las prioridades indican el orden en que se procesa el dialplan para una determinada extensión. Otra forma de escribir esta parte del dialplan es: exten => 123,1,Answer exten => 123,n,Playback(hello-world) exten => 123,n,Hangup La n de la segunda y tercera linea está por “next” y añade una prioridad a la que la precede. Desde la versión 1.6.2.X de Asterisk hay una forma mucho más sencilla de escribir el dialplan y es la que se utilizará en este libro: exten => 123,1,Answer same => n,Playback(hello-world) same => n,Hangup el same con que empieza la segunda y la tercera linea significa que se está trabajando con el mismo numero de extensión (123 en este caso) y ya no hace falta indicarlo. Ahora se configura otra extensión que permita escuchar la música de espera MP3 creada en el párrafo 2.5: exten => 200,1,Answer same => n,MusicOnHold(mp3,60) same => n,Hangup
57
Marcando la extensión 200, Asterisk contestará la llamada (Answer) ejecutará la aplicación MusicOnHold que permite escuchar la música de espera de una clase configurada en el archivo musiconhold.conf (es este caso la clase mp3). La segunda opción (60) define el tiempo, en segundos, que se escuchará la música. Pasados los 60 segundos, se ejecutará la prioridad que sigue donde con la aplicación Hangup se termina la llamada. En el dialplan se pueden definir contextos que incluyen otros contextos. De esta forma si un determinado contexto incluye otro, ese contexto tendrá acceso a las extensiones presentes en el contexto incluido. Por ahora se definen dos de esta forma: [externas] include => internas [locales] include => internas Con estos primeros datos se construye el dialplan. Se renombra el archivo predefinido: mv /etc/asterisk/extensions.conf /etc/asterisk/extensions.conf.old se crea uno nuevo: nano /etc/asterisk/extensions.conf y se copian las siguientes lineas: [general] static=yes writeprotect=yse autofallthrough=yse extenpatternmatchnew=yse clearglobalvars=yes [globals] 1000=SIP/1000 voztovoice=SIP/voztovoice marko=IAX2/marko [internas] exten => 123,1,Answer same => n,Playback(hello-world) same => n,Hangup exten => 200,1,Answer same => n,MusicOnHold(mp3,60) same => n,Hangup
58
[externas] include => internas [locales] include => internas Se guarda la configuración y se recarga el dialplan desde la consola de Asterisk: asterisk -rvvvvvvvvvvvvv CLI> dialplan reload Para ver el contexto externas: CLI> dialplan show externas [ Context 'externas' created by 'pbx_config' ] Include => 'internas' -= 0 extensions (0 priorities) in 1 context. =-
[pbx_config]
Para ver el contexto internas: CLI> dialplan show internas [ Context 'internas' created by 'pbx_config' ] '123' => 1. Answer() [pbx_config] 2. Playback(helloworld) [pbx_config] 3. Hangup() [pbx_config] '200' => 1. Answer() [pbx_config] 2. MusicOnHold(mp3,60) [pbx_config] 3. Hangup() [pbx_config] -= 2 extensions (6 priorities) in 1 context. =Para una lista de comandos disponibles: CLI> help dialplan dialplan add extension Add new extension into context dialplan add ignorepat Add new ignore pattern dialplan add include Include context in other context dialplan debug Show fast extension pattern matching data structures dialplan reload Reload extensions and *only* extensions dialplan remove extension Remove a specified extension dialplan remove ignorepat Remove ignore pattern from context dialplan remove include Remove a specified include from context dialplan save Save current dialplan into a file dialplan set chanvar Set a channel variable dialplan set extenpatternmatch Use the Old extension pattern matching algorithm. dialplan set extenpatternmatch Use the New extension pattern matching algorithm. dialplan set global Set global dialplan variable 59
dialplan show chanvar Show channel variables dialplan show globals Show global dialplan variables dialplan show Show dialplan
60
Capitulo III Protocolo SIP y el archivo sip.conf El protocolo SIP es un protocolo de señalización que permite: • • • • •
localizar un usuario contactar un usuario para determinar su voluntad de establecer una sesión Negociación de los media (audio/vídeo) que se utilizarán a lo largo de la sesión Modificar una sesión establecida Terminar una sesión establecida
Este protocolo ha sido definido por la IETF (The Internet Engineering Task Force) que es la entidad que se encarga de definir los estándar para la red Internet. En este caso el documento que contiene todas las especificaciones del protocolo SIP es el RFC (Request for Comments) 3261. En ese documento se explica como deben funcionar programas y/o dispositivos que quieran implementar el protocolo SIP. Desde un punto de vista del funcionamiento, los mensajes que se envían son una mezcla entre el protocolo HTTP (Hypertext Transfer Protocol) y el protocolo SMTP (Simple Mail Transfer Protocol). Dentro del protocolo SIP existen los métodos, que representan las distintas solicitudes que un dispositivo puede enviar a otro. Los seis métodos principales del protocolo SIP son: • • • • • •
REGISTER – Para registrar un dispositivo INVITE – par iniciar una llamada BYE – para terminar una llamada establecida ACK – para notificar que se ha recibido un determinado mensaje CANCEL – para anular una llamada que todavía no se ha establecido OPTIONS – para descubrir los métodos disponibles en un determinado dispositivo y al mismo tiempo para averiguar si todavía el dispositivo es alcanzable y con que latencia.
Cada mensaje SIP está compuesto de distintas lineas llamadas Headers (cabeceras). Un ejemplo de un mensaje de INVITE: INVITE sip:[email protected]:2464 SIP/2.0 Via: SIP/2.0/UDP 192.168.1.101:14396;branch=z9hG4bK-d8754z-0517b801e519b777-1---d8754zMax-Forwards: 70 Contact: To: "AndreaGS" From: "Andrea PC";tag=e7c0a709 Call-ID: MzA3N2U5OWJlYjk5NDdmN2JlZDMwMjNlNTVmOThhZDY CSeq: 1 INVITE Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO Content-Type: application/sdp Supported: replaces User-Agent: Bria 3 release 3.5.5 stamp 71238 Content-Length: 262
Asterisk PBX es un B2BUA (back-to-back user agent) y su función es la de hacer de “intermediario” entre los usuarios. Un usuario (o User Agent como definido en el protocolo SIP) enviará todas sus peticiones a Asterisk que se encargará de procesarlas y de esta forma permitir establecer sesiones media. Como Asterisk implementa distintos tipos de protocolos (SIP, IAX2, H323), él mismo se encargará de establecer llamadas entre usuarios que están utilizando diferentes protocolos. En Asterisk, el archivo sip.conf es donde se definen las extensiones SIP, los proveedores SIP y, en general, todo lo relacionado con el protocolo SIP. El archivo sip.conf está estructurado en tres bloques: • • •
Una parte general donde se define la configuración global del protocolo SIP. Al momento de configurar una extensión o una troncal, si no se definen algunos parámetros, estos serán tomados de la parte general del archivo. Un ejemplo son los codecs audio. Un bloque central donde se configura el registro a los proveedores VoIP y/o otros servidores Asterisk Una parte final donde se configuran las extensiones internas, las troncales y las conexiones a otros servidores Asterisk.
Hay que pensar en Asterisk como un conmutador que quizás algún día hemos visto en la recepción de un Hotel o una empresa. Asterisk tiene las mismas funcionalidades. Con las extensiones configuradas se podrán llamar entre ellas, se podrán efectuar llamadas a teléfonos fijos y/o celulares, utilizar proveedores SIP, Gateway PSTN, y aprovechar los típicos servicios de una PBX como llamada en espera, desvío de llamadas, llamada a tres, contestador automático, buzón de voz, conferencias a tres etc. En los VPS Linode hay la posibilidad de activar una dirección IP local. Normalmente se utiliza para la creación de una red local entre distintos VPS que se encuentran en el mismo Centro de datos. En este caso se activa para volver la configuración del sip.conf lo más real posible. Para hacerlo se entra en la pagina de administración del VPS y en la pestaña “Remote Access” se escoge el enlace evidenciado en la imagen que sigue:
Aparecerá la dirección IP local:
63
Se anota el valor y se configura una nueva tarjeta de red virtual: nano /etc/sysconfig/network-scripts/ifcfg-eth0:1 Se añaden estas lineas: DEVICE=eth0:1 BOOTPROTO=none ONBOOT=yes IPADDR=192.168.163.207 NETMASK=255.255.128.0 En IPADDR se pone la IP local creada en su VPS Linode. Se guardan las modificaciones y se reinicia la red del servidor: service network restart Con el comando: ifconfig se verá la nueva tarjeta de red configurada:
3.1 sip.conf La configuración que sigue abarca los parámetros más importantes del sip.conf; cada línea de la tabla viene acompañada por una breve explicación Si es presente un asterisco antes del nombre del parámetro, significa que es una nueva funcionalidad añadida con la versión 11.X de Asterisk o que han habido cambios en su configuración. En negrita la opción que se utilizará para cada parámetro. Al final de la tabla, la configuración completa del archivo. Parámetro
Descripción
[general]
etiqueta que introduce la parte general de la configuración
context
default = el contexto donde llegarán las llamadas no autenticadas si allowguest=yes
allowguest
No = no se permiten llamadas entrantes (INVITE) de usuarios no autenticados/configurados (aumenta la seguridad de Asterisk) Yes = se permiten llamadas entrantes (INVITE) de usuarios no autenticados/configurados. Este tipo de llamadas llegarán al 64
Parámetro
Descripción contexto especificado en el parametro anterior
match_auth_username
Si disponible autentica un usuario utilizando el parámetro username presente en la cabecera de autentificación en lugar de la cabecera SIP From.
allowtransfer
En casi todos los teléfonos SIP, a lo largo de una llamada, es posible presionar un botón para realizar una transferencia a otra extensión/numero. Este parámetro define si Asterisk aceptará este tipo de solicitudes. Posibles opciones: No y Yes
realm
si al servidor está asociado un dominio registrado, se puede definir este parámetro para que la autentificación se realice utilizando ese nombre de dominio (digest authentication RFC2617). Se deja comentado
domainsasrealm
Si en el archivo se defines distintos dominios y este parametro está configurado en yes, los dominios configurados se utilizarán para la DIGEST autentificación. Valor No
*recordonfeature *recordofffeature
Si se recibe un mensaje SIP INFO que contiene una cabecera Record:, si el valor contenido en la cabecera es on se activará la grabación de la llamada, si es off se desactivará. En estos dos parámetros se define que tipo de grabación de activará/desactivará. Posibles valores: automon y automixmon. El parametro funciona correctamente si para el canal involucrado está activada esa funcionalidad (véase features.conf)
udpbindaddr
Es la dirección IP y el puerto donde Asterisk se pondrá a la escucha para las señalización SIP utilizando el protocolo UDP. Como desde la versión 1.8, Asterisk soporta el protocolo IPv6 para el protocolo SIP, es posible configurar cuatro escenarios distintos: 1. 192.168.1.30 – Asterisk aceptará la señalización SIP solamente si enviada a la dirección IPv4 indicada 2. 2600:3c00::f03c:91ff:fedf:a455 - Asterisk aceptará la señalización SIP solamente si enviada a la dirección IPv6 indicada 3. 0.0.0.0 – Asterisk aceptará la señalización SIP en todas las direcciones IPv4 presentes en el servidor Linux 4. :: - Asterisk aceptará la señalización SIP en todas las direcciones IPv4 y IPv6 dando prioridad a la primera IP que encuentra. En el caso de Linode será IPv6 Como se va a trabajar con IPv4, para que Asterisk escuche en todas las direcciones IPv4 puerto 5060 (el predefinido) el Valor es: 0.0.0.0:5060
;disallowed_methods=UPDATE
Cuando un dispositivo se comunica con Asterisk normalmente entre las cabeceras que envía hay una que se llama Allow. En esa 65
Parámetro
Descripción cabecera el dispositivo comunica a Asterisk los métodos SIP que soporta. En algunas ocasiones los métodos presenten no corresponden a verdad (el dispositivo miente). En estos casos, si se tiene la certeza que el dispositivo no soporta uno o más métodos, se indican en este parámetro separados por una coma. El parámetro se puede configurar en la parte general del archivo sip.conf y/o directamente en el bloque de configuración del dispositivo. La segunda opción tiene la precedencia sobre la primera. En este caso se deja comentado (punto y coma por delante).
tcpenable
Desde la versión 1.6 es posible configurar Asterisk para que permita la señalización SIP sobre el protocolo TCP Valor: yes
tcpbindaddr
Es la dirección IP y el puerto donde Asterisk se pondrá a la escucha para las señalización SIP utilizando el protocolo TCP. Como para el protocolo UDP es posible utilizar cuatro escenarios distintos para indicar IP y puerto de escucha. En este caso se configurará para que escuche en todas las direcciones IPv4 puerto 5060. Valor: 0.0.0.0:560
tcpauthtimeout
Representa el números de segundos que tiene a disposición un cliente para autenticarse utilizando el protocolo TCP. Si no lo hace dentro del tiempo indicado, sera desconectado. Valor: 30
tcpauthlimit
Numero máximo de sesiones no autenticadas permitidas utilizando el protocolo TCP. Valor:100
transport
Define el protocolo de trasporte predefinido para la señalización SIP. Valor: udp
srvlookup
Permite realizar búsquedas de registros DNS SRV basadas en los nombres de dominio para llamadas SIP salientes del tipo: [email protected] Asterisk realiza esta búsqueda limitándose al primer valor encontrado. Valor: Yes
pedantic=yes
Realiza un chequeo de las cabeceras SIP recibidas para que respeten las reglas del protocolo.
maxexpiry
Tiempo máximo, en segundos, permitido para REGISTER entrantes. Valor 3600 Esto significa que cuando una extensión se registra a Asterisk, máximo cada 3600 segundos tendrá que volver a registrarse aunque en la configuración de la extensión (Softphone, ATA, teléfono SIP se haya indicado un valor mayor a 3600)
minexpiry
Tiempo mínimo, en segundos, permitido para REGISTER entrantes. Valor: 60
defaultexpiry
Cuando un cliente se registra a Asterisk, envía en el paquete SIP REGISTER el tiempo de duración de su registro. En el caso que 66
Parámetro
Descripción no lo haga, Asterisk considerará que el registro durará el tiempo indicado en este parámetro expresado en segundos. Valor: 120
*submaxexpiry
Tiempo máximo, en segundos, permitido para SUBSCRIBE entrantes. Valor 3600 Esto significa que cuando una extensión subscribe un servicio en Asterisk (por ejemplo el estado de una extensión) cada 3600 segundos tendrá que volver a subscribir el servicio.
*subminexpiry
Tiempo mínimo, en segundos, permitido para SUBSCRIBE entrantes. Valor: 60
mwiexpiry
La mayoría de los teléfonos SIP, cuando la extensión registrada recibe un nuevo mensaje en el buzón de voz, lo señalan a través de un icono en la pantalla o un indicador luminoso. Esto porque se “subscribe” a este tipo de servicio en el servidor Asterisk. Este parámetro indica cada cuantos segundos Asterisk tendrá que renovar sus suscripciones hacia servicios externos. En este caso es Asterisk que se comporta como si fuera un telefono SIP. Valor 3600
maxforwards
Cada vez que un “mensaje” SIP se envía puede atravesar distintos servidores/proxy antes de llegar al destinatario. Con este parámetro se limita el numero de servidores/proxy que puede atravesar. Se utiliza también para evitar que se creen bucles. Valor. 70
qualifyfreq
Cada cuantos segundos enviar un paquete OPTIONS a la extensión/troncal configurada en Asterisk. Esto permite saber si la extensión/troncal misma es alcanzable y al mismo tiempo mantener abierta la conexión con la extensiones que se encuentran detrás de un NAT. El método OPTIONS del protocolo SIP se utiliza también para conocer los métodos disponible en un determinado dispositivo. Valor 60
*keepalive
Este parámetro permite enviar un paquete UDP vacío para mantener abierta la conexión con dispositivos que se encuentran detrás de un NAT. El valor indica cada cuantos segundos enviar el paquete. Yes (60 segundos), No (no se envía). Se puede indicar directamente el números de segundos (ej: 30)
*preferred_codec_only
Asterisk contesta a un INVITE entrante con un solo codec audio en lugar de enviar toda la lista de codecs configurados para una determinada extensión. Esto permite que el llamante envíe el flujo audio con el codec que se ha establecido. Valor: no
disallow
all – Se desactivan todos los codec audio y video
allow
Se indican los codec audio y video utilizables. Pueden ser indicados uno por linea o en la misma linea separados por una 67
Parámetro
Descripción coma: allow=alaw allow=ulaw o allow=alaw,ulaw ulaw: se utiliza en Estados Unidos, Canadá y Australia alaw = se utiliza en Asia, Europa, África y América Latina
mohinterpret
clase de música de espera predefinida – default
mohsuggest
Clase de música de espera predefinida cuando un canal de tipo peer se pone en espera – default
parkinglot
Asterisk, entre sus funcionalidades, permite parquear una llamada. Como desde la versión 1.6.X es posible configurar más de un “contexto” de parqueo, en este parámetro se indica el predefinido. Valor: default
language
el idioma predefinido para las locuciones audio. Valor es (Español)
tonezone
Define los tonos (ocupado, timbrado, congestión) para un país especifico y para todas las extensiones configuradas si no se cambia en la configuración de la extensión. Véase archivo indications.conf. Valor: es
relaxdtmf
Configurar en yes si Asterisk tiene problemas en reconocer los DTMF (tonos) recibidos. Valor: no
trustrpid
yes = la cabecera Remote-Party-ID tiene que ser de confianza para ser aceptada.
sendrpid
Como se verá más adelante cada “mensaje” SIP se compone de diferentes lineas. Cada linea se llama HEADER o cabecera. Este parámetro define se entre los distintos HEADER se envía también el Remote-Party-ID. Este parámetro es muy útil para las transferencias atendida de las llamadas entre extensiones Valor: yes
rpid_update
En algunos casos, la única forma de actualizar el identificativo del llamante de una llamada es enviando un paquete SIP UPDATE. Con este parámetro se activa o desactiva. Valor: yes
useragent
Asterisk se presentará con este nombre al momento de comunicarse con otros servidores o proveedores SIP. Valor: VozToVoice v. 1.0 Personalizar
auth_options_requests
Normalmente los paquete OPTIONS recibidos por Asterisk se contestan sin solicitar autentificación. Si este parámetro se configura con Yes, Asterisk solicitará que el dispositivo que está enviando el paquete se autentifique. Valor: No 68
Parámetro
Descripción
*accept_outofcall_message
Si se configura con no, los mensajes instantáneos entre distintos dispositivos, se procesarán solamente si enviados a lo largo de una llamada. Con yes se procesarán aunque no haya llamada activa.
*outofcall_message_context
Contexto del dialplan donde se enviarán los mensajes instantáneos recibidos por Asterisk. Valor: message
*auth_message_requests
Si configurado con Yes, Asterisk solicitará la autentificación del dispositivo antes de aceptar el mensaje instantáneo y procesarlo. Con No no solicitará la autentificación.
sdpsession
asterisk
sdpowner
asterisk
dtmfmode
protocolo para el envío de los DTMF (Dual-Tone MultiFrequency). Serían los tonos que se generan cuando se presionan las teclas del teléfono. Valor: rfc2833 Otro valor bastante común es inband. Con inband los tonos se envían en el flujo audio (protocolo RTP). Inband no funciona con el codec audio G729 y G722. A cada tecla del teléfono están asociados dos tonos de diferente frecuencia:
RFC4733 videosupport
no=no se activa el soporte para vídeo llamadas yes=se activa el soporte para vídeo llamadas
maxcallbitrate
Banda máxima utilizable para vídeo llamadas (predefinida 384 kb/s)
callevents
yes=cuando el estado de una extensión cambia, el Asterisk Manager Interface (AMI) genera el correspondiente evento
authfailureevents
yes=el AMI generará un evento cuando una peer no se puede autenticar con la PBX
alwaysauthreject
yes=cuando un INVITE o un REGISTER es rechazado por Asterisk, en lugar de enviar el verdadero motivo del rechazo, Asterisk contestará siempre con un 401 Unauthorized. De esta forma no da pistas a los que están intentando acceder al sistema 69
Parámetro
Descripción
use_q850_reason
Yes Permite el envío de los códigos Q850 en el Header Reason que normalmente se utilizan para conocer el porque una llamada SIP ha sido terminada. Esta serie de códigos, es utilizado por algunos Gateway para mejorar la compatibilidad con el protocolo SIP
rtptimeout
60=si en una llamada establecida no hay flujo audio por 60 segundos la llamada será terminada
rtpholdtimeout
300=si en una llamada en espera no hay flujo audio por 300 segundos, la llamada será terminada
rtpkeepalive
0=no envía un paquete UDP utilizando el protocolo RPT para mantener abierto el NAT a lo largo de una sesión media.
session-timers
SIP Session Timers (RFC4028) provee un mecanismo para mantener activa y/o terminar una sesión SIP. Este mecanismo logra detectar si una sesión SIP no se ha terminado correctamente y terminarla. Este parámetro acepta 3 valores: • originate: solicita y activa el session-timers para todas las sesiones SIP • activa el session-timers solamente si solicitado por el dispositivo remoto • refuse: no activa el session-timers bajo ninguna circunstancia. Valor: originate
session-expires
Máximo numero de segundos cada cuanto controlar la sesión SIP. Por defecto 1800. Valor: 600
session-minse
Mínimo numero de segundos cada cuanto controlar la sesión SIP. Por defecto 90. Valor: 90
session-refresher
Quiens se encarga de controlar la sesión SIP: UAC (User Agent Client o llamante), UAS (User Agent Server o llamado) Valor: uas
allowsubscribe
yes=permite suscribir el estado de una extensión
subscribecontext
subscribe=Este parámetro define el contexto predefinido que se utilizará para permitir a las extensiones acceder al estado de otras.
notifyringing
yes=Notifica si la extensión está timbrando
notifyhold
yes= Notifica si la extensión está en espera
callcounter
yes=cuenta el numero de canales utilizados por una extensión. Este parámetro junto a las funciones GROUP y GROUP_COUNT permite limitar el numero de llamadas simultaneas que una extensión puede efectuar/recibir 70
Parámetro
Descripción
*t38pt_udptl
Permite el uso del protocolo T38 (fax sobre IP). Desde la versión 1.8.X de, la aplicación para enviar y recibir fax ha sido reescrita totalmente. El nuevo modulo se llama res_fax que sustituye el viejo app_fax ahora “deprecated”. Con la versión 11, Asterisk puede actuar como gateway T38 permitiendo el envío y recepción de FAX entre terminales que soportan el protocolo T.30 (audio) y terminales que soportan el protocolo T.38 Valor: yes,fec,maxdatagram=400
faxdetect
Permite diferenciar el tratamiento de las llamadas entrantes según sea un fax o una llamada de voz. Los valores permitidos son: • yes = Habilita la detección de FAX T30 y T38 • no = deshabilitado • cng = Habilita la detección de FAX T30 • t38 = Habilita la detección de FAX T38
localnet
En el caso que Asterisk esté instalado en una red local que se encuentra detrás de un NAT, hay que indicar el rango de direcciones IP de la red local. En el caso del VPS Linode se pone la dirección IP local creada (personalizar con la IP local de su VPS) Ejemplo: 192.168.128.0/255.255.128.0
externaddr
Si Asterisk está instalado detrás de un NAT, con este parámetro se indica la dirección IP publica de la red. En el VPS Linode se pone la IP del servidor. Ejemplo 96.126.121.135 Personalizar
;externhost
Si la dirección IP publica es dinámica o está asociada a un nombre de dominio, en lugar de externaddr se utiliza este parámetro. Si no se posee un nombre de dominio, se puede utilizar el servicio de dyndns. En el VPS Linode se deja comentado
;externrefresh
Cada cuantos segundos actualizar la asociación dirección IP – nombre de dominio. En el VPS Linode se deja comentado
*nat
Define el tipo de comportamiento que debe tener Asterisk al conectarse con otras extensiones/dispositivos. Los distintos valores son: no = usa el parámetro rport (RFC3581) solamente si el cliente remoto lo requiere force_rport = impone siempre el uso del parámetro rport comedia = usa el parámetro rport solamente si requerido por el dispositivo remoto y utiliza el “Comedia RPT handling”, es decir envía el flujo media por el mismo puerto de donde lo recibe desde el dispositivo remoto. auto_force_rport=Asterisk setea automáticamente force_rport si 71
Parámetro
Descripción detecta que el dispositivo remoto se encuentra detrás de un NAT auto_comedia=Asterisk setea automáticamente comedia si detecta que el dispositivo remoto se encuentra detrás de un NAT Valor: force_rport,comedia
icesupport
Este parámetro define si se activa o no el soporte del protocolo ICE. Valor: no
directmedia
no=no se permite el flujo media directo (protocolo RPT) entre las extensiones. El flujo directo solo es posible cuando las extensiones no se encuentran detrás de un NAT nonat=se permite el flujo media directo entre las extensiones solamente si no están detrás de un NAT. El mismo protocolo RTP logra reconocer si una extensión se encuentra detrás de un NAT o no. update= utiliza el método UPDATE en lugar de un reINVITE para enviar el flujo media directamente entre las extensiones.
;media_address
Si se quiere que el trafico RTP (audio/video) viaje sobre una IP distinta a la de la señalización SIP, se puede definir en este parámetro. Se deja comentado
rtcachefriends
Este parámetro aplica cuando las extensiones están configuradas en una base de datos (se verá más adelante). Valor no
rtupdate
este parámetro también aplica cuando las extensiones están configuradas en una base de datos. Cuando una de estas extensiones se registre a Asteirsk, en la base de datos se guardará la dirección IP, el puerto, el tiempo de registro y el nombre de usuario. Valor yes
register =>
Con esta linea empieza el segundo bloque del archivo sip.conf y se utiliza para registrarse a servidores externos; normalmente proveedores SIP o otro servidores Asterisk. El parámetro se deja comentado y a seguir se presentan algunos ejemplos: • register => fulano:[email protected] Para el registro con el proveedor el username será fulano, la contraseña sesamo y el dominio sip.provider1.com. Si el proveedor usa un puerto que no es el 5060 hay que especificarlo al final de la línea de esta forma: • register => fulano:[email protected]:5061 En los dos casos las llamadas entrantes llegaran a la extensión s y al contexto que se define en la configuración de la extensión. Si se quiere que las llamadas entren a una extensión predefinida, hay que añadir al final de la linea el numero. Este numero puede ser arbitrario siempre y cuando los proveedores SIP no especifiquen diversamente: • register => fulano:contraseñ[email protected]/1234 72
Parámetro
Descripción
registertimeout
Si Asterisk pierde el registro, este parámetro representa el numero de segundos que Asterisk esperará antes de volver a intentar registrarse. Valor 20
registerattempts
este parámetro representa el numero de intentos que Asterisk efectuará para registrarse. Si se pone 0, los intentos serán ilimitados. Valor 10
mwi =>
Desde la versión 1.6.2.X se puede subscribir el estado de un buzón de voz de un servidor remoto. En este ejemplo el buzón 1234 y contexto SIP_remote. Para subscribirse en la configuración de la extensión se indicará: mailbox=1234@SIP_Remote. Valor: 1234:[email protected]/1234
La ultima parte es dedicada a la configuración de las extensiones. En el caso del VPS Linode todas las extensiones se conectarán detrás de un NAT (router banda ancha y/o otro tipo de conexión Internet). Parámetro
Descripción
[1000]
Numero de la extensión
accountcode
Código que aparecerá en el registro de llamadas para esta extensión. Valor 1000
language
es=esta extensión utilizará las locuciones audio en español
type
friend=es un user y peer al mismo tiempo • user: una extensión que se autentica al servidor Asterisk usando el campo From para hacer llamadas. • peer una extensión que se autentica para las llamadas entrantes utilizando la dirección IP y el puerto
secret
La contraseña para la extensión. Personalizar Valor: pbx909090
qualify
Este parámetro se utiliza para mantener activa la conexión de una extensión que se conecta al servidor Asterisk detrás de una NAT. Valor Yes Puede ser también un numero expreso en milisegundos. Asterisk el paquete OPTIONS cada tantos milisegundos indicados en el parámetro. Si no recibe una respuesta considerará la extensión no alcanzable
mailbox
Si este parámetro es configurado, cuando la 73
extensión se registre al servidor Asterisk y se ha subscrito para recibir este tipo de notificaciones, Asterisk controlará si hay mensajes de voz pendientes y en caso positivo se lo comunicará usando MWI = Message Waiting Indicator (paquetes SIP NOTIFY). que puede ser recibida por la mayoría de los teléfonos IP o Softphone Valor 1000@default host
Si la extensión se conecta remotamente con un IP dinámico se pone dynamic. En caso contrario se pone la dirección IP
dtmfmode
Protocolo para los tonos DTMF Valor rfc2833
context
El contexto a que tendrá acceso la extensión. Valor externas como se ha creado en el dialplan
directmedia
Si las extensiones, como es el caso de una VPS Linode, están detrás de un NAT, el valor es no
callerid
el nombre y el numero que identifica la extensión cuando llama. valor Fulano <1000> Personalizar
callgroup pickupgroup
estos dos parámetros definen una de las funcionalidades avanzadas de Asterisk, es decir la posibilidad de capturar la llamada de una extensión que está timbrando, desde otra extensión. Valor 1 para ambos
disallow
all=se deshabilita todos los codec (audio/video)
allow
alaw=se habilita el codec audio alaw
allow
g722=se habilita el codec audio g722
allow
g729=se habilita el codec audio g729
allow
h263=se habilita el codec video H263
Se configura una segunda extensión: [1001] type=friend accountcode=1001 language=es secret=pbx9091 qualify=yes mailbox=1001@default host=dynamic dtmfmode=rfc2833 context=externas directmedia=no 74
callerid=zutano <1001> callgroup=1 pickupgroup=1 disallow=all allow=alaw allow=g722 allow=g729 allow=h263 Cuando se deben configurar muchas extensiones, se pueden crear templates (plantillas) donde se definen todos los parámetros compartidos entre todas las extensiones. Luego para cada una de ellas, se configuran solamente los parámetros que las diferencian de las demás. Para crear un template la primera linea debe tener esta sintaxis: [int-locales](!) [int-locales] es la descripción del template (en este ejemplo se utilizará para configurar todas las extensiones que tienen acceso solo a llamadas locales). (!) es las sintaxis que indica que se trata de un template. Luego se añaden todas las lineas comunes a todas las extensiones: type=friend language=es qualify=yes host=dynamic dtmfmode=rfc2833 context=locales directmedia=no callgroup=1 pickupgroup=1 disallow=all allow=alaw allow=g722 allow=g729 allow=h263 Ahora para configurar una nueva extensión se puede utilizar ese template de la siguiente forma: [1002](int-locales) accountcode=1002 secret=pbx9092 mailbox=1002@default callerid=Mengano <1002> Terminada la configuración de las extensiones, se pasa a la troncal SIP utilizando, en este caso, el proveedor SIP VozToVoice. Claramente puede ser cualquier proveedor VoIP. Para utilizar este proveedor se puede abrir una cuenta desde este enlace. Una vez que la cuenta ha sido activada, se tendrá 1 dólar de crédito para realizar gran parte de las llamadas presentes en este libro. 75
Parámetro
Descripción
[voztovoice]
nombre que se le asigna a la troncal
type
la troncal es de tipo peer (se utiliza solamente para llamadas saliente).
host
sip.voztovoice.eu=dominio del proveedor SIP
fromdomain
sip.voztovoice.eu=Este parámetro permite definir el nombre de dominio que aparecerá en la campo From: de la cabecera SIP. Mucho proveedores lo exigen para autenticar las llamadas
fromuser
nombre de usuario. Este parámetro permite definir el nombre de usuario que aparecerá en el campo From de la cabecera SIP. Muchos proveedores lo exigen para autenticar las llamadas.
defaultuser
el mismo valor del parámetro fromuser
secret
la contraseña.
qualify
yes
dtmfmode
rfc2833
context
from-voztovoice=el contexto donde llegarán las llamadas si se utiliza el proveedor también para las llamadas entrantes
directmedia
no
language
es
nat
no=no hay NAT entre el servidor Asterisk y el proveedor SIP
disallow
all
allow
alaw
allow
g729
Ahora se puede copiar toda la configuración en el archivo sip.conf. Antes que nada se renombra el archivo sip.conf predefinido y se crea uno nuevo: mv /etc/asterisk/sip.conf /etc/asterisk/sip.conf.old nano /etc/asterisk/sip.conf Se pegan las lineas que siguen: 76
[general] context=default allowguest=no allowtransfer=yes match_auth_username=yes ;realm=mydomain.tld domainsasrealm=no recordonfeature=automixmon recordofffeature=automixmon udpbindaddr=0.0.0.0:5060 tcpenable=yes tcpbindaddr=0.0.0.0:5060 tcpauthtimeout=30 tcpauthlimit=100 transport=udp srvlookup=yes maxexpiry=3600 minexpiry=60 defaultexpiry=120 submaxexpiry=3600 subminexpiry=60 mwiexpiry=3600 maxforwards=70 qualifyfreq=60 keepalive=yes preferred_codec_only=no disallow=all allow=ulaw allow=alaw mohinterpret=default mohsuggest=default parkinglot=default language=es tonezone=es relaxdtmf=no sendrpid=yes trustrpid=yes rpid_update=yes useragent=VozToVoice v. 1.0 auth_options_requests=no accept_outofcall_message=yes outofcall_message_context=message auth_message_requests=yes session-timers=originate session-expires=600 session-minse=90 77
session-refresher=uas sdpsession=asterisk sdpowner=asterisk dtmfmode=rfc2833 videosupport=yes maxcallbitrate=384 callevents=yes authfailureevents=yes alwaysauthreject=yes use_q850_reason=yes rtptimeout=60 rtpholdtimeout=300 rtpkeepalive=0 allowsubscribe=yes subscribecontext=subscribe notifyringing=yes notifyhold=yes callcounter=yes t38pt_udptl=yes,fec,maxdatagram=400 faxdetect=yes localnet= externaddr= ;externhost=prueba.dyndns.org ;externrefresh=180 nat=force_rport,comedia icesupport=no directmedia=no ;media_address=0.0.0.0 rtcachefriends=no rtupdate=yes ;register => fulano:[email protected] ;register => fulano:[email protected]:5061 ;register => fulano:contraseñ[email protected]/1234 registertimeout=20 registerattempts=10 ;mwi => 1234:[email protected]/1234 [1000] accountcode=1000 language=es type=friend secret=pbx9090 qualify=yes mailbox=1000@default host=dynamic dtmfmode=rfc2833 78
context=externas directmedia=no callerid=Fulano <1000> callgroup=1 pickupgroup=1 disallow=all allow=alaw allow=g722 allow=g729 allow=h263 [1001] type=friend accountcode=1001 language=es secret=pbx9091 qualify=yes mailbox=1001@default host=dynamic dtmfmode=rfc2833 context=externas directmedia=no callerid=zutano <1001> callgroup=1 pickupgroup=1 disallow=all allow=alaw allow=g722 allow=g729 allow=h263 [int-locales](!) type=friend language=es qualify=yes host=dynamic dtmfmode=rfc2833 context=locales directmedia=no callgroup=1 pickupgroup=1 disallow=all allow=alaw allow=g722 allow=g729 allow=h263
79
[1002](int-locales) accountcode=1002 secret=pbx9092 mailbox=1002@default callerid=Mengano <1002> [voztovoice] type=peer host=sip.voztovoice.eu fromdomain=sip.voztovoice.eu fromuser= defaultuser= secret= qualify=yes dtmfmode=rfc2833 context=from-voztovoice directmedia=no language=es nat=no disallow=all allow=alaw allow=g729 Antes de guardar los cambios, hay que personalizar los parámetros localnet y externaddr en el bloque general; en el bloque del proveedor SIP VozToVoice se ponen los datos de usuario y contraseña escogidos al momento de la creación de la cuenta con el proveedor. Cada vez que se modifica la configuración del sip.conf hay que recargarla. Se entra en la consola de Asterisk: asterisk -rvvvvvvvvvv Se escribe el comando: CLI> sip reload Para ver los peer configurados: CLI> sip show peers Name/username Host Dyn Forcerport Comedia 1000 (Unspecified) D Yes Yes 0 1001 (Unspecified) D Yes Yes 0 1002 (Unspecified) D Yes Yes 0 voztovoice/4260141991 72.14.184.31 No No 4 sip peers [Monitored: 1 online, 3 offline Unmonitored: 0 online, 0 offline]
ACL Port Status UNKNOWN UNKNOWN UNKNOWN 5060 OK (1 ms)
Para ver los users configurados: CLI> sip show users 80
Username 1000 1001 1002
Secret pbx9090 pbx9091 pbx9092
Accountcode Def.Context 1000 externas 1001 externas 1002 locales
ACL No No No
Forcerport Yes Yes Yes
Para una lista de los comandos disponibles para el protocolo SIP en Asterisk: CLI> help sip sip notify Send a notify packet to a SIP peer sip prune realtime [peer|all] Prune cached Realtime users/peers sip qualify peer Send an OPTIONS packet to a peer sip reload Reload SIP configuration sip set debug {on|off|ip|peer} Enable/Disable SIP debugging sip set history {on|off} Enable/Disable SIP history sip show {channels|subscriptio List active SIP channels or subscriptions sip show channelstats List statistics for active SIP channels sip show channel Show detailed SIP channel info sip show domains List our local SIP domains sip show history Show SIP dialog history sip show inuse List all inuse/limits sip show mwi Show MWI subscriptions sip show objects List all SIP object allocations sip show peers List defined SIP peers sip show peer Show details on specific SIP peer sip show registry List SIP registration status sip show sched Present a report on the status of the scheduler queue sip show settings Show SIP global settings sip show tcp List TCP Connections sip show users List defined SIP users sip show user Show details on specific SIP user sip unregister Unregister (force expiration) a SIP peer from the registry 3.2 Directmedia Como se ha dicho anteriormente, este parámetro permite definir si el flujo audio es directo entre los dispositivos o pasa por Asterisk que se encarga de enviarlo de una extensión a otra. En la versiones anteriores al a 1.6.X se llamaba canreinvite. Para poder entender un poco mejor este comportamiento, se puede ver el gráfico que sigue:
SIP
SIP RTP
RTP 81
En este escenario directmedia=no. El trafico SIP y RTP pasa completamente por Asterisk. En el caso que directmedia= yes el gráfico cambiaría de la siguiente forma:
SIP
SIP
RPT
La señalización SIP sigue pasando por Asterisk, mientras que el flujo media va directo de un dispositivo a otro. Este escenario funciona solamente si: • • • • •
las extensiones no están detrás de un NAT las extensiones están configuradas con el parámetro directmedia=yes las extensiones utilizan el mismo codec audio en la aplicación DIAL (que veremos más adelante) no están presentes las siguientes opciones: ''t'', ''T", "h", "H", "w", "W" or "L" el parámetro dtmfmode=info
Un típico ejemplo es cuando se instala el servidor Asterisk dentro de una red local y los teléfonos SIP están conectados en la misma red. La ventaja es que de esta forma se ahorran recursos del servidor Linux donde está instalado Asterisk ya que la PBX realiza menos tareas. 3.3 Contraseñas seguras En el archivo sip.conf las contraseñas de las extensiones aparecen en texto plano. Si alguien lograra entrar en el servidor Linux, con solo abrir el archivo, podría conocer todas las contraseñas de las extensiones configuradas. Para evitar esto y volver más seguro el sistema, es posible utilizar el cifrado con el algoritmo MD5. Tomamos como ejemplo la primera extensión cuya contraseña es pbx9090. Para cifrar la sintaxis es: echo -n "::" | md5sum Como el parámetro real presente en la parte general del sip.conf se ha dejado comentado, el valor predefinido es asterisk; pues el comando sería: 82
echo -n "1000:asterisk:pbx9090" | md5sum cuyo resultado será: 5b09185bfc9148923c47cdf60c3a1681 Para utilizar la contraseña cifrada en la configuración de una extensión, en el sip.conf en el bloque de la extensión se quita el parámetro secret y se añade el parámetro md5secret asignándole el valor creado. 3.4 Ngrep Como se quiere tener la traza de los mensajes SIP enviados entre Asterisk y las extensiones, se instala en el servidor Linux el programa NGREP que permite capturar cualquier tipo de paquete que entre o salga del sistema: cd /usr/src primero se instalan unas dependencias: yum install libpcap-devel -y luego se descarga el paquete: wget http://downloads.sourceforge.net/project/ngrep/ngrep/1.45/ngrep-1.45.tar.bz2 se descomprime: tar -xf ngrep-1.45.tar.bz2 se entra en la carpeta creada: cd ngrep-1.45 se compila y se instala: ./configure --prefix=/usr --libdir=/usr/lib64 Si aparece este mensaje: more than one set found in: /usr/include /usr/include/pcap please wipe out all unused pcap installation
83
Hay que ejecutar el siguiente comando: rm /usr/include/pcap* y volver al configure: ./configure -prefix=/usr --libdir=/usr/lib64 make make install 3.5 SoftPhone X-Lite y REGISTER X-lite es un softphone gratuito desarrollado por la empresa CounterPath que a pesar de sus limitaciones, puede ser utilizado para las pruebas presentes en este libro. Se descarga, se instala y se inicia. Primero se entra en el menú “Softphone → Account Settings” y se configura la cuenta 1000 creada en Asterisk:
84
Account name: una descripción de la cuenta UserID: el numero de la extensión Domain: la dirección IP o el nombre de dominio del servidor Asterisk (la IP del VPS Linode) Password: la contraseña de la extensión 1000 (pbx9090) Display name: el numero de la extensión Authorization name: el numero de la extensión En la pestaña Voicemail:
Se selecciona la casilla “check for voicemail” y en “Number to dial for checking voicemail” se pone 97. Este será el numero que hay que marcar para entrar al buzón de voz y que se configurará posteriormente en el dialplan.
85
En Topology, como la extensión está detrás de un NAT, se selecciona la casilla “Auto-detect firewall trasversal method using ICE”. Interactive Connectivity Establishment es un protocolo (RFC5245) que permite a los dispositivos que lo utilizan, lograr atravesar el NAT en el 90% de los casos. Si la conexión es contra un servidor local, hay que seleccionar la casilla “None”.
86
En Advanced se configura cada cuantos segundos X-lite volverá a registrarse a Asterisk (3600). Como el softphone se encuentra detrás de un NAT, se selecciona “Send SIP keep-alives” y “Use rport”, para mantener la conexión abierta. Si la conexión es a un servidor local se pueden desactivar las dos casillas. Antes de presionar el botón Ok para guardar la configuración, se vuelve a la consola de Linux y se escribe el siguiente comando: ngrep 1000 -W byline port 5060 > /tmp/register De esta forma se capturan todos los paquetes enviados y recibidos por la extensión 1000 y se guardan en el archivo register. Se vuelve al X-Lite y se presiona el botón OK. Después de unos segundos el softphone debería estar registrado a Asterisk. Se regresa a la consola Linux y se hunden las teclas CTRL-C para terminar la captura de paquetes por parte de Ngrep. Ahora se abre el archivo register: 87
nano /tmp/register Encontraremos esta secuencia: X-Lite ------------------Register---------------> Asterisk X-Lite <-------401 Unauthorized-------------- Asterisk En el mensaje 401 Unauthorized, Asterisk indica a X-Lite que se requiere una autentificación basada en el protocolo http digest y envía los datos necesarios para que el softphone pueda autenticarse de esta forma. X-Lite responde enviando una nueva petición de REGISTER añadiendo los datos de autentificación en la cabecera: Authorization: X-Lite ------------------Register---------------> Asterisk X-Lite <------------------200 Ok---------------- Asterisk Ahora el X-Llite está registrado y Asterisk puede localizarlo en el caso entre una llamada para la extensión 1000. De hecho el método REGISTER del protocolo SIP sirve para esto. Se recomienda la lectura del RFC3261 para entender como funciona la señalización SIP. Si se continua a mirar el archivo register se notará que aparece otro bloque que utiliza el método SUBSCRIBE (RFC4235). Todo este bloque está relacionado con el buzón de voz de la extensión 1000 y es el que permite a la misma extensión suscribirse a Asterisk para recibir notificaciones cuando sea presente un nuevo mensaje en el buzón de voz. La secuencia es: X-Lite ------------------Subscribe-------------> Asterisk X-Lite <-------401 Unauthorized-------------- Asterisk X-Lite ------------------Subscribe-------------> Asterisk X-Lite <------------------200 Ok---------------- Asterisk X-Lite <-----------------NOTIFY---------------- Asterisk X-Lite ------------------200 Ok-----------------> Asterisk Una vez que Asterisk acepte el SUBSCRIBE enviado por X-Lite, le enviará un NOTIFY para que el softphone sepa si hay mensajes en el buzón de voz. Claramente todavía no hay ninguno (ultima parte del mensaje NOTIFY enviado por Asterisk): Messages-Waiting: no. Message-Account: sip:[email protected]. Voice-Message: 0/0 (0/0). En la consola de Asterisk aparecerá la extensión registrada: asterisk -rvvvvvvvvvvvvvvvvv CLI> sip show peers 88
Name/username 1000/1000
Host 79.44.192.186
Dyn Forcerport Comedia ACL Port Status D Yes Yes 6000 OK (251 ms)
Description
Otra forma de ver los mensajes SIP es activar el sip debug en Asterisk. Se puede hacer de forma general: CLI> sip set debug on SIP Debugging re-enabled o solamente para una extensión/troncal especifica: CLI> sip set debug peer 1000 SIP Debugging Enabled for IP: 190.255.234.54:10527 CLI> sip set debug peer voztovoice SIP Debugging Enabled for IP: 77.72.169.129:5060 Para desactivar el SIP debug: CLI> sip set debug off 3.6 Softphone 3CX Se instalará un segundo softphone para las pruebas. En este caso 3CX. Se descarga, se instala y se inicia:
Se presiona el botón evidenciado y, en la pantalla que sigue, se selecciona el icono Conexión: 89
En la nueva ventana se presiona el botón New y se configura la extensión 1001:
Terminada la configuración se presiona el botón OK y nuevamente OK. La extensión se registrará a Asterisk: CLI> sip show peers Name/username 1000/1000
Host 79.44.192.186
Dyn Forcerport Comedia ACL Port Status D Yes Yes 6000 OK (250 ms)
Description
90
1001/1001
79.44.192.186
D Yes
Yes
52236
OK (369 ms)
Se sale de la consola de Asterisk: CLI> quit
3.7 Llamadas entre extensiones Si desde la extensión 1000 se llama la extensión 1001, en la consola de Asterisk aparecerá: NOTICE[2036][C-00000000]: chan_sip.c:25632 handle_request_invite: Call from '1000' (79.44.192.186:6000) to extension '1001' rejected because extension not found in context 'externas'. Esto porque no se ha configurado todavía el dialplan para permitir las llamadas entre las extensiones. nano /etc/asterisk/extensions.conf y al final del contexto internas se añaden las siguientes lineas: exten => _100[0-2],1,Dial(SIP/${EXTEN},30) same => n,Hangup En la primera linea, después del comando exten => la “_” indica que se está utilizando un Patternmatching. En el párrafo 7.2 se explicará cosa son y como se utilizan los Pattern-matching. En este ejemplo [0-2] significa que la cuarta cifra puede ser uno 0 un 1 o un 2. De esta formas si marcamos 1000 1001 o 1002 todas las llamadas entrarán en este bloque de dialplan. 1 es la prioridad y Dial es la aplicación que se utiliza para iniciar una llamada. La sintaxis es: Dial(Technology/Resource[&Technology2/Resource2[&...]][,timeout[,options[,URL]]]) En este caso Technology es SIP, resource es ${EXTEN} y timeout es 30 segundos. La variable $ {EXTEN} es una variable de canal (los distintos tipos de variables se presentarán en el párrafo 7.1) y contendrá el numero marcado. Si nadie contesta dentro de 30 segundos la llamada terminará (Hangup). El proveedor VozToVoice requiere que la sintaxis para marcar cualquier numero sea: 00 + código país + numero. Para poder utilizar el proveedor para las llamadas salientes, después del contexto internas se crea el contexto internacio y se añaden las siguientes lineas: [internacio] exten => _00.,1,Dial(SIP/voztovoice/${EXTEN},30) same => n,Hangup Si en el contexto internacio se quiere diferenciar las llamadas nacionales (fijo/celulares) de las llamadas internacionales se añaden los dos bloques que siguen (para Colombia):
91
Celulares: exten => _3XXXXXXXXX,1,Dial(SIP/voztovoice/0057${EXTEN},30) same => n,Hangup Fijos: exten => _[12,4-9]XXXXXXX,1,Dial(SIP/voztovoice/0057${EXTEN},30) same => n,Hangup Como se quiere que solamente las extensiones configuradas con el contexto externas tengan acceso a este contexto se añade esta linea al contexto externas: include => internacio para que el bloque quede: [externas] include => internas include => internacio Se guardan los cambios y se recarga el dialplan. asterisk -rvvvvvvvvvvvvvvv CLI> dialplan reload Ahora desde la extensión 1000 se marca el numero 1001. El resultado en la consola de Asterisk será: Executing [1001@externas:1] Dial("SIP/1000-00000000", "SIP/1001,30") in new stack y en el teléfono 3CX:
3.8 SIP INVITE y CANCEL El método SIP que se utiliza para iniciar una sesión media, es INVITE. Para ver como funciona se capturará la traza de una llamada con ngrep. En la ventana terminal del servidor se escribe:
92
ngrep 1000 -W byline port 5060 > /tmp/invite Luego desde la extensión 1000 se llama la extensión 1001. Se contesta la llamada y después de unos segundos se cuelga. Se vuelve a la ventana terminal y se termina la captura de los paquetes con CTRLC En el archivo invite estará presente esta secuencia: X-Lite
Asterisk
3CX
----------------INVITE---1001-----> <-------401 Unauthorized--------------------------ACK------------------> ----------------INVITE---1001-----> <------------100 Trying-------------------------INVITE 1000--------> <--------180 Ringing-------------<------------180 Ringing------------<------------200 OK--------------------------------ACK---------------> <---------------200 OK--------------------------------ACK------------------> Sesion Media <----------------BYE-------------------------------200 OK-------------> <----------------BYE-----------------------------------200 OK-------------------> El X-LIte envía un INVITE para la extensión 1001 a Asterisk. Asterisk contesta diciendo que para aceptar el INVITE, X-Lite tiene que autenticarse. X-Lite contesta con ACK confirmando que ha recibido la respuesta de Asterisk; luego envía otro INVITE con sus datos de autentificación. Asterisk contesta con un Trying (probando) y envía el INVITE al 3CX que contesta con un 180 Ringing (timbrando). Asterisk devuelve el 180 Ringing a X-Lite. Cuando la extensión 1001 contesta la llamada genera un 200 OK y Asterisk un ACK confirmando que ha recibido el 200 OK. Asterisk envía el 200 OK a X-Lite y cuando este confirma la recepción del mensaje con un ACK inicia la sesión media (en este caso solo audio) entre las dos extensiones. Cuando la extensión 1001 cuelga se genera un BYE que es recibido por Asterisk que contesta con un 200 OK. Asterisk envía el BYE al X-Lite que contesta con un 200 OK. A partir de este momento termina realmente la llamada. Una segunda prueba es que la extensión 1000 cuelgue antes que la extensión 1001 conteste. En la ventana terminal de Linux se escribe: ngrep 1000 -W byline port 5060 > /tmp/cancel Luego desde la extensión 1000 se llama la extensión 1001 y después de unos segundos se cuelga. Se 93
vuelve a la ventana terminal y se termina la captura de los paquetes con CTRL-C. Analizando el archivo cancel, esta es la secuencia:
X-Lite
Asterisk
3CX
----------------INVITE---1001-----> <-------401 Unauthorized--------------------------ACK------------------> ----------------INVITE---1001-----> <------------100 Trying-------------------------INVITE 1000--------> <--------180 Ringing-------------<------------180 Ringing----------------------------CANCEL-------------------> <--------------200 OK----------------<-------487 Request Terminated--------------------ACK-----------------> --------------CANCEL-----------> <-------------200 OK-------------<----- 487 Request Terminated------------------ACK----------------> Una tercera prueba es llamar desde el Sofphone X-Lite sin que este esté registrado a Asterisk. Se entra en el menú Softphone → Account Settings:
Se deselecciona la casilla “Register with domain and receive calls” y se presiona la tecla OK. El teléfono ya no estará registrado en Asterisk: CLI> sip show peers Name/username Host 1000/1000 (Unspecified)
Dyn Forcerport ACL Port Status D N 0 UNKNOWN
pero podrá seguir efectuando llamadas (marcar a la extensión 1001). Lo que no podrá es recibir llamadas (marcar desde la extensión 1001 a la extensión 1000). Para recibir llamadas el Softphone tiene 94
que estar registrado a Asterisk (REGISTER); para efectuar llamadas (INVITE) no hace falta que esté registrado pero si los datos de autentificación tienen que ser aquellos definidos en el sip.conf. Ahora para probar el proveedor SIP se marca, desde la extensión 1000, un numero internacional (por ejemplo la linea de atención al cliente de Avianca): 005714013434 Si se intenta marcar el mismo numero, como se verá más adelante, desde la extensión 1002 no funcionará ya que esa extensión no tiene acceso al contexto internacio: NOTICE[10455]: chan_sip.c:20785 handle_request_invite: Call from '005714013434' rejected because extension not found in context 'locales'.
'1002'
to
extension
De esta forma podemos controlar las extensiones que tienen acceso a las llamadas salientes. 3.9 Los codecs La palabra codec es la abreviatura de codificador-decodificador. Los codecs se utilizan para comprimir el audio antes de enviarlo y/o utilizarlo en un determinado sistema/software. En Asterisk los codecs permiten la transmisión del audio/video entres los dos canales que componen una llamada (el llamante y el llamado). Es el mismo Asterisk que se hace cargo de la negociación de los codecs y en el caso que las dos extensiones estén utilizando codec distintos, será Asterisk que transcodificará el audio de un formato a otro. Esto es cierto para la mayoría de los codecs. Para algunos, ejemplo el G729, Asterisk actuará como pasarela. Esto quiere decir que ambas extensiones/dispositivos tendrán que tener configurado y disponible el codec G729. La diferencia entre un codec y otro es el tipo de algoritmo utilizado para la compresión de audio y, en base a eso, el ancho de banda utilizado y la calidad del audio proporcionada. Si se quiere ver la lista de codec suportados por Asterisk, se entra en la consola: asterisk -rvvvvvvvvvvvvvv y se escribe el comando: CLI> core show codecs Aparecerá la lista completa. Si se quiere obtener información del “costo” para transcodificar el audio de un codec a otro: CLI> core show translation Translation times between formats (in microseconds) for one second of data
95
Source Format (Rows) Destination Format (Columns) gsm ulaw alaw g726 adpcm slin lpc10 speex speex16 ilbc g726aal2 g722 slin16 testlaw speex32 slin12 slin24 slin32 slin44 slin48 slin96 slin192 gsm - 15000 15000 15000 15000 9000 15000 15000 23000 15000 15000 17250 17000 15000 23000 17000 17000 17000 17000 17000 17000 17000 ulaw 15000 - 9150 15000 15000 9000 15000 15000 23000 15000 15000 17250 17000 15000 23000 17000 17000 17000 17000 17000 17000 17000 alaw 15000 9150 - 15000 15000 9000 15000 15000 23000 15000 15000 17250 17000 15000 23000 17000 17000 17000 17000 17000 17000 17000 g726 15000 15000 15000 - 15000 9000 15000 15000 23000 15000 15000 17250 17000 15000 23000 17000 17000 17000 17000 17000 17000 17000 adpcm 15000 15000 15000 15000 - 9000 15000 15000 23000 15000 15000 17250 17000 15000 23000 17000 17000 17000 17000 17000 17000 17000 slin 6000 6000 6000 6000 6000 - 6000 6000 14000 6000 6000 8250 8000 6000 14000 8000 8000 8000 8000 8000 8000 8000 lpc10 15000 15000 15000 15000 15000 9000 - 15000 23000 15000 15000 17250 17000 15000 23000 17000 17000 17000 17000 17000 17000 17000 speex 15000 15000 15000 15000 15000 9000 15000 - 23000 15000 15000 17250 17000 15000 23000 17000 17000 17000 17000 17000 17000 17000 speex16 23500 23500 23500 23500 23500 17500 23500 23500 - 23500 23500 15000 9000 23500 23000 17500 17000 17000 17000 17000 17000 17000 ilbc 15000 15000 15000 15000 15000 9000 15000 15000 23000 - 15000 17250 17000 15000 23000 17000 17000 17000 17000 17000 17000 17000 g726aal2 15000 15000 15000 15000 15000 9000 15000 15000 23000 15000 - 17250 17000 15000 23000 17000 17000 17000 17000 17000 17000 17000 g722 15600 15600 15600 15600 15600 9600 15600 15600 15000 15600 15600 - 9000 15600 23000 17500 17000 17000 17000 17000 17000 17000 slin16 14500 14500 14500 14500 14500 8500 14500 14500 6000 14500 14500 6000 - 14500 14000 8500 8000 8000 8000 8000 8000 8000 testlaw 15000 15000 15000 15000 15000 9000 15000 15000 23000 15000 15000 17250 17000 - 23000 17000 17000 17000 17000 17000 17000 17000 speex32 23500 23500 23500 23500 23500 17500 23500 23500 23500 23500 23500 23500 17500 23500 - 17500 17500 9000 17000 17000 17000 17000 slin12 14500 14500 14500 14500 14500 8500 14500 14500 14000 14500 14500 14000 8000 14500 14000 - 8000 8000 8000 8000 8000 8000 slin24 14500 14500 14500 14500 14500 8500 14500 14500 14500 14500 14500 14500 8500 14500 14000 8500 - 8000 8000 8000 8000 8000 slin32 14500 14500 14500 14500 14500 8500 14500 14500 14500 14500 14500 14500 8500 14500 6000 8500 8500 - 8000 8000 8000 8000 slin44 14500 14500 14500 14500 14500 8500 14500 14500 14500 14500 14500 14500 8500 14500 14500 8500 8500 8500 - 8000 8000 8000 slin48 14500 14500 14500 14500 14500 8500 14500 14500 14500 14500 14500 14500 8500 14500 14500 8500 8500 8500 8500 - 8000 8000 slin96 14500 14500 14500 14500 14500 8500 14500 14500 14500 14500 14500 14500 8500 14500 14500 8500 8500 8500 8500 8500 - 8000 slin192 14500 14500 14500 14500 14500 8500 14500 14500 14500 14500 14500 14500 8500 14500 14500 8500 8500 8500 8500 8500 8500 -
En las lineas donde no aparece un valor, significa que Asterisk actúa como pasarela (ejemplo: G723, G729, siren7, siren14). ¿Cómo funciona el envío de audio en Asterisk? Una vez negociada la sesión SIP, con el protocolo RTP (RFC3550) se enviaran paquetes de audio de 20 milisegundos (normalmente). Visto gráficamente:
El paquete audio estará encapsulado en un paquete RTP que a su vez estará encapsulado en un paquete UDP (protocolo de transporte) que a su vez estará encapsulado en un paquete IP (donde estarán presentes los datos de destino).
96
Esto quiere decir que a pesar de que un codec teóricamente necesite un determinado ancho de banda, en la practica este ancho de banda es más grande ya que hay que tener en cuenta los bytes que se van sumando con las cabeceras de cada protocolo. En la tabla que sigue, los consumos reales de banda de los codecs más utilizados: Codec
Banda teorica
Banda Practica
G711
64 Kbps
95,2 Kbps
G722
64 Kbps
95,2 Kbps
GSM
13 Kbps
43,7 Kbps
G729a
8 Kbps
39,2 Kbps
Aunque el codec G722 tiene el mismo consumo de banda del G711, la calidad del audio es mucho mejor ya que el muestreo se efectúa a 16 kHz mientra que con el codec G711 se realiza a 8 kHZ (más alta la frecuencia de muestreo, mejor la calidad del audio). Del codec G711 existen dos variantes: • •
µlaw utilizado en Estados Unidos y Japón alaw utilizado en Europa
3.9.1 Negociación de Codec en Asterisk Como se ha dicho en el párrafo dedicado a la configuración del sip.conf, Asterisk normalmente actúa como intermediario entre las distintas extensiones. Esto quiere decir que a lo largo de una llamada, primero negocia los codec con la extensión llamante y luego con la extensión llamada. En la configuración de la extensión 1000 si han añadido estos parámetros: allow=alaw allow=g722 allow=g729 esto quiere decir que Asterisk espera negociar con la extensión 1000 uno de los tres codecs. Para hacer una prueba se entra en el menú Sopftphone → Preferences → Audio Codecs del X-Lite y se configura de la siguiente manera:
97
Se deja activo solamente el codec OPUS. Luego desde el X-Lite se marca la extensión 1001. En la pantalla del Softphone aparecerá:
y en la consola de Asterisk: NOTICE[2036][C-00000008]: chan_sip.c:10564 process_sdp: No compatible codecs, not accepting this offer! ¿Qué significa? Que Asterisk no puede procesar la llamada porque el softphone X-Lite, extensión 1000, está utilizando el codec OPUS mientras en la configuración del sip.conf la extensión 1000 no tiene configurado el codec OPUS. Se vuelve al menú Sopftphone → Preferencias → Codecs de audio y se configura de la siguiente manera:
98
Se presiona el botón Aceptar. Ahora si se vuelve a marcar la extensión 1001 todo funcionará correctamente. ¿Qué tipo de configuración utilizar? En una instalación de Asterisk local con troncal SIP para sacar las llamadas, una buena solución es activar el codec G722 para las llamadas entre extensiones (una buena calidad) y utilizar el codec G729 para las llamadas salientes (casi todos los proveedores VoIP lo soportan). Para hacer una prueba se abre el archivo sip.conf: nano /etc/asterisk/sip.conf y en la configuración de la troncal voztovoice se comenta este parámetro: allow=alaw para que quede: ;allow=alaw Se guardan los cambios y se recarga la configuración sip: asterisk -rvvvvvvvvvvvvvvv CLI> sip reload Ahora desde el X-Lite se marca un numero fijo o celular. La llamada no tendrá éxito. ¿Por qué? Porque en el Softphone están configurados los codec alaw y ulaw mientras en la troncal el codec G729. Como Asterisk para ese codec actúa solamente como pasarela, la llamada no se puede completar. En la consola de Asterisk: WWARNING[20382][C-00000009]: channel.c:6164 ast_channel_make_compatible_helper: No path to translate from SIP/voztovoice-0000000f to SIP/1000-0000000e
99
Para que la llamada funcione hay que instalar la versión “educational” del codec g729: cd /usr/lib64/asterisk/modules Para el VPS Linode es: wget http://asterisk.hosting.lv/bin/codec_g729-ast110-gcc4-glibc-x86_64-barcelona.so Se vuelve ejecutable el archivo: chmod +x codec_g729-ast110-gcc4-glibc-x86_64-barcelona.so Se entra en la consola de Asterisk: asterisk -rvvvvvvvvvvvvvvv si carga el modulo: CLI> module load codec_g729-ast110-gcc4-glibc-x86_64-barcelona.so Loaded codec_g729-ast110-gcc4-glibc-x86_64-barcelona.so == Registered translator 'g729tolin' from format g729 to slin, table cost, 900000, computational cost 1000 == Registered translator 'lintog729' from format slin to g729, table cost, 600000, computational cost 3999 Loaded codec_g729-ast110-gcc4-glibc-x86_64-barcelona.so => (g729 Coder/Decoder, based on Intel IPP )
Ahora desde el Softphone X-Lite se marca a un numero fijo/celular. Una vez contestada la llamada: CLI> sip show channels 9.44.192.186 1000 Y2MyNWY1N2FjNDd (alaw) 72.14.184.31 005714013434 1e0bf5c2794cc86 (g729)
No No
Rx: ACK Tx: ACK
1000 voztovoice
En el canal de la troncal se está utilizando el codec G729 mientras en la extensión 1000 el codec alaw que es el primero configurado en la extensión 1000 del sip.conf. En este caso Asterisk se encarga de descodificar (transcoding) la llamada desde G729 a alaw y viceversa. Para terminar se vuelve a activar el codec alaw para la troncal voztovoice quitando el punto y coma que precede esta linea: ;allow=alaw y se recarga la configuración SIP: asterisk -rvvvvvvvvvvvvvvv CLI> sip reload
100
CAPITULO IV Protocolo IAX2 – iax.conf El protocolo IAX (ahora IAX2) ha sido desarrollado por Mark Spencer, primer autor del código de Asterisk PBX y actual gerente de la empresa Digium. La idea detrás de IAX era crear un protocolo que pudiera utilizar el mismo puerto para la señalización y la sesión media, eliminando, de esta forma, los problemas relacionados con el NAT que padece el protocolo SIP. De hecho IAX2 utiliza el puerto estándar 4569 UDP para la señalización y el transporte de la sesión media. A pesar de haber sido aceptado por la IETF y haberse vuelto un estándar de hecho (RFC5456) son muy pocos los proveedores que ofrecen este tipo de conexión y los teléfonos que lo soportan. Una funcionalidad interesante de este protocolo y que quizás puede ser útil implementar en una instalación de Asterisk, es la del trunking, que permite encapsular los paquetes audio de distintas llamadas en un mismo paquete UDP, reduciendo de hecho el ancho de banda necesario. Para que el trunking sea utilizable en Asterisk, DAHDI tiene que ser instalado porque es la fuente de sincronización que IAX2 necesita para funcionar en esta modalidad. 4.1 iax.conf Este archivo, como el sip.conf, se divide en tres bloques: • • •
Una parte general donde se configuran los parámetros del protocolo Un bloque central donde se configuran los registros a proveedores IAX2 o otro servidores Asterisk Un bloque final dedicado a la configuración de las extensiones
En la columna descripción aparecerá en negrita el valor del parámetro. Al final del modulo, toda la configuración del archivo. Parámetro
Descripción
[general]
Esta etiqueta define el inicio de la parte general de la configuración del protocolo IAX2
bindport
El puerto UDP usado por este protocolo. Este parámetro va configurado antes del parámetro bindaddr. Valor 4569
bindaddr
Es la dirección IP y el puerto donde Asterisk se pondrá a la escucha para las señalización IAX2 utilizando el protocolo UDP. Si se indica 0.0.0.0 Asterisk escuchará en todas la direcciones IPv4 presentes en el servidor Linux. Valor: 0.0.0.0
nochecksums
yes=no se realiza la suma de verificación de los paquetes UDP
delayreject
yes=mejora la seguridad contra “brute force password attacks” retrasando el envío de los rechazos de autentificación
amaflags
Automated Message Accounting. Con este parámetro se configura un
Parámetro
Descripción campo del CDR (call detail records) univoco para todas las llamadas. Este campo se puede personalizar en cada extensión. Valor: documentation
srvlookup
yes=Permite realizar búsquedas de registros DNS SRV basadas en los nombres de dominio para llamadas SIP salientes del tipo: usuario@dominio.
language
es=el idioma predefinido para las locuciones
mohinterpret
clase de música de espera predefinida – default
mohsuggest
Clase de música de espera cuando un canal de tipo peer se pone en espera – default
bandwidth
Con este parámetro se define el ancho de banda disponible para las llamadas y en base a este se escogerán los codecs audio a utilizar entre los configurados. Este parámetro acepta como valores: low, medium, high
disallow
all – Se desactivan todos los codec audio
allow
Se indican los codec audio utilizables. Pueden ser indicados uno por linea o en la misma linea separados por una coma: allow=alaw allow=ulaw o allow=alaw,ulaw
minregexpire
60=tiempo mínimo, en segundos, de espiración del registro de las troncales IAX2
maxregexpire
60=tiempo máximo, en segundos, de espiración del registro de las troncales IAX2
encryption
yes=se habilita el cifrado de la señalización y del flujo media
forceencryption
no=no se fuerza el uso del cifrado
trunkmaxsize
define el tamaño máximo de los datos (bytes) que pueden pasar por una troncal IAX2 cuando se configura el parámetro trunk=yes. Con 128000 bytes pasarán por la troncal 800 llamadas con codec alaw y paquetes audio de 20ms
trunkmtu
cuando el trafico que pasa por una troncal IAX2 es bastante alto, si los paquetes UDP los fragmenta el sistema operativo Linux, hay la posibilidad que se verifique una mala calidad del audio. Configurando este parámetro con el valor 1240, significa que será el mismo Asterisk que se encargará de fragmentar los paquetes audio más grandes de 1240 byte, mejorando la calidad del audio en las conversaciones
autokill
yes=si no se recibe un ACK, después de una NEW enviado, dentro de 103
Parámetro
Descripción 2000ms, para evitar que el servidor Asterisk se estanque, se anula la solicitud
codecpriority
Controla quien tiene la prioridad en la negociación de los codec audio. Puede ser: • caller • host • disabled
rtcachefriends
Este parámetro aplica cuando las extensiones están configuradas en una base de datos (se verá más adelante). Valor no
rtupdate
este parámetro también aplica cuando las extensiones están configuradas en una base de datos. Cuando una de estas extensiones se registre a Asterisk, en la base de datos se guardará la dirección IP, el puerto, el tiempo de registro y el nombre de usuario. Valor yes
parkinglot
Asterisk, entre sus funcionalidades, permite parquear una llamada. Como desde la versión 1.6.X es posible configurar más de un “contexto” de parqueo, en este parámetro se indica el predefinido. Valor: default
calltokenoptional
En septiembre del 2009 hubo una actualización del protocolo IAX2 para mejorar la seguridad. Este parámetro con el que sigue hace referencia a esa nueva implementación. Como la mayoría de los teléfonos IAX no la soportan se indica que es opcional para todas las direcciones IP. 0.0.0.0/0.0.0.0
requirecalltoken
auto=se requiere el calltoken solo si el teléfono lo soporta
maxcallnumbers
Este parámetro se utiliza para limitar el numero de llamadas que puede efectuar una IP remota. Si se supera este valor, las nuevas llamadas serán rechazadas. Valor:100
maxcallnumbers_nonvalidated En este parámetro se indica el numero máximo de llamadas no autenticadas, con el sistema del calltoken, que el sistema aceptará. A diferencia del parámetro anterior, este no se calcula para cada IP remota sino de manera global. Valor: 1000 register =>
El segundo bloque empieza con las lineas de register. Algunos ejemplos: • register => marko:[email protected] Registro con nombre usuario, contraseña y dominio • register => joe@remotehost:5656 Registo con nombre, dominio y puerto remoto (sin contraseña) • register => marko:[key]@tormenta.linux-support.net Registro con nombre, clave RSA (key) y dominio
104
En en tercero y ultimo bloque se configuran las troncales/extensiones IAX2. Por ahora se configurará solamente una extensión. Más adelante se verá como configurar una troncal y utilizar IAX2 para el envío de FAX utilizando IAXmodem y Hylafax. Parametro
Descripción
[marko]
Nombre de la extensión
type
friend Puede ser peer y user
host
Si la extensión se conecta remotamente con un IP dinámico se pone dynamic. En caso contrario se pone la dirección IP
secret
La contraseña para la extensión. Valor predefinido: pbx9094
context
El contexto a que tendrá acceso la extensión. Valor externas
mailbox
Si este parámetro es configurado, cuando la extensión se conecte al servidor Asterisk, éste controlará si hay mensajes de voz pendientes y en caso positivo se lo comunicará usando MWI = Message Waiting Indicator. que es una señal audio o vídeo que puede ser recibida por la mayoría de los teléfonos IP o Softphone Valor 1234@default
qualify
Este parámetro se utiliza para mantener activa la conexión de una extensión que se conecta al servidor Asterisk detrás de una NAT. Valor Yes
callerid
marko
requirecalltoken
Véase parte general. Valor auto
Para crear el archivo de configuración de iax.conf, se renombra el predefinido y se crea uno nuevo: mv /etc/asterisk/iax.conf /etc/asterisk/iax.conf.old nano /etc/asterisk/iax.conf Se copian las siguientes lineas: [general] bindport=4569 bindaddr=0.0.0.0 nochecksums=yes delayreject=yes amaflags=documentation srvlookup=yes 105
language=es mohinterpret=default mohsuggest=defautl bandwidth=high disallow=all allow=alaw allow=alaw minregexpire=60 maxregexpire=60 encryption=yes forceencryption=no trunkmaxsize=128000 trunkmtu=1240 autokill=yes codecpriority=host rtcachefriends=no rtupdate=yes parkinglot=default calltokenoptional=0.0.0.0/0.0.0.0 requirecalltoken=auto maxcallnumbers=100 maxcallnumbers_nonvalidated=1000 ;register => marko:[email protected] ;register => joe@remotehost:5656 ;register => marko:[key]@tormenta.linux-support.net [marko] type=friend host=dynamic secret=pbx9094 context=externas mailbox=1234@default qualify=yes callerid=marko requirecalltoken=auto Se guardan los cambios y se actualiza la configuración de IAX2: asterisk -rvvvvvvvvvvvvvvv CLI> iax2 reload Para ver la configuración de la extensión recién creada: CLI> IAX2 show peer marko 106
* Name : marko Description : Secret : Context : externas Parking lot : Mailbox : 1234@default Dynamic : Yes Callnum limit: 0 Calltoken req: Auto Trunk : No Encryption : (aes128,keyrotate) Callerid : "marko" <> Expire : -1 ACL : No Addr->IP : (Unspecified) Port 0 Defaddr->IP : 0.0.0.0 Port 4569 Username : Codecs : (alaw) Codec Order : (alaw) Status : UNKNOWN Qualify : every 60000ms when OK, every 10000ms when UNREACHABLE (sample smoothing Off Para una lista de los comandos disponibles para el protocolo IAX2: CLI> help IAX2 4.2 Softphone Zoiper Para conectarse a la extensión recién creada en el archivo iax.conf, se utilizará el softphone Zoiper. Se descarga y se instala. Una vez instalado se escoge el menú Settings -> Preferences:
en la ventana que aparece se elige "Create account": 107
En la nueva ventana se selecciona IAX y se continua con el botón “NEXT”: se pone el nombre de la cuenta (marko) y se presiona el botón OK:
En user / user@host se pone marko, en password, la contraseña configurada para el usuario marko y en Domain /Outbound proxy se pone la IP del servidor Linode. Se continua presionando el botón “NEXT”:
108
En la ventana que sigue se selecciona un nombre para la nueva cuenta creada y se presiona el botón “NEXT”:
Se continua presionando el botón “Add more” para añadir la cuenta SIP 1002:
109
110
Si toda la configuración se ha efectuado correctamente, aparecerán las dos extensiones registradas en Asterisk: CLI> IAX2 show peers Name/Username Host Mask Port Status Description marko 79.44.192.186 (D) 255.255.255.255 4569 (E) OK (243 ms) 1 iax2 peers [1 online, 0 offline, 0 unmonitored] CLI> sip show peers Name/username Host Dyn Forcerport Comedia ACL Port Status 1000/1000 79.44.192.186 D Yes Yes 6000 OK (241 ms) 1001/1001 79.44.192.186 D Yes Yes 62225 OK (368 ms) 1002/1002 79.44.192.186 D Yes Yes 9000 OK (250 ms) voztovoice/4260141991 72.14.184.31 No No 5060 OK (1 ms) 4 sip peers [Monitored: 4 online, 0 offline Unmonitored: 0 online, 0 offline]
Description
CLI> quit A partir de este momento, todas las extensiones SIP y IAX2 están conectadas al servidor Asterisk. Los iconos de los tres softphone:
Ahora la pregunta: ¿Cómo se configura el dialplan para que se pueda llamar el usuario marko ya que la extensión no es un numero sino un nombre? Se hace de la siguiente manera: nano /etc/asterisk/extensions.conf 111
al final del contexto internas se añade: exten => 1234,1,Dial(IAX2/marko,30) same => n,Hangup Se guardan los datos y se recarga el dialplan asterisk -rvvvvvvvvvvvv CLI> dialplan reload Ahora desde la extensión 1000 se marca 1234. El resultado en la consola de Asterisk: Executing [1234@externas:1] Dial("SIP/1000-00000000", "IAX2/marko,30") in new stack El resultado en Zoiper:
De esta forma se ha realizado la prueba de una llamada entre dos teléfonos con distintos protocolos.
112
CAPITULO V GoogleTalk – motif.conf xmpp.conf Como se ha visto a lo largo de la instalación de Asterisk, la centralita soporta el protocolo XMPP que permite conectarla a servidores que utilizan ese protocolo. En Asterisk el modulo relacionado es el res_xmpp.so. Para ver si efectivamente este modulo ha sido compilado y instalado correctamente, se entra en la consola de Asterisk: asterisk -rvvvvvvvvvvvvvvvvvvv Primero se controla que el modulo exista: CLI> module show like res_xmpp Module Description res_xmpp.so Asterisk XMPP Interface 1 modules loaded
Use Count 0
luego se quita y se vuelve a cargar para controlar eventuales errores: CLI> module unload res_xmpp.so -- Message technology handler 'xmpp' unregistered. == Unregistered application 'JabberSend' == Unregistered application 'JabberSendGroup' == Unregistered application 'JabberStatus' == Unregistered application 'JabberJoin' == Unregistered application 'JabberLeave' == Manager unregistered action JabberSend == Unregistered custom function JABBER_STATUS == Unregistered custom function JABBER_RECEIVE CLI> module load res_xmpp.so == Parsing '/etc/asterisk/xmpp.conf': Found == Manager registered action JabberSend == Registered application 'JabberSend' == Registered application 'JabberSendGroup' == Registered application 'JabberStatus' == Registered application 'JabberJoin' == Registered application 'JabberLeave' == Registered custom function 'JABBER_STATUS' == Registered custom function 'JABBER_RECEIVE' -- Message technology handler 'xmpp' registered. Loaded res_xmpp.so => (Asterisk XMPP Interface) Al cargar un modulo aparecen las aplicaciones y las funciones que ese modulo activa.
Se sale de la consola: CLI> quit Para la configuración de un usuario GoogleTalk en Asterisk además del modulo res_xmpp.so, hay que configurar el modulo chan_motif (nueva funcionalidad de Asterisk 11) que es el que permite llamadas de este tipo: • • • •
Asterisk → GoogleTalk GoogleTalk → Asterisk Asterisk → GoogleVoice GoogleVoice → Asterisk
Esto significa que se podrán recibir llamadas de usuarios GoogleTalk en Asterisk y luego, a través de la configuración del dialplan, transferirlas a cualquier extensión configurada en la PBX. Siempre configurando adecuadamente el dialplan será posible, desde una extensión, llamar usuarios GoogleTalk y efectuar llamadas utilizando el servicio GoogleVoice. Para la configuración se aconseja crear una nueva cuenta en Google. La ultima funcionalidad funciona solamente si asociada a la cuenta Gmail se tiene una cuenta Gvoice con un numero geográfico de Estados Unidos (disponible solamente para cuentas de Estados Unidos). IMPORTANTE: el soporte de Google para XMPP supuestamente ha terminado el 15 de Mayo 2014. Esto quiere decir que no se podrá acceder a los servicios con aplicaciones/programas de terceras partes. Esto implica que quizás el chan motif deje de funcionar.
5.1 xmpp.conf y motif.conf Se empieza con el archivo de configuración xmpp.conf. Como siempre en la columna descripción, en negrita, aparecen los valores que hay que configurar. Al final de las tablas, la configuración de los dos archivos. Parámetro
Descripción
[general]
etiqueta que define el inicio de la parte general
debug
no=no se activa el debug en la consola de Asterisk yes=se activa el debug en la consola de Asterisk
autoprune
yes=elimina automáticamente los usuario de la lista de amigos no=no elimina automáticamente los usuarios de la lista de amigos
autoregister
yes=si un usuario añade el usuario configurado en este archivo a 115
su lista de amigos, Asterisk automáticamente lo añadirá a la lista de amigos no=no lo añade automáticamente ;collection_nodes=yes
A partir de la versión 1.8 de Asterisk es posible monitorear el estado de las extensiones remotas (otros servidores Asterisk) utilizando el protocolo XMPP. Este parámetro indica si se habilita el soporte para la especificación XEP-048 del protocolo XMPP. Se deja comentado
;pubsub_autocreate=yes
Este parámetro especifica si los nodos para el monitoreo de las extensiones remotas se crean en automático o no. Se deja comentado.
;auth_policy=accept=yes
La especificación XEP-048 se basa en un sistema de suscripciones que los usuarios activan para recibir notificaciones. Con este parámetro en yes las suscripciones de los usuarios se aceptan en automático. Se deja comentado
[campusvtv]
A partir de esta etiqueta, la configuración del usuario GoogleTalk. Suponiendo que el usuario creado es [email protected], en la etiqueta se pone el nombre de usuario. Personalizar con el nombre del usuario google creado.
type
puede ser client o component
serverhost
dominio del servidor GoogleTalk. Valor: talk.google.com
;pubsub_node=pubsub.dominio.com Nombre del nodo para publicar los eventos para la configuración del monitoreo de extensiones remotas. Se deja comentado username
El nombre del usuario creado en Google. En este ejemplo [email protected]. Personalizar
secret
la contraseña asociada al usuario creado en Google. Personalizar
priority
Ya que es posible conectarse a la cuenta desde distintos dispositivos, en este parámetro se indica la prioridad que tendrá esta cuenta. Valor: 1
port
5222 Es el puerto que utiliza GoogleTalk para aceptar conexiones
usetls
yes=se activa el protocolo TLS. De esta forma todos los paquetes intercambiados entre cliente y servidor serán cifrados
usesasl
yes=se activa el protocolo sasl. Sasl es un protocolo de autentificación y autorización que permite la negociación de protocolos de cifrado entre cliente y servidor.
buddy
si se quiere añadir un amigo a la lista de amigos directamente desde la configuración del archivo se indica en este parámetro. Si los amigos que se quieren añadir son distintos, se agrega una linea con este parámetro para cada amigo. Por ejemplo se pone 116
[email protected] (personalizar con una otra cuenta gmail propria o de un amigo). ;distribute_events=yes
Se especifica si esta conexión se utilizará o no para la generación de eventos en la configuración del monitoreo de las extensiones remotas. Se deja comentado
status
En este parámetro se configura el estado de la cuenta como aparecerá a los demás contactos. Posibles valores: • chat • available • away • xaway • dnd
statusmessage
Mensaje de estado que aparecerá junto al nombre de usuario. Valor: Asterisk Server
timeout
100=tiempo máximo para la entrega de un mensaje (en segundos) recibido por Asterisk. Pasado este tiempo, si Asterisk no ha podido entregar el mensaje, lo borrará. Este parametro es pensado para funcionar con la función JABBER_RECEIVE que se verá más adelante.
sendtodialplan
Este parámetro define si los mensajes instantáneos recibidos por el usuario configurado se enviarán al dialplan. Valor: yes
context
Contexto del dialplan donde se enviarán los mensajes recibidos. Valor: message
Terminada la configuración del archivo xmpp.conf, se continua con el archivo motif.conf. En este archivo es posible configurar tres diferentes transportes y protocolos: • • •
Jingle utilizando ICE-UDP Google Jingle Google Voice
En este caso se configurará Google Jingle y Google Voice. Para que las llamadas funcionen, en el archivo rtp.conf, el parámetro icesupport tiene que estar activado (valor yes). En la columna descripción, en negrita, aparecen los valores que hay que configurar. Parámetro
Desc
[gtalk]
Etiqueta que da inicio a la configuración de Google Jingle.
context
contexto del dialplan donde entrarán las llamadas de los usuarios GoogleTalk. Valor: google-in 117
Parámetro
Desc
transport
En el caso de Google Jingle este parámetro tiene que ser google
disallow
all Se desactivan todos los codecs Audio
allow=alaw allow=h264
Se activan el codec audio ulaw y el codec vídeo h264
connection
se pone la etiqueta definida en el jabber.conf para el usuario GoogleTalk configurado en Asterisk. en este ejemplo es campusvtv. Personalizar
[gvoice]
Etiqueta que da inicio a la configuración de Google Jingle.
context
contexto del dialplan donde entrarán las llamadas de las llamadas googlevoice. Valor: google-in
transport
En el caso de Google Voice este parámetro tiene que ser google-v1
disallow
all Se desactivan todos los codecs Audio
allow=alaw allow=h264
Se activan el codec audio ulaw y el codec video h264
connection
se pone la etiqueta definida en el jabber.conf para el usuario GoogleTalk configurado en Asterisk. en este ejemplo es campusvtv. Personalizar
Una vez definidos todos los parámetros de xmpp.conf y gtalk.conf, se crean los respectivos archivos. Primero se renombran los predefinidos: mv /etc/asterisk/xmpp.conf /etc/asterisk/xmpp.conf.old mv /etc/asterisk/motif.conf /etc/asterisk/motif.conf.old Luego se crea el archivo xmpp.conf: nano /etc/asterisk/xmpp.conf se pegan las siguientes lineas: [general] debug=yes autoprune=no autoregister=yes ;collection_nodes=yes ;pubsub_autocreate=yes ;auth_policy=accept=yes 118
[campusvtv] type=client serverhost=talk.google.com ;pubsub_node=pubsub.dominio.com [email protected] secret=password priority=1 port=5222 usetls=yes usesasl=yes [email protected] ;distribute_events=yes status=available statusmessage=Asterisk Server timeout=100 sendtodialplan=yes context=message IMPORTANTE: antes de guardar la configuración, hay que personalizar los parámetros username, secret y la etiqueta [campusvtv], con los datos de su cuenta Google y el parámetro buddy con una cuenta google real. Se pasa al archivo motif.conf nano /etc/asterisk/motif.conf [gtalk] context=google-in transport=google disallow=all allow=ulaw allow=h264 connection=campusvtv [gvoice] context=google-in transport=google-v1 disallow=all allow=ulaw allow=h264 connection=campusvtv
119
IMPORTANTE: antes de guardar la configuración, hay que personalizar el parámetro connection con la etiqueta inicial de la configuración del usuario GoogleTalk en el archivo xmpp.conf (en este ejemplo campusvtv). Terminada la configuración de los dos archivos se entra en la consola de Asterisk y se recargan los dos módulos; primero res_jabber.so y luego chan_gtalk.so: asterisk -rvvvvvvvvvvvvv CLI> module unload res_xmpp.so CLI> module unload chan_motif.so CLI> module load res_xmpp.so CLI> module load chan_motif.so Después de algunos segundos, el usuario debería estar conectado: CLI> xmpp show connections JJabber Users and their status: [campusvtv] [email protected] ---Number of clients: 1
- Connected
Para ver la lista de amigos conectados ([email protected]) CLI> xmpp show buddies JXMPP buddy lists Client: campusvtv Buddy: [email protected] Resource: gmail.2FB963FC node: http://mail.google.com/xmpp/client/caps version: 1.1 Google Talk capable: yes Jingle capable: no Para una lista de comandos disponibles en los dos módulos CLI> help xmpp xmpp create collection Creates a PubSub node collection. xmpp create leaf Creates a PubSub leaf node xmpp delete node Deletes a PubSub node xmpp list nodes Lists PubSub nodes xmpp purge nodes Purges PubSub nodes xmpp set debug {on|off} Enable/Disable Jabber debug 120
xmpp show buddies Show buddy lists of our clients xmpp show connections Show state of clients and components Por ultimo si se entra en la cuenta Gmail añadida en el parámetro buddy del archivo xmpp.conf y, si no está activada, se activa la ventana de chat que se encuentra al fondo de la columna de las carpetas del correo electrónico:
Si la solicitud de amistad de la cuenta configurada en Asterisk no aparece, se añade esa cuenta directamente desde la ventana de chat:
En el menú que aparece, se selecciona añadir contacto y en la nueva ventana se añade la cuenta configurada en el archivo xmpp.conf:
Se escribe la dirección del contacto (personalizar) y se presiona el botón “Enviar invitaciones”. Después de unos segundos el contacto aparecerá en linea:
Ahora se pasa al dialplan. Como contexto para las llamadas entrantes de usuarios GoogleTalk, se ha definido google-in. Este contexto va creado en el dialplan: nano /etc/asterisk/extensions.conf Después del bloque internas se añaden estas lineas. [google-in] exten => s,1,NoOp( Call from Gtalk ) same => n,Dial(SIP/1000,30) 121
same => n,Hangup() Todas las llamadas que entren desde GoogleTalk se desvían a la extensión 1000. Si dentro de treinta segundos la extensión 1000 no contesta, la llamadas terminará Para las llamadas salientes se pone al final del contexto internas: exten => _[a-z].,1,Dial(motif/gtalk/${EXTEN}@gmail.com,30) same => n,Hangup Una explicación de las dos lineas: Se dice a Asterisk de llamar a través del canal motif, usando la conexión gtalk que es la etiqueta que da inicio al bloque de configuración de Google Jingle en el archivo motif.conf. Con _[a-z]. se puede marcar a cualquier usuario GoogleTalk cuyo nombre empieza con una letra del alfabeto (de a a z). Si después de 30 segundos, nadie contesta, se termina la llamada. Se guardan los cambios. Otra forma de actualizar el dialplan sin entrar en la consola de Asterisk es: asterisk -rx "dialplan reload" Dialplan reloaded. Se puede realizar una primera prueba llamando el usuario [email protected] desde el X-LIte (personalizar con el usuario añadido en el parámetro buddy del archivo xmpp.conf: Se marca de esta manera:
Se presiona el icono del telefono. El resultado:
Contestando la llamada se averiguará si el audio es presente en ambos lados. Otra prueba que se puede realizar es llamar el usuario configurado en el archivo xmpp.conf desde la cuenta gmail del contacto presente en el mismo archivo. Primero se selecciona el contacto; aparecerá: 122
Se selecciona el icono del auricular del teléfono para iniciar la llamada. Luego:
En X-Lite (la extensión 1000), aparecerá:
5.2 Google Voice Google Voice es el servicio de Google que permite efectuar llamadas a cualquier parte del mundo. Esta funcionalidad es disponible en la pagina personal de la cuenta Google:
123
Es posible efectuar llamadas utilizando una cuenta Google Voice directamente desde Asterisk. Para llamar, por ejemplo, a Estados Unidos, la sintaxis es 1 más el numero a llamar. En el contexto internacio del dialplan: nano /etc/asterisk/extensions.conf se añade: exten => _1XXXXXXXXXX,1,Dial(motif/gtalk/+${EXTEN}@voice.google.com) same => n,Hangup Como se puede ver el + se pone delante de la variable ${EXTEN} (+${EXTEN}). De esta forma no hace falta marcarlo. En el párrafo 7.2 se explicará como extraer solamente algunas partes de una variable. En la primera linea después de motif se pone el mismo parámetro gtalk utilizado para las llamadas entre usuario Gmail. Esto porque el sistema intentará sacar la llamada por Google Jingle y si no lo logra, por Google Voice (segundo bloque del archivo motif.conf). Para realizar una prueba, se puede llamar el numero de Avianca de Estados Unidos: 18002842622 Para las llamadas a cualquier otro país la sintaxis es +, código país, numero. En el mismo contexto internacio se añade: exten => _NNXX.,1,Dial(motif/gtalk/+${EXTEN}@voice.google.com) same => n,Hangup En el caso se disponga de un numero geografico de GoogleVoice y se quiera recibir las llamadas a la cuenta Gmail configurada en el archivo de configuración xmpp.conf, primero hay que entrar en la cuenta de GoogleVoice y en Settings:
124
configurar que todas las llamadas entrantes sea desviadas a la cuenta Google, luego en el dialplan hay que modificar el bloque [google-in], para que quede: [google-in] exten => s,1,NoOP(Llamada desde Google/Voice) same => n,Answer() same => n,Wait(1) same => n,SendDTMF(1) same => n,Dial(SIP/1000,30) same => n,Hangup() Esta configuración es necesaria porque GoogleVoice, aunque esté desactivado en la cuenta, antes de conectar la llamada espera el tono DTMF 1 para que el usuario “diga” que quiere aceptar la llamada entrante:
5.3 Aplicación JabberSend Una aplicación que se activa con el modulo res_xmpp.conf es “JabberSend” que permite enviar mensajes instantáneos a usuarios GoogleTalk y/o conectados a un servidor XMPP. La sintaxis de la aplicación es: JabberSend(Jabber,JID,Message) Un ejemplo. Cada vez que una extensión llame la extensión de la música en espera, se quiere enviar un 125
mensaje a un usuario GoogleTalk para que se entere. Se modifica el dialplan: nano /etc/asterisk/extensions.conf se cambia este bloque: exten => 200,1,Answer same => n,MusicOnHold(mp3,60) same => n,Hangup para que quede: exten => 200,1,Answer same => n,Jabbersend(campusvtv,[email protected],Estamos escuchando MP3) same => n,MusicOnHold(mp3,60) same => n,Hangup Cambiar “campusvtv” con la etiqueta que define el usuario configurado en el archivo xmpp.conf; cambiar el usuario [email protected] con el usuario Gmail al que se quiere enviar el mensaje. Se guardan los cambios y se recarga el dialplan: asterisk -rx "dialplan reload" Desde la extensión 1000 se marca la extensión 200. El resultado:
5.4 La función JABBER_RECEIVE La función JABBER_RECEIVE ha sido añadida desde la versión 1.8 de Asterisk. Esta función permite interaccionar con un usuario Google a través del envío y recepción de mensajes instantáneos. Para el envío de mensajes de texto se utiliza la aplicación SendText que permite, cuando un canal ya está abierto, enviar texto a ese canal. La sintaxis de la función es: asterisk -rvvvvvvvvvvvvvv
126
CLI> core show function JABBER_RECEIVE JABBER_RECEIVE(account,jid[,timeout]) • • •
account, es la etiqueta definida para el usuario Google Talk configurado en el archivo xmpp.conf (en este caso campusvtv) jid, es el nombre del usuario Google Talk con el que se quiere interactuar timeout, es el tiempo, en segundos, que tendrá el usuario Google Talk para escribir una respuesta
Un ejemplo sencillo, para que se vea como funciona, es enviar un mensaje de texto a un usuario Google Talk para pedirle su nombre y luego almacenar su respuesta en una variable. Para efectuar la prueba, se modifica el dialplan: nano /etc/asterisk/extensions.conf este bloque: [google-in] exten => s,1,NoOp( Call from Gtalk ) same => n,Dial(SIP/1000,30) same => n,Hangup() para que quede: [google-in] exten => s,1,NoOp( Call from Gtalk ) same => n,SendText(Hola,Como te llamas?) same => n,Set(nombre=${JABBER_RECEIVE(campusvtv,${CALLERID(name)},20)}) same => n,SendText(Hola ${nombre}, bienvenido en VozToVoice) same => n,Set(CALLERID(name)=${nombre}) same => n,Wait(2) same => n,SendText(Espera un momento mientras te comunicamos con un operador) same => n,Dial(SIP/1000,30) same => n,Hangup() La variable ${CALLERID(name)} contendrá el nombre del usuario Google Talk. Antes de guardar los cambios, modificar campusvtv con la etiqueta que da inicio a la configuración del usuario google en el archivo xmpp.conf. Se guardan los cambios y se recarga el dialplan: asterisk -rx "dialplan reload" Ahora desde un usuario GoogleTalk, se llama el usuario configurado en Asterisk. En la ventana de chat 127
de Google Talk:
En el X-Lite:
Aparecerá como callerid, el nombre que el usuario ha digitado en la ventana de chat de Google Talk. Este es un ejemplo muy sencillo. Posibles aplicaciones de esta función: • • •
Brindar a los usuarios Google Talk, la posibilidad de crear una extensión en Asterisk digitando todos los parámetros relacionados crear un IVR textual que permita al usuario GoogleTalk escoger una opción que, por ejemplo, lo ponga en comunicación con un determinado departamento de la empresa Solicitar al usuario Google Talk dos números a llamar y luego desde Asterisk comunicarlos entre ellos.
128
CAPITULO VI Asterisk y la red PSTN Asterisk puede ser conectado a la red telefónica tradicional a través de tarjetas telefónica o Gateway. Estos dispositivos pueden ser de distintos tipos: • • • • • •
Tarjetas o Gateway FXO Tarjetas o Gateway FXS Tarjetas o Gateway mixtos (FXO-FXS) Tarjetas o Gateway BRI (ISDN) Tarjetas o Gateway PRI (primarios E1, T1, J1) Tarjetas o Gateway GSM/UMTS
FXO (Foreign Exchange Office) es un dispositivo de computador que permite conectar éste a las lineas telefónicas analógicas, y mediante un software especial, realizar y recibir llamadas de teléfono. FXS (Foreign Exchange Station) es un dispositivo de computador que permite conectar éste a un teléfono analógico. Los dispositivos Mixtos FXO/FXS combinan los dos tipos de conexiones según las necesidades del cliente. Un ejemplo de dispositivo FXO/FXS son las tarjetas Digium de la serie A4 que permiten instalar un total de 4 módulos, sean FXO o FXS. Los dispositivos BRI (Basic rate interface) permiten conectar una linea ISDN (Integrated Services Digital Network) al servidor Asterisk.. Las lineas ISDN están compuestas por dos canales audio (de 64Kbit/s cada uno) y un canal (D) para la señalización con la central telefónica (de 16 Kbit/s). Los dispositivos E1, T1, J1, que también se pueden denominar primarios, son lineas digitales que según el tipo brindan de 23 (T1) a 30 (E1) canales de voz. En la T1 los canales 0 y 24 están reservados para la señalización. En la E1 los canales de señalización son los 0 y 16. La diversa nomenclatura de estas lineas está relacionada con los países donde se utilizan. T1 son la lineas disponibles en Estados Unidos, E1 en Europa y gran parte de latino América, J1 en Japón. En este modulo se verá como instalar las siguientes tarjetas: • • •
Digium serie A4 con 4 puertos FXO Digium serie A4 con 2 puertos FXS Digium TE131 (E1)
y los siguientes programas: • • •
OSLEC para la cancelación de eco El driver Wanpipe para tarjetas Sangoma La librería open2r para la señalización de primarios que se utiliza en algunos países de latino América (entre ellos México, Brasil y Argentina).
6.1 Tarjeta Digium serie A4 con 4 puertos FXO La tarjeta Digium serie A4 puede hospedar 4 módulos de tipo FXO y FXS. En este caso se instalará con 4 módulos FXO para cuatro lineas telefónicas analógicas.
Los pasos a seguir son: 1. 2. 3. 4. 5. 6. 7.
Apagar el computador Desconectar el cable de alimentación Abrir el chasis del Computador Insertar la tarjeta en una ranura PCI/PCI Express disponible Volver a poner el chasis del computador Conectar el cable de alimentación al computador Conectar las lineas telefónicas a los puertos FXO de la tarjeta a través de un normal cable telefónico 8. Encender el computador Normalmente CentOS reconoce automáticamente la nueva tarjeta instalada y le asigna un IRQ para que pueda comunicar con el procesador del computador. Se comprueba que la tarjeta ha sido reconocida: lspci -n debe aparecer algo parecido:
131
0000:01:00.0 0200:d161:8005 Ahora se puede configurar. Antes de iniciar con la configuración se para Asterisk y luego DAHDI: /etc/init.d/asterisk stop /etc/init.d/dahdi stop El primer archivo que hay que modificar es el /etc/dahdi/system.conf En ese archivo se define, entre otras cosas, la zona geográfica donde se va a utilizar la tarjeta. Esto sirve para la generación de los tonos de la linea (timbrado, ocupado, congestión, etc..). Los países cuya configuración está disponibles son: • • • • • • • • • • • • • • • • • • • • • • • • • • • •
Estados Unidos (us) Australia (au) Francia (fr) Holanda (nl) Inglaterra (uk) Finlandia (fi) España (es) Japon (jp) Noruega (no) Austria (at) Nueva Zelanda (nz) Italia (it) Grecia (gr) Taiwan (tw) Chile (cl) Suecia (se) Bélgica (be) Singapur (sg) Israel (il) Brasil (br) Hungría (hu) Lituania (lt) Polonia (pl) Sudáfrica (za) Portugal (pt) Estonia (ee) México (mx) India (in) 132
• • • • • • • • • • • • • • • • •
Alemania (de) Suiza (ch) Dinamarca (dk) Republica Checa (cz) China (ch) Argentina (ar) Malasia (my) Tailandia (th) Bulgaria (bg) Venezuela (ve) Filipinas (ph) Rusia (ru) Turquía (tr) Panamá (pa) Macao China (mo) Costa Rica (cr) Emiratos Árabes (ae)
Para Colombia esta configuración no está presente y para activarla hay que modificar un archivo de la fuentes de dahdi-tools: cd /usr/src/dahdi-tools-2.10.0.1 nano zonedata.c al final del archivo, antes de esta linea: { .zone = -1 } se añaden las siguientes lineas: { .zone = 46, .country = "co", .description = "Colombia", .ringcadence = { 1500, 4000 }, .tones = { /* References: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf */ { DAHDI_TONE_DIALTONE, "425" }, { DAHDI_TONE_BUSY, "425/250,0/250" }, { DAHDI_TONE_RINGTONE, "425/1000,0/4500" }, { DAHDI_TONE_CONGESTION, "425/100,0/250,425/350,0/250,425/650,0/250" }, { DAHDI_TONE_CALLWAIT, "400+450/300,0/6000" }, { DAHDI_TONE_DIALRECALL, "425" }, 133
{ DAHDI_TONE_RECORDTONE, "1400/500,0/15000" }, { DAHDI_TONE_INFO, "!950/330,!1400/330,!1800/330,0/1000" }, { DAHDI_TONE_STUTTER, "!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,! 425/100,!0/100,!425/100,!0/10,!0/100,!425/100,!0/100,425" }, }, .dtmf_high_level = -9, .dtmf_low_level = -11, .mfr1_level = -7, .mfr2_level = -8, }, IMPORTANTE: El contenido de la linea DAHDI_TONE_SHUTTER tiene que estar en la misma linea. Se guardan los cambios y se vuelve a compilar dahdi-tools: make distclean ./configure make make install make config se renombra el archivo predefinido: mv /etc/dahdi/system.conf /etc/dahdi/system.conf.old y se crea uno nuevo: nano /etc/dahdi/system.conf Se añaden las primeras dos lineas relacionadas con la zona geográfica: loadzone = co defaultzone = co Se define el tipo de señalización (fxsks para FXO y fxoks para FXS); en este caso se configuran 4 módulos FXO: fxsks=1-4 que se puede escribir también: fxsks=1,2,3,4 para terminar se define la cancelación de eco. Predefinida es mg2:
134
echocanceller = mg2,1-4 El archivo final será: loadzone = co defaultzone = co fxsks=1-4 echocanceller = mg2,1-4 Para mejorar la cancelación del eco se instala OSLEC 6.1.1 OSLEC El eco es generado por la reflexión del audio trasmitido que se devuelve a quien lo ha originado con un retraso que puede variar de algunos mili segundos a centenares de mili segundos. Más alto el tiempo de retraso, más fastidioso el eco. Las librerías DAHDI vienen con un cancelador de eco software que a veces no logra solucionar este tipo de problema. En estos casos la mejor solución es instalar el cancelador de eco OSLEC. OSLEC ha sido desarrollado por David Rowe, un ingeniero electrónico australiano. ¿Por qué OSLEC logra solucionar con mayor eficacia los problemas de eco? Porque a pesar que sea un cancelador de eco de 32ms, actúa justo en los casos en que se produce este tipo de retraso. Cuando las llamadas son locales o de larga distancia, las compañías telefónicas no aplican ningún tipo de cancelación de eco y es propio en estos casos que los 32ms de OSLEC son suficientes para cancelar el eco de manera satisfactoria. Cuando las llamadas son internacionales y el eco producido considerable (centenares de ms), son las mismas compañías telefónicas que normalmente se encargan (a nivel de centrales) de eliminar el eco que se produce. OSLEC está disponible en la fuentes del Kernel a partir de la versión 2.28 Para instalarlo se siguen estos pasos: cd /usr/src se descargan las fuentes del Kernel 2.6.28 wget http://www.voztovoice.org/campus/pbx05/linux-2.6.28.tar.bz2 se descomprimen: tar -xf linux-2.6.28.tar.bz2 Se preparan las fuentes de DAHDI para la compilación de OSLEC: mkdir /usr/src/dahdi-linux-2.10.0.1/drivers/staging 135
cp -fR /usr/src/linux-2.6.28/drivers/staging/echo /usr/src/dahdi-linux-2.10.0.1/drivers/staging sed -i "s|#obj-m += dahdi_echocan_oslec.o|obj-m += dahdi_echocan_oslec.o|" /usr/src/dahdilinux-2.10.0.1/drivers/dahdi/Kbuild sed -i "s|#obj-m += ../staging/echo/|obj-m += ../staging/echo/|" /usr/src/dahdi-linux-2.10.0.1/drivers/dahdi/Kbuild
echo 'obj-m += echo.o' > /usr/src/dahdi-linux-2.10.0.1/drivers/staging/echo/Kbuild Ahora se vuelve a compilar DAHDI-linux y DAHDI-tools: cd /usr/src/dahdi-linux-2.10.0.1 make distclean make make install DAHDI-Tools: cd /usr/src/dahdi-tools-2.10.0.1 make distclean ./configure make make install make config Se modifica el system.conf nano /etc/dahdi/system.conf se cambia esta linea echocanceller=mg2,1-4 para que quede: echocanceller=oslec,1-4 Para terminar la configuración de la tarjeta hay que modificar el archivo chan_dahdi.conf se renombra el predefinido: mv /etc/asterisk/chan_dahdi.conf /etc/asterisk/chan_dahdi.conf.old y se crea uno nuevo: 136
nano /etc/asterisk/chan_dahdi.conf Se añaden las siguientes lineas: [trunkgroups] [channels] language=es context=from-pstn overlapdial=yes signalling=fxs_ks toneduration=100 usecallerid=yes cidsignalling=v23 cidstart=polarity hidecallerid=no callwaiting=yes callwaitingcallerid=yes threewaycalling=yes transfer=yes canpark=yes cancallforward=yes callreturn=yes echocancel=yes relaxdtmf=yes rxgain=2.0 txgain=3.0 callerid = asreceived amaflags=documentation accountcode=pstn busydetect=yes busycount=6 mohinterpret=default mohsuggest=default group=1 channel => 1-4 En el bloque channels se configuran los parámetros validos para todos los canales. A partir de la linea channel => se configuran los canales. En este caso los cuatro canales FXO pertenecen todos al grupo 1 Si se han disactivados todos los módulos en el archivo /etc/dahdi/modules, hay que activar el modulo para la tarjeta Digium serie A4. Se abre el archivo: nano /etc/dahdi/modules
137
se cambia esta linea: # wcaxx para que quede: wcaxx Se guardan los cambio y se reinicia primero DAHDI y luego Asterisk: /etc/init.d/dahdi start /etc/init.d/asterisk start Se controla que efectivamente la cancelación de echo configurada sea OSLEC: dahdi_cfg -vvv DAHDI Tools Version - 2.10.0.1 DAHDI Version: 2.10.0.1 Echo Canceller(s): Configuration ====================== Channel map: Channel 01: FXS Kewlstart (Default) (Echo Canceler: oslec) (Slaves: 01) Channel 02: FXS Kewlstart (Default) (Echo Canceler: oslec) (Slaves: 02) Channel 03: FXS Kewlstart (Default) (Echo Canceler: oslec) (Slaves: 03) Channel 04: FXS Kewlstart (Default) (Echo Canceler: oslec) (Slaves: 04) 4 channels to configure. El en servidor Linode, se recibirán una serie de errores ya que la tarjeta no está realmente instalada. Se entra en la consola de Asterisk: asterisk -rvvvvvvvvvvvvvvvvv se mira la configuración del canales: CLI> dahdi show channels Se sale de la consola:
138
CLI> quit Si se decide utilizar las 4 lineas telefónicas para las llamadas locales y nacionales hay cuatro forma de escribir el dialplan (para Colombia). Se antepone el numero 9 para indicar que marcando 9 más el numero de destino se está saliendo por las lineas analógicas. Este dialplan no se utilizará para llamadas a celulares. exten => _9[12456789]XXXXXXX!,1Dial(DAHDI/g1/${EXTEN:1},45) same => n,Hangup g1= Usa las líneas del grupo X de menor a Mayor exten => _9[12456789]XXXXXXX!,1,Dial(DAHDI/G1/${EXTEN:1},45) same => n,Hangup G1= Usa las líneas del grupo X de Mayor a menor exten => _9[12456789]XXXXXXX!,1,Dial(DAHDI/r1/${EXTEN:1},45) same => n,Hangup r1= Usa las líneas del grupo X de menor a Mayor pero de manera aleatoria exten => _9[12456789]XXXXXXX!,1,Dial(DAHDI/R1/${EXTEN:1},45) same => n,Hangup R1= Usa las líneas del grupo X de Mayor a menor pero de manera aleatoria Se usará este ultimo bloque. nano /etc/asterisk/extensions.conf al final del contexto internas se pone: exten => _9[12456789]XXXXXXX!,1,Dial(DAHDI/R1/${EXTEN:1},45) same => n,Hangup Para llamadas entrantes después del contexto google-in: [from-pstn] exten => s,1,Dial(SIP/1000,45) exten => s,n,Hangup El contexto from-pstn es el que se ha definido en el archivo chan_dahdi.conf Se recarga el dialplan: asterisk -rvvvvvvvvvvvvv 139
CLI> dialplan reload se sale de la consola: CLI> quit 6.2 Tarjeta Digium serie A4 con 2 puertos FXS En este caso, como la señalización cambia, hay que modificar el archivo /etc/dahdi/system.conf para que quede: loadzone = co defaultzone = co fxoks=1-2 echocanceller = oslec,1-2 Luego se modifica el archivo /etc/asterisk/chan_dahdi.conf para que quede: [trunkgroups] [channels] ; esta sección es deprecada desde la versión 1.8 de Asterisk. En su lugar se utilizan plantillas [phones](!) ; ; La plantilla con los parámetros compartidos por todos los módulos FXS ; usecallerid = yes hidecallerid = no callwaiting = no threewaycalling = yes transfer = yes echocancel = yes echotraining = yes immediate = no context = externas signalling = fxo_ks [phone1](phones) callerid = "TelAna1" <101> dahdichan = 1 [phone2](phones) callerid = "TelAna2" <102> dahdichan = 2 140
Como se nota en la configuración, en la plantilla [phones](!) se configuran los parámetros validos para los dos módulos FXS. En los dos bloques que siguen se utiliza la plantilla y se configuran solamente los parámetros específicos de cada modulo FSX. En este caso son dos: • •
callerid: se indica un callerid para el teléfono analógico dahdichan: se indica el numero de canal asociado a cada modulo FXS
Para los dos teléfonos analógicos el contexto configurado es externas (bajo el bloque [phones](!). Esto quiere decir que los dos teléfonos analógicos conectados a los módulos FXS de la tarjeta tendrán acceso a ese contexto del dialplan. Esto para las llamadas salientes. Para las llamadas entrantes, hay que modificar el dialplan de la siguiente manera: nano /etc/asterisk/extensions.conf en el contexto internas se pone: exten => 101,1,Dial(DAHDI/1,30) same => n,Hangup exten => 102,1,Dial(DAHDI/2,30) same => n,Hangup De esta forma será posible llamar los dos teléfonos analógicos. 6.3 Tarjeta Digium TE131 La tarjeta TE131 es una tarjeta con una conexión T1, E1 o J1. El tipo de conexión se configura a través de un jumper presente en la tarjeta:
141
Los pasos a seguir son: 1. 2. 3. 4. 5. 6. 7. 8.
Apagar el computador Desconectar el cable de alimentación Abrir el chasis del Computador Insertar la tarjeta en una ranura PCI disponible Volver a poner el chasis del computador Conectar el cable de alimentación al computador Conectar el cable RJ45 de la linea E1 a la tarjeta Encender el computador
Se paran los servicios Asterisk y DAHDI: service asterisk stop service dahdi stop Como en algunos países de latino América, se utiliza la señalización MFG/R2 para que DAHDI la pueda implementar hay que instalar la librería Openr2: se descarga: cd /usr/src wget http://openr2.googlecode.com/files/openr2-1.3.3.tar.gz se descomprime: tar -xf openr2-1.3.3.tar.gz se entra en la carpeta: cd openr2-1.3.3 y se compila: ./configure --prefix=/usr --libdir=/usr/lib64 make make install Luego hay que volver a compilar Asterisk: cd /usr/src/asterisk-11.17.1 make distclean ./configure --prefix=/usr libdir=/usr/lib64 make menuselect 142
Asegurarse que en el menú “Compilers Flags” el parametro BUILD_NATIVE esté desactivado. Se guardan los cambios y se continua: make make install Si aparece este WARNING: WARNING WARNING WARNING Your Asterisk modules directory, located at /usr/lib64/asterisk/modules contains modules that were not installed by this version of Asterisk. Please ensure that these modules are compatible with this version before attempting to run Asterisk. app_meetme.so app_mysql.so app_saycountpl.so cdr_mysql.so codec_g729-ast110-gcc4-glibc-x86_64-barcelona.so format_mp3.so res_config_mysql.so WARNING WARNING WARNING no hay problema ya que esos módulos se han compilado anteriormente con la misma versión de Asterisk. make config Para averiguar que la librería ha sido englobada en el el modulo chan_dahdi.so: ldd channels/chan_dahdi.so | grep openr2 libopenr2.so.3 => /usr/lib64/libopenr2.so.3 (0x00007fd6311ed000) Para ver las distintas versiones de la señalización MFG/R2 soportadas por la librería: r2test -l Variant Code AR BR CN CZ CO
Country Argentina Brazil China Czech Republic Colombia 143
EC ID ITU MX PH VE
Ecuador Indonesia International Telecommunication Union Mexico Philippines Venezuela
Terminada la instalación de la librería se averigua si la tarjeta ha sido reconocida por CentOS: lspci -n el resultado debe ser: 0000:01:00.0 0200: ISDN controller: Unknown device d161:0120 Cuando se configura una linea E1 la sintaxis en el archivo system.conf es: span => ,,,,[,Yellow] Number: el puerto donde está conectado el cable de la linea E1. En este caso 1 Timing: determina la fuente de sincronización para la tarjeta. Posibles valores: 0 = la fuente es remota 1 = la fuente la genera la misma tarjeta Line Build Out: 0 predefinido Framing: en las lineas E1 puede ser CAS (Channel Associated Signaling) o CSS (Common Channel Signaling ) Coding: puede ser AMI o HBD3. En algunos casos al final de la linea se pone CRC4 para el control de los paquetes. Estos datos normalmente los facilita el proveedor de la linea. Algunos ejemplos podrían ser: span => 1,1,0,cas,hdb3,crc4 o span => 1,1,0,css,hdb3 Luego se configuran los canales: bchan = 1-15,17-31 dchan = 16 bchan son los canales audio y dchan el canal para la señalización. y la cancelación de eco: echocanceller => oslec,1-15,17-31 144
se termina con: loadzone = co defaultzone = co Por ultimo se configura el chan_dahdi.conf los dos valores más importantes son: switchtype signaling que también facilita el proveedor. Lo más común es: switchtype=euroisdn signaling=pri_cpe Un ejemplo de archivo de configuración es: [trunkgroups] [channels] usecallerid=yes hidecallerid=no callwaiting=yes usecallingpres=yes callwaitingcallerid=yes threewaycalling=yes transfer=yes canpark=yes cancallforward=yes callreturn=yes echocancel=yes echocancelwhenbridged=yes relaxdtmf=yes rxgain=2.0 txgain=3.0 immediate=no context=from-pstn group=1 switchtype=euroisdn signaling=pri_cpe channel => 1-15,17-31 Para la señalización MFC/R2 sería:
145
system.conf span=1,1,0,cas,hdb3 cas=1-15:1101 dchan=16 cas=17-31:1101 loadzone = co defaultzone = co chan_dahdi.conf [trunkgroups] [channels] usecallerid=yes hidecallerid=no callwaiting=yes usecallingpres=yes callwaitingcallerid=yes threewaycalling=yes transfer=yes canpark=yes cancallforward=yes callreturn=yes echocancel=yes echocancelwhenbridged=yes relaxdtmf=yes rxgain=2.0 txgain=3.0 immediate=no context=from-pstn group=1 signalling = mfcr2 mfcr2_variant = co mfcr2_get_ani_first = no mfcr2_max_ani = 10 mfcr2_max_dnis = 4 mfcr2_category = national_subscriber mfcr2_mfback_timeout = -1 mfcr2_metering_pulse_timeout = -1 mfcr2_logdir = log mfcr2_logging = all channel => 1-15,17-31 Terminada la configuración se reinician los servicios: service dahdi start 146
service asterisk start y se averigua en la consola si todos los canales están configurados: CLI> dahdi show channels 6.4 Wanpipe Wanpipe es el driver que se utiliza para las tarjetas SANGOMA. Primero se instala la tarjeta (un primario): Los pasos a seguir son: 1. 2. 3. 4. 5. 6. 7. 8.
Apagar el computador Desconectar el cable de alimentación Abrir el chasis del Computador Insertar la tarjeta en una ranura PCI disponible Volver a poner el chasis del computador Conectar el cable de alimentación al computador Conectar el cable RJ45 de la linea E1 a la tarjeta Prender el computador
se para Asterisk y DAHDI: service asterisk stop service dahdi stop Se descarga el driver: cd /usr/src wget ftp://ftp.sangoma.com/linux/current_wanpipe/wanpipe-7.0.12.tgz se descomprime: tar -xf wanpipe-7.0.12.tgz se entra en la carpeta: cd wanpipe-7.0.12 se instala: ./Setup dahdi
147
se escribe “y” y se continua con envío:
se selecciona 1 más envío. Empieza la compilación del driver y de las utilidades. Al finalizar aparecerá:
Ahora se ejecuta: wancfg_dahdi que creará todos los datos de configuración para la tarjeta instalada. Luego se inicia wanpipe: wanrouter start DAHDI service dahdi start Asterisk: service asterisk start Para terminar se personalizan los parámetros creados por wancfg. 6.5 DAHDI_GENCONF La utilidad dahdi_genconf se instala con el paquete dahdi-tools y permite generar las configuraciones de forma automática para las tarjetas instaladas. Se ejecuta una vez que las tarjetas estén instaladas en el servidor.
148
La utilidad modificará el archivo /etc/dahdi/system.conf y creará un nuevo archivo en la carpeta /etc/asterisk llamado dahdi-channels.conf. Los pasos a seguir son revisar la configuración del archivo system.conf y averiguar que todos los parámetros sean correctos; luego hay dos posibles opciones: incluir el archivo dahdi-channels.conf en el archivo chan_dahdi.conf con el siguiente parámetro: nano /etc/asterisk/chan_dahdi.conf al final del archivo se pone: #include /etc/asterisk/dahdi-channels.conf La segunda opción es abrir el archivo y copiar la configuración en los respectivos bloques del archivo chan_dahdi.conf Si han efectuado las pruebas presentes hasta el momento en el servidor Linode, para restablecer la configuración inicial: service asterisk stop service dahdi stop mv /etc/dahdi/system.conf.old /etc/dahdi/system.conf mv: ¿sobreescribir «/etc/dahdi/system.conf»? (s/n) y mv /etc/asterisk/chan_dahdi.conf.old /etc/asterisk/chan_dahdi.conf mv: ¿sobreescribir «/etc/asterisk/chan_dahdi.conf»? (s/n) y service dahdi start service asterisk start 6.6 Linksys SPA3102 – Gateway FXO/FXS El SPA3102 es un Gateway que soporta una linea FXO y una linea FXS; cada linea se puede configurar como si fuera una extensión SIP. La configuración que sigue abarca solamente la parte FXO ya que todas las llamadas entrantes se contestarán desde una extensión SIP. Por defecto el SPA3102 no permite conectarse a su pagina de administración desde remoto, pues lo primero que hay que hacer es activar esta funcionalidad.
149
En Line se conecta el cable del teléfono que viene de la línea telefónica. En Ethernet se conecta un cable de red que luego se conectará al enchufe de red del computador. Para finalizar, en Internet se conecta un cable de red que luego se conectará al Router/Switch. Se abre una pestaña nueva del navegador y se pone la siguiente dirección: http://192.168.0.1 Aparecerá la pagina de administración del SPA3102:
Se averigua la versión del Firmware instalada y la dirección IP asignada por el Router. Se da click en el enlace “advanced” y luego en la pestaña “Wan Setup”. Se activa la conexión desde remoto:
Para guardar cada cambio, al final de la pagina se presiona el botón “Submit All Changes”. Ya se puede desconectar el cable del puerto Ethernet del ATA y volver a conectar el computador al router. Ahora se puede acceder al SPA3102 indicando la dirección IP asignada por el Router. En este caso 192.168.100.100 El segundo paso es configurar una clave para el administrador y una para el usuario. Esto se realiza en la pestaña Voice y luego System:
150
Se presiona el botón Submit All Changes. Si la versión del firmware no es la 5.1.10 se actualiza. Los firware para el SPA3102, se pueden descargar desde esta pagina. Se descomprime el archivo en el escritorio del computador. Entre los nuevo iconos:
Se da click dos veces. Aparecerá:
Para aceptar la advertencia se presiona el botón “Continue”:
151
Se pone la dirección IP local del SPA3102 y la del computador donde se ha descargado el Firmware. Se continua con el botón “OK”:
Se pone el usuario admin y la clave que se acaba de crear. Se presiona el botón “OK”:
152
Se revisan todos los datos y para iniciar la actualización se presiona el botón “Upgrade”. La operación tarda unos minutos. Cuando termine, se vuelve a entrar en la pagina de administración del ATA y se configura la cuenta SIP para la línea FXO. Se va a la pestaña Voice y luego en PSTN Line donde se configura solamente la parte que interesa:
Line Enable = yes NAT Keep Alive Enable = yes (si el Asterisk es remoto y el ATA se encuentra detrás de un NAT) NAT Keep Alive Msg = viene por defecto con la opción $NOTIFY que envía un paquete de tipo SIP NOTYFY para tener abierta la conexión. Se puede dejar la linea en blanco. De esta forma se envía a Asterisk solamente un paquete UDP vacío como hacen la mayoría de los teléfonos SIP:
153
Proxy = dirección IP o nombre de dominio del servidor Asterisk remoto Register = yes Display Name = poner el numero de teléfono de la línea telefónica (por ejemplo) UserID = el nombre de la extensión que luego se configurará en Asterisk Use Auth ID =yes Auth ID = lo mismo que User ID
Como codec predefinido se activa alaw y como segundo G729:
Se definen dos Dialplan: El primero para las llamadas salientes y el segundo para las llamadas entrantes. Todas las llamadas entrantes se enrutan a la extensión s de Asterisk:
En la configuración del Gateway VoIP –> PSTN se pone:
154
VoIP-To-PSTN Gateway Enable =yes VoIP Caller Auth Method = none (ninguna autentificación) One Stage Dialing = yes Line 1 VoIP Caller DP = para las llamadas salientes se utilizará el dialplan 1
En la configuración del Gateway PSTN – > VoIP se pone: PSTN-To-VoIP Gateway Enable =yes PSTN Calles Auth Method = none (de esta forma cuando el ATA conteste no solicitará ningún PIN para acceder al Gateway VoIP) PSTN Ring Thru Line 1 = no (ya que no se va a conectar un teléfono analógico al ATA) PSTN Caller Default DP = 2 (Para este Gateway se utilizará el diaplan 2)
Cuando entre una llamada desde la red PSTN el Gateway VoIP del ATA contestará después de 2 segundos y pasará la llamada también a las extensión s de Asterisk:
Detect Polarity Reversal = no (para Colombia) Detect PSTN Long silence = yes (si no hay flujo audio del lado PSTN por 30 segundos (parámetro que sigue) la llamada terminará PSTN Long Silence Duration = 30 155
Detect VoIP Long Silence = yes Lo mismo para lado VoIP VoIP Long Silence Duration = 30 Detect Disconnect Tone = Yes Disconnect Tone = el valor de su país. Esto valores, para muchos países, aparecen en la guía de administrador del SPA3102. Se termina presionando el botón “Submit All Changes”. Ahora el ATA intentará conectarse a Asterisk sin éxito ya que la extensión no ha sido creada. Se abre el archivo sip.conf y al final del archivo, se añade el siguiente bloque: nano /etc/asterisk/sip.conf [spa3102] type=friend secret=pbx9093 qualify=yes nat=force_rport,comedia host=dynamic directmedia=no context=from-spa3102 dtmfmode=rfc2833 language=es callerid=LineaTel allowtransfer=yes allowsubscribe=yes subscribecontext=subscribe callcounter=yes disallow=all allow=alaw allow=g729 Se guardan los cambios y se recarga la configuración SIP: asterisk -rx "sip reload" Después de unos segundos en la pagina del SPA3102 (Menú Voice, pestaña Info, debería aparecer):
156
El dialplan: nano /etc/asterisk/extensions.conf para las llamadas salientes al final del contexto internas se pone: exten => _8[12456789]XXXXXXX!,1,Dial(SIP/spa3102,45,D(${EXTEN:1})) same => n,Busy(3) same => n,Hangup De esta forma marcando 8 + el numero a llamar, todas las llamadas pasarán para el SPA3102. En cuanto el ATA conteste, se le envía los dígitos del numero a marcar quitando el 8 (opción D de la aplicación Dial). Para las llamadas entrantes, después del contexto google-in, se configura el contexto from-spa3102 (como definido en la configuración de la extensión en el sip.conf) y se pone: [from-spa3102] exten => s,1,NoOp same => n,Dial(SIP/1000) same => n,Hangup De esta forma cuando alguien llamará el numero de la línea telefónica, después de dos segundos empezará a timbrar también la extensión 1000. Claramente la llamada entrante se puede enviar a un IVR o configurar para que timbre más de una extensión. Se guardan los cambios y se recarga el dialplan: asterisk –rvvvvvvvvvvvvvvv CLI> dialplan reload Ahora desde cualquier teléfono SIP conectado a Asterisk se marca un numero anteponiendo el 8. La llamada saldrá por el SPA3102. Otra prueba: se marca desde un celular al numero de la línea telefónica 157
y se espera que empiece a timbrar la extensión 1000.
158
CAPITULO VII Dialplan – Configuración avanzada Para poder entender mejor como funciona y como se construye un dialplan en Asterisk, hay que aclarar algunos conceptos claves. En el párrafo 2.7, se ha explicado la división del dialplan en contextos, extensiones y prioridades. En esta parte se ilustrarán: • • • • • • • • •
las variables los pattern matching (patrones de marcado) la aplicación ECHO el contexto subscribe Monitoreo de las extensiones remotas las subrutinas la aplicación Authenticate Limitar llamadas salientes Mensaje instantáneos entre extensiones
7.1 Las variables Una variable es un objeto al que se asocia un valor. Se utilizan mucho en matemática y su función en Asterisk es reducir la complexidad del dialplan, simplificar su construcción y añadir una lógica más comprensible. En Asterisk existen tres tipos de variables: • • •
variables globales variables de canal variables de ambiente
Las variables globales son aquellas cuyo valor no cambia a lo largo del dialplan. En la preparación del dialplan se ha presentado el bloque dedicado a las variables globales y se han configurado tres, entre ellas: marko=IAX2/marko De esta forma se asocia al nombre de variable marko el valor IAX2/marko. ¿Cual es su función en el dialplan? En este caso simplificarlo. Si se retoma el bloque de dialplan: exten => 1234,1,Dial(IAX2/marko,30) same => n,Hangup que se ha creado para llamar la extensión IAX2 marko, esta parte puede ser escrita también de la siguiente forma: exten => 1234,1,Dial(${marko},30)
same => n,Hangup Cuando se utiliza una variable en el dialplan la sintaxis es: carácter dolar $ seguido por el nombre de la variable entre dos llaves {}. Las variables son case sensitive, es decir que hay diferencia si se escriben en mayúsculas y minúsculas. En el caso de la variable ${marko} que está escrita toda en minúsculo, no es lo mismo si en el dialplan se pone: exten => 1234,1,Dial(${MARKO},30) same => n,Hangup La variable ${MARKO} estará totalmente vacía. Algunas aplicaciones y funciones de Asterisk al ejecutarse generan variables. Todas las variables generadas son en mayúsculo, como, por ejemplo, la que ya se ha presentado anteriormente: ${EXTEN}. Es una buena practica, cuando se crean variables personalizadas, utilizar nombres en minúsculo para diferenciarlas de las variables generadas por Asterisk. Las variables de canal tienen validez solamente para la llamada corriente. Para crearlas se utiliza la aplicación Set. Un ejemplo: Set(numero=1) Para toda la duración de la llamada el valor de la variable ${numero} será 1. Cuando la llamada termine, el valor asociado a la variable volverá a ser nulo. Este tipo de variables se utilizan mucho en el dialplan para modificar valores del canal y/o para guardar algunos datos de la llamada para utilizarlos luego. A lo largo de la construcción del dialplan se presentarán distintos ejemplos. Hay muchas variables predefinidas que se crean durante una llamada. Para saber cuales son y que valor tienen en un determinado canal, se utiliza la aplicación Dumpchan. Para verla en acción se abre el archivo del dialplan: nano /etc/asterisk/extensions.conf se modifica este bloque: exten => 123,1,Answer same => n,Playback(hello-world) same => n,Hangup para que quede: exten => 123,1,Answer same => n,Dumpchan same => n,Playback(hello-world) same => n,Hangup Se guardan las modificaciones y se recarga el dialplan: 161
asterisk -rvvvvvvvvvvvvvvv CLI> dialplan reload Ahora desde la extensión 1000 se marca el numero 123. El resultado en la consola de Asterisk será: Dumping Info For Channel: SIP/1000-00000000: ============================================================= =================== Info: Name= SIP/1000-00000000 Type= SIP UniqueID= 1396977764.0 LinkedID= 1396977764.0 CallerIDNum= 1000 CallerIDName= callerid=Fulano ConnectedLineIDNum= (N/A) ConnectedLineIDName=(N/A) DNIDDigits= 123 RDNIS= (N/A) Parkinglot= default Language= es State= Up (6) Rings= 0 NativeFormat= (alaw) WriteFormat= alaw ReadFormat= alaw RawWriteFormat= alaw RawReadFormat= alaw WriteTranscode= No ReadTranscode= No 1stFileDescriptor= 27 Framesin= 1 Framesout= 0 TimetoHangup= 0 ElapsedTime= 0h0m0s DirectBridge= IndirectBridge= Context= externas Extension= 123 Priority= 2 CallGroup= 1 PickupGroup= 1 Application= DumpChan Data= (Empty) Blocking_in= (Not Blocking) 162
Variables: SIPCALLID=YzkwNDdlYWM0MWYwZTk1NWUzYzFjOGFlMzg4ZWViOGQ SIPDOMAIN=72.14.178.214 SIPURI=sip:[email protected]:6000 CLI> quit Para una lista completa de las variables predefinidas se puede consultar la Wiki de Asterisk. Las variables se pueden manipular para extraer solamente una parte de su contenido. En este ejemplo se utilizará la variable ${EXTEN}, que contiene el numero marcado. La manipulación de las variables tiene la siguiente sintaxis ${EXTEN:x:y) donde x es la posición inicial e y el numero de dígitos que se quieren extraer: Tomando como numero de partida 57300200: ${EXTEN:1} devolverá 7300200 ${EXTEN:1:4} devolverá 7300 ${EXTEN:2:6} devolverá 300200 ${EXTEN:5:3} devolverá 200 Las variables de ambiente se utilizan para leer las variables del sistema (Linux). Para crearlas se utiliza la aplicación SET y la función ENV. Un ejemplo: Set(PBX=${ENV(LANG)}) En este ejemplo a la variable PBX estará asociado el idioma configurado en el servidor Linux. para probarla en el dialplan: nano /etc/asterisk/extensions.conf en el contexto internas se ánade este bloque: exten => 50,1,Set(PBX=${ENV(LANG)}) same => n,Noop(Idioma Servidor ${PBX}) same => n,Hangup Se guardan los cambios y se recarga el dialplan. asterisk -rvvvvvvvvvvvvvv CLI> dialplan reload
163
Desde la extensión 1000 se marca el numero 50. En la consola de Asterisk: Executing [50@externas:1] Set("SIP/1000-00000001", "PBX=es_CO.iso88591") in new stack Executing [50@externas:2] NoOp("SIP/1000-00000001", "Idioma Servidor es_CO.iso88591") in new stack Executing [50@externas:3] Hangup("SIP/1000-00000001", "") in new stack Spawn extension (externas, 50, 3) exited non-zero on 'SIP/1000-00000001'
No todas las variables de ambiente se pueden leer desde Asterisk. 7.2 Pattern Matching El dialplan se construye de modo que todos los posibles números marcados puedan ser “interceptados” por Asterisk. Sería absurdo indicar todos los números de teléfono de Colombia porque un usuario podría marcar uno de ellos. Para este tipo de situaciones, se utilizan los Pattern Marching o patrones de marcado, que permiten crear extensiones en el dialplan que “intercepten” los números marcados. Estos caracteres se ponen en lugar de uno o más dígitos. La lista es la siguiente: • • • • • •
X Z N [1-4,6-8] . !
puede ser un numero de 0 a 9 puede ser un numero de 1 a 9 puede ser un numero de 2 a 9 puede ser un numero de 1 a 4 o de 6 a 8 (punto) puede ser uno o más caracteres puede ser cero o más caracteres.
Algunos ejemplos. Si se quiere crear una extensión donde entren todas las llamadas a los celulares de Colombia (prefijo 3) con el proveedor VozToVoice, la primera linea sería: exten => _00573XXXXXXXXX,1,Dial(SIP/voztovoice/${EXTEN}) Si no se conoce exactamente de cuantos dígitos está compuesto un numero de celular la misma linea cambiaría de la siguiente forma: exten => _00573.,1,Dial(SIP/voztovoice/${EXTEN}) El punto después del 00573, indica que lo que sigue puede ser compuesto de uno o más dígitos. Cuando se pone un pattern matching en la creación de una extensión, hay que anteponer siempre el guion abajo _ Si, por ejemplo, el numero de extensiones configuradas en Asterisk van desde 1000 hasta 1099 el dialplan para las llamadas entre extensiones sería: exten => _10XX,1,Dial(SIP/${EXTEN})
164
7.3 La aplicación Echo La aplicación Echo se utiliza para medir el tiempo de retorno de la voz. Puede ser útil para revisar eventuales retrasos y/o problemas en la calidad del audio. Para su configuración se modifica el dialplan: nano /etc/asterisk/extensions.conf y en el contexto internas se añade el siguiente bloque: exten => 150,1,Answer same => n,Playback(demo-echotest) same => n,Echo same => n,Playback(demo-echodone) same => n,Hangup Se guardan los cambios y se recarga el dialplan: asterisk -rx "dialplan reload" Desde cualquier extensión registrada a Asterisk se marca el numero 150 y se efectúa la prueba. 7.4 El contexto Subscribe A lo largo de la configuración del archivo sip.conf se ha hablado de la posibilidad de monitorear el estado de una extensión y en la parte general del archivo se han configurados los siguientes parámetros para activar esta funcionalidad: callcounter=yes allowsubscribe=yes subscribecontext=subscribe notifyringing=yes notifyhold=yes Ahora para que el sistema funcione, en el dialplan hay que configurar el contexto subscribe. Se abre el archivo: nano /etc/asterisk/extensions.conf y después del contexto internas se añade el siguiente bloque: [subscribe] exten => 1000,hint,SIP/1000 165
exten => 1001,hint,SIP/1001 exten => 1002,hint,SIP/1002 exten => marko,hint,IAX2/marko La prioridad Hint es una prioridad especial que permite monitorear el estado de las extensiones. En este caso las extensiones SIP 1000,1001 y 1002 y la extensión IAX2 marko. Se guardan los cambios y se recarga el dialplan: asterisk -rvvvvvvvvvvvvvvvvvv CLI> dialplan reload Con el comando: CLI> core show hints -= Registered Asterisk Dial Plan Hints =1000@subscribe : SIP/1000 1001@subscribe : SIP/1001 1002@subscribe : SIP/1002 marko@subscribe : IAX2/marko
State:Idle Watchers 0 State:Unavailable Watchers 0 State:Unavailable Watchers 0 State:Unavailable Watchers 0
Se verán los hints configurados y en la ultima columna cuantas extensiones se han subscrito al estado de las demás (en este caso ninguna). En el Softphone X-lite se selecciona el icono indicado:
y luego:
En la nueva ventana:
Al lado de la casilla “Softphone” se escribe 1001 y luego se presiona el botón Add. Antes de presionar el botón “OK” para terminar la operación, en la ventana del terminal se sale de la consola de Asterisk:
166
CLI> quit y se inicia la captura de los paquetes SIP: ngrep 1000 -W byline port 5060 > /tmp/subscribe Se vuelve al X-Lite y se presiona el botón OK. Se vuelve a la ventana terminal y se termina la captura de los paquetes SIP. La secuencia de los paquetes será: X-Lite ------------------Subscribe---------------> Asterisk X-Lite <-------401 Unauthorized-------------- Asterisk X-Lite ------------------Subscribe---------------> Asterisk X-Lite <-------------------200 Ok---------------- Asterisk X-Lite <-----------------NOTIFY---------------- Asterisk X-Lite -------------------200 OK----------------> Asterisk Y en el NOTIFY final, estará anexa esta parte: Not online sip:[email protected] closed Asterisk está comunicando a la extensión 1000 que la extensión 1001 no está en linea (Not online) Se capturan nuevamente los paquetes con el comando: ngrep 1000 -W byline port 5060 > /tmp/notify Se abre el softphone 3CX configurado como extensión 1001 y una vez que esté registrado a Asterisk se termina la captura de los paquetes. En el archivo notify se encontrará la siguiente secuencia: Asterisk --------NOTIFY--------------> Xlite Asterisk <--------200 OK-------------- Xlite 167
La parte final del paquete de Notify enviado por Asterisk a la extensión 1000 será: Ready sip:[email protected] open Asterisk estará comunicando a la extensión 1000 que la extensión 1001 está en linea ya que la extensión 1000 ha subscrito el estado de esa extensión. Si se vuelve a la consola de Asterisk: asterisk -rvvvvvvvvvvvvvvv CLI> core show hints -= Registered Asterisk Dial Plan Hints =1000@subscribe : SIP/1000 1001@subscribe : SIP/1001 1002@subscribe : SIP/1002 marko@subscribe : IAX2/marko
State:Idle Watchers 0 State:Idle Watchers 1 State:Unavailable Watchers 0 State:Unavailable Watchers 0
En la columna Watchers de la extensión 1001 hay un 1 que indica que hay una extensión que está monitoreando su estado. Se abre Zoiper (configurado con las cuentas SIP 1002 y IAX2 marko) y en el X-lite se subscribe el estado de ambas. El resultado será:
168
Desde la extensión 1001 se marca el numero 150 (test de echo). En el X-Lite aparecerá:
Por ultimo, desde la extensión 1002 se llama la extensión 1001:
La misma cosa se puede hacer en los Teléfonos SIP de mesa que soportan los BLF (Busy Lamp Field). 7.4.1 Monitoreo de las extensiones remotas con Corosync Una funcionalidad muy interesante introducida con la versión 11 de Asterisk, es la posibilidad de monitorear el estado de extensiones registradas en otros Asterisk, con el programa Corosync. Corosync ha sido desarrollado a partir de OpenAIS que antes era el programa utilizado por Asterisk para esta tarea. Normalmente este programa se utiliza para la creación de cluster de servidores en escenarios de alta disponibilidad y de hecho es posible utilizarlo para la creación de este tipo de soluciones también en Asterisk. En Asterisk el modulo que “comunica” con Corosync y permite el monitoreo de extensiones registradas en otros Asterisk es res_corosync y para que sea instalado correctamente al momento de compilar Asterisk, depende de estos tres paquetes: •
corosync 169
• •
corosynclib corosynclib-devel
Luego hay que asegurarse que el modulo sea seleccionado: make menuselect
En el escenario utilizado para demostrar su funcionamiento, se utilizarán dos servidores Asterisk con la misma versión 11.17.1 instalada y con seis extensiones SIP configuradas: 1000, 1001 y 1002 en el primer servidor y 2000, 2001 y 2002 en el segundo. Aprovechando la IP local brindada por cada Linode, la conexión entre los dos instancias de Corosync se realizará utilizando estas IP. Servidor A IP local: 192.168.128.144 ServidorB IP local 192.168.128.145 El primer paso es crear el archivo de configuración de Corosync. Normalmente este programa trabaja en Multicast pero como los VPS de Linode soportan solamente Unicast, hay que optar para este tipo de configuración. En ambos servidores se crea el archivo de configuración: nano /etc/corosync/corosync.conf Se copian las lineas que siguen: totem { version: 2 secauth: off interface { member { memberaddr: 192.168.128.144 } member { memberaddr: 192.168.128.145 } ringnumber: 0 bindnetaddr: 192.168.128.0 mcastport: 5405 ttl: 1 } transport: udpu 170
token: 10000 } logging { fileline: off to_logfile: yes to_syslog: yes debug: on logfile: /var/log/cluster/corosync.log debug: off timestamp: on logger_subsys { subsys: AMF debug: off } } Los datos importantes: • • •
en los dos memberaddr se indica la dirección IP local de cada servidor en bindaddress se indica el gateway de Linode para las IP locales (el mismo che se ha indicado al momento de la configuración de la IP local) en trasport se indica que se utilizará Unicast
Se guardan los cambios y se continua con la configuración del modulo corosync en Asterisk. Primero se renombra el predefinido: mv /etc/asterisk/res_corosync.conf /etc/asterisk/res_corosync.conf.old Se crea uno nuevo: nano /etc/asterisk/res_corosync.conf se copian las lineas que siguen: [general] publish_event = mwi subscribe_event = mwi publish_event = device_state subscribe_event = device_state Se guardan las modificaciones. Con esta configuración, cada servidor Asterisk publicará cualquier evento relacionado con MWI (Message Waiting Indicator); en la practica significa que cuando habrá un mensaje de voz en un buzón de voz local, Asterisk enviará la notifica al segundo servidor Asterisk siempre y cuando éste se haya subscrito para recibir ese tipo de información. Lo mismo para cualquier 171
cambio de estado de una extensión local. El mismo servidor Asterisk se subscribirá para recibir los mismos datos de un servidor Asterisk remoto con el cual tenga una conexión. Corosync utiliza el puerto 5405 UDP para recibir conexiones de otras instancias del mismo programa. Es por eso que hay que modificar la configuración del cortafuegos: ServidorA nano /etc/sysconfig/iptables después de esta linea: -A INPUT -p tcp -m state --state NEW -m tcp --dport 15000 -j ACCEPT Se añade: # Corosync -A INPUT -p udp -m udp -s 192.168.128.145 --dport 5405 -j ACCEPT Se indica la IP del servidorB. Se guardan los cambios y se reinicia IPtables: service iptables restart ServidorB nano /etc/sysconfig/iptables después de esta linea: -A INPUT -p tcp -m state --state NEW -m tcp --dport 15000 -j ACCEPT Se añade: # Corosync -A INPUT -p udp -m udp -s 192.168.128.144 --dport 5405 -j ACCEPT Se indica la IP del servidorA. Se guardan los cambios y se reinicia IPtables: service iptables restart Ahora se entra en la consola de ambos servidores y se carga el modulo res_corosync: asterisk -rvvvvvvvvvvvvvv CLI> module load res_corosync.so
172
Se espera unos segundos y se averigua que los dos servidores estén conectados: CLI> corosync show members ========================================================= === Cluster members ========================================= ========================================================= === Node 1 === --> Group: asterisk === --> Address 1: 192.168.128.144 === Node 2 === --> Group: asterisk === --> Address 1: 192.168.128.145 === ================================ Se mira la configuración de ambos: CLI> corosync show config === res_corosync config ===================================== ======================================================= === === ==> Publishing Event Type: mwi === ==> Subscribing to Event Type: mwi === ==> Publishing Event Type: device_state === ==> Subscribing to Event Type: device_state === ==> Publishing Event Type: ping === ==> Subscribing to Event Type: ping === ======================================================= CLI> quit Para que las extensiones remotas de cada servidor se puedan monitorear hay que modificar el bloque del contexto subscribe en ambos servidores: ServidorA nano /etc/asterisk/extensión se modifica este bloque: [subscribe] exten => 1000,hint,SIP/1000 exten => 1001,hint,SIP/1001 exten => 1002,hint,SIP/1002 173
exten => marko,hint,IAX2/marko para que quede: [subscribe] exten => 1000,hint,SIP/1000 exten => 1001,hint,SIP/1001 exten => 1002,hint,SIP/1002 exten => 2000,hint,SIP/2000 exten => 2001,hint,SIP/2001 exten => 2002,hint,SIP/2002 exten => marko,hint,IAX2/marko Se recarga el dialplan: asterisk -rvvvvvvvvvvvvv CLI> dialplan reload ServidorB nano /etc/asterisk/extensión se modifica este bloque: [subscribe] exten => 2000,hint,SIP/2000 exten => 2001,hint,SIP/2001 exten => 2002,hint,SIP/2002 exten => marko2,hint,IAX2/marko2 para que quede: [subscribe] exten => 2000,hint,SIP/2000 exten => 2001,hint,SIP/2001 exten => 2002,hint,SIP/2002 exten => 1000,hint,SIP/1000 exten => 1001,hint,SIP/1001 exten => 1002,hint,SIP/1002 exten => marko,hint,IAX2/marko Se recarga el dialplan: asterisk -rvvvvvvvvvvvvv CLI> dialplan reload 174
Para realizar una prueba se registran dos softphone a las extensiones 1000 y 1001 del servidorA y 2000 y 2001 del servidorB. En el X-Lite conectado como extensión 1000 en el servidorA, se añade a la lista de contactos, las extensiones 2000 y 2001 del servidorB. El resultado:
Pareciera que el monitoreo de las extensiones remotas está funcionando. Para tener la certeza, desde la extensión 2000 del servidorB se marca a la extensión 2001 siempre del servidorB. En X-Lite:
Funciona perfecto. Se puede tener una confirmación mirando los que pasa en la consola de Asterisk activando, antes de la llamada, el debug a nivel 1: CLI> core set debug 1 DEBUG[1570]: devicestate.c:641 process_collection: Aggregate state for device 'SIP/2001' has changed to 'In use' DEBUG[1570]: devicestate.c:666 handle_devstate_change: Processing device state change for 'SIP/2001' DEBUG[1570]: devicestate.c:612 process_collection: Adding per-server state of 'In use' for 'SIP/2001' DEBUG[1570]: devicestate.c:619 process_collection: Aggregate devstate result is 'In use' for 'SIP/2001' DEBUG[1570]: devicestate.c:635 process_collection: Aggregate state for device 'SIP/2001' has not changed from 'In use' DEBUG[1570]: devicestate.c:666 handle_devstate_change: Processing device state change for 'SIP/2000' DEBUG[1570]: devicestate.c:612 process_collection: Adding per-server state of 'In use' for 'SIP/2000' DEBUG[1570]: devicestate.c:619 process_collection: Aggregate devstate result is 'In use' for 'SIP/2000' DEBUG[1570]: devicestate.c:635 process_collection: Aggregate state for device 'SIP/2000' has not changed from 'In use'
Terminada la prueba, se vuelve modificar el contexto subscribe de cada servidor a su configuración anterior.
175
7.5 Las Subrutinas Si en el dialplan algunas acciones se repiten a menudo, Asterisk brinda la posibilidad de crear una Subrutina que permite simplificar este tipo de operaciones. Antes se podía utilizar la aplicación Macro pero ha sido declarada obsoleta y aunque siga funcionando, es aconsejado utilizar la aplicación Gosub. La sintaxis de esta aplicación es: asterisk -rvvvvvvvvvvvv CLI> core show application Gosub -= Info about application 'Gosub' =[Synopsis] Jump to label, saving return address. [Description] Jumps to the label specified, saving the return address. [Syntax] Gosub([[context,]exten,]priority[(arg1[,...][,argN])]) [Arguments] Not available [See Also] GosubIf(), Macro(), Goto(), Return(), StackPop() El comando seria: Gosub (contexto,extensión,prioridad(argumento1, argumento2,argumentoN) ArgumentoN es un valor o una variable que se pasa a la subrutina al momento de llamarla desde el plan de marcado. Para empezar a utilizar la aplicación Gosub se creará una muy sencilla que antes de marcar a una extensión controle su estado y, en base a éste, envíe la llamada a una determinada parte del dialplan. Primero hay que salir de la consola y modificar el plan de marcado: CLI> quit nano /etc/asterisk/extensions.conf Al final del archivo se añaden estas líneas: [disponible] exten => s,1,Set(estado=${DEVICE_STATE(SIP/${ARG1})}) 176
exten => s,n,Gotoif($["${estado}" = "NOT_INUSE"]?5) exten => s,n,Busy exten => s,n,Hangup exten => s,n,Return Una explicación de las aplicaciones y funciones nuevas que aparecen en las lineas de la subrutina: La función DEVICE_STATE: devuelve el estado de una extensión que en este caso se asignará a la variable “estado”. Los posibles valores son: • • • • • • • • •
UNKNOWN – El canal es valido pero su estado no es conocido NOT_INUSE - No se está usando INUSE - El canal está en uso BUSY - El canal está ocupado INVALID - El canal no es valido UNAVAILABLE - El canal no está disponible (no está registrado a Asterisk) RINGING - El canal está timbrando RINGINGUSE - El canal está timbrando y en uso ONHOLD - El canal está en espera
La aplicación Gotoif: literalmente es: ve a la prioridad indicada si se presenta una determinada condición (verdadero), sino ve a otra prioridad indicada (falso). Si la segunda prioridad no se especifica, el dialplan continua con la prioridad que sigue. La aplicación Busy: si la extensión no se encuentra libre se envía al llamante una señal de ocupado La aplicación Return: sale de la subrutina y vuelve al mismo contexto, extensión, prioridad + 1 de donde se llamó. Para insertar la subrutina en el dialplan creado, se modifica el bloque configurado para las llamadas entre extensiones. exten => _100[0-2],1,Dial(SIP/${EXTEN},30) same => n,Hangup Para que quede: exten => _100[0-2],1,Gosub(disponible,s,1(${EXTEN})) same => n,Dial(SIP/${EXTEN},45) same => n,Hangup Se guardan los cambios y se actualiza el plan de marcado: asterisk -rvvvvvvvvvvvvvvv
177
CLI> dialplan reload Ahora se marca desde la extensión 1000 la extensión 1001 (ambas conectadas a Asteirsk) y se controla lo que aparece en la consola de Asterisk: Executing [1001@externas:1] Gosub("SIP/1000-00000004", "disponible,s,1(1001)") in new stack -- Executing [s@disponible:1] Set("SIP/1000-00000004", "estado=NOT_INUSE") in new stack -- Executing [s@disponible:2] GotoIf("SIP/1000-00000004", "1?5") in new stack -- Goto (disponible,s,5) -- Executing [s@disponible:5] Return("SIP/1000-00000004", "") in new stack -- Executing [1001@externas:2] Dial("SIP/1000-00000004", "SIP/1001,45") in new stack == Using SIP VIDEO CoS mark 6 == Using SIP RTP CoS mark 5 -- Called SIP/1001 Se cierra el 3CX Softphone (extensión 1001) y se marca otra vez desde la extensión 1000 la extensión 1001: -- Executing [1001@externas:1] Gosub("SIP/1000-00000006", "disponible,s,1(1001)") in new stack -- Executing [s@disponible:1] Set("SIP/1000-00000006", "estado=UNAVAILABLE") in new stack -- Executing [s@disponible:2] GotoIf("SIP/1000-00000006", "0?5") in new stack -- Executing [s@disponible:3] Busy("SIP/1000-00000006", "") in new stack == Spawn extension (disponible, s, 3) exited non-zero on 'SIP/1000-00000006'
Como el estado de la extensión 1001 es “UNAVAILABLE” (en negrita) se procesa la prioridad 3 (el Busy) y se termina la llamada. 7.6 Autenticar las Llamadas Salientes con la aplicación Authenticate Al momento de crear las extensiones en el archivo sip.conf, a la extensión 1002 se ha asociado el contexto locales. Ese contexto no tiene acceso al contexto internacio, pues la extensión 1002 no puede efectuar llamadas salientes utilizando el proveedor SIP VozToVoice. Este es un caso típico en la configuración de Asterisk. Algunas extensiones tienen acceso a la lineas salientes y otras no. Para comprobarlo, si se marca el numero 00573126814740 desde las extensión 1002, el resultado será: NOTICE[3594][C-00000006]: chan_sip.c:25632 handle_request_invite: Call from '1002' (79.44.192.186:9000) to extension '00573126814740' rejected because extension not found in context 'locales'. En el Softphone Zoiper:
178
Otra forma de configurar Asterisk es que las extensiones que no tienen acceso a las lineas salientes, para tenerlo, tengan que autenticarse. De esta forma hay un control sobre la llamadas salientes y se puede tener un registro de los usuarios que han utilizado el servicio. Este tipo de configuración se realizará utilizando la aplicación Authenticate. Para conocer la sintaxis de la aplicación: asterisk -rvvvvvvvvvvvvvv CLI> core show application authenticate [Syntax] Authenticate(password[,options[,maxdigits[,prompt]]]) [Arguments] password Password the user should know options a: Set the channels' account code to the password that is entered d: Interpret the given path as database key, not a literal file. NOTE: The value is not used at all in the authentication when using this option. If the family/key is set to '/pin/100' (value does not matter) then the password field needs to be set to '/pin' and the pin entered by the user would be authenticated against '100'. m: Interpret the given path as a file which contains a list of account codes and password hashes delimited with ':', listed one per line in the file. When one of the passwords is matched, the channel will have its account code set to the corresponding account code in the file. r: Remove the database key upon successful entry (valid with 'd' only) maxdigits 179
maximum acceptable number of digits. Stops reading after maxdigits have been entered (without requiring the user to press the '#' key). Defaults to 0 - no limit - wait for the user press the '#' key. prompt Override the agent-pass prompt file. La opción password puede contener un valor o referirse a un archivo de texto que contenga una lista de nombres con las respectivas contraseñas separada por el carácter “:”. Las contraseñas se pueden escribir en claro o cifradas con MD5. En este caso se cifrarán. Si el PIN para la extensión 1002 (Mengano) es 4488, su valor cifrado será: echo -n "4488" | md5sum c4819d06b0ca810d38506453cfaae9d8 Luego se crea el archivo de texto con el nombre del usuario de la extensión y la respectiva contraseña cifrada: nano /var/spool/asterisk/pin.txt se añade la siguiente linea: Mengano:c4819d06b0ca810d38506453cfaae9d8 Se guardan los cambios. Ahora se crea un nuevo contexto al cual tenga acceso la extensión 1002. Se llamará este contexto “auten” nano /etc/asterisk/extensions.conf después del contexto internas se añade el siguiente bloque: [auten] exten => _00.,1,NoOP same => n,Authenticate(/var/spool/asterisk/pin.txt,am,4) same => n,Goto(internacio,${EXTEN},1) same => n,Hangup Los parámetros utilizados en la aplicación Authenticate: • • •
El primero define la carpeta y el nombre del archivo que contiene las contraseñas. La Opción a define que en el registro de las llamadas el campo Accountcode contendrá el nombre del usuario independientemente de la extensión que se haya utilizado para efectuar la llamada La opción m define que el archivo de texto indicado contendrá las contraseñas cifradas con 180
•
MD5. El ultimo parámetro indica que los dígitos del PIN son 4 evitando de tener que utilizar la tecla numero para terminar el envío de los dígitos.
Si la contraseña digitada está en el archivo de texto creado, el dialplan pasará a la línea que sigue donde, con la aplicación Goto se saltará al contexto internacio, extensión igual al numero marcado y prioridad 1, es decir que se iniciará la llamada. En el contexto locales se añade el contexto auten para que la extensión 1002 tenga acceso al bloque recién creado (en negrita los cambios): [locales] include => internas include => auten Se guardan los cambios y se recarga el dialplan: asterisk -rvvvvvvvvvv CLI> dialplan reload Desde la extensión 1002 se marca el numero 005714013434. Cuando Asterisk lo pide, se ingresará la contraseña 4488. Empezará la llamada al numero marcado. Se sale de la consola de Asterisk: CLI> quit Para averiguar que efectivamente la llamada ha sido cargada a la cuenta del usuario Mengano se entra en el cliente MySQL: mysql -u root -psesamo Se selecciona la base de datos asteriskcdr (donde se ha creado la tabal CDR): mysql> use asteriskcdr y se realiza una consulta en la tabla CDR (que contiene todos los registros de las llamadas): mysql> select src,dst,channel,billsec,accountcode from cdr where accountcode='Mengano'; El resultado será: +------+--------------+-------------------+---------+-------------+ | src | dst | channel | billsec | accountcode +------+--------------+-------------------+---------+-------------+ 181
| 1002 | 005714013434 | SIP/1002-00000014 | 15 | Mengano +------+--------------+-------------------+---------+-------------+ 1 row in set (0.00 sec) Se sale del cliente MySQL: mysql> quit 7.7 Limitar llamadas salientes: funciones GROUP y GROUP_COUNT Hasta la versión 1.4.X si se quería limitar el numero de llamadas salientes/entrantes para una extensión, se utilizaba el parámetro call-limit que había que añadir en la configuración de la extensión en el sip.conf. A partir de la versión 1.6.X de Asterisk y por consecuencia en la versión 1.8.X y 11, este parámetro ha sido marcado como “deprecated”; esto quiere decir que no se recomienda su uso en las nuevas versiones. En su lugar se han introducido dos funciones: • •
GROUP GROUP_COUNT
A través de estas dos funciones, es posible limitar el numero de canales utilizados en las llamadas entrantes y salientes. Un ejemplo practico. Se quiere limitar a 2 el numero de llamadas salientes para cada extensión configurada y al mismo tiempo se quieres limitar a 2 las llamadas salientes por la troncal VozToVoice. Lo que hay que hacer es construir un dialplan donde si una extensión intenta sacar la tercera llamada simultanea, se le avise que no puede y al mismo tiempo si los 2 canales de la troncal se están utilizando, se le avise al usuario que no hay más canales disponibles para las llamadas salientes. Si se quiere conocer en cualquier momento los canales utilizados por cada extensión/troncal configurada en Asterisk, el comando es: asterisk -rvvvvvvvvvvvvvvvvv CLI> sip show inuse * Peer name In use 1000 0/0/0 1001 0/0/0 1002 0/0/0 justvoip 0/0/0
Limit 2147483647 2147483647 2147483647 2147483647
Bajo la columna In use, los significados de los tres valores (de la izquierda a la derecha) son: • •
Canales in uso Canales timbrando 182
•
Canales en espera
Bajo la columna Limit se puede notar que prácticamente no existe ningún limite. Retomando el dialplan hasta ahora creado, se va a aplicar la regla definida a las llamadas salientes. Se abre el archivo del dialplan: nano /etc/asterisk/extensions.conf En el contexto internacio se modifican estas lineas: exten => _00.,1,Dial(SIP/voztovoice/${EXTEN},30) same => n,Hangup Para que queden: exten => _00X.,1,NoOp same => n,Set(GROUP(voip)=voztovoice) same => n,Set(GROUP(salida)=${CALLERID(num)}) same => n,Set(trunksal=${GROUP_COUNT(voztovoice@voip)}) same => n,Set(extsal=${GROUP_COUNT(${CALLERID(num)}@salida)}) same => n,NoOp(Hay ${extsal} llamadas desde la extension ${CALLERID(num)} y ${trunksal} con el proveedor VozToVoice)
same => n,Gotoif($[${extsal} > 2 | ${trunksal} > 2]?busy) same => n,Dial(SIP/voztovoice/${EXTEN}) same => n,Hangup same => n(busy),Playback(all-outgoing-lines-unavailable) same => n,Hangup Una explicación del dialplan creado: • • • • • • •
En la segunda linea se asigna al grupo voip la troncal voztovoice En la tercera linea se asigna al grupo salida la variable ${CALLERID(num)} que contiene el numero de la extensión que está llamando En la cuarta linea se aumenta de una unidad el valor del grupo voip y se asigna el nuevo valor a la variable trunksal En la quinta linea se aumenta de una unidad el valor del grupo salida y se asigna el nuevo valor a la variable extsal En la sexta linea se envía el valor de las llamadas totales de las extensiones y de la troncal a la consola de Asterisk En la séptima linea se define este comportamiento. Si las llamadas desde las extensiones son mayores a dos o las llamadas de la troncal son mayores a dos, ir a la etiqueta (busy), sino seguir con el dialplan. El operador lógico | está en lugar de la palabra inglés OR. En la linea que empieza con la etiqueta busy, se comunica a la extensión que no hay lineas disponibles para las llamadas salientes.
Se guardan los cambios y se actualiza el dialplan: 183
asterisk -rvvvvvvvvvvvvvvvvvvv CLI> dialplan reload Ahora para efectuar una primera prueba, desde la extensión 1001 (el softphone 3CX) se marca el numero 005714013434 y al mismo tiempo desde la extensión 1000 se marca dos veces al mismo numero. En la consola de Asterisk aparecerá: Primera llamda Executing [005714013434@externas:1] NoOp("SIP/1001-0000000d", "") in new stack Extension Changed 1001[subscribe] new state InUse for Notify User 1000 Executing [005714013434@externas:2] Set("SIP/1001-0000000d", "GROUP(voip)=voztovoice") in new stack Executing [005714013434@externas:3] Set("SIP/1001-0000000d", "GROUP(salida)=1001") in new stack Executing [005714013434@externas:4] Set("SIP/1001-0000000d", "trunksal=1") in new stack Executing [005714013434@externas:5] Set("SIP/1001-0000000d", "extsal=1") in new stack Executing [005714013434@externas:6] NoOp("SIP/1001-0000000d", "Hay 1 llamadas desde la extension 1001 y 1 con el proveedor VozToVoice") in new stack Executing [005714013434@externas:7] GotoIf("SIP/1001-0000000d", "0?busy") in new stack Executing [005714013434@externas:8] Dial("SIP/1001-0000000d", "SIP/voztovoice/005714013434") in new stack == Using SIP RTP CoS mark 5 -- Called SIP/voztovoice/005714013434 Segunda Llamada Executing [005714013434@externas:1] NoOp("SIP/1000-0000000f", "") in new stack -- Executing [005714013434@externas:2] Set("SIP/1000-0000000f", "GROUP(voip)=voztovoice") in new stack -- Executing [005714013434@externas:3] Set("SIP/1000-0000000f", "GROUP(salida)=1000") in new stack -- Executing [005714013434@externas:4] Set("SIP/1000-0000000f", "trunksal=2") in new stack -- Executing [005714013434@externas:5] Set("SIP/1000-0000000f", "extsal=1") in new stack -- Executing [005714013434@externas:6] NoOp("SIP/1000-0000000f", "Hay 1 llamadas desde la extension 1000 y 2 con el proveedor VozToVoice") in new stack -- Executing [005714013434@externas:7] GotoIf("SIP/1000-0000000f", "0?busy") in new stack -Executing [005714013434@externas:8] Dial("SIP/1000-0000000f", "SIP/voztovoice/005714013434") in new stack == Using SIP RTP CoS mark 5 -- Called SIP/voztovoice/005714013434 Tercera Llamada Executing [005714013434@externas:1] NoOp("SIP/1000-00000011", "") in new stack -- Executing [005714013434@externas:2] Set("SIP/1000-00000011", "GROUP(voip)=voztovoice") in new stack -- Executing [005714013434@externas:3] Set("SIP/1000-00000011", "GROUP(salida)=1000") in new stack 184
-- Executing [005714013434@externas:4] Set("SIP/1000-00000011", "trunksal=3") in new stack -- Executing [005714013434@externas:5] Set("SIP/1000-00000011", "extsal=2") in new stack -- Executing [005714013434@externas:6] NoOp("SIP/1000-00000011", "Hay 2 llamadas desde la extension 1000 y 3 con el proveedor VozToVoice") in new stack -- Executing [005714013434@externas:7] GotoIf("SIP/1000-00000011", "1?busy") in new stack -- Goto (externas,005714013434,10) -- Executing [005714013434@externas:10] Playback("SIP/1000-00000011", "all-outgoing-linesunavailable") in new stack > 0x7fbbf4076330 -- Probation passed - setting RTP source address to 79.44.192.186:58538 > 0x7fbbf4076330 -- Probation passed - setting RTP source address to 79.44.192.186:58538 > 0x7fbbf40abcb0 -- Probation passed - setting RTP source address to 79.44.192.186:53368 -- Playing 'all-outgoing-lines-unavailable.alaw' (language 'es') > 0x7fbbf40abcb0 -- Probation passed - setting RTP source address to 79.44.192.186:53368 -- Executing [005714013434@externas:11] Hangup("SIP/1000-00000011", "") in new stack Con el comando sip show inuse, a lo largo de la segunda llamada, aparecerá: CLI> sip show inuse * Peer name In use 1000 1/0/0 1001 1/0/0 1002 0/0/0 justvoip 2/0/0
Limit 2147483647 2147483647 2147483647 2147483647
Cuando la extensión 1000 intenta sacar la tercera llamada, el Gotoif es verdadero y el dialplan sigue desde la prioridad con la etiqueta busy anunciando que no hay más linea salientes disponibles. Está configuración es funcional si a todas las extensiones se quiere asignar máximo dos canales salientes, pero ¿Cómo se puede configurar el dialplan para diferenciar los canales salientes para cada extensión? Una posible solución es utilizar, en la configuración de las extensiones, el parámetro SetVar. Este parámetro permite crear variables personalizadas para cada extensión. En este ejemplo, se creará una variable para la extensión 1002 llamada canales y se le asignará el valor 1: nano /etc/asterisk/sip.conf se modifica este bloque: [1002](int-locales) accountcode=1002 secret=pbx9092 mailbox=1002@default callerid=Mengano <1002>
185
para que quede: [1002](int-locales) accountcode=1002 secret=pbx9092 mailbox=1002@default callerid=Mengano <1002> Setvar=canales=1 Se guardan los cambios y se actualiza la configuración SIP: asterisk -rvvvvvvvvvvvvvvvv CLI> sip reload Para averiguar que efectivamente el valor se ha configurado correctamente: CLI> sip show peer 1002 entre todas las lineas aparecerá: Variables
: canales = 1
Ahora se va a utilizar esta variable en el dialplan. Se modifica este bloque: [auten] exten => _00.,1,NoOP same => n,Authenticate(/var/spool/asterisk/pin.txt,am,4) same => n,Goto(internacio,${EXTEN},1) same => n,Hangup para que quede: [auten] exten => _00.,1,NoOP same => n,Set(GROUP(numcan)=${CALLERID(num)}) same => n,Set(numcan=${GROUP_COUNT(${CALLERID(num)}@numcan)}) same => n,GotoIf($[${numcan} > ${canales}]?busy) same => n,Authenticate(/var/spool/asterisk/pin.txt,am,4) same => n,Goto(internacio,${EXTEN},1) same => n,Hangup same => n(busy),Playback(all-outgoing-lines-unavailable) same => n,Hangup Se guardan los cambios. De esta forma antes de autenticar la llamada de la extensión 1002, se controla cuantos canales esa extensión está utilizando. Si son más de uno se salta a la etiqueta busy, si son 186
menos se cursa la llamada normalmente. La parte importante es la linea del GotoIf donde se compara el numero de canales in uso con la variable canales configurada en el archivo sip.conf con el parámetro SetVar. Esto quiere decir que cada vez que la extensión efectuará cualquier tipo de llamada, llevará consigo la variable canales y su valor. Para averiguarlo, desde la extensión 1002 se marca 123. El resultado: Dumping Info For Channel: SIP/1002-00000012: ============================================================= Info: Name= SIP/1002-00000012 Type= SIP UniqueID= 1396981284.18 LinkedID= 1396981284.18 CallerIDNum= 1002 CallerIDName= Mengano ConnectedLineIDNum= (N/A) ConnectedLineIDName=(N/A) DNIDDigits= 123 RDNIS= (N/A) Parkinglot= default Language= es State= Up (6) Rings= 0 NativeFormat= (alaw) WriteFormat= alaw ReadFormat= alaw RawWriteFormat= alaw RawReadFormat= alaw WriteTranscode= No ReadTranscode= No 1stFileDescriptor= 27 Framesin= 1 Framesout= 0 TimetoHangup= 0 ElapsedTime= 0h0m1s DirectBridge= IndirectBridge= Context= locales Extension= 123 Priority= 2 CallGroup= 1 PickupGroup= 1 Application= DumpChan Data= (Empty) Blocking_in= (Not Blocking)
187
Variables: canales=1 SIPCALLID=YzJhMTdiZjdiOTMxNGE5MDM4ZGMzMzU5NDFiNTE0ZWY. SIPDOMAIN=72.14.178.214 SIPURI=sip:[email protected]:9000 En negrita la variable canales. 7.8 Los mensajes instantáneos entre extensiones Otra interesante novedad de la versión 11 es la posibilidad de poder enviar mensajes instantáneos entre extensiones aunque no estén en una llamada. La primera pregunta es: ¿esta funcionalidad es compatible con todos los dispositivos SIP que se han instalado hasta ahora? Como se ha dicho en la introducción del capitulo 3, el método OPTIONS del protocolo SIP se utiliza también para conocer los métodos disponible in un determinado dispositivo/PBX. Si se mira como Asterisk envía el paquete OPTIONS al X-Lite (extensión 1000), se verá: Reliably Transmitting (NAT) to 190.67.135.55:16417: OPTIONS sip:[email protected]:16417;rinstance=c62828cfc0df2a3e;transport=UDP SIP/2.0 Via: SIP/2.0/UDP 173.255.194.236:5060;branch=z9hG4bK1af7e146;rport Max-Forwards: 70 From: "asterisk" ;tag=as49b6bec3 To: Contact: Call-ID: [email protected]:5060 CSeq: 102 OPTIONS User-Agent: VozToVoice v. 1.0 Date: Mon, 08 Sep 2014 22:29:33 GMT Session-Expires: 600 Min-SE: 90 Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH, MESSAGE Supported: replaces, timer Content-Length: 0 En la cabecera Allow aparece el método MESSAGE. Esto quiere decir que la funcionalidad de los mensajes instantáneos sigue el estándar definido en el RFC3428. En el caso de X-Lite: SIP/2.0 200 OK Via: SIP/2.0/UDP 72.14.178.214:5060;branch=z9hG4bK44a9758e;rport=5060 Contact: To: ;tag=159a3e3d From: "asterisk";tag=as48d35379 Call-ID: [email protected]:5060 188
CSeq: 102 OPTIONS Accept: application/sdp Accept-Language: en Allow: INVITE, ACK, CANCEL, OPTIONS, SUBSCRIBE, INFO Supported: replaces, eventlist User-Agent: X-Lite release 4.5.4 stamp 70866 Allow-Events: hold, talk Content-Length: 0
BYE,
REFER,
NOTIFY,
MESSAGE,
Como se puede ver en la cabecera Allow, el X-Lite si soporta el método MESSAGE según como definido en la RFC mencionada. El problema es que a partir de la versión (4.7.0) X-Lite soporta el envío de los mensajes solamente en formato text/html mientras Asterisk acepta los mensajes solamente en formato text/plain pues contesta con un 415 Unsupported Media Type. La segunda pregunta es: ¿De verdad es una funcionalidad útil? La respuesta es: depende. Si se piensa utilizar los mensajes instantáneos entre un Softphone instalado en un computador y otro instalado en un móvil, la verdad no es muy util ya que hay disponibles aplicaciones que son muchos más cómodas y con más funcionalidades, tipo Telegram. Si se piensa en su utilizo entre distintos Softphone instalados en distintos computadores, quizás puede ser útil ya que permite a las distintas extensiones utilizar una herramienta más para comunicar. ¿Cuanto Softphone permiten el envío y la recepción de mensajes instantáneos? De los que se han instalado hasta el momento ninguno. Es por eso que para ver en acción esta funcionalidad se utilizará el Softphone Jitsi y el Softphone Bria (de pago). En Bria se configura la extensión 1000 y se añade en la lista de contactos la extensión 1001.
En Jitsi se configura la extensión 1001 y luego se añade la extensión 1000 en la lista de contactos. El resultado:
189
Como se puede ver la extensión 1000 se ha añadido correctamente y se encuentra en linea. Para que el envío de mensajes instantáneos funcionen, los siguientes parámetros tienen que estar configurados en la parte general del archivo sip.conf: • • •
accept_outofcall_message=yes outofcall_message_context=message auth_message_requests=yes
Con el primero se define que Asterisk aceptará mensajes instantáneos aunque entre las dos extensiones no esté activa una llamada. Con el segundo se define el contexto del dialplan donde llegarán los mensajes instantáneos. Con el tercero que todos los mensajes instantáneos enviados deberán pasar por el mismo proceso de autentificación de un INVITE o SUBSCRIBE. Además de estos tres parámetros, otro importante es el parámetro subscribecontext, que se ha configurado con el valor subscribe. Esto para que las extensiones puedan conocer el estado de las demás. El paso a seguir es crear el nuevo contexto en el dialplan. Se abre el archivo de configuración: nano /etc/asterisk/extensions.conf antes del contexto internas se añade: [message] exten => _X.,1,Noop(Mensaje de ${MESSAGE(from)}) same => n,Noop(Mensaje para ${MESSAGE(to)}) 190
same => n,Noop(Texto = ${MESSAGE(body)}) same => n,Messagesend(sip:${EXTEN},${MESSAGE(from)}) same => n,Noop(Estado del mensaje ${MESSAGE_SEND_STATUS}) same => n,Hangup Se guardan los cambios y se recarga el dialplan: asterisk -rx "dialplan reload" En las primeras tres lineas se utiliza la función MESSAGE para conocer algunos datos del mensaje que se está enviando. En este caso, el remitente (from), el destinatario (to) y el contenido del mensaje (body). En la cuarta linea se utiliza la aplicación MESSAGESEND para enviar el mensaje. La variable ${EXTEN} contendrá el destinatario y ${MESSAGE(from)} nuevamente el remitente. En la quinta linea con la variable ${MESSAGE_SEND_STATUS}, generada por la aplicación MESSAGESEND, se podrá conocer el estado del mensaje que se está enviando. Posibles valores son: • • • •
INVALID_PROTOCOL: mensaje enviando desde un protocolo invalido (ejemplo IAX2 en lugar de SIP) INVALID_URI: el destinatario del mensaje no es correcto SUCCESS: mensaje enviado con éxito FAILURE: envío del mensaje fallido
Ante de efectuar la primera prueba, se activa la captura de paquetes con Ngrep: ngrep MESSAGE -W byline port 5060 > /tmp/message Luego desde Bria se envía un mensaje a la extensión 1001 (Jitsi):
El mensaje ha sido recibido correctamente. Se sale de la captura de paquetes y se abre el archivo 191
/tmp/message: nano /tmp/message Se encontrará una primera secuencia:
donde Bria envía el mensaje a Asterisk y este contesta que necesita que la extensión se autentifique. La segunda secuencia:
192
Bria vuelve a enviar el paquete con sus datos de identificación y Asterisk lo acepta. En la tercera secuencia:
Asterisk envía el mensaje a la extensión 1001 (Jitsi) que contesta con un 200 OK. En la consola de Asterisk: 193
Executing [1001@message:1] NoOp("Message/ast_msg_queue", "Mensaje de "1000" ") in new stack Executing [1001@message:2] NoOp("Message/ast_msg_queue", "Mensaje para sip:[email protected]") in new stack Executing [1001@message:3] NoOp("Message/ast_msg_queue", "Texto = Hola") in new stack Executing [1001@message:4] MessageSend("Message/ast_msg_queue", "sip:1001,"1000" ") in new stack Executing [1001@message:5] NoOp("Message/ast_msg_queue", "Estado del mensaje SUCCESS") in new stack Executing [1001@message:6] Hangup("Message/ast_msg_queue", "") in new stack
En negrita los datos más salientes. En Jitsi:
Si se desconecta la extensión 1001 (Jitsi) de Asterisk y se intenta enviar un nuevo mensaje desde Bria, en la consola de Asterisk aparecerá: Executing [1001@message:1] NoOp("Message/ast_msg_queue", "Mensaje de "1000" ") in new stack Executing [1001@message:2] NoOp("Message/ast_msg_queue", "Mensaje para sip:[email protected]") in new stack Executing [1001@message:3] NoOp("Message/ast_msg_queue", "Texto = hola") in new stack Executing [1001@message:4] MessageSend("Message/ast_msg_queue", "sip:1001,"1000" ") in new stack Executing [1001@message:5] NoOp("Message/ast_msg_queue", "Estado del mensaje FAILURE") in new stack Executing [1001@message:6] Hangup("Message/ast_msg_queue", "") in new stack
El mensaje no se ha podido entregar. La verdad si la extensión 1001 no aparece en linea es normal que no se le pueda entregar el mensaje pero, a veces, puede suceder que la extensión aparezca en linea aunque en la realidad no lo esté. Esto porque en algunos casos el sistema de monitoreo de Asterisk tarda un poco en actualizar el estado de la extensión y/o se ha presentado algún problema especifico. Es por eso que puede ser útil conocer si el mensaje enviado ha sido recibido correctamente o no. Para este tipo de solución se modifica nuevamente el dialplan: nano /etc/asterisk/extensions.conf se modifica este bloque: [message] exten => _X.,1,Noop(Mensaje de ${MESSAGE(from)}) same => n,Noop(Mensaje para ${MESSAGE(to)}) same => n,Noop(Texto = ${MESSAGE(body)}) same => n,Messagesend(sip:${EXTEN},${MESSAGE(from)}) same => n,Noop(Estado del mensaje ${MESSAGE_SEND_STATUS}) same => n,Hangup Para que quede:
194
[message] exten => _X.,1,Noop(Mensaje de ${MESSAGE(from)}) same => n,Noop(Mensaje para ${MESSAGE(to)}) same => n,Noop(Texto = ${MESSAGE(body)}) same => n,Set(dest=${EXTEN}) same => n,Messagesend(sip:${EXTEN},${MESSAGE(from)}) same => n,Noop(Estado del mensaje ${MESSAGE_SEND_STATUS}) same => n,GotoIf($["${MESSAGE_SEND_STATUS}" != "SUCCESS"]?failed,s,1) same => n,Hangup Se ha añadido la linea 7 donde si el resultado del envío del mensaje es distinto (!=) a SUCCESS se envia el canal al contexto failed, extensión s, prioridad 1. Este contexto se añade al final del archivo: [failed] exten => s,1,Set(texto=${MESSAGE(body)}) same => n,Set(MESSAGE(body)="El Mensaje - ${texto} - para ${dest} no ha sido enviado") same => n,Set(remit=${CUT(MESSAGE(from),<,2)}) same => n,Set(remit=${CUT(remit,@,1)}) same => n,MessageSend(${remit},CentroMensajes) same => n,Noop(Estado del mensaje ${MESSAGE_SEND_STATUS}) same => n,Hangup Se guardan los cambios y se recarga el dialplan: asterisk -rx "dialplan reload" El bloque failed se utiliza para notificar a la extensión que ha enviado un mensaje que no se ha podido entregar. Para probar el nuevo dialplan, se envía un mensaje desde Bria a la extensión 1001 cuando no esté conectada, el resultado será:
Que es un control más para conocer el estado de los mensajes enviados.
195
7.9 WebRTC (Comunicación en tiempo real vía Web) La palabra WebRTC en los últimos tiempos se ha vuelto muy popular ya que, para muchos, representa una verdadera revolución en la forma de comunicar. Es la posibilidad de comunicar utilizando navegadores Web, y no solamente, que implementen las API en JavaScript que permiten a los desarrolladores implementar servicios y aplicaciones que interaccionan con los navegadores mismos. Estas API son de tres tipos: • • •
getUserMedia que se utiliza para solicitar el acceso a los dispositivos (audio/vídeo) presentes en el dispositivo (computador, tablet, Smartphone, etc) RTCPeerConnection que se utiliza para crear un flujo media directo entre los dos puntos RTCDataChannel que permite a los dos puntos intercambiar datos que no son parte del flujo media (chat, fotos, archivos, etc.)
La idea detrás de WebRTC es la comunicación sin plugins y programas que no sea un navegador Web. Claramente se pueden desarrollar aplicaciones que implementen WebRTC en programas que no sean navegadores Web y quizás esta es la parte más interesante de este nuevo sistema de comunicación. Para el flujo media se utiliza el Protocolo SRTP sobre DTLS que es un protocolo de cifrado basado en TLS y específicamente pensado para los datagramas. Un protocolo que utiliza los datagramas es UDP que notoriamente es el preferido en la comunicaciones VoIP y, en general, en cualquier tipo de aplicación donde haya un flujo media. Los codec audio permitidos en el flujo media son: alaw, ulaw y Opus. Para los codec vídeo todavía no hay una acuerdo entre VP8 o H.264. Como los dos puntos trasmiten el flujo audio directamente (sin pasar por un intermediario) y como normalmente se encuentran detrás de una NAT, para resolver este tipo de problema se ha optado para utilizar el protocolo ICE (RFC5245) que logra resolver el 99% de los posibles tipos de NAT. Una parte muy importante de este nuevo protocolo es que para la señalización puede ser utilizado cualquier tipo de protocolo (propietario o no). Dos ejemplos: SIP y XMPP. En enero de este año, la IETF ha publicado un nuevo RCF (el 7118) donde se especifica y estandariza el uso de la señalización SIP para WebRTC. Esto significa que es posible hacer comunicar WebRTC vía SIP con programas que ya utilizan este protocolo. De hecho Asterisk, desde la versión 11 implementa el protocolo WebRTC y esto vuelve posible una comunicación entre extensiones SIP y programas que implementan las API WebRTC. En este párrafo se verá como configurar Asterisk para comunicarse con un navegador Web a través de dos librerías Javascript que implementan el protocolo SIP sobre WebRTC: • •
JSSIP SIPML5
Como se decía Asterisk 11 implementa el WebRTC a través del modulo res_http_websocket y el mini servidor web incluido en la PBX que se utiliza, por ejemplo, para la GUI de Digium que se verá en el 196
capitulo XXVI de este libro. Los pasos a seguir para la implementación son: • • • • •
modificar el archivo de configuración de Asterisk http.conf abrir el puerto 8088 en el cortafuegos Crear los certificados para el cifrado media DTLS crear una nueva extensión que utilice como método de trasporte en lugar de UDP, WS (WebSocket) y el cifrado media DTLS modificar el dialplan para permitir las llamadas entre la nueva extensión y las demás
Si inicia con la modificación del archivo http.conf. Se renombra el predefinido: mv /etc/asterisk/http.conf /etc/asterisk/http.conf.old Se crea uno nuevo: nano /etc/asterisk/http.conf se pegan las siguientes líneas: [general] enabled=yes bindaddr=0.0.0.0 bindport=8088 En al primera linea se activa el mini servidor Web presente en Asterisk, en la segunda se especifica que se pondrá a la escucha en todas las direcciones IPv4 presentes en el servidor y que escuchará en el puerto 8088 TCP que hay que abrir en el cortafuego. Se guardan los cambios y se abre la configuración del cortafuego: nano /etc/sysconfig/iptables Después de esta linea: -A INPUT -p tcp -m state --state NEW -m tcp --dport 15000 -j ACCEPT se añade: # Asterisk HTTP -A INPUT -p tcp -m state --state NEW -m tcp --dport 8088 -j ACCEPT Se guardan los cambios y se reinicia IPtables: service iptables restart 197
Se crean los certificados para el protocolo DTLS aprovechando una utilidad presente en las fuentes de Asterisk. Primero se crea la carpeta donde se guardarán los certificados: mkdir /etc/asterisk/keys Luego se crea el certificado que se utilizará para el cifrado DTLS: cd /usr/src/asterisk-11.17.1/contrib/scripts En la opción -C se pone la IP o el nombre de dominio del servidor Asterisk: ./ast_tls_cert -C 173.255.194.236 -O "LibroAsterisk" -d /etc/asterisk/keys No config file specified, creating '/etc/asterisk/keys/tmp.cfg' You can use this config file to create additional certs without re-entering the information for the fields in the certificate Creating CA key /etc/asterisk/keys/ca.key Generating RSA private key, 4096 bit long modulus .........................++ ...........................++ e is 65537 (0x10001) Enter pass phrase for /etc/asterisk/keys/ca.key: Verifying - Enter pass phrase for /etc/asterisk/keys/ca.key: Creating CA certificate /etc/asterisk/keys/ca.crt Enter pass phrase for /etc/asterisk/keys/ca.key: Creating certificate /etc/asterisk/keys/asterisk.key Generating RSA private key, 1024 bit long modulus .............................................................++++++ ....................................++++++ e is 65537 (0x10001) Creating signing request /etc/asterisk/keys/asterisk.csr Creating certificate /etc/asterisk/keys/asterisk.crt Signature ok subject=/CN=173.255.194.236/O=LibroAsterisk Getting CA Private Key Enter pass phrase for /etc/asterisk/keys/ca.key: Combining key and crt into /etc/asterisk/keys/asterisk.pem Cuando el script lo pide se ingresa una contraseña (por ejemplo asterisk). Ya se puede crear la nueva extensión SIP: nano /etc/asterisk/sip.conf y al final del archivo se añade:
198
[8000] type=friend secret=pbx8080 context=externas host=dynamic qualify=yes qualifyfreq=600 callerid=WebRTC <8000> callcounter=yes transport=udp,ws avpf=yes force_avp=yes encryption=yes icesupport=yes directmedia=no dtlsenable=yes dtlsverify=no dtlscertfile=/etc/asterisk/keys/asterisk.pem dtlsprivatekey=/etc/asterisk/keys/asterisk.pem dtlssetup=actpass Los datos importantes: • • • • • •
trasport=udp,ws: se activa el trasporte udp y ws (WebSocket sin cifrado) avpf=yes: el perfil audio/vídeo requerido por WebRTC para el flujo media force_avp=yes: obliga Asterisk a utilizar avp. Parámetro presente desde la versión 11.11 de Asterisk encryption=yes: el flujo media será cifrado icesupport=yes: se activará el soporte del protocolo ICE para esta extensión (como requerido por el protocolo WebRTC. Este parámetro tiene que estar presente también en el archivo de configuración de Asterisk rtp.conf (véase párrafo 2.1) Las ultimas 5 líneas donde se configura el protocolo DTLS
Se guardan los cambios y se modifica el dialplan: nano /etc/asterisk/extensions.conf después de este bloque: exten => 1234,1,Dial(IAX2/marko,30) same => n,Hangup se añade: exten => 8000,1,NoOp(Llamada usuario WebRTC) same => n,Dial(SIP/${EXTEN},45) 199
same => n,Hangup Se modifica también este bloque: [subscribe] exten => 1000,hint,SIP/1000 exten => 1001,hint,SIP/1001 exten => 1002,hint,SIP/1002 exten => marko,hint,IAX2/marko para que quede: [subscribe] exten => 1000,hint,SIP/1000 exten => 1001,hint,SIP/1001 exten => 1002,hint,SIP/1002 exten => 8000,hint,SIP/8000 exten => marko,hint,IAX2/marko permitiendo de esta forma las llamadas a la extensión 8000 que se acaba de crear y el monitoreo de la misma. Se guardan los cambios y se reinicia Asterisk para que actualice todas las nuevas configuraciones realizadas: service asterisk restart Ya se pueden realizar las dos pruebas con JSSIP y SIPML5 7.9.1 JSSIP La primera prueba se realiza con la librería Javascript JSSIP. Se abre el navegador web Chrome y se accede a esta pagina: http://tryit.jssip.net/ En la pagina que aparece se rellenan los campos presentes de la siguiente forma:
200
En Name se pone el nombre de la extensión, en SIP URI se pone la URI de la extensión. En lugar de IPAsterisk se pone la IP del servidor Asterisk; en SIP password se pone la contraseña de la extensión 8000 (pbx8080) y en WS URI se pone la dirección del WebSocket de Asterisk cambiando IPAsterisk con la IP del servidor Asterisk. Para terminar se presiona la tecla envío. Aparecerá:
201
Como se puede ver la extensión aparece registrada al servidor Asterisk. De hecho en la consola de la PBX: asterisk -rvvvvvvvvvvvvv CLI> sip show peers like 8000 Name/username Host 8000/8000 79.44.192.186
Dyn Forcerport Comedia ACL Port Status D Yes Yes 59089 OK (665 ms)
Como no se va a utilizar la parte vídeo, se deselecciona la casilla “enable video”. Se inicia el X-Lite configurado como extensión 1000 y se añade en la lista de contactos la extensión 8000. El resultado:
Ahora desde JSSIP se marca la la extensión 1000: 202
En seguida en Chrome se abrirá una pestaña solicitando el permiso de utilizar el micrófono presente en el computador (ya que se han desactivado las vídeo llamadas):
Una vez concedido el permiso aparecerá una ventanilla indicando que la llamada se está cursando:
Después de unos segundos, timbrará el X-Lite:
Cuando en X-lite se conteste la llamada en Chrome:
En X-Lite el estado de la extensión 8000 cambiará:
203
El audio se debería escuchar perfectamente. Se termina la llamada y se llama desde X-Lite a JSSIP:
Se presiona el icono indicado:
Se dan los permisos:
La llamada será contestada. Ya se puede colgar.
7.9.2 SIPML5 La segunda prueba se realizará con la demo de SIPML5. Se abre en Chrome la siguiente pagina: http://sipml5.org/call.htm En la pagina que aparece se selecciona el Botón “Expert mode”. Se abrirá una nueva pestaña donde se configuran los campos que aparecen de la siguiente manera:
204
En “WebSocket Server URL” se pone la dirección como aparece modificando IPservidor con la IP de Asterisk. En “ICE Servers” se pone la dirección del servidor STUN publico de Google: [{ url: 'stun:stun.l.google.com:19302'}]. Se guardan los cambios presionando el botón “Save” y luego se vuelve a la pestaña anterior donde se configura el WebPhone:
Se sustituye IPServidor con la IP del servidor Asterisk. Una vez terminada la configuración se presiona el botón Login. Aparecerá:
205
Desde el WebPhone se llama la extensión 1000:
Se escribe el numero de la extensión (1000) y en el menú despegable que aparece cuando se selecciona el botón “Call” se escoge la opción “Audio”:
Como siempre se solicitará el acceso al micrófono. Luego aparecerá:
y una vez que la llamada ha sido contestada por X-Lite:
También en este caso audio perfecto. Se cuelga y desde el X-Lite se llama la extensión 8000:
206
Una vez que se conceda el permiso para acceder al micrófono:
Se podrá contestar la llamada presionando el botón “Answer” y escuchar nuevamente un audio casi perfecto. Claramente estas dos pruebas que se han realizado no sirven de mucho para implementar soluciones integradas entre Asterisk y WebRTC pero dan una idea de lo que se pueda desarrollar implementando soluciones propias que aprovechen este nuevo “protocolo” utilizando las librerías disponibles y/o creando nuevas.
207
CAPITULO VIII IVR IVR es la sigla de Interactive Voice Response, que se traduce del inglés como Respuesta de Voz Interactiva. Consiste en un central telefónica (en este caso Asterisk) que es capaz de recibir una llamada e interaccionar con el usuario a través de grabaciones de voz y el reconocimiento de respuestas a través del uso de las teclas del teléfono y/o de la voz. Algunos ejemplos: el menú que se escucha cuando se llama un centro de atención al cliente; los bancos que permiten realizar consultas o pagos a través de un menú vocal. En el lenguaje técnico habría que diferenciar dos tipos de sistemas: • •
El IVR permite efectuar consultas a base de datos, devolver los resultados y, en general, interaccionar de forma activa con el usuario. la contestadora automática permite navegar entre menús vocales permitiendo elegir entre distintas opciones hasta llegar a la información que se está buscando
En este capitulo se presentará la configuración de una contestadora automática. 8.1 Grabación de las locuciones En Asterisk con la aplicación Record se pueden grabar archivos audios para luego utilizarlos en la creación de un IVR. Para implementarla hay que modificar el dialplan. nano /etc/asterisk/extensions.conf En el contexto internas se pone el siguiente bloque: exten => _66XX,1,Answer() same => n,Wait(2) same => n,Record(/tmp/prompt${EXTEN:2}.wav) same => n,Wait(2) same => n,Playback(/tmp/prompt${EXTEN:2}) same => n,Wait(2) same => n,Hangup() • • • • • • •
Línea 1: contesta la llamada Línea 2: espera 2 segundos Línea 3: Graba el archivo audio en la carpeta /tmp con nombre promptXX donde XX son los últimos dos dígitos de la extensión que se ha marcado desde el Softphone. Ejemplo: Si se llama la extensión 6650 el archivo audio tendrá el nombre prompt50.waw Línea 4: espera 2 segundos Línea 5: devuelve el archivo recién grabado Línea 6: espera 2 segundos Línea 7: cuelga la llamada
Si la grabación no es satisfactoria, se vuelve a grabar marcando el mismo numero. La nueva grabación remplazará la vieja. IMPORTANTE: para terminar la grabación hay que presionar la tecla numero # Se guardan los cambios y se actualiza el dialplan: asterisk -rvvvvvvvvvvvvvvvv CLI> dialplan reload CLI> quit Esta solución permite grabar hasta 99 archivos audio. Para el ejemplo a seguir hay que grabar tres archivos de audio que contengan las siguientes frases: • • •
prompt01.wav - “for english press one, para español marque dos” prompt02.wav - “para efectuar un test de eco marque 1, para escuchar la música en espera marque 2, para la oficina de ventas marque 3” prompt03.wav - “for echo test press 1, for music on hold press 2, for sales office, press 3”
Desde la extensión 1000 se marca 6601 y se graba la primera frase; luego 6602 y se graba la segunda; se termina con 6603 y se graba la tercera. Una vez terminadas las grabaciones se crea un nueva carpeta: mkdir /var/lib/asterisk/sounds/custom y se mueven los tres archivos (prompt01.wav prompt02.wav y prompt03.wav) a la carpeta creada cd /tmp mv prompt* /var/lib/asterisk/sounds/custom El formato audio de las locuciones es Wav. A veces es útil y aconsejable crear las mismas locuciones en otros formatos audio; esto para que Asterisk no tenga que decodificar y codificar las locuciones a otro formato audio según el codec negociado con el teléfono IP o softphone que está llamando. Este proceso se llama transcoding y utiliza bastantes recursos del servidor. Para crear las locuciones en otros formatos audio hay un comando disponible en la consola de Asterisk: asterisk -rvvvvvvvvvvvvvvvv Asterisk de manera predefinida busca las locuciones en la carpeta /var/lib/asterisk/sounds. Como han sido copiadas en la carpeta custom, el comando será: CLI> file convert custom/prompt01.wav custom/prompt01.ulaw 210
Converted custom/prompt01.wav to custom/prompt01.ulaw in 0ms De esta forma se convierte la locución al formato audio ulaw CLI> file convert custom/prompt01.wav custom/prompt01.alaw Converted custom/prompt01.wav to custom/prompt01.alaw in 0ms para el formato alaw. Ya que se ha instalado el codec G729, se puede convertir el archivo también a este formato audio: CLI> file convert custom/prompt01.wav custom/prompt01.g729 Converted custom/prompt01.wav to custom/prompt01.g729 in 24ms Para conocer la sinopsis del comando record: CLI> core show application record CLI> quit 8.2 Configuración numero geográfico Cuando se adquiere un numero geográfico, la empresa que lo vende, facilita siempre el rango de IP de donde llegarán los INVITE para las llamadas entrantes. Esta lista de IP hay que incluirla en el sip.conf sino las llamadas no serán autenticadas pues serán rechazadas. Otra cosa que el proveedor permite, es configurar el “Mapping”, es decir definir que dirección SIP o numero de teléfono hay que llamar cuando entre una llamada al numero geográfico. Esto normalmente se realiza desde el panel de control que cada cliente tiene a disposición. Para tener una idea de como funciona y de como se configuran los números geográficos, puede visitar la pagina de la empresa VozToVoice. En el caso que se adquiera un numero geográfico, al momento de la configuración, en “Ingresar Nombre Dominio o Dirección IP “ se pone la dirección IP del servidor y en “Usuario o Extensión” la letra s. Con ese numero ya se puede realizar una primera prueba. Desde la extensión 1000 se marca el numero. La sintaxis es 00 + código país + numero geográfico. El resultado en la consola de Asterisk será: NOTICE[7577]: chan_sip.c:20701 handle_request_invite: Sending fake auth rejection for device "6620016037" ;tag=as4dbd19b8 Asterisk no puede autenticar el INVITE en entrada porque todavía no se ha incluido la lista de IP en el archivo sip.conf. Estas direcciones están configuradas en un archivo que se descargará: cd /etc/asterisk
211
wget http://www.voztovoice.org/tmp/didvoztovoice Ahora se incluye el archivo didvoztovoice en el sip.conf aprovechando el comando include: nano sip.conf al final del archivo se añade: #include didvoztovoice El comando #include toma un archivo de texto y lo engloba en la configuración. Se guardan los cambios, se entra en la consola de Asterisk y se recarga la configuración SIP: asterisk -rvvvvvvvvvvvvvvvvvv CLI> sip reload Segunda prueba: se marca nuevamente el numero se mira que pasa en la consola de Asterisk: NOTICE[7577]: chan_sip.c:20785 handle_request_invite: Call from '46.19.209.78' to extension 's' rejected because extension not found in context 'from-voztovoice' Ya la llamada no viene rechazada sino que no se puede enviar a ninguna parte del dialplan porque Asterisk no encuentra el contexto from-voztooice. Más adelante se creará ese contexto. CLI> quit 8.3 Creación del IVR Con la locuciones grabadas, ya se puede configurar el IVR. Para hacerlo se crea un nuevo archivo que luego se incluirá en el dialplan. nano /etc/asterisk/IVR se copian los tres bloques que siguen: [IVR] exten => s,1,Wait(1) exten => s,2,Set(CHANNEL(language)=es) exten => s,3,Set(TIMEOUT(digit)=7) exten => s,4,Set(TIMEOUT(response)=10) exten => s,5,BackGround(custom/prompt01) exten => s,6,WaitExten() exten => 1,1,goto(IVR1,s,1) exten => 2,1,goto(IVR2,s,1) exten => i,1,Playback(invalid) 212
exten => i,2,Goto(IVR,s,2) exten => i,3,Hangup exten => t,1,goto(IVR,s,2) exten => h,1,Hangup [IVR1] exten => s,1,Set(TIMEOUT(digit)=7) exten => s,2,Set(TIMEOUT(response)=10) exten => s,3,Set(CHANNEL(language)=en) exten => s,4,BackGround(custom/prompt03) exten => s,5,WaitExten() exten => 1,1,Playback(demo-echotest) exten => 1,2,Echo() exten => 1,3,Playback(demo-echodone) exten => 1,4,Hangup exten => 2,1,MusicOnHold exten => 2,2,Hangup exten => 3,1,Playback(pls-wait-connect-call) exten => 3,2,Goto(internas,100,1) exten => i,1,Playback(invalid) exten => i,2,Goto(IVR1,s,1) exten => i,3,hangup exten => t,1,goto(IVR1,s,1) exten => h,1,Hangup [IVR2] exten => s,1,Set(TIMEOUT(digit)=7) exten => s,2,Set(TIMEOUT(response)=10) exten => s,3,Set(CHANNEL(language)=es) exten => s,4,BackGround(custom/prompt02) exten => s,5,WaitExten() exten => 1,1,Playback(demo-echotest) exten => 1,2,Echo() exten => 1,3,Playback(demo-echodone) exten => 1,4,Hangup exten => 2,1,MusicOnHold exten => 2,2,Hangup exten => 3,1,Playback(pls-wait-connect-call) exten => 3,2,Goto(internas,100,1) exten => i,1,Playback(invalid) exten => i,2,Goto(IVR2,s,1) exten => i,3,hangup exten => t,1,goto(IVR2,s,1) exten => h,1,Hangup Se guardan los cambios. Una explicación de las nueva funciones y aplicaciones que aparecen en el IVR: 213
• • • • • • • • • • • •
Wait(1) – Espera un segundo Set(CHANNEL(language)=es) – Se pone como idioma predefinido para las locuciones el español Set(TIMEOUT(digit)=7) – numero máximo de segundos que esperará el sistema (7) entre el primer dígito y los siguientes Set(TIMEOUT(response)=10) – numero máximo de segundos que el sistema esperará para que el llamante presione una tecla del teléfono. BackGround(custom/prompt01) – presenta la locución prompt01 y al mismo tiempo se pone a la escucha de los dígitos que pueda presionar el llamante. WaitExten() - Espera que el llamante presione una tecla 1,1,goto(IVR1,s,1) – si el llamante presiona 1 va (goto) al contexto IVR1, extensión s, prioridad 1 2,1,goto(IVR2,s,1) – si el llamante presiona 2, va (goto) al contexto IVR2, extensión s, prioridad 1 i,1,Playback(invalid) – si la tecla presionada no es valida (ni 1 ni 2) comunica el error i,2,Goto(IVR,s,2) – y devuelve el llamante al contexto IVR, extensión s, prioridad 2 (presenta nuevamente el menú inicial) t,1,goto(IVR,s,2) – si dentro de 10 segundos (TIMEOUT(response)), el llamante no presiona ninguna tecla, vuelve a presentar el menú inicial h,1,Hangup – si el llamante cuelga, se ejecuta la extensión h
La extensión i se utiliza para capturar dentro del dialplan, dígitos errados. La extensión t se utiliza cuando la función TIMEOUT está presente en el dialplan La extensión h se utiliza para añadir nuevas lineas de dialplan cuando se cuelga la llamada El segundo bloque del IVR es bastante parecido y envía el llamante a la extensión que haya digitado. La parte interesante es que si se presiona el numero tres, la llamada se enviará al contexto internas, extensión 100, prioridad 1 Como esa extensión todavía no existe, hay que crearla: nano /etc/asterisk/extensions.conf en el contexto internas se añade el siguiente bloque: exten => 100,1,Noop same => n,Dial(SIP/1000&SIP/1001&SIP/1002,30) same => n,Hangup Lo que hará es marcar a las extensiones 1000, 1001 y 1002 simultáneamente hasta que una de las tres conteste la llamada. Este tipo de configuración se llama Ring Group. Para que todas las llamadas externas sean atendidas por el IVR, antes del contexto internas, se añade este bloque: 214
[from-didvoztovoice] exten => s,1,Answer same => n,Goto(IVR,s,2) same => n,Hangup from-didvoztovoice es el contexto donde llegarán las llamadas del numero geográficos (configurado para cada troncal IP presente en el archivo didvoztovoice). Para probar el IVR en local se añaden estas lineas en el contexto internas: exten => 75,1,Answer same => n,Wait(1) same => n,Goto(IVR,s,1) y para incluir el archivo IVR al dialplan, al final del archivo se añade esta linea #include IVR Se guardan los cambios y desde la consola de Asterisk: asterisk -rvvvvvvvvvvvvvv CLI> dialplan reload Ahora desde la extensión 1000, se marca la extensión 75 para probar el IVR desde local. Al momento de crear un IVR, las posibilidades son prácticamente infinitas. Ejemplos: • • •
un IVR que gestione colas de espera diferenciadas por departamento (ventas, compras, asistencia técnica, etc.) un IVR que permita marcar directamente una extensión o, en el caso que no se marque ninguna, envíe la llamada a una operadora. un IVR que avise el llamante que las oficinas están cerradas y que envíe la llamada al buzón de voz
A veces a los IVR están asociados numero geográficos gratuitos para quien llama pero no para quien los utiliza. En estos casos es aconsejable limitar el tiempo máximo de duración de la llamadas entrantes para evitar gastos indeseados. Para este tipo de configuración se utiliza la función TIMEOUT(absolute). Para configurarla se retoma el archivo IVR y en el contexto IVR se sustituye esta linea: exten => s,1,Wait(1) con la que sigue: 215
exten => s,1,Set(TIMEOUT(absolute)=30) Se guardan los cambios y se actualiza el dialplan: asterisk -rvvvvvvvvvvvvvv CLI> dialplan reload Desde la extensión 1000 se marca nuevamente 75 y se escoge escuchar la música en espera. Después de 30 segundos la llamada debería terminar. 8.4 IVR “Clásico” El segundo ejemplo es el clásico IVR que pregunta por el numero de extensión y si no se marca nada, envía la llamada a una operadora. En este caso la frase que se va a grabar es: “Si conoce el numero de la extensión, márquelo ahora, de lo contrario espere en la linea. Una operadora lo atenderá” Para grabar el mensaje se marca desde la extensión 1000, la extensión 6604. Se copia el mensaje audio grabado en la misma carpeta de las demás grabaciones: cd /tmp mv prompt04.wav /var/lib/asterisk/sounds/custom Se construye el nuevo IVR modificando el plan de marcado: nano /etc/asterisk/extensions.conf en el contexto internas se ánade el siguiente bloque: exten => 76,1,Answer same => n,Wait(1) same => n,Goto(IVRCLA,s,1) y al final del archivo se incluye otro archivo que luego se creará: #include IVRCLA Se guardan los cambios y se crea el nuevo archivo:
216
nano /etc/asterisk/IVRCLA Se copian las lineas que siguen: [IVRCLA] exten => s,1,NoOP(IVR Clasico) same => n,Set(TIMEOUT(digit)=4) same => n,Set(TIMEOUT(response)=5) same => n,Wait(1) same => n,Background(custom/prompt04) same => n,WaitExten(5) exten => _100[0-2],1,Dial(SIP/${EXTEN},60) same => n,Hangup exten => i,1,Playback(invalid) same => n,Goto(IVRCLA,s,2) exten => t,1,Dial(SIP/1002,60) same => n,Hangup() La lógica es bastante sencilla. Se presenta al llamante la grabación contenida en el archivo audio prompt04 y se espera que el llamante digite una extensión. Las extensiones admitidas son desde la 1000 hasta la 1002. Si dentro del tiempo definido en la variable (TIMEOUT(response) el llamante no digita nada, la llamada se enviará a la extensión 1002 (exten => t,1,Dial(SIP/1002,60). Se recarga el dialplan: asterisk -rx "dialplan reload" Para realizar una prueba, desde la extensión 1000 se marca el numero 76. IMPORTANTE: aunque no esté documentada en ningún texto, existe también la extensión “e” que puede ser utilizada en lugar de las extensiones “i” “t” y “T” 8.5 Horario Apertura/Cierre Cada oficina y/o empresa tiene su horario de apertura/cierre y no tiene mucho sentido enviar las llamadas a un IVR si luego no hay nadie que las atienda. Es por eso que normalmente se configura el dialplan de forma que envíe las llamadas al IVR o a cualquier parte de dialplan, solamente si se reciben dentro del horario laboral. En Asterisk tenemos distintas formas para configurar este tipo de escenario. La primera, y seguramente la más utilizada, es con la aplicación GotoIfTime. La sintaxis de la aplicación es: asterisk -rvvvvvvvvvvvvvvvvvv CLI> core show application gotoiftime GotoIfTime(times,weekdays,mdays,months[,timezone]?[labeliftrue][:labeliffalse]) 217
Las opciones: • • • • • •
times – rango horario weekdays – días de la semana mdays – días del mes timezone – huso horario labeliftrue – etiqueta del dialplan donde seguir si la declaración es verdadera labeliffalse - etiqueta del dialplan donde seguir si la declaración es falsa
Antes de configurar el dialplan hay que definir los horarios laborales de la empresa/oficina. En este ejemplo se supone que el horario de apertura sea de lunes a viernes de 08:00 a 12:00 y de 14:00 a 18:00. Claramente hay que tener en cuenta todos los días festivos del año que caen entre lunes y viernes. Ahora se puede modificar el dialplan: nano /etc/asterisk/extensions.conf el contexto del numero geográfico [from-voztovoice] se modifica para que quede: [from-didvoztovoice] exten => s,1,Answer same => n,GotoIfTime(08:00-12:00,mon-fri,*,*,/usr/share/zoneinfo/America/Bogota?abierto) same => n,GotoIfTime(14:00-18:00,mon-fri,*,*,/usr/share/zoneinfo/America/Bogota?abierto) same => n,GotoIfTime(*,mon-fri,25,dec,/usr/share/zoneinfo/America/Bogota?cerrado) same => n,GotoIfTime(*,mon-fri,1-15,jul,usr/share/zoneinfo/America/Bogota?cerrado) same => n,Playback(beeperr) same => n,Hangup same => n(abierto),Goto(IVR,s,2) same => n,Hangup same => n(cerrado),Playback(beeperr) same => n,Hangup La lógica de las distintas lineas: •
•
•
Linea 2 – Si la llamada llega entre las 08:00 y las 12:00 de la mañana hora colombiana, de lunes a viernes de cualquier día del mes y de cualquier mes, sigue desde la linea con la etiqueta abierto. En esa linea se envía la llamada al IVR; de lo contrario continua con la prioridad siguiente Linea 3 - Si la llamada llega entre las 14:00 y las 18:00 de la tarde hora colombiana, de lunes a viernes de cualquier día del mes y de cualquier mes, siguen desde la linea con la etiqueta abierto. En esa linea se envía la llamada al IVR; de lo contrario continua con la prioridad siguiente Linea 4 – si la llamada llega a cualquier hora colombiana de lunes a viernes, el día 25 del mes 218
•
de diciembre, sigue desde la linea con la etiqueta cerrado donde se utiliza una locución (que hay que crear) que anuncia al llamante que la oficina está cerrada. En esta linea se han definidos los días de lunes a viernes porque si la navidad cae un sábado o un domingo el sistema ya sabe que la oficina está cerrada (linea 2 y 3); de lo contrario continua con la prioridad siguiente Linea 5 – en esta linea se define los días en que la oficina está cerrada para las vacaciones. En este caso de 1 a 15 de Julio.
Para probar la configuración en local, se modifica la extensión 75 del contexto internas para que quede: exten => 75,1,Answer same => n,GotoIfTime(08:00-12:00,mon-fri,*,*,/usr/share/zoneinfo/America/Bogota?abierto) same => n,GotoIfTime(14:00-18:00,mon-fri,*,*,/usr/share/zoneinfo/America/Bogota?abierto) same => n,GotoIfTime(*,mon-fri,25,dec,/usr/share/zoneinfo/America/Bogota?cerrado) same => n,GotoIfTime(*,mon-fri,1-15,jul,usr/share/zoneinfo/America/Bogota?cerrado) same => n,Playback(beeperr) same => n,Hangup same => n(abierto),Goto(IVR,s,2) same => n,Hangup same => n(cerrado),Playback(beeperr) same => n,Hangup Se guardan los cambios y se actualiza el dialplan: asterisk -rvvvvvvvvvvvvvvvv CLI> dialplan reload Se efectúan las correspondientes pruebas, marcando durante el horario de cierre y de apertura para averiguar que la llamada sea procesada correctamente. La ventaja de este tipo de solución, es que una vez definidas las reglas no hay que preocuparse más de las llamadas entrantes. Las desventajas son que la configuración no es flexible (los horarios no se pueden modificar sin cambiar el dialplan), los días de vacaciones pueden cambiar cada año y hay días festivos que cada año cambian (semana santa, carnaval,etc.) Cuando la oficina es pequeña, es mucho más funcional adoptar otro tipo de solución que permite al cliente decidir cuando activar o desactivar el horario de cierre. En este caso se utiliza la base de datos interna de Asterisk. En esta base de datos es posible guardar las entradas utilizando la sintaxis: familia clave valor. Se abre el dialplan: nano /etc/asterisk/extensions.conf Dentro del contexto interna se pone: 219
exten => *81,1,NoOP same => n,Set(DB(empresaA/horario)=1) same => n,Playback(beep) same => n,Hangup exten => *82,1,NoOP same => n,Set(DB(empresaA/horario)=0) same => n,Playback(beep) same => n,Hangup En el primer bloque se asigna el valor 1 a la familia empresaA, clave horario y significa que la oficina/empresa está abierta. En el segundo bloque a la misma familia y clave se le asigna el valor 0 que significa que la oficina/empresa está cerrada. Luego se utiliza esta configuración para el IVR clásico. Se modifica este bloque: exten => 76,1,Answer same => n,Wait(1) same => n,Goto(IVRCLA,s,1) para que quede: exten => 76,1,Answer same => n,GotoIf($["${DB(empresaA/horario)}" = "1"]?abierto) same => n,Playback(beeperr) same => n,Hangup same => n(abierto),Goto(IVRCLA,s,1) same => n,Hangup En la segunda linea se controla si el valor de la entrada en la base de datos interna de Asterisk es igual a 1. Si así fuera se va a la etiqueta abierto, sino se continua con la siguiente prioridad donde hay que poner el anuncio de los horarios de la oficina/empresa o comunicar el cierre. Se guardan los cambios y se actualiza el dialplan: asterisk -rvvvvvvvvvvvvvv CLI> dialplan reload ¿Cómo funciona? La primera persona que llegue a la oficina marca *81 y de esta forma todas las llamadas entrantes llegarán al IVR clásico. Luego cuando la ultima persona deja la oficina marca *82 para activar la locución de cierre. Esta configuración permite tener horarios más flexibles y además modificar en cualquier momento la hora de apertura/cierre. Para probar la nueva configuración, desde la extensión 1000 se marca *81. En la consola de Asterisk: -- Executing [*81@externas:1] NoOp("SIP/1000-0000001f", "") in new stack 220
-- Executing [*81@externas:2] Set("SIP/1000-0000001f", "DB(empresaA/horario)=1") in new stack -- Executing [*81@externas:3] Playback("SIP/1000-0000001f", "beep") in new stack > 0x7fbbf4082590 -- Probation passed - setting RTP source address to 79.44.192.186:58656 -- Playing 'beep.alaw' (language 'es') > 0x7fbbf4082590 -- Probation passed - setting RTP source address to 79.44.192.186:58656 -- Executing [*81@externas:4] Hangup("SIP/1000-0000001f", "") in new stack == Spawn extension (externas, *81, 4) exited non-zero on 'SIP/1000-0000001f' En la base interna de Asterisk: CLI> database show /empresaA/horario
:1
Ahora llamando la extensión 76 debería contestar el IVR clásico. Si la prueba ha funcionado siempre desde la extensión 1000 se marca *82 para activar el horario de cierre. En la base de datos de Asterisk: CLI> database show /empresaA/horario
:0
Claramente los valore contenidos en la base de datos interna de Asterisk se pueden crear/modificar/borrar desde la consola de la PBX: CLI> database put empresaA horario 1 Updated database successfully CLI> database show /empresaA/horario
:1
La entrada estará nuevamente en 1. Para borrar definitivamente la entrada: CLI> database del empresaA horario Database entry removed. Para conocer los comando disponibles para la base de datos interna de Asterisk: CLI> help database database del Removes database key/value database deltree Removes database keytree/values database get Gets database value database put Adds/updates database value database query Run a user-specified query on the astdb database show Shows database contents database showkey Shows database contents Además de las dos soluciones presentadas en este párrafo, se pueden utilizar otras que se mencionan para que las conozcan:
221
• •
Conectar Asterisk a un calendario (como se verá en el capitulo X) y efectuar las consultas directamente en ese calendario donde se han definido los horarios de apertura/cierre y todos los días festivos. Trabajar con una base de datos donde guardar todos los días festivos y los horarios de apertura/cierre y efectuar consultas directamente desde Asterisk.
222
CAPITULO IX Funcionalidades avanzadas de Asterisk – features.conf El archivo features.conf es donde se configuran las funcionalidades avanzadas de Asterisk que luego se pueden utilizar a lo largo de una llamada.. Estas son: • • • •
Parqueo de las llamadas Transferencia ciega o asistida Captura de las llamadas (Pickup) Grabación de las llamadas
Antes de empezar con la configuración del archivo, una pequeña explicación de cada funcionalidad. Parqueo - El usuario contesta una llamada en su oficina. El llamante solicita una información que el usuario tiene guardada en otra oficina. El usuario parquea la llamada. El sistema le anunciará en que extensión ha sido parqueada. El usuario cuando llega a la otra oficina llama el numero de extensión donde se ha parqueado la llamada y de esta forma vuelve a hablar con el llamante. Transferencia ciega (blindxfer) - A lo largo de una conversación se quiere transferir la llamada a otra extensión. Se presiona la tecla configurada en este archivo y luego el numero de la extensión. La llamada será transferida y el el canal de quien la transfirió será colgado. Transferencia asistida (atxfer) - A lo largo de una conversación se quiere transferir la llamada a otra extensión. Se presiona la secuencia de teclas definidas en este archivo y luego el numero de la extensión donde se quiere transferir la llamada. Se escuchará timbrar la extensión y una vez que el interlocutor conteste, se podrá hablar con él (por ejemplo para anunciar la llamada que se va a transferir). Solamente cuando quien está transfiriendo la llamada colgará, la llamada será efectivamente transferida. Captura de llamada (Pickup) - En una oficina hay cuatro extensiones. Empieza a timbrar una extensión en un escritorio donde en ese momento no hay nadie. Desde otra extensión se presiona la secuencia de teclas definida en este archivo y se captura la llamada de la extensión que estaba timbrando. Grabación de la llamada (automon) – A lo largo de la llamada se presiona la secuencia de teclas definidos en este archivo. Empezará la grabación de la llamada en un dos archivos audio, uno para cada canal. Se vuelve a presionar la misma secuencia de teclas para parar la grabación. (automixmon) A lo largo de una llamada se presiona la secuencia de teclas definidas en este archivo y empezará la grabación de la llamada en un único archivo donde se mezclarán los dos canales audio. Cuando se vuelve a presionar la misma secuencia de teclas, la grabación terminará. 9.1 features.conf A seguir la tabla con los parámetros del archivo y la descripción. En negrita la opción que se utilizará
para cada parámetro. Al final de tabla, la configuración completa del archivo. Parámetro
Descripción
[general]
Inicia la parte general del archivo
parkext =>
700 = numero de extensión donde transferir una llamada para parquearla
parkext_exclusive
yes= las extensiones configuradas para el parqueo de las llamadas podrán ser utilizadas solamente por las extensiones que tendrán acceso al contexto configurado en el parámetro context.
parkpos =>
701-709 = numero de extensiones reservadas para el parqueo de las llamadas
context
contexto para las extensiones de parqueo configuradas en este bloque. Valor: parkedcalls
parkinghints
no = las prioridades Hint para monitorear el estado de las extensiones dedicadas al parqueo se configuraran manualmente en el dialplan. Con yes se crean de forma automática
parkingtime =>
Numero de segundos que quedará parqueada una llamada. Pasado ese tiempo la llamada se transfiere a la extensión definida en el próximo parámetro. Valor 45
comebacktoorigin
yes = la llamada parqueada se transfiere a la extensión que la parqueó. Con no se envía al contexto definido en el parámetro comebackcontext, el numero de extensión será el numero de canal de la extensión que ha parqueado la llamada. Si por ejemplo la llamada ha sido parqueada por una extensión SIP cuyo canal es 0001234, la extensión será SIP_ 0001234, si ese canal no es alcanzable se enviará a la extensión s. Si también este desvío no funciona, se enviará al contexto default, extensión s.
comebackdialtime
El numero de segundos que durará la llamada devuelta a la extensión que ha parqueado la llamada si el parámetro comebacktoorigin se configura en yes. Valor: 30
comebackcontext
Contexto donde se enviara la llamada parqueada si el parámetro comebacktoorigin está configurado en no. Valor: parkedcallstimeout
courtesytone
Locución que se enviará al canal parqueado cuando alguien lo llama o cuando se activa/desactiva la grabación de la llamada Valor beep
parkedplay
Define a quien hay que enviar el courtesytone. Puede ser: • parked (canal parqueado) • caller (quien llama un canal parqueado) • both (ambos)
parkedcalltransfers
Activa o desactiva la secuencia de tonos para transferir la llamada
225
Parámetro
Descripción cuando se trata de una llamada parqueada. Puede ser: • callee (llamado) • caller (llamante) • both (ambos) • no (no permitido)
parkedcallreparking
Activa o desactiva la secuencia de tonos para parquear la llamada cuando se trata de una llamada parqueada. Puede ser: • callee (llamado) • caller (llamante) • both (ambos) • no (no permitido)
parkedcallhangup
Activa o desactiva la secuencia de tonos para terminar una llamada cuando se trata de una llamada parqueada. Puede ser: • callee (llamado) • caller (llamante) • both (ambos) • no (no permitido)
parkedcallrecording
Activa o desactiva la secuencia de tonos para grabar una llamada cuando se trata de una llamada parqueada. Puede ser: • callee (llamado) • caller (llamante) • both (ambos) • no (no permitido)
parkeddynamic
Con yes se crean dinámicamente las extensiones de parqueo. Con no se utilizan solamente las extensiones configuradas con el parámetro parkpos
findslot =>
Con next se parquea la llamada en la siguiente (numéricamente) extensión de parqueo disponible, Con first la primera disponible de la lista.
parkedmusicclass
La clase de música en espera que escuchará el canal que ha sido parqueado. Valor default
transferdigittimeout =>
Numero de segundos de espera entre los dígitos cuando se está transfiriendo una llamada. Valor 5
xfersound
La locución que avisará que la transferencia de llamada asistida ha tenido éxito. Valor beep
xferfailsound
La locución que avisará que la transferencia de llamada no ha tenido éxito. Valor beeperr
pickupexten
Secuencia de tonos para capturar la llamada de una extensión que 226
Parámetro
Descripción está timbrando. Depende también de la configuración de los parámetros callgroup y pickupgroup de cada extensión. Valor *8
pickupsound
La locución que avisará que la captura de llamada ha tenido éxito. Valor beep
pickupfailsound
La locución que avisará que la captura de llamada no ha tenido éxito. Valor beeperr
featuredigittimeout
Tiempo máximo de espera entre los dígitos para activar las funcionalidades definidas después de la etiqueta [featuremap] (en mili segundos) Valor 2000
atxfernoanswertimeout
Tiempo máximo disponible para contestar una transferencia asistida (en segundos). Valor 15
atxferdropcall
Si quien transfiere una llamada con el método “asistido” cuelga antes que la llamada sea transferida completamente, Asterisk devuelve la llamada a quien la estaba transfiriendo. Si está en yes la llamada no se devuelve y se considera terminada. Valor no
atxferloopdelay
Numero de segundos de espera antes de intentar nuevamente devolver la llamada (si atxferdropcall = no). Valor 10
atxfercallbackretries
Numero de veces que se intentará devolver una llamada transferida a quien la transfirió sin éxito. Valor 2
;[parkinglot_empresa2]
Se puede crear más de un bloque de extensiones para parquear las llamadas. Un ejemplo es si quiere diferenciar las llamadas parqueadas por el departamento de ventas, de las llamadas parqueadas por el departamento de compras. La etiqueta define el nuevo bloque y los tres parámetros que siguen el contexto, el numero de las extensiones reservadas y como se van utilizando las extensiones. Para asignar una extensión a un determinado “slot” de parqueo, en la configuración de la extensión en el sip.conf, parámetro parkinglot, se pone el nombre del contexto presente en la linea que sigue. Se dejan las cuatro lineas comentadas.
;context => empresa2 ;parkpos => 801-810 ;findslot => next [featuremap]
A partir de esta etiqueta empieza la configuración de las funcionalidades
blindxfer =>
# = tecla para activar la transferencia ciega
disconnect =>
*0 = secuencia de dígitos para terminar una llamada
automon =>
*1 = secuencia de dígitos para iniciar la grabación de la llamada (en dos archivos audio, uno para cada canal)
227
Parámetro
Descripción
atxfer =>
*2 = secuencia de dígitos para activar la transferencia asistida
parkcall =>
*7 = secuencia de dígitos para parquear una llamada (se puede usar esta secuencia o #700)
automixmon =>
*3 = secuencia de dígitos para iniciar la grabación de una llamada (en un único archivo audio donde se mezclarán los dos canales audio)
[applicationmap]
A partir de esta etiqueta se pueden configurar funcionalidades personalizadas. La sintaxis es: => ,[/], [,[,MOH_Class]] • • • • • • •
test1 =>
FeatureName: El nombre de la funcionalidad; DTMF_sequence: la secuencia de dígitos para activar la funcionalidad; ActivateOn: se define para quien activar la funcionalidad. Los valores son self y peer. Con self la funcionalidad se activa para quien la inicia, con peer para el otro canal; ActivatedBy: Este parámetro define quien tiene acceso a la funcionalidad. Las opciones son: caller (llamante), callee (llamado), both (ambos); Application: La aplicación que se va a ejecutar; AppArguments: Las opciones asociadas a la aplicación; MOH_Class: la clase de música en espera que escuchará el canal libre mientras se ejecuta la funcionalidad en el otro canal.
*9,peer,Playback,tt-monkeys,default = Digitando la secuencia *9 desde un canal, el otro escuchará la locución tt-monkeys mientras el canal que activó la funcionalidad, escuchará la música en espera
Ahora se crea el archivo de configuración features.conf. Se renombra el predefinido: mv /etc/asterisk/features.conf /etc/asterisk/features.conf.old se crea uno nuevo nano /etc/asterisk/features.conf y se copian las lineas que siguen: [general] parkext => 700 parkext_exclusive=yes 228
parkpos => 701-709 parkinghints=no parkingtime => 45 comebacktoorigin=yes comebackdialtime=30 comebackcontext=parkedcallstimeout courtesytone=beep parkedplay=boht parkedcalltransfers=caller parkedcallreparking=caller parkedcallhangup=caller parkedcallrecording=caller parkeddynamic=no findslot => next parkedmusicclass=default transferdigittimeout => 5 xfersound=beep xferfailsound=beeperr pickupexten=*8 pickupsound=beep pickupfailsound=beeperr featuredigittimeout=2000 atxfernoanswertimeout=15 atxferdropcall=no atxferloopdelay=10 atxfercallbackretries=2 ;[parkinglot_empresa2] ;context => empresa2 ;parkpos => 801-810 ;findslot => next [featuremap] blindxfer => # disconnect => *0 automon => *1 atxfer => *2 parkcall => *7 automixmon => *3 [applicationmap] test1 => *9,peer,Playback,tt-monkeys,default Se guardan los cambios. Para volver disponibles estas funcionalidades hay que modificar el plan de marcado. Se va a recoger la configuración del archivo así como se dejó en el capitulo anterior. En negrita aparecen las modificaciones:
229
nano /etc/asterisk/extensions.conf [general] static=yes writeprotect=yse autofallthrough=yse extenpatternmatchnew=yes clearglobalvars=yes [globals] 1000=SIP/1000 voztovoice=SIP/voztovoice marko=IAX2/marko DYNAMIC_FEATURES=test1#blindxfer#automon#disconnect#atxfer#parkcall#automixmon [message] exten => _X.,1,Noop(Mensaje de ${MESSAGE(from)}) same => n,Noop(Mensaje para ${MESSAGE(to)}) same => n,Noop(Texto = ${MESSAGE(body)}) same => n,Set(dest=${EXTEN}) same => n,Messagesend(sip:${EXTEN},${MESSAGE(from)}) same => n,Noop(Estado del mensaje ${MESSAGE_SEND_STATUS}) same => n,GotoIf($["${MESSAGE_SEND_STATUS}" != "SUCCESS"]?failed,s,1) same => n,Hangup [from-didvoztovoice] exten => s,1,Answer same => n,GotoIfTime(08:00-12:00,mon-fri,*,*,/usr/share/zoneinfo/America/Bogota?abierto) same => n,GotoIfTime(14:00-18:00,mon-fri,*,*,/usr/share/zoneinfo/America/Bogota?abierto) same => n,GotoIfTime(*,mon-fri,25,dec,/usr/share/zoneinfo/America/Bogota?cerrado) same => n,GotoIfTime(*,mon-fri,1-15,jul,usr/share/zoneinfo/America/Bogota?cerrado) same => n,Playback(beeperr) same => n,Hangup same => n(abierto),Goto(IVR,s,2) same => n,Hangup same => n(cerrado),Playback(beeperr) same => n,Hangup [internas] exten => *81,1,NoOP same => n,Set(DB(empresaA/horario)=1) same => n,Playback(beep) same => n,Hangup exten => *82,1,NoOP same => n,Set(DB(empresaA/horario)=0) same => n,Playback(beep) 230
same => n,Hangup exten => 50,1,Set(PBX=${ENV(LANG)}) same => n,Noop(Idioma Servidor ${PBX}) same => n,Hangup exten => 75,1,Answer same => n,GotoIfTime(08:00-12:00,mon-fri,*,*,/usr/share/zoneinfo/America/Bogota?abierto) same => n,GotoIfTime(14:00-18:00,mon-fri,*,*,/usr/share/zoneinfo/America/Bogota?abierto) same => n,GotoIfTime(*,mon-fri,25,dec,/usr/share/zoneinfo/America/Bogota?cerrado) same => n,GotoIfTime(*,mon-fri,1-15,jul,usr/share/zoneinfo/America/Bogota?cerrado) same => n,Playback(beeperr) same => n,Hangup same => n(abierto),Goto(IVR,s,2) same => n,Hangup same => n(cerrado),Playback(beeperr) same => n,Hangup exten => 76,1,Answer same => n,GotoIf($["${DB(empresaA/horario)}" = "1"]?abierto) same => n,Playback(beeperr) same => n,Hangup same => n(abierto),Goto(IVRCLA,s,1) same => n,Hangup exten => 100,1,Noop same => n,Dial(SIP/1000&SIP/1001&SIP/1002,30) same => n,Hangup exten => 101,1,Dial(DAHDI/1,30) same => n,Hangup exten => 102,1,Dial(DAHDI/2,30) same => n,Hangup exten => 123,1,Answer same => n,Dumpchan same => n,Playback(hello-world) same => n,Hangup exten => 150,1,Answer same => n,Playback(demo-echotest) same => n,Echo same => n,Playback(demo-echodone) same => n,Hangup exten => 200,1,Answer 231
same => n,Jabbersend(campusvtv,[email protected],Estamos escuchando MP3) same => n,MusicOnHold(mp3,60) same => n,Hangup exten => _100[0-2],1,Gosub(disponible,s,1(${EXTEN})) same => n,Dial(SIP/${EXTEN},45) same => n,Hangup exten => 1234,1,Dial(IAX2/marko,30) same => n,Hangup exten => _66XX,1,Answer() same => n,Wait(2) same => n,Record(/tmp/prompt${EXTEN:2}.wav) same => n,Wait(2) same => n,Playback(/tmp/prompt${EXTEN:2}) same => n,Wait(2) same => n,Hangup() exten => 8000,1,NoOp(Llamada usuario WebRTC) same => n,Dial(SIP/${EXTEN},45) same => n,Hangup exten => _[a-z].,1,Dial(motif/gtalk/${EXTEN}@gmail.com,30,r) same => n,Hangup exten => _8[12456789]XXXXXXX!,1,Dial(SIP/spa3102,45,D(${EXTEN:1})) same => n,Busy(3) same => n,Hangup exten => _9[12456789]XXXXXXX!,1,Dial(DAHDI/R1/${EXTEN:1},45) same => n,Hangup [auten] exten => _00.,1,NoOP same => n,Set(GROUP(numcan)=${CALLERID(num)}) same => n,Set(numcan=${GROUP_COUNT(${CALLERID(num)}@numcan)}) same => n,GotoIf($[${numcan} > ${canales}]?busy) same => n,Authenticate(/var/spool/asterisk/pin.txt,am,4) same => n,Goto(internacio,${EXTEN},1) same => n,Hangup same => n(busy),Playback(all-outgoing-lines-unavailable) same => n,Hangup [subscribe] exten => 1000,hint,SIP/1000 exten => 1001,hint,SIP/1001 232
exten => 1002,hint,SIP/1002 exten => 8000,hint,SIP/8000 exten => marko,hint,IAX2/marko exten => 701,hint,park:701@parkedcalls exten => 702,hint,park:702@parkedcalls exten => 703,hint,park:703@parkedcalls exten => 704,hint,park:704@parkedcalls exten => 705,hint,park:705@parkedcalls exten => 706,hint,park:706@parkedcalls exten => 707,hint,park:707@parkedcalls exten => 708,hint,park:708@parkedcalls exten => 709,hint,park:709@parkedcalls [google-in] exten => s,1,NoOp( Call from Gtalk ) same => n,SendText(Hola,Como te llamas?) same => n,Set(nombre=${JABBER_RECEIVE(campusvtv,${CALLERID(name)},20)}) same => n,SendText(Hola ${nombre}, bienvenido en VozToVoice) same => n,Set(CALLERID(name)=${nombre}) same => n,Wait(2) same => n,SendText(Espera un momento mientras te comunicamos con un operador) same => n,Dial(SIP/1000,30) same => n,Hangup() [from-spa3102] exten => s,1,NoOp same => n,Dial(SIP/1000) same => n,Hangup [from-pstn] exten => s,1,Dial(SIP/1000,45) exten => s,n,Hangup [internacio] exten => _00X.,1,NoOp same => n,Set(GROUP(voip)=voztovoice) same => n,Set(GROUP(salida)=${CALLERID(num)}) same => n,Set(trunksal=${GROUP_COUNT(voztovoice@voip)}) same => n,Set(extsal=${GROUP_COUNT(${CALLERID(num)}@salida)}) same => n,NoOp(Hay ${extsal} llamadas desde la extension ${CALLERID(num)} y ${trunksal} con el proveedor VozToVoice) same => n,Gotoif($[${extsal} > 2 | ${trunksal} > 2]?busy) same => n,Dial(SIP/voztovoice/${EXTEN}) same => n,Hangup same => n(busy),Playback(all-outgoing-lines-unavailable) same => n,Hangup
233
exten => _3XXXXXXXXX,1,Dial(SIP/voztovoice/0057${EXTEN},30) same => n,Hangup exten => _[12,4-9]XXXXXXX,1,Dial(SIP/voztovoice/0057${EXTEN},30) same => n,Hangup exten => _1XXXXXXXXXX,1,Dial(motif/gtalk/+${EXTEN}@voice.google.com) same => n,Hangup exten => _NNXX.,1,Dial(motif/gvoice/+${EXTEN}@voice.google.com) same => n,Hangup [externas] include => internas include => internacio include => parkedcalls [locales] include => internas include => auten include => parkedcalls [disponible] exten => s,1,Set(estado=${DEVICE_STATE(SIP/${ARG1})}) exten => s,n,Gotoif($["${estado}" = "NOT_INUSE"]?5) exten => s,n,Busy exten => s,n,Hangup exten => s,n,Return [failed] exten => s,1,Set(texto=${MESSAGE(body)}) same => n,Set(MESSAGE(body)="El Mensaje - ${texto} - para ${dest} no ha sido enviado") same => n,Set(remit=${CUT(MESSAGE(from),<,2)}) same => n,Set(remit=${CUT(remit,@,1)}) same => n,MessageSend(${remit},CentroMensajes) same => n,Noop(Estado del mensaje ${MESSAGE_SEND_STATUS}) same => n,Hangup #include didvoztovoice #include IVR #include IVRCLA Para que las funcionalidades configuradas en features.conf sean activas hay dos posibles configuraciones: •
definir la variable global DYNAMIC_FEAUTURES y añadirle todas las funcionalidades que se 234
•
han configurado en el archivo features.conf (configuración predefinida). definir en el bloque del dialplan donde se quieran utilizar, una variable de canal tipo: Set(__DYNAMIC_FEATURES=funcionalidad1#funcionalidad2#funcionalidad3). En lugar de funcionalidad1, 2 o 3, se pone el nombre de la funcionalidad que se quiere activar (ejemplo: blindxfer#atxfer#parkcall. El doble guion abajo que aparece significa que la variable aplica al canal que llama y al canal llamado; esto quiere decir que ambos canales pueden activar las funcionalidades definidas si así se decide en el dialplan.
Después de la etiqueta [subscribe] se han añadido nueve líneas para poder monitorear el estado de las extensiones utilizadas para parquear las llamadas. De esta forma siempre se podrá saber cuantas llamadas están parqueadas. Para terminar en las etiquetas [externas] y [locales] se ha añadido el contexto parkedcalls. Todas las extensiones que tengan acceso al contexto externas, además de tener acceso al contexto internas y internacio, tendrán acceso al contexto parkedcalls es decir podrán llamar una extensión parqueada. Lo mismo para las extensiones que tienen acceso al contexto [locales]. Se guardan los cambios y se reinicia Asterisk: /etc/init.d/asterisk restart Desde la consola de Asterisk se pueden ver las funcionalidades activadas. asterisk -rvvvvvvvvvvvv CLI> features show Builtin Feature Default Current --------------------- ------Pickup *8 *8 Blind Transfer # # Attended Transfer *2 One Touch Monitor *1 Disconnect Call * *0 Park Call *7 One Touch MixMonitor *3 Dynamic Feature Default Current --------------------- ------test1 no def *9 Feature Groups: --------------(none) Call parking (Parking lot: default) 235
-----------Parking extension : 700 Parking context : parkedcalls Parked call extensions: 701-709 Parkingtime : 45000 ms Comeback to origin : yes Comeback context : parkedcallstimeout (comebacktoorigin=yes, not used) Comeback dial time : 30 MusicOnHold class : default Enabled : Yes 9.2 Callgroup y Pickupgroup En todas las extensiones SIP configuradas se han definido los siguientes parámetros: callgroup=1 pickupgroup=1 ¿Qué significa? Significa que todas las extensiones pertenecen al grupo de llamadas 1 y pueden capturar las llamadas del grupo de llamadas 1. La secuencia de dígitos para capturar una llamada se acaba de configurar el el archivo features.conf y es *8. Una configuración un poco más compleja podría ser: Extensiones ventas: 1000 - 1001 - 1002 Extensiones soporte: 2000 - 2001 - 2002 Extensiones compras: 3000 - 3001 - 3002 Extensión oficina dirección: 4000 El escenario es que cada empleado de cada departamento pueda capturar las llamadas de los teléfonos del departamento en que trabaja y que desde la oficina de dirección se pueda capturar las llamadas de cualquier extensión de cualquier departamento. Para que esto sea posible, en la configuración de cada extensión se pone: 236
[1000] callgroup=1 pickupgroup=1 [1001] callgroup=1 pickupgroup=1 [1002] callgroup=1 pickupgroup=1 [2000] callgroup=2 pickupgroup=2 [2001] callgroup=2 pickupgroup=2 [2002] callgroup=2 pickupgroup=2 [3000] callgroup=3 pickupgroup=3 [3001] callgroup=3 pickupgroup=3 [3000] callgroup=3 pickupgroup=3 [4000] callgroup=4 pickupgroup=1,2,3 La extensión 4000, con el parámetro pickupgroup configurado con 1,2,3 podrá capturar las llamadas de las extensiones que perteneces a uno de los grupos configurados, es decir: • •
grupo 1 – 1000,1001,1002 grupo 2 – 2000,2001.2002 237
•
grupo 3 – 3000,3001,3002
9.2.1 namedcallgroup y namedpickupgroup El limite de los parámetros callgroup y pickupgroup es que no se pueden configurar más de 64 grupos para cada opción. Con la versión 11.X de Asterisk se ha creado dos nuevos parámetros que permiten superare este limite: • •
namedcallgroup namedpickupgroup
Tomando la configuración ilustrada en el párrafo anterior y aplicándola utilizando los dos nuevos parámetros cambiaría de la siguiente forma: [1000] namedcallgroup=ventas namedpickupgroup=ventas [1001] namedcallgroup=ventas namedpickupgroup=ventas [1002] namedcallgroup=ventas namedpickupgroup=ventas [2000] namedcallgroup=soporte namedpickupgroup=soporte [2001] namedcallgroup=soporte namedpickupgroup=soporte [2002] namedcallgroup=soporte namedpickupgroup=soporte [3000] namedcallgroup=compras namedpickupgroup=compras [3001] namedcallgroup=compras 238
namedpickupgroup=compras [3000] namedcallgroup=compras namedpickupgroup=compras [4000] namedcallgroup=gerencia namedpickupgroup=ventas,soporte,compras 9.3 Aplicación Dial y features.conf En este párrafo se ilustrará como integrar en el dialplan las funcionalidades configuradas en el archivo features.conf utilizando la aplicación Dial. La sintaxis de la aplicación Dial: Dial(Technology/resource[&Tech2/resource2...][,timeout][,options][,URL]): • • • • • •
Dial: el nombre de la aplicación que permite efectuar una llamada Technology: el protocolo o la tecnología usada para efectuar la llamada (ej: SIP, IAX2) resource: el recurso utilizado para efectuar la llamada o el numero de extensión a llamar timeout: define los segundos dentro de los cuales la llamada tiene que ser contestada options: son las opciones que podemos añadir a la aplicación URL: para enviar una dirección Web a la extensión llamada (si el teléfono soporta la funcionalidad)
Algunos ejemplos: exten => 1000,1,Dial(SIP/1000,45) same => n,,Hangup Si se marca la extensión 1000 Asterisk llamará dicha extensión usando el protocolo SIP, esperará 45 segundos. Si la extensión 1000 no contesta dentro de los treinta segundos, Asterisk procesará la línea siguiente del dialplan, es decir terminará la llamada. exten => 00573001000000,1,Dial(SIP/voztovoice/00573001000000,45) same => n,,Hangup En este caso si desde un SoftPhone o IP Phone conectados a la centralita se marca el numero 0057300100000, Asterisk llamará dicho numero usando un proveedor VoIP (en este caso especifico VozToVoice). Esperará una respuesta por 45 segundos y si nadie contesta terminará la llamada. Como tecnología se ha indicado SIP porque VozToVoice usa solo este tipo de protocolo. En el caso de proveedores que utilicen el protocolo IAX2 sería:
239
exten => 00573001000000,1,Dial(IAX2/proveedor00573001000000,45) same => n,,Hangup Para configurar las funcionalidades definidas en el archivo features.conf se tendrá que utilizar unas opciones de la aplicación Dial. exten => 100X,1,Dial(SIP/${EXTEN},45,hH) Las opciones presentes: • •
h: permite al llamado colgar la llamada presionando la secuencia de dígitos definida en features.conf H: permite al llamante colgar la llamada presionando la secuencia de dígitos definida en features.conf
exten => 100X,1,Dial(SIP/${EXTEN},45,kK) • •
k: permite al llamado parquear la llamada presionando la secuencia de dígitos definida en features.conf K: permite al llamante parquear la llamada presionando la secuencia de dígitos definida en features.conf
exten => 100X,1,Dial(SIP/${EXTEN},45,tT) • •
t: permite al llamado transferir la llamada presionando la secuencia de dígitos definida en features.conf T: permite al llamante transferir la llamada presionando la secuencia de dígitos definida en features.conf
exten => 100X,1,Dial(SIP/${EXTEN},45,wW) • •
w: permite al llamado empezar la grabación de la llamada presionando la secuencia de dígitos definida en features.conf. Asterisk, en este caso, creará dos archivos audio, uno por cada canal W: permite al llamante empezar la grabación de la llamada presionando la secuencia de dígitos definida en features.conf. Asterisk, en este caso, creará dos archivos audio, uno por cada canal.
exten => 100X,1,Dial(SIP/${EXTEN},45,xX) • •
x: permite al llamado empezar la grabación de la llamada presionando la secuencia de dígitos definida en features.conf. La diferencia con las opciones w y W es que en este caso los dos canales (llamante y llamado) se grabaran en un único archivo audio X: permite al llamante empezar la grabación de la llamada presionando la secuencia de dígitos definida en features.conf. La diferencia con las opciones w y W es que en este caso los dos canales (llamante y llamado) se grabaran en un único archivo audio
240
Si se quiere, por ejemplo, activar todas estas opciones a la vez, la aplicación Dial aparecerá de esta forma: exten => _100X,1,Dial(SIP/ ${EXTEN},45,hHkKtTwWxX) A seguir se presentarán algunos registros como aparecen en la consola de Asterisk al activar o desactivar las funcionalidades descritas. Para terminar se modifica el dialplan para incluir estas funcionalidades en las llamadas entre extensiones SIP. (en negrita los cambios): nano /etc/asterisk/extensions.conf exten => _100[0-2],1,Gosub(disponible,s,1(${EXTEN})) same => n,Dial(SIP/${EXTEN},45,hHkKtTwWxX) same => n,Hangup Se actualiza el dialplan: asterisk -rvvvvvvvvvvvvv CLI> dialplan reload En el X-Lite se añaden todas las extensiones reservadas para el parqueo de las llamadas. El resultado tienes que ser:
241
IMPORTANTE: Tener mucho cuidado cuando se añade la funcionalidad “t” a una llamada saliente porque de esta forma el llamado tiene la posibilidad de transferir la llamada a cualquier extensión pero también a cualquier numero de teléfono y la llamada la estarían pagando ustedes. Ahora desde la extensión 1001 se marca la extensión 1002 y cuando esta conteste se parquea la llamada (con la secuencia de dígitos *7 o #700). El resultado será:
La extensión 1002 esta parqueada en la extensión 703. Desde el X-Lite, presionando el botón derecho del ratón sobre la linea de la extensión 701 se podrá llamar la extensión parqueada es decir la extensión 1002. Otra prueba que se puede efectuar es grabar la llamada utilizando la secuencia de dígitos *3 para tener un solo archivo audio de toda la conversación.
242
Desde la extensión 1001 se marca nuevamente a las 1002 y cuando esta conteste, se activa la grabación de la llamada digitando *3. En la consola de Asterisk aparecerá: -- Playing 'beep.ulaw' (language 'es') -- User hit '*3' to record call. filename: auto-1318460210-1001-1002 == Begin MixMonitor Recording SIP/1002-0000000a -- Playing 'beep.ulaw' (language 'es') Digitando nuevamente la secuencia *3 terminará la grabación de la llamada: -- User hit '*3' to stop recording call. == MixMonitor close filestream == End MixMonitor Recording SIP/1002-0000000a Se sale de la consola de Asterisk: CLI> quit Se averigua que se haya creado el archivo: ls -l /var/spool/asterisk/monitor/ -rw-r--r-- 1 root root 156204 abr 9 14:08 auto-1397070491-1001-1002.wav Para probar la captura de llamada, se llama desde la extensión 1001 a la extensión 1002 y cuando ésta timbre, desde la extensión 1000 (X-Lite) se digita *8.
Si todo funciona bien, la llamada será capturada por la extensión 1000 que podrá hablar con la extensión 1001. A seguir se presenta un ejemplo de captura de llamada con un teléfono Grandstream GXP2000 y que es valida para la mayoría de los teléfono que soportan las teclas programables. Se accede a la configuración del teléfono vía Web y se selecciona el menú “Configuración Básica”. En la pagina que aparece se configura la primera tecla disponible con los siguientes datos:
Modo tecla: Asterisk PBL Cuenta: Cuenta 1 Nombre: Fulano ID Usuario: 1000 Se esta forma se monitorea el estado de la extensión 1000. Luego se pasa al menú “Cuenta 1” y se 243
configura la extensión 1002 como se realizaría normalmente en un softphone. La parte importante de la configuración de la cuenta, es este parámetro:
Donde se define la secuencia de dígitos para capturar las llamadas. Se guarda la configuración. Ahora desde la extensión 1001 se marca a la extensión 1000. Cuando la extensión 1000 esté timbrando, la tecla programada en el teléfono Grandstream empezará a parpadear. Si se presiona en la consola de Asterisk aparecerá: NOTICE[1832]: chan_sip.c:20792 handle_request_invite: Call from '1002' to extension '*81000' rejected because extension not found in context 'internas'. Parece que la captura de la llamada no tuvo éxito porque hace falta algo en el dialplan. Se abre el archivo: nano /etc/asterisk/extensions.conf y en el contexto internas se añade: exten => *8XXXX,1,Pickup(${EXTEN:2}) same => n,Hangup De esta forma se podrá capturar las llamadas utilizando la aplicación Pickup. Se guardan los cambios y se actualiza el dialplan: asterisk -rvvvvvvvvvv CLI> dialplan reload Se repite la prueba anterior y se verá que ahora se logra capturar correctamente la llamada cuando la extensión 1000 está timbrando. 9.4 Las aplicaciones Park y ParkAndAnnounce La aplicación Park permite parquear una extensión directamente desde el dialplan. Un ejemplo de su utilizo es cuando se llama una extensión y esta resulta ocupada. En lugar de terminar la llamada o enviarla al buzón de voz, puedes ser útil parquearla unos cuantos segundos, pasados los cuales, devolver la llamada a la extensión que se encontraba ocupada esperando que ya esté libre. La sintaxis de la aplicación es: Park([timeout][,return_context[,return_exten[,return_priority[,options[,parking_lot_name]]]]]) •
timeout – el tiempo, en mili segundos, que quedará parqueada la llamada 244
• • • •
•
return_context – contexto donde se enviará la llamada una vez que hayan pasado los segundos definidos en el parámetro timeout return_exten – numero de extensión donde se enviará la llamada parqueda return_priority - numero de prioridad donde se enviar la llamada parqueada options: • r – envía a la llamada parqueada la señal de timbrado en lugar de la música de espera • R – escoge de forma aleatoria la extensión donde parquear la llamada • s – no anuncia el numero de extensión donde se ha parqueado la llamada. parking_lot_name – En nombre del parkinglot a utilizar para parquear la llamada.
Ahora para verla funcionar se modifica el dialplan: nano /etc/asterisk/extensions.conf se modifica este bloque [disponible] exten => s,1,Set(estado=${DEVICE_STATE(SIP/${ARG1})}) exten => s,n,Gotoif($["${estado}" = "NOT_INUSE"]?5) exten => s,n,Busy exten => s,n,Hangup exten => s,n,Return para que quede: [disponible] exten => s,1,Set(estado=${DEVICE_STATE(SIP/${ARG1})}) exten => s,n,Gotoif($["${estado}" = "NOT_INUSE"]?8) exten => s,n,Gotoif($["${estado}" = "INUSE"]?park) exten => s,n,Busy exten => s,n,Hangup exten => s,n(park),Park(30000,externas,${ARG1},1,rs,default) exten => s,n,Hangup exten => s,n,Return Se guardan los cambios y se actualiza el dialplan: asterisk -rx "dialplan reload" Ahora desde la extensión 1000 se marca a la extensión 1001. Se contesta la llamada. Desde la extensión 1002 se marca la extensión 1000. Como estará ocupada, la llamada se parqueará por 45 segundos. La extensión 1000 termina la llamada con la extensión 1001. Después de unos segundos recibe la llamada de la extensión 1002 (cuando termina el tiempo de parqueo de 30 segundos). La aplicación ParkAndAnnounce es parecida a la primera pero se diferencia porque la llamada 245
parqueada se anuncia a una extensión que se define a priori. La sintaxis: ParkAndAnnounce(announce[:announce1[:...]],timeout,dial[,return_context]) • • • •
announce – se utiliza una locución para anunciar el parqueo. Si se utiliza la palabra PARKED, esta será sustituida por el anuncio de la extensión donde se ha parqueado la llamada timeout – tiempo, en segundos, antes de enviar la llamada parqueada al contexto indicado en el parámetro return_context. Si no se indica ningún contexto, la llamada volverá a la extensión de donde se parqueó, prioridad + 1 dial – se utiliza la aplicación Dial para llamar una extensión y anunciar la llamada parqueada return_context – contexto donde enviar la llamada después que pasen los segundos indicados en el parámetro timeout
Un ejemplo practico para utilizar esta aplicación es cuando se intenta transferir una llamada a la operadora pero esta está ocupada, pues se transfiere a otra extensión donde se parquea y al mismo tiempo se anuncia la extensión de parqueo a la operadora. Para la prueba se modifica el dialplan: nano /etc/asterisk/extensions.conf en el contexto internas se añade: exten => 175,1,NoOp same => n,Parkandannounce(vm-youhave:vm-extension:PARKED,60,SIP/1000,externas,175,3) same => n,Playback(vm-nobodyavail) same => n,Hangup Se guardan los cambios y se actualiza el dialplan: asterisk -rvvvvvvvvvvvvvvvvvv CLI> dialplan reload Ahora desde la extensión 1002 se llama la extensión 1001; se contesta la llamada y desde la extensión 1001 se transfiere a la extensión 175 utilizando la tecla numero. La llamada será parqueada por 60 segundos y al mismo tiempo se anunciará a la extensión 1000 que hay una llamada parqueada y el numero de extensión donde se parqueó. Si la extensión 1000 no llama el numero de extensión donde se parqueó la llamada dentro de 60 segundos, la llamada parqueada volverá al contexto externas, extensión 175, prioridad 3 donde se le anunciará que no hay nadie disponible que pueda atender la llamada e se colgará.
246
9.5 La aplicación FollowMe (Sígueme) Un empleado tiene que ausentarse de su oficina por unas cuantas horas y quiere que a partir de ese momento todas las llamadas con destino su extensión, sean desviadas a una serie de números que el ha definido anteriormente. Además por cada llamada desviada quiere saber quien lo está llamando y tener la posibilidad de rechazar la llamada. Para este tipo de escenario, se utiliza la aplicación FollowMe (Sígueme). Esta aplicación se compone de dos partes: • •
el archivo de configuración followme.conf la aplicación followme
Se inicia con la configuración del archivo followme.conf. En la tabla a seguir los distintos parámetros presentes en el archivo con una breve explicación. En negrita el valor que se utilizará para cada parámetro: Parámetro
Descripción
[general]
Etiqueta que da inicio a la configuración general del archivo
featuredigittimeout=>
El tiempo, en mili segundos, que tendrá el llamado para presionar los dígitos para aceptar o rechazar la llamada entrante. Valor: 5000
takecall=>
1 = la tecla que tendrá que presionar el llamado para aceptar la llamada
declinecall=>
2 = la tecla que tendrá que presionar el llamado para rechazar la llamada
call_from_prompt=>followme/call-from norecording_prompt=>followme/no-recording options_prompt=>followme/options pls_hold_prompt=>followme/pls-hold-while-try status_prompt=>followme/status sorry_prompt=>followme/sorry
Las locuciones audio predefinidas de la aplicación
[1000]
Desde esta etiqueta inicia la configuración de desvío para la extensión 1000
musicclass=>
default – la música de espera predefinida que escuchará el llamante mientras se intenta localizar el llamado.
context=>
El contexto que se utilizará para efectuar las llamadas para localizar el llamado: Valor: externas
number=>
A partir de este parámetro se indica la lista de números a llamar. La sintaxis es: numero1&numero2&numero3,tiempo,orden 247
Parámetro
Descripción Si se indica más de un numero en la misma linea, todos los números indicados se marcarán al mismo tiempo. Si se indican los números uno por linea se marcarán de forma secuencial. En este caso se van a configurar dos: 0057111111111 y 00573101234567 es decir un fijo y un celular
[1001]
Si se quiere configurar el servicio para la extensión 1001, se inicia con esta etiqueta y se siguen las mismas pautas de la configuración para la extensión 1000.
Se renombra el archivo predefinido: mv /etc/asterisk/followme.conf /etc/asterisk/followme.conf.old y se crea uno nuevo: nano /etc/asterisk/followme.conf Se copian las siguientes lineas: [general] featuredigittimeout=> 5000 takecall=> 1 declinecall=> 2 call_from_prompt=>followme/call-from norecording_prompt=>followme/no-recording options_prompt=>followme/options pls_hold_prompt=>followme/pls-hold-while-try status_prompt=>followme/status sorry_prompt=>followme/sorry [1000] musicclass=> default context=> externas number=> 0057111111111,15 number => 00573101234567,15 Con esta configuración, si oportunamente configurado en el dialplan, primero se llamará el numero 0057111111111 por 15 segundos y luego el numero 00573101234567 por otros 15 segundos. Si nadie contesta, se le anunciará al llamante que no se ha podido localizar el destinatario de la llamada. En este 248
caso el timeout de 15 segundos no representa el tiempo que tiene el llamado para contestar sino el tiempo total que tiene el llamado para aceptar la llamada (presionando 1 una vez que haya contestado). Antes de guardar los cambios, se personalizan los dos números que aparecen en el archivo. Ahora para utilizar esta funcionalidad hay que configurar la aplicación FollowMe en el dialplan. Hay dos formas de hacerlo. Activarla cada vez que la extensión no conteste, o solamente si la extensión la ha activado anteriormente. La primera opción puede generar transferencias indeseadas ya que se puede verificar que la extensión no conteste porque no alcanza y/o porque está hablando con otra extensión. En el ejemplo a seguir se permitirá al usuario activar y desactivar la funcionalidad en cualquier momento. Esto se realiza utilizando la base de datos interna de Asterisk. Se abre el dialplan: nano /etc/asterisk/extensions.conf y en el contexto internas se añaden los dos bloques que siguen: ;Activar FollowMe exten => *00,1,NoOp same => n,Set(DB(FM/${CALLERID(num)})=1) same => n,Playback(beep) same => n,hangup ;Desactivar FollowMe exten => *01,1,NoOp same => n,Set(DB(FM/${CALLERID(num)})=0) same => n,Playback(beep) same => n,hangup Con el primer bloque se crea una entrada en la base de datos interna de Asterisk y se asigna a esa entrada el valor 1. Con el segundo bloque se asigna a la misma entrada el valor 0. El valor uno significa funcionalidad activada y el valor 0 significa funcionalidad desactivada. Desde la extensión 1000 se marca *00 para activar la funcionalidad. En la base de datos interna de Asterisk, aparecerá: /FM/1000
:1
Marcando *01 el resultado será: /FM/1000
:0
Ahora falta utilizarla en las llamadas entre extensiones: nano /etc/asterisk/extensions.conf 249
exten => _100[0-2],1,Gosub(disponible,s,1(${EXTEN})) same => n,Dial(SIP/${EXTEN},45,hHkKtTwWxX) same => n,Hangup se modifica para que quede: exten => _100[0-2],1,Gosub(disponible,s,1(${EXTEN})) same => n,GotoIf($[${DB(FM/${EXTEN})} = 1]?FM) same => n,Dial(SIP/${EXTEN},45,hHkKtTwWxX) same => n,Hangup same => n(FM),FollowMe(${EXTEN},n) same => n,Hangup Se guardan los cambios, se actualiza el dialplan y la aplicación FollowMe: asterisk -rvvvvvvvvvvvvvv CLI> dialplan reload CLI> module reload app_followme.so Se vuelve a activar la funcionalidad marcando *00 desde la extensión 1000. Luego desde la extensión 1001 se llama la extensión 1000. Empezará el desvío a los dos números indicados en el archivo de configuración followme.conf. Si se quiere que los dos números sean marcados a la vez, se abre el archivo followme.conf: nano /etc/asterisk/followme.conf y se modifica este bloque: [1000] musicclass=> default context=> externas number=> 0057111111111,15 number => 00573101234567,15 para que quede: [1000] musicclass=> default context=> externas number=> 0057111111111&00573101234567,20 Se guardan los cambios y se vuelve a entrar en la consola de Asterisk: asterisk -rvvvvvvvvvvvvvvvv 250
se recarga la configuración del FollowMe: CLI> module reload app_followme.so y se marca nuevamente desde la extensión 1001 a la extensión 1000. En este caso los dos números timbrarán contemporáneamente. Algunas opciones que se pueden utilizar con la aplicación FollowMe: • • • •
a – antes de empezar a localizar el llamado, el llamante tiene que grabar su nombre d – deshabilita la locución que anuncia al llamante que se está intentando localizar el llamado n – si el sistema no logra localizar el llamado, envía al llamante una locución anunciando que no pudo localizar el llamado s – anuncia al llamante que la persona llamada no se encuentra en su escritorio y que el sistema intentará localizarla.
La desventaja de esta solución es que el usuario no puede modificar por su cuenta los números de desvío ya que hay que definirlos anteriormente en el archivo followme.conf. Una alternativa más “cómoda” desde el punto de vista del usuario, es que éste decida cada vez donde desviar la llamada. En este caso el dialplan cambiaría de la siguiente manera: nano /etc/asterisk/extensions.conf en el contesto internas se añaden los siguientes bloques: exten => _#.,1,NoOp same => n,Set(DB(FW/${CALLERID(num)})=${EXTEN:1}) same => n,Playback(beep) same => n,hangup exten => #,1,NoOp same => n,NoOp(${DB_DELETE(FW/${CALLERID(num)})}) same => n,Playback(beep) same => n,hangup Con el primero se configura el desvío, con el segundo se borra. Luego en el bloque de las llamadas entre extensiones: exten => _100[0-2],1,Gosub(disponible,s,1(${EXTEN})) same => n,GotoIf($[${DB(FM/${EXTEN})} = 1]?FM) same => n,Dial(SIP/${EXTEN},45,hHkKtTwWxX) same => n,Hangup same => n(FM),FollowMe(${EXTEN},s) same => n,Hangup Se modifica para que quede:
251
exten => _100[0-2],1,NoOp(prueba transferencia) same => n,GotoIf(${DB_EXISTS(FW/${EXTEN})}?fw) same => n,Dial(SIP/${EXTEN},45,hHkKtTwWxX) same => n,Hangup same => n(fw),Set(fw=${DB(FW/${EXTEN})}) same => n,Goto(externas,${fw},1) same => n,Hangup Una explicación. En la linea 2 se averigua si existe una entrada en la base de datos interna para la extensión llamada. Si existe significa que esa extensión ha configurado el desvío. En ese caso se “salta” a la linea con la etiqueta (fw) donde se asigna a la variable fw el numero de desvío configurado. Luego en la linea 6 se envía la llamada al contexto [externas], extensión igual al numero de desvío, prioridad 1, es decir se marca el numero de desvío configurado Se guardan los cambios y se recarga el dialplan: asterisk -rvvvvvvvvvvvvvvvvvvvvvv CLI> dialplan reload Ahora desde la extensión 1000 se marca #numerodesvío; ejemplo: #00573101234567. En la base de datos interna de Asterisk aparecerá: CLI> database show /FW/1000
: 00573101234567
El desvío para la extensión 1000 ha sido activado. Ahora si desde la extensión 1001 se marca a la extensión 1000. Como el desvío está activado, el sistema llamará al numero 00573101234567: Dial("SIP/1001-0000000d", "SIP/justvoip/00573101234567") Cuando la extensión 1000 quiere borrar el desvío, marcará #: Si se busca en la base de datos de Asterisk: CLI> dabatase show la configuración de desvío ya no estará presente. Una vez efectuadas todas las pruebas del caso, se sale de la consola de Asterisk: CLI> quit Se abre el dialplan: nano /etc/asterisk/extensions.conf
252
y se vuelve a modificar este bloque: exten => _100[0-2],1,NoOp(prueba transferencia) same => n,GotoIf(${DB_EXISTS(FW/${EXTEN})}?fw) same => n,Dial(SIP/${EXTEN},45,hHkKtTwWxX) same => n,Hangup same => n(fw),Set(fw=${DB(FW/${EXTEN})}) same => n,Goto(internacio,${fw},1) same => n,Hangup para que quede: exten => _100[0-2],1,Gosub(disponible,s,1(${EXTEN})) same => n,Dial(SIP/${EXTEN},45,hHkKtTwWxX) same => n,Hangup y el bloque: [disponible] exten => s,1,Set(estado=${DEVICE_STATE(SIP/${ARG1})}) exten => s,n,Gotoif($["${estado}" = "NOT_INUSE"]?8) exten => s,n,Gotoif($["${estado}" = "INUSE"]?park) exten => s,n,Busy exten => s,n,Hangup exten => s,n(park),Park(30000,externas,${ARG1},1,rs,default) exten => s,n,Hangup exten => s,n,Return para que quede: [disponible] exten => s,1,Set(estado=${DEVICE_STATE(SIP/${ARG1})}) exten => s,n,Gotoif($["${estado}" = "NOT_INUSE"]?5) exten => s,n,Busy exten => s,n,Hangup exten => s,n,Return Se guardan los cambios y se actualiza el dialplan: asterisk -rvvvvvvvvvvvvvvvvvvv CLI> dialplan reload CLI> quit
253
Capitulo X Asterisk y los calendarios Asterisk puede ser integrado con distintos formatos de calendarios. Los formatos soportados son: • •
• •
iCalendar: es un estándar Internet (RFC5546) que ha sido utilizado por primera vez por Apple con su aplicación iCal CalDAV: es un estándar Internet (RFC4791) que permite a un cliente acceder a la información de eventos programados presentes en un servidor. Es una extensión del estándar Internet WebDAV (RCF 4918). Para el formato de los datos se apoya a iCalendar. Actualmente es utilizado por muchas aplicaciones, entre ellas, Google Calendar, Zimbra, Yahoo! Calendar y Thunderbird de Mozilla Fundation. MS Exchange: utilizado por Microsoft Exchange 2003 Ms Exchange Web Services: utilizado por Exchange 2007 y superiores.
Esto significa que Asterisk, oportunamente configurado, puede interaccionar con estos formatos de Calendario. Los módulos que se encargan de esta integración son: asterisk -rvvvvvvvvvvvvv CLI> module show like res_calendar Module Description Use Count res_calendar.so Asterisk Calendar integration 4 res_calendar_caldav.so Asterisk CalDAV Calendar Integration 0 res_calendar_ews.so Asterisk MS Exchange Web Service Calenda 0 res_calendar_icalendar.so Asterisk iCalendar .ics file integration 0 res_calendar_exchange.so Asterisk MS Exchange Calendar Integratio 0 5 modules loaded Para que estén activados en Asterisk, hay que compilar las siguientes dos librerías: • •
Neon libical
Al momento de ejecutar, desde la carpeta de las fuentes de Asterisk, el comando make menuselect, se averigua que los módulos estén habilitados:
10.1 calendar.conf El archivo para la configuración de los calendarios es calendar.conf y se encuentra en la carpeta /etc/asterisk. En este archivo se puede configurar más de un calendario y cada uno será identificado por una etiqueta inicial. Para crear un entorno real, se simulará la conexión al calendario de Google, que se puede activar utilizando una cuenta Gmail registrada. A seguir la tabla con los parámetros de configuración. En negrita, la opción que se utilizará para cada parámetro. Al final de la tabla, la configuración completa del archivo.
Parámetro
Descripción
[campusvtv]
Etiqueta que permite identificar el calendario que se está configurando. Personalizar
type
Puede ser: • iCal • caldav • exchange (Microsoft Exhange 2003) • ews ( Microsoft Exchange 2007 y superiores) Para Google Calendar el tipo es ical
url
La URL para conectarse al calendario. En el caso de GoogleCalendar la sintaxis es: https://www.google.com/calendar/dav/[email protected]/events/ Personalizar fulano@gmail con su cuenta de Google
user
Nombre usuario Personalizar
secret
la contraseña del usuario Google
refresh
Cada cuantos minutos consultar el Calendario de Google para actualizar los datos en Asterisk. Valor: 10
timeframe
Por cada consulta extraer los eventos que tendrán lugar en los próximos N minutos. Este valor tiene que ser mayor del parámetro refresh. Valor: 180 (3 horas)
autoreminder
Este parámetro anula cualquiera notificación configurada para un evento y la cambia por el valor indicado en minutos. Valor 10
channel
Cuando falten los N minutos definidos en el parámetro autoreminder, es posible enviar una llamada a la extensión indicada en este parámetro. La sintaxis es: Tecnología/numero. Suponiendo que este calendario es asociado a la extensión 1000, se pone SIP/1000. A partir de los próximos parámetros podemos definir dos comportamientos distintos cuando la extensión 1000 conteste la llamada: • enviar la llamada a un contexto, extensión definida
gmail.
En
este
ejemplo:
[email protected]
256
Parámetro
Descripción •
ejecutar una aplicación y definir sus parámetros.
context extension
nombre del contexto: calendario numero de extensión: cal
app appdata
aplicación a ejecutar cuando la extensión conteste: Playback opciones para la aplicación: demo-congrats
waittime
este ultimo parámetro define el tiempo (en segundos) que tendrá la extensión 1000 para contestar la llamada. Valor 45
Con estos parámetros se configura el primer calendario. Como configuración predefinida, cuando la extensión 1000 conteste, se utilizarán los dos parámetros context/extension. Primero se crea una copia del archivo predefinido: mv /etc/asterisk/calendar.conf /etc/asterisk/calendar.conf.old y se crea uno nuevo: nano /etc/asterisk/calendar.conf [campusvtv] type=ical url=https://www.google.com/calendar/dav/[email protected]/events/ [email protected] secret=password refresh=10 timeframe=180 autoreminder=10 channel=SIP/1000 context=calendario extension=cal waittime=45 ;app= Playback ;appdata=demo-conrats IMPORTANTE: Personalizar los datos de la etiqueta inicial, el parámetro url, el parámetro user y el parámetro secret con los datos de su cuenta Google. Se guardan los cambios. Ahora se entra en la pagina del calendario de Google y se van añadiendo una serie de eventos para el día en que se está configurando este modulo. En este ejemplo se han creado tres:
257
Se entra en la consola de Asterisk: asterisk -rvvvvvvvvvvvvvvvvvvvv Se recarga el modulo calendario: CLI> module reload res_calendar.so Si aparece esta advertencia: Apr 9 15:25:43] WARNING[2081]: res_calendar_icalendar.c:150 fetch_icalendar: Unable to retrieve iCalendar 'campusvtv' from 'https://www.google.com/calendar/dav/[email protected]/events/': Could not read status line: connection was closed by server [Apr 9 15:25:43] WARNING[2081]: res_calendar_icalendar.c:442 ical_load_calendar: Unable to parse iCalendar 'campusvtv' [Apr 9 15:25:43] ERROR[2081]: res_calendar_icalendar.c:330 icalendar_update_events: The iCalendar has not been parsed! significa que la configuración no está funcionando. ¿Por qué? Primero se descarta que sea un problema de la configuración de los datos en el archivo calendar.conf. Se abre una ventana del navegador y se pega la url que aparece en el archivo calendar.conf. En este caso (personalizar [email protected] con su cuenta Google): https://www.google.com/calendar/dav/[email protected]/events/ Aparecerá:
258
Se pone el nombre de usuario de Google y la contraseña. Se termina presionando el botón “Iniciar sesión”. Si la conexión tiene éxito aparecerá una ventana de descarga que pedirá de guardar un archivo de texto:
El archivo descargado contendrá todos los datos del calendario. Esto significa que los datos de configuración del archivo calendar.conf son correctos. Si se mira el parámetro url del archivo, se notará que empieza con https, esto quiere decir que se basa en una conexión segura y que la librería que permite la conexión CalDAV (neon) debe implementar el protocolo SSL. ¿Será que Neon no se ha compilado con el soporte SSL? Se entra en la carpeta de las fuentes de neon: cd /usr/src/neon-0.30.0 y se ejecuta nuevamente un configure: ./configure
259
Cuando el comando termine:
Por defecto neon no se compila con el soporte SSL, pues para solucionar el problema hay que volver a compilar neon y luego Asterisk: make distclean ./configure --prefix=/usr --with-ssl=openssl --libdir=/usr/lib64
Ahora si se compiló con el soporte SSL. Se termina la compilación e instalación: make make install Ahora hay que volver a compilar Asterisk. Primero se para el servicio: service asterisk stop Se entra en la carpeta de las fuentes: cd /usr/src/asterisk-11.17.1 se borra la compilación anterior: make distclean se vuelve a compilar: ./configure --libdir=/usr/lib64 Se necesita volver a entrar en la interfaz gráfica para deseleccionar El parámetro BUILD_NATIVE en el menú “Compiler Flags”
260
make menuselect
Se guardan los cambios y se vuelve a compilar: make make install Como siempre aparecerá la siguiente advertencia: WARNING WARNING WARNING Your Asterisk modules directory, located at /usr/lib64/asterisk/modules contains modules that were not installed by this version of Asterisk. Please ensure that these modules are compatible with this version before attempting to run Asterisk. app_meetme.so app_mysql.so app_saycountpl.so cdr_mysql.so codec_g729-ast110-gcc4-glibc-x86_64-barcelona.so format_mp3.so res_config_mysql.so WARNING WARNING WARNING make config Terminada esta operación, se inicia nuevamente Asterisk: service asterisk start Se entra en la consola y se recarga nuevamente el modulo Calendario: asterisk -rvvvvvvvvvvvvv 261
CLI> module reload res_calendar.so Si no aparecen errores y/o advertencias significa que esta vez la conexión al calendario de Google ha tenido éxito y se debería poder ver algunos eventos programados. CLI> calendar show calendars Con este comando aparecerá la lista de calendarios configurados y el estados de cada uno: Calendar -------campusvtv
Type Status --------ical free
Con este comando: CLI> calendar show calendar campusvtv se pueden ver los eventos programados en los próximos 180 minutos (parámetro timeframe=180). Si no aparecen es porque todavía Asterisk no ha actualizado la información ya que lo hace cada 10 minutos (parametro refresh=10). Modificar campusvtv con el nombre de su calendario.
262
Aparece el evento de las 7:30 y el evento de las 9:30. El evento programado a las 11 no aparece porque el modulo está configurado para que lea los eventos de los próximos 180 minutos. Ahora para que la llamada llegue a la extensión 1000 hay que crear el contexto calendario y la extensión cal (como configurado en el archivo calendar.conf). ¿Cómo se construye el dialplan para que la extensión 1000 pueda saber que cita está para iniciar?. Hay que instalar un sistema de texto a voz que lea un texto y lo transforme en audio. Lefteris Zafiris, ha desarrolado un AGI que se conecta al sistema de texto a voz de Google y transforma un texto en audio. Aunque la parte de los AGI se verá de manera más detallada en el capitulo XIX del libro, en este caso se implementará esta solución. Para que el AGI funcione, los requisitos son: • • • • •
Paquete Perl Paquete perl-libwww sox mpg123 el servidor donde está instalado Asterisk debe tener acceso a Internet 263
Como sox ya está instalado, se instalan los paquetes de perl: yum install perl perl-libwww-perl -y se descarga, compila e instala mpg123: cd /usr/src wget http://downloads.sourceforge.net/project/mpg123/mpg123/1.22.1/mpg123-1.22.1.tar.bz2 tar -xf mpg123-1.22.1.tar.bz2 cd mpg123-1.22.1 ./configure --prefix=/usr --libdir=/usr/lib64 make make install Se prueba si funciona: mpg123 Si sale este error: mpg123: error while loading shared libraries: libmpg123.so.0: cannot open shared object file: No such file or directory Se crea un enlace simbólico del archivo en la carpeta de las librerías 64bit: ln -s /usr/lib/libmpg123.so.0 /usr/lib64/libmpg123.so.0 Se ejecuta nuevamente el comando: mpg123 You made some mistake in program usage... let me briefly remind you: High Performance MPEG 1.0/2.0/2.5 Audio Player for Layers 1, 2 and 3 version 1.19.0; written and copyright by Michael Hipp and others free software (LGPL) without any warranty but with best wishes Ya está funcionando. Ahora se puede descargar el archivo que contiene el AGI: cd /usr/src wget http://www.voztovoice.org/campus/pbx18/asterisk-googletts-0.6.tar.gz Se descomprime: tar -xf asterisk-googletts-0.6.tar.gz
264
Se entra en la carpeta creada: cd asterisk-googletts-0.6 Por defecto Asterisk busca los AGI en la carpeta /var/lib/asterisk/agi-bin. Por eso se copia el AGI en esa carpeta y se vuelve ejecutable: cp googletts.agi /var/lib/asterisk/agi-bin/ chmod +x /var/lib/asterisk/agi-bin/googletts.agi Por ultimo se modifica el dialplan: nano /etc/asterisk/extensions.conf y antes del contexto internas se crea el nuevo contexto: [calendario] exten => cal,1,NoOp(Llamada desde el calendario) same => n,Agi(googletts.agi,"${CALENDAR_EVENT(summary)}.",es) same => n,Agi(googletts.agi,"a las ${STRFTIME(${CALENDAR_EVENT(start)},,%H:%M)}.",es) same => n,Wait(1) same => n,Playback(goodbye) same => n,Hangup En la segunda y tercera linea se inicia el AGI y se leen las variables $ {CALENDAR_EVENT(summary)} y ${CALENDAR_EVENT(start)} que contienen el titulo del evento y la hora de inicio respectivamente. Como la hora se lee en el formato EPOCH, hay que transformarla en el formato de hora y minutos a través de la función STRFTIME Se recarga el dialplan: asterisk -rx "dialplan reload" 10 minutos antes del inicio del evento, Asterisk llamará la extensión 1000 y cuando esta conteste, le anunciará el tipo de evento y la hora en que va a iniciar. La llamada llegará normalmente con este CALLERID:
Si en lugar de ese CallerID, se quiere obtener una información acerca del evento que va a iniciar, se 265
abre el archivo de configuración del calendario: nano /etc/asterisk/calendar.conf y al final se añade esta linea (funcionalidad disponible a partir de la versión 11.X de Asterisk: setvar = CALLERID(name)=${CALENDAR_EVENT(summary)} Con el parámetro servar es posible asociar al CALLERID (nombre y/o numero) un dato relacionado con el evento que va a iniciar. Posibles valores: • • • • • • • • •
summary – El titulo del evento. description – La descripción del evento organizer – El organizador del evento location – Sitio donde tiene lugar el evento calendar – Nombre del calendario asociado con el evento uid – numero único que identifica el evento start – Fecha y hora de inicio de un evento end – Fecha y hora en que termina el evento busystate – El estado configurado para el evento
Se guardan las modificaciones y desde la consola de Asterisk, se recarga el modulo del calendario: asterisk -rvvvvvvvvvvvvvv CLI> module reload res_calendar.so Cuando faltarán 10 minutos para el próximo evento programado y se recibirá la llamada de notificación, en X-Lite aparecerá:
prueba el titulo del evento programado en el calendario (summary).
266
IMPORTANTE: Si por cualquier motivo no se escucha el Audio del AGI hay que seguir estos pasos: Instalar el Perl-CPAN: yum install perl-CPAN -y y luego el modulo CGI::Util: perl -MCPAN -e "install CGI::Util" Contestar yes a todas las preguntas. Volver a probar el Agi googletts.agi: make test had returned bad status, won't install without force Se continua con: perl -MCPAN -e "install DBM::Deep" Luego: perl -MCPAN -e "install CGI::Util" Cuando el evento iniciará en el calendario aparecerá el estado ocupado: asterisk -rvvvvvvvvvvvvvv CLI> calendar show calendars Calendar -------campusvtv
Type Status --------ical busy
Esto es así siempre y cuando en la configuración del evento en el Calendario se haya configurado la opción:
Para saber que tipo de informaciones se pueden conocer acerca de un evento programado el comando es:
267
asterisk -rvvvvvvvvvvvvvv CLI> core show function CALENDAR_EVENT -= Info about function 'CALENDAR_EVENT' =[Synopsis] Get calendar event notification data from a notification call. [Description] Whenever a calendar event notification call is made, the event data may be accessed with this function. [Syntax] CALENDAR_EVENT(field) [Arguments] field summary - The VEVENT SUMMARY property or Exchange event 'subject' description - The text description of the event organizer - The organizer of the event location - The location of the eventt categories - The categories of the event priority - The priority of the event calendar - The name of the calendar associated with the event uid - The unique identifier for this event start - The start time of the event end - The end time of the event busystate - The busy state of the event 0=FREE, 1=TENTATIVE, 2=BUSY Todos los parámetros bajo la etiqueta [Arguments] se pueden extraer del calendario y utilizar en el dialplan. Para conocer todas las funciones disponibles en Asterisk para trabajar con los calendarios: CLI> core show function calendar + tecla tabulador CALENDAR_BUSY CALENDAR_EVENT CALENDAR_QUERY_RESULT CALENDAR_WRITE
CALENDAR_QUERY
10.2 CALENDAR_BUSY Es una función que permite consultar un calendario para ver si su estado es libre o ocupado. Este tipo de respuesta se puede utilizar en el dialplan asociando el calendario a una determinada extensión y en base al estado del calendario procesar la llamada de diferentes formas. Un ejemplo: el calendario configurado en Asterisk está asociado a la extensión 1000. Si el estado del calendario es ocupado, se anuncia al llamante de llamar más tarde, sino se pasa la llamada a la extensión 1000. 268
Se abre el dialplan nano /etc/asterisk/extensions.conf se modifica este bloque: exten => _100[0-2],1,Gosub(disponible,s,1(${EXTEN})) same => n,Dial(SIP/${EXTEN},45,hHkKtTwWxX) same => n,Hangup para que quede: exten => _100[0-2],1,Gosub(disponible,s,1(${EXTEN})) same => n,Gosub(calendario,s,1(${EXTEN})) same => n,Dial(SIP/${EXTEN},45,hHkKtTwWxX) same => n,Hangup y al final del archivo, antes de esta linea: #include IVR se añade la nueva subrutina: [calendario] exten => s,1,Noop(${ARG1}) same => n,GotoIf($[${ARG1} = 1000]?calendario) same => n,Return same => n(calendario),Set(estado=${CALENDAR_BUSY(campusvtv)}) same => n,Noop(Estado = ${estado}) same => n,Gotoif($[${estado} = 1]?ocupado) same => n,MacroExit same => n(ocupado),Agi(googletts.agi,"la extensión se encuentra ocupada, llame mas tarde. Gracias",es)
same => n,Hangup Esta nueva subrutina controla primero si la extensión que se está llamando es la 1000. Si es así continua desde la etiqueta calendario donde revisa si el calendario asociado a la extensión 1000 (en este caso campusvtv) resulta libre o ocupado. Si resulta ocupado, Asterisk devuelve el valor 1, si resulta libre Asterisk devuelve el valor 0). En el caso que el resultado sea 1, se le anuncia al llamante (con el AGI de google) que la extensión se encuentra ocupada y que llame más tarde). Si el resultado es 0 se sale de la subrutina y se vuelve al contexto, extensión, prioridad +1 de donde la subrutina se ha llamado. Se guardan los cambios y se recarga el dialplan: asterisk -rvvvvvvvvvvvvvvvvvvvvv
269
CLI> dialplan reload se averigua el estado del calendario: CLI> calendar show calendars Calendar -------campusvtv
Type Status --------ical busy
Como en este caso resulta el ocupado, si desde la extensión 1001 se marca a la extensión 1000, se debería escuchar el anuncio que la extensión se encuentra ocupada. El resultado de la llamada en la consola: == Extension Changed 1001[subscribe] new state InUse for Notify User 1000 -- Executing [1000@externas:1] Gosub("SIP/1001-00000002", "disponible,s,1(1000)") in new stack -- Executing [s@disponible:1] Set("SIP/1001-00000002", "estado=NOT_INUSE") in new stack -- Executing [s@disponible:2] GotoIf("SIP/1001-00000002", "1?5") in new stack -- Goto (disponible,s,5) -- Executing [s@disponible:5] Return("SIP/1001-00000002", "") in new stack -- Executing [1000@externas:2] Gosub("SIP/1001-00000002", "calendario,s,1(1000)") in new stack -- Executing [s@calendario:1] NoOp("SIP/1001-00000002", "1000") in new stack -- Executing [s@calendario:2] GotoIf("SIP/1001-00000002", "1?calendario") in new stack -- Goto (calendario,s,4) -- Executing [s@calendario:4] Set("SIP/1001-00000002", "estado=1") in new stack -- Executing [s@calendario:5] NoOp("SIP/1001-00000002", "Estado = 1") in new stack -- Executing [s@calendario:6] GotoIf("SIP/1001-00000002", "1?ocupado") in new stack -- Goto (calendario,s,8) -- Executing [s@calendario:8] AGI("SIP/1001-00000002", "googletts.agi,"la extensión se encuentra ocupada, llame mas tarde. Gracias",es") in new stack -- Launched AGI Script /var/lib/asterisk/agi-bin/googletts.agi 10.3 CALENDAR_EVENT Como ya se ha visto más arriba, esta función permite extraer todas las informaciones relacionadas con un evento programado en el calendario. Más en detalle: • • • • • •
summary – El titulo del evento. description – La descripción del evento organizer – El organizador del evento location – Sitio donde tiene lugar el evento categories – Categoría del evento priority – Prioridad asignada al evento
270
• • • • •
calendar – Nombre del calendario asociado con el evento uid – numero único que identifica el evento start – Fecha y hora de inicio de un evento end – Fecha y hora en que termina el evento busystate – El estado configurado para el evento
Con estos datos, se pueden construir diferentes bloques de dialplan. Un ejemplo es configurar un evento de Conferencia y en la casilla lugar indicar un numero de cuarto de conferencia. En Google Calendar sería:
¿Parece complicado? La verdad no. Lo importante es que cada persona que tiene o quiere participar a la conferencia ponga en su calendario personal la misma información en los campos Titulo y lugar. En en dialplan: 271
nano /etc/asterisk/extensions.conf Se modifica este bloque: [calendario] exten => cal,1,NoOp(Llamada desde el calendario) same => n,Agi(googletts.agi,"${CALENDAR_EVENT(summary)}.",es) same => n,Agi(googletts.agi,"a las ${STRFTIME(${CALENDAR_EVENT(start)},,%H:%M)}.",es) same => n,Wait(1) same => n,Playback(goodbye) same => n,Hangup Para que quede: [calendario] exten => cal,1,NoOp(Llamada desde el calendario) same => n,Gotoif($[${ISNULL(${CALENDAR_EVENT(location)})} = 0 & "$ {CALENDAR_EVENT(summary)}" = "Conferencia"]?conf) same => n,Agi(googletts.agi,"${CALENDAR_EVENT(summary)} a las ${STRFTIME($ {CALENDAR_EVENT(start)},,%H:%M)}.",es) same => n,Wait(1) same => n,Playback(goodbye) same => n,Hangup same => n(conf),Agi(googletts.agi,"${CALENDAR_EVENT(description)}",es) same => n,Meetme(${CALENDAR_EVENT(location)},dM(default)) same => n,Hangup En la linea dos se utiliza la función ISNULL que permite averiguar si una variable está vacía. Si la variable está vacía devuelve 1 sino 0. La lógica de la linea funciona de la siguiente manera: Si la variable ${CALENDAR_EVENT(location)} no está vacía “y” (el carácter &) la variable $ {CALENDAR_EVENT(summary) contiene el valor Conferencia ir a la etiqueta conf sino continuar con la linea que sigue. En la linea con la etiqueta conf se utiliza el AGI de texto a voz de Google y se le anuncia a la extensión la descripción del evento. En la linea siguiente se utiliza la aplicación Meetme para crear una conferencia dinámica cuyo numero es el que aparece en el campo lugar (location) del calendario y se envía la extensión a esa conferencia. Se profundizará el tema de las conferencias en el Capitulo XV. 10.4 CALENDAR_QUERY y CALENDAR_QUERY_RESULT Esta dos funciones sirven para efectuar consultas en los calendarios configurados en Asterisk y sacar los datos de interés. Para saber que datos se pueden extraer, desde la consola de Asterisk:
272
asterisk -rvvvvvvvvvvvvvv CLI> core show function CALENDAR_QUERY_RESULT • • • • • • • • • • • •
getnum – numero de eventos que tendrán lugar en el rango de tiempo indicado en la consulta (en este caso 180 minutos) summary – Titulo del evento description – Descripción del evento organizer – Organizador del evento location – Lugar del evento categories – Categoría del evento priority – Prioridad del evento calendar – Nombre del calendario uid – Numero que identifica de manera univoca el evento start – Hora de inicio del evento end – Hora en que termina el evento busystate – El estado del calendario
La sintaxis de la función es: CALENDAR_QUERY_RESULT(id,field[,entry]) • • •
id – el valor obtenido con la función CALENDAR_QUERY field – El campos que se quiere extraer de un determinado evento entry – en el caso que la función CALENDAR_QUERY haya almacenado en su id más de un evento, con esta opción se define a que evento hace referencia el campo que se quiere extraer
Para ver como funcionan, se crean dos nuevos eventos:
Se averigua que los eventos aparecen en Asterisk:
273
Perfecto! Ahora se crea el dialplan para realizar una consulta al calendario: nano /etc/asterisk/extensions.conf En el contexto internas se añade este bloque: exten => 51,1,Noop(Consulta en el calendario) same => n,Set(fin=$[${EPOCH}+10800]) same => n,Set(id=${CALENDAR_QUERY(campusvtv,${EPOCH},${fin})}) same => n,Set(numeve=${CALENDAR_QUERY_RESULT(${id},getnum)}) same => n,Set(num=1) same => n,While($[${numeve} > 0]) same => n,Agi(googletts.agi,"${CALENDAR_QUERY_RESULT(${id},summary,${num})}",es) same => n,Agi(googletts.agi,"a las ${STRFTIME(${CALENDAR_QUERY_RESULT(${id},start,${num})},,%H:%M)}",es)
same => n,Set(numeve=$[${numeve}-1]) same => n,Set(num=$[${num}+1]) same => n,Endwhile same => n,Hangup •
•
Linea 2 – Como en la configuración de los calendarios se ha puesto como limite de consulta los 180 minutos, se añade a la variable ${EPOCH} el valor 10800 segundos que corresponden a 180 minutos. No se pueden realizar consultas más allá de este tiempo sin cambiar la configuración del parámetro timeframe en calendar.conf Linea 3 – se asigna a la variable id el resultado de la consulta en el calendario campusvtv indicando la ora de inicio y la hora final de la consulta, es decir los eventos que tendrán lugar en lo próximos 180 minutos 274
• • • • • • • •
Linea 4 – se asigna a la variable numeve el numero de eventos que tendrán lugar en los próximos 180 minutos Linea 5 – se asigna a la variable num el valor 1 Linea 6 – la aplicación While se utiliza para crear un ciclo y este ciclo se ejecutará hasta que la variable ${numeve} sea mayor que 0 Linea 7 – con el AGI del TTS de Google se anuncia el titulo del evento (summary) de la entrada cuyo numero es el contenido en la variable ${num} Linea 8 - con el AGI del TTS de Google se anuncia la hora (start) de la entrada cuyo numero es el contenido en la variable ${num} Linea 9 – se asigna a la variable ${numeve} el valor de la misma variable menos 1. Ejemplo: si el calendario contiene dos eventos en los próximos 180 minutos, la variable ${numeve} contiene el valor 2. Después de esta linea contendrá el valor 1 Linea 10 – Se asigna a la variable ${num} el valor de la variable ${num} + 1. Como inicialmente la variable contenía el valor 1, después de esta linea contendrá el valor 2 Llinea 11 – Con la aplicación EndWhile se cierra el ciclo y el dialplan vuelve a la linea con la aplicación While. Ahora, como la variable ${numeve} es todavía mayor que 0, el ciclo se repite y se leerá el titulo y la hora del segundo evento.
La siguiente vez que se vuelve a la aplicación While, la variable ${numeve} contendrá el valor cero pues se saldrá del ciclo “While - Endwhile” y se ejecutará la linea que sigue la aplicación EndWhile, es decir same => n,Hangup De esta forma si llegando a la oficina, se quiere conocer los eventos programados en las próximas 3 horas, basta marcar la extensión 51. Claramente cada persona de la empresa puede tener su calendario personal. 10.5 CALENDAR_WRITE Con la función CALENDAR_WRITE, es posible crear nuevos eventos en el calendario desde Asterisk. En este ejemplo se mostrará como grabar las llamadas salientes con el proveedor VozToVoice en un calendario. Para este ejemplo se utilizará un nuevo calendario. Desde la pagina de administración del calendario principal, se entra en la pagina de configuración y se crea un nuevo calendario:
275
Se presiona el botón “Crear un calendario nuevo” y en la nueva pagina se rellenas los campos:
Se concluye la creación presionando el botón “Crear calendario”. Se entra en la configuración del nuevo calendario y se toma nota del siguiente dato:
Con el valor del ID del nuevo calendario se configura Asterisk: nano /etc/asterisk/calendar.conf al final del archivo se añade: [llamadas] type=caldav url=https://www.google.com/calendar/dav/[email protected]/events
[email protected] secret=password refresh=10 timeframe=180 autoreminder=10 channel=SIP/1000 context=calendario extension=cal waittime=45 276
IMPORTANTE: Personalizar los datos de la etiqueta inicial, el parámetro url, el parámetro user y el parámetro secret con los datos de su cuenta Google. Se guardan los cambios y se entra en la consola de Asterisk: asterisk -rvvvvvvvvvvvvvvvvvvv Se recarga el modulo: CLI> module reload res_calendar.so Si no aparecen errores y/o advertencias, todo debería estar bien configurado. Con el comando: CLI> calendar show calendars Calendar Type Status ---------------llamadas caldav free campusvtv ical free Se puede comprobar que efectivamente los dos calendarios están conectados. Los datos de las llamadas que se guardarán en el calendario son: • • • •
extensión que ha iniciado la llamada IP de la extensión numero marcado Fecha de la llamada
Para implementar está solución se abre el dialplan: nano /etc/asterisk/extensions.conf se modifica este bloque: [internacio] exten => _00X.,1,NoOp same => n,Set(GROUP(voip)=voztovoice) same => n,Set(GROUP(salida)=${CALLERID(num)}) same => n,Set(trunksal=${GROUP_COUNT(voztovoice@voip)}) same => n,Set(extsal=${GROUP_COUNT(${CALLERID(num)}@salida)}) same => n,NoOp(Hay ${extsal} llamadas desde la extension ${CALLERID(num)} y ${trunksal} con el proveedor VozToVoice) same => n,Gotoif($[${extsal} > 2 | ${trunksal} > 2]?busy) 277
same => n,Dial(SIP/voztovoice/${EXTEN}) same => n,Hangup same => n(busy),Playback(all-outgoing-lines-unavailable) same => n,Hangup Para que quede: [internacio] exten => _00X.,1,NoOp same => n,Set(CALENDAR_WRITE(llamadas,summary,description,location,start)=Llamada de $ {CALLERID(num)} a ${EXTEN},Llamada desde la extension ${CALLERID(num)} al numero $ {EXTEN},IP = ${CHANNEL(peerip)},${EPOCH}) same => n,Set(GROUP(voip)=voztovoice) same => n,Set(GROUP(salida)=${CALLERID(num)}) same => n,Set(trunksal=${GROUP_COUNT(voztovoice@voip)}) same => n,Set(extsal=${GROUP_COUNT(${CALLERID(num)}@salida)}) same => n,NoOp(Hay ${extsal} llamadas desde la extension ${CALLERID(num)} y ${trunksal} con el proveedor VozToVoice) same => n,Gotoif($[${extsal} > 2 | ${trunksal} > 2]?busy) same => n,Dial(SIP/voztovoice/${EXTEN}) same => n,Hangup same => n(busy),Playback(all-outgoing-lines-unavailable) same => n,Hangup Se ha añadido la linea 2 (en amarillo). El contenido de esa linea tiene que quedar en la mismo renglón. Con esa linea se le dice a Asterisk que guarde en el calendario “llamadas” los campos: • • • •
summary description location start
En la segunda parte de la linea se le asigna a cada campo un valor y más en detalle: • • • •
Summary = Llamada de ${CALLERID(num)} a ${EXTEN} Description = Llamada desde la extension ${CALLERID(num)} al numero ${EXTEN} Location = IP = ${CHANNEL(peerip)} Start = ${EPOCH}
Las variables presentes: • • • •
${CALLERID(num)} – Contiene el numero de la extensión que ha llamado ${EXTEN} – Contiene el numero marcado ${CHANNEL(peerip)} = Contiene la IP de donde la extensión ha iniciado la llamada ${EPOCH} = Contiene la fecha de inicio de la llamada en formato EPOCH que es el requerido 278
por Google Calendar El resultado en Google Calendar será:
Si tenemos sincronizado el calendario en un sistema Android:
Claramente este es ejemplo muy sencillo. Se puede elaborar más para sacar más datos de la llamada. Otro ejemplo para utilizar esta función podría ser programar una conferencia a través de un IVR indicando las extensiones que deben participar y guardar los datos en el Calendario. 10.6 Enviar las notificaciones de los calendarios a números fijos/celulares En la configuración que se ha visto hasta el momento, es posible asociar el calendario a una extensión y llamar la extensión configurada para notificarle el comienzo de un evento. Una forma más elaborada de configurar el calendario y de consecuencia el dialplan, es modificar el CALLERID antes de marcar a la 279
extensión y en el caso que no conteste, desviar la llamada a un numero fijo/celular. Para este tipo de configuración se utilizará el chan_local. Primero se modifica la configuración del calendario: nano /etc/asterisk/calendar.conf Se modifica esta linea del calendario campusvtv: channel=SIP/1000 para que quede: channel=Local/6500@internas Se guardan los cambios. De esta forma cuando se acerca un evento y Asterisk envía la notificación, llamará el canal Local, extensión 6500, contexto internas; esa extensión hay que crearla en el dialplan: nano /etc/asterisk/extensions.conf En el contesto internas se añaden las siguientes lineas: exten => 6500,1,Set(CALLERID(name)=Calendario) same => n,Set(CALLERID(num)=CampusVozToVoice) same => n,Dial(SIP/1000,15) same => n,Gotoif($[${DIALSTATUS} = ANSWER)]?contestada) same => n,Dial(SIP/voztovoice/0057XXXXXXXXXX) same => n,hangup same => n(contestada),Hangup • • • • •
En la primera linea se asigna al la variable CALLERID(name) la palabra Calendario En la segunda linea se asigna a la variable CALLERID(num) el nombre del calendario (en este caso CampusVozToVoice) En la tercera linea se marca a la extensión 1000 por 15 segundos Si la extensión contesta (GotoIF verdadero), se va a la etiqueta (contestada) y se termina la llamada Si la extensión no contesta dentro de 15 segundos, se marca al un numero fijo o celular.
Se guardan los cambios y se crea un nuevo evento en el calendario para probar la configuración. Se reinicia Asterisk: service asterisk restart Se espera la llamada del calendario. Primero timbrará la extensión 1000: Dialing Local/6500@internas for notification on calendar campusvtv
280
-- Called 6500@internas -- Executing [6500@internas:1] Set("Local/6500@internas-00000000;2", "CALLERID(name)=Calendario") in new stack -- Executing [6500@internas:2] Set("Local/6500@internas-00000000;2", "CALLERID(num)=CampusVozToVoice") in new stack -- Executing [6500@internas:3] Dial("Local/6500@internas-00000000;2", "SIP/1000,15") in new stack
Si no se contesta dentro de 15 segundos, la llamada se enviará al numero fijo/celular configurado: Executing [6500@internas:4] GotoIf("Local/6500@internas-00000000;2", "0?contestada") in new stack Executing [6500@internas:5] Dial("Local/6500@internas-00000000;2", "SIP/voztovoice/00573163435746")
En este caso el CALLERID no es el que se ha configurado en el dialplan ya que su envío/recepción depende del Proveedor VoIP utilizado.
281
Capitulo XI CCSS (Call Completion Supplementary System) – Rellamada El CCSS es una funcionalidad que permite solicitar el servicio de rellamada cuando el llamado no ha contestado y/o su extensión se encuentra ocupada. El sistema se basa en el RFC6910. En este caso los desarrolladores de Asterisk han optado por implementar un protocolo que a pesar de ser un estándar de hecho, no es muy utilizado hasta el momento. Esto explica porque muchas veces no hay interoperatividad entre dispositivos SIP de distintos productores aunque, supuestamente, todos acatan el protocolo SIP. Actualmente la única PBX que utiliza este RFC es Asterisk y no hay sofphone ni teléfonos SIP que lo implementen. Es por este motivo que al momento de configurar esta funcionalidad, se podrá utilizar su configuración nativa solamente entre servidores Asterisk (desde la versión 1.8.X). Para su utilizo entre Asterisk y los teléfonos SIP o softphone hay que optar por su configuración genérica que realmente no se basa en el RFC mencionado, sino en un sub-sistema que se apoya a la función DEVICE_STATE. ¿Cómo funciona el sistema? El sistema aplica a llamadas no contestadas CCNR (Call Completion on No Response) o cuando la extensión llamada se encuentra ocupada CCBR (Call Completion on Busy Subscriber) y solamente para canales SIP. Si para solicitar la rellamada se utiliza el agente genérico, habrá que utilizar la aplicación CallCompletion. Si se utiliza el agente nativo, el mismo productor del dispositivo que implementa el RFC, indicará como activarla. Normalmente es a través de una tecla del teléfono o presionando un botón ya programado para esta función. Un ejemplo. La extensión 1000 llama la extensión 1001. Si la extensión 1001 no contesta, la extensión 1000 tendrá un tiempo predefinido para solicitar una rellamada. La solicitud se efectúa utilizando la aplicación CallCompletion en el dialplan. Una vez solicitada la rellamada, se activará un temporizador que definirá por cuanto tiempo la solicitud quedará activa. Si dentro de este tiempo la extensión 1001 efectúa una llamada, Asterisk la considerará nuevamente activa y en cuanto termine la llamada, marcará primero la extensión 1000 y luego la extensión 1001. Si la rellamada tiene éxito, la solicitud sera eliminada. Si la rellamada no tiene éxito (la extensión 1001 no contesta nuevamente o está hablando), habrá que solicitar una nueva rellamada. En cualquier momento se puede anular una solicitud de rellamada utilizando en el dialplan la aplicación CallCompletionCancel. 11.1 Configuración del CCSS ¿Cómo se configura el sistema de rellamada en Asterisk? Primero hay que configurar el archivo ccss.conf. En este archivo se define un único parámetro que es el numero máximo de solicitudes que pueden estar activas en la PBX. Los demás datos que se encuentran el el archivo son para la configuración de las extensiones. Se renombra el archivo predefinido:
mv /etc/asterisk/ccss.conf /etc/asterisk/ccss.conf.old Se crea uno nuevo: nano /etc/asterisk/ccss.conf y copian las lineas que siguen: [general[ cc_max_request=20 De esta forma se limita a veinte el numero máximo de solicitudes activas en el sistema. Se guardan los cambios. Ahora la parte dedicada a las extensiones, donde se pueden configurar una serie de parámetros. Los parámetros que no se configuran, tomarán como valor el predefinido: Parámetro
Descripción
cc_offer_timer
Tiempo máximo, en segundos, para solicitar una rellamada cuando una llamada no ha tenido éxito. Valor 20
ccbs_available_timer
Tiempo de vida, en segundos, de una solicitud de rellamada cuando le extensión llamada estaba ocupada. Valor 4800
ccnr_available_timer
Tiempo de vida, en segundos, de una solicitud de rellamada cuando la extensión llamada no ha contestado. Valor 7200
cc_recall_timer
Cuando la extensión que ha solicitado la rellamada, recibe la llamada del sistema tendrá el numero de segundos indicados en este parámetro para contestar. Si no lo hace la rellamada será anulada. Valor: 20
cc_agent_policy
Este parámetro describe el tipo de comportamiento de Asterisk cuando se comunicará con el llamante para una rellamada. Puede ser: • never: deshabilita la posibilidad de solicitar una rellamada para el llamante • generic: cuando no se utiliza el RFC sino el sub-sistema basado en el DEVICE_STATE • native: cuando se utiliza el RFC para el 284
sistema de rellamada (el teléfono del llamante lo soporta) cc_monitor_policy
Este parámetro describe el tipo de comportamiento de Asterisk cuando se comunicará con el llamado para una rellamada. Puede ser: • never: deshabilita la posibilidad de recibir una rellamada • generic: activará el monitoreo del llamado utilizando el sub-sistema basado en el DEVICE_STATE • native: cuando se utiliza el RFC para el sistema de rellamada (el teléfono del llamado lo soporta) • always: cuando no se sabe si el teléfono soporta el RFC. De esta forma Asterisk intentará utilizar el sistema nativo y si no funciona, el genérico
cc_max_agents
Limita el numero de rellamadas activas para el llamante. Si cc_agent_policy=generic, este valor no será tomado en consideración. Valor: 5
cc_max_monitors = 5
Limita el numero de rellamadas que un dispositivo puede aceptar. Valor: 5
Para poder efectuar una prueba se configurará en las extensiones 1000,1001 y 1002 solamente dos parámetros: • •
cc_agent_policy=generic cc_monitor_policy=generic
Se abre el archivo sip.conf nano /etc/asterisk/sip.conf y al final del bloque de configuración de cada extensión se pone: cc_agent_policy=generic cc_monitor_policy=generic Se guardan los cambios. Como se va a utilizar el sistema genérico, en el dialplan hay que configurar una extensión para la aplicación CallCompletion y otra para la aplicación CallCompletionCancel nano /etc/asterisk/extensions.conf
285
en el contexto internas se añaden las siguientes lineas: exten => *30,1,CallCompletionRequest same => n,Agi(googletts.agi,"Rellamada activada",es) same => n,Hangup exten => *31,1,CallCompletionCancel same => n,Agi(googletts.agi,"Rellamada anulada",es) same => n,Hangup Se guardan los cambios y se recarga toda la configuración de Asterisk: service asterisk reload 11.2 CCSS 1ª Prueba Desde la extensión 1000 se llama la extensión 1001. Cuando esta esté timbrando, se rechaza la llamada:
A partir de ese momento, la extensión 1000 tendrá 20 segundos para solicitar la rellamada. Se puede ver, desde la consola de Asterisk, que la rellamada ha sido ofrecida por parte de la extensión 1001: CLI> cc report status
Ahora para solicitarla desde la extensión 1000 se marca *30. CLI> cc report status
286
Siendo el tipo de solicitud CCNR, tendrá un tiempo de vigencia de 7200 segundo (dos horas), como indicado en ccnr_available_timer como valor predefinido. Para que la rellamada se realice, el sistema esperará que la extensión 1001 efectúe una llamada y de esta forma saber que ya está activa nuevamente. Para averiguarlo, desde la extensión 1001 se marca 150 (test de echo) y después de unos segundos se cuelga. Casi en seguida entrará una llamada a la extensión 1000:
Como se puede ver el CallerID es la misma extensión 1000 y esto indica que se trata de una rellamada. Cuando la extensión 1000 contesta se pueden presentar dos escenarios: • •
la extensión 1001 no contesta nuevamente. La rellamada corriente se anula y la extensión 1001 ofrece nuevamente a la extensión 1000 la posibilidad de solicitar una rellamada. la extensión 1001 contesta. La rellamada solicitada se anula.
La extensión 1000 tiene 20 segundos para contestar la llamada entrante (valor predefinido del parámetro cc_recall_timer). Si no lo hace, la rellamada se considerará terminada. 11.3 CCSS 2ª Prueba Desde la extensión 1000 se llama la extensión 1001. La extensión 1001 rechaza la llamada. La extensión 1000 solicita la rellamada marcando *30. Después de unos minutos, decide que ya no la necesita. Marcando *31 la anula. Las distintas secuencias desde la consola de Asterisk:
287
Si la solicitud de CC es anulada, no se puede solicitar nuevamente. 11.4 CCSS 3ª Prueba Desde la extensión 1000 se llama la extensión 1001. La extensión 1001 contesta la llamada. Cuando la conversación termine, la extensión 1000, a pesar que la extensión 1001 ha contestado, podrá solicitar una rellamada. Este tipo de comportamiento tiene su lógica ya que el hecho que la llamada ha sido contestada, no significa que el llamante ha podido hablar con el llamado (como en este caso). Esto porque si en el dialplan se configura que si la extensión 1001 no contesta dentro de un tiempo, la llamada pasa a un buzón de voz o a un IVR, realmente la extensión 1000 no ha podido hablar con la extensión 1001. Si se mira la consola, efectivamente la rellamada se está ofreciendo:
288
Consejos: 1. El sistema de rellamada consuma bastante recursos del sistema. Para limitar este consumo es buena practica: • configurar el parámetro cc_max_requests con un valor bajo • configurar el parámetro cc_offer_time con un valor bajo • En el sip.conf, por cada extensión, configurar el parámetro cc_agent_policy con never y activar el agente desde el dialplan utilizando la función CALLCOMPLETETION. Para el bloque de las llamadas entre extensiones seria algo como: exten => _100[0-2],1,Macro(disponible) same => n,Macro(calendario) same => n,Set(CALLCOMPLETION(cc_agent_policy)=generic) same => n,Dial(SIP/${EXTEN},45,hHkKtTwWxX) same => n,Hangup 2. la rellamada nativa funciona solamente si el paquete libxml2-devel ha sido instalado en el servidor Linux antes de compilar Asterisk. Esto porque el RFC se basa en un sistema de SUBSCRIBE, NOTIFY y PUBLISH donde el cuerpo del paquete SIP contiene la información en ese formato (XML).
289
Capitulo XII Asterisk Realtime ARA (The Asterisk Realtime Architecture) es un método para almacenar los archivos de configuración de Asterisk y/o objetos en una base de datos. Existen dos tipos de Realtime: • •
Estático Dinámico
12.1 Realtime estático Con el Realtime estático es posible guardar los archivos de configuración de Asterisk en una base de datos. Se dice estático porque cuando se efectúen cambios en la base de datos, hay que recargar la configuración de Asterisk. Si las configuraciones se guardan en la base de datos, ya no se podrán utilizar los archivos de texto, es decir que si por ejemplo se guarda la configuración del dialplan en Realtime estático, la PBX no leerá el archivo extensions.conf. El archivo donde se configura el Realtime estático es extconfig.conf y la sintaxis es: file.conf => driver,database[,table] • • • •
file.conf: archivo de configuración que se quiere guardar en la base de datos driver: que motor de base de datos se va a utilizar (MySQL, ODBC, Postgres, SQLite3) database: el nombre de la base de datos table: el nombre de la tabla en la base de datos
Los únicos archivos de configuración que no se pueden guardar con el Realtime estático son: • • •
asterisk.conf logger.conf extconfig.conf
Otros tres archivos se pueden guardar en la base de datos solamente si el modulo del motor que se va a utilizar se carga en el modules.conf antes de los demás módulos. Esto se realiza con la declaración preload. Como se va a utilizar ODBC, la modifica que hay que hacer es: nano /etc/asterisk/modules.conf se buscan estas dos lineas: ;preload => res_odbc.so ;preload => res_config_odbc.so y se modifican para que queden:
preload => res_odbc.so preload => res_config_odbc.so Los dos módulos (que se utilizan para el Realtime con ODBC), se cargarán antes de los demás módulos y de esta formas se podrán guardar en Realtime también estos archivos: • • •
manager.conf cdr.conf rtp.conf
¿Cual es el procedimiento para configurar el Realtime estático en Asterisk con ODBC? 1. 2. 3. 4. 5.
Se crea una nueva base de datos Se crea la tabla para el Realtime estático Se configurar el conector ODBC Se configura el archivo de configuración de Asterisk res_odbc.conf Se configura el archivo extconfig.conf
Visto gráficamente sería:
Se inicia creado una nueva base de datos: mysql -u root -psesamo mysql> create database asterisk; 292
Se otorgan los permisos de acceso a la base de datos creada al usuario asterisk, desde local: mysql> GRANT ALL PRIVILEGES ON asterisk.* TO 'asterisk'@'localhost' IDENTIFIED BY 'sesamo'; desde remoto: mysql> GRANT ALL PRIVILEGES ON asterisk.* TO 'asterisk'@'%' IDENTIFIED BY 'sesamo'; se crea la tabla para el Realtime estático: mysql> use asterisk mysql> CREATE TABLE `ast_config` ( `id` int(11) NOT NULL auto_increment, `cat_metric` int(11) NOT NULL default '0', `var_metric` int(11) NOT NULL default '0', `filename` varchar(128) NOT NULL default '', `category` varchar(128) NOT NULL default 'default', `var_name` varchar(128) NOT NULL default '', `var_val` varchar(128) NOT NULL default '', `commented` int(11) NOT NULL default '0', PRIMARY KEY (`id`), KEY `filename_comment` (`filename`,`commented`) ); El nombre de la tabla es totalmente arbitrario y se puede personalizar para volverlo más amigable. Una explicación de los parámetros que aparecen en la tabla: • • • • • • • •
ID – es un numero progresivo que se crea automáticamente cat_metric – el peso de la categoría o bloque dentro del archivo. Un valor bajo significa que la categoría aparecerá más arriba en el archivo de configuración var_metric – el peso de un objeto o parámetro dentro de la categoría. Un valor bajo significa que el objeto aparecerá más arriba en la categoría filename – el nombre del archivo de configuración de Asterisk que se quiere guardar en la base de datos category – la categoría o bloque del archivo de configuración var_name – el nombre del objeto o del parámetro que se está configurando var_val – el valor del objeto o parámetro commented – si es cualquier valor diferente a cero, la entrada en la base de datos aparecerá como comentada.
Para entender mejor como funciona, se guardará el archivo musiconhold.conf en Realtime estático.
293
mysql> INSERT INTO ast_config (cat_metric,var_metric,filename,category,var_name,var_val) VALUES ('0','0','musiconhold.conf','default','mode','files'); Con esta primera linea se crea la clase default y se define que el modo es files. mysql> INSERT INTO ast_config (cat_metric,var_metric,filename,category,var_name,var_val) VALUES ('0','1','musiconhold.conf','default','directory','/var/lib/asterisk/moh'); Con esta segunda linea se define que la carpeta que contiene los archivos audio para la clase default es /var/lib/asterisk/moh mysql> INSERT INTO ast_config (cat_metric,var_metric,filename,category,var_name,var_val) VALUES ('0','2','musiconhold.conf','default','random','yes'); En la ultima linea se define que los archivos audio de la música de espera de la clase default se reproducirán de forma aleatoria. Se repiten las tres lineas para la música de espera MP3 (como se había configurado en el párrafo 2.5): mysql> INSERT INTO ast_config (cat_metric,var_metric,filename,category,var_name,var_val) VALUES ('1','0','musiconhold.conf','mp3','mode','files'); Como se puede notar en esta primera linea el cat_metric es 1 e indica que estamos creando un segundo bloque en el archivo de configuración. mysql> INSERT INTO ast_config (cat_metric,var_metric,filename,category,var_name,var_val) VALUES ('1','1','musiconhold.conf','mp3','directory','/var/lib/asterisk/mohmp3'); Con esta segunda linea se define que la carpeta que contiene los archivos audio para la clase mp3 es /var/lib/asterisk/mohmp3 mysql> INSERT INTO ast_config (cat_metric,var_metric,filename,category,var_name,var_val) VALUES ('1','2','musiconhold.conf','mp3','random','yes'); En la ultima linea se define que los archivos audio de la música de espera de la clase mp3 se reproducirán de forma aleatoria. Se sale del cliente MySQL: mysql> quit Creada la base de datos y la tabla, se configura el conector ODBC. Esto se realiza en dos archivos de configuración: • •
odbcinst.ini odbc.ini
294
En el primero se configuran las conexiones ODBC → librerías base de datos. En el segundo se configuran las base de datos. Para iniciar se borra el archivo predefinido odbcinst.ini rm /etc/odbcinst.ini rm: remove regular file `/etc/odbcinst.ini'? y se crea uno nuevo: nano /etc/odbcinst.ini y para ODBC → MySQL se ponen las siguientes lineas: [MySQL] Description = ODBC para MySQL Driver = /usr/lib64/libmyodbc5.so Setup = /usr/lib64/libodbcmyS.so FileUsage = 1 Para una versión 32 bit de CentOS sería: [MySQL] Description = ODBC para MySQL Driver = /usr/lib/libmyodbc5.so Setup = /usr/lib/libodbcmyS.so FileUsage = 1 Se continua con odbc.ini nano /etc/odbc.ini se copian las siguientes lineas que crean una conexión a la base de datos MySQL asterisk: [asterisk] Description = MySQL Asterisk Driver = MySQL Database = asterisk Server = localhost User = asterisk Password = sesamo Port = 3306 Option = 3 Se guardan los cambios. Para probar la conexión entre ODBC y la base de datos asterisk se utiliza el comando: isql asterisk asterisk sesamo
295
• • •
asterisk – etiqueta que da inicio al bloque configurado en odbc.ini asterisk – nombre del usuario que tiene acceso a la base de datos creada sesamo – la contraseña del usuario asterisk creado en MySQL
El resultado: +---------------------------------------+ | Connected! | | | | sql-statement | | help [tablename] | | quit | | | +---------------------------------------+ La conexión entre ODBC y la base de datos MySQL asterisk funciona perfectamente. Para salir: SQL> quit El siguiente paso es configurar res_odbc.conf. Se renombra el archivo predefinido y se crea uno nuevo: mv /etc/asterisk/res_odbc.conf /etc/asterisk/res_odbc.conf.old nano /etc/asterisk/res_odbc.conf Se copian las siguientes lineas: [ENV] [asterisk] enabled => yes dsn => asterisk username => asterisk password => sesamo pre-connect => yes sanitysql => select 1 idlecheck => 3600 connect_timeout => 10 La linea más importante es dsn => asterisk. El valor asterisk es el que se ha configurado en el bloque que se acaba de crear en el archivo odbc.ini Se guardan los cambios y se modifica el ultimo archivo: nano /etc/asterisk/extconfig.conf
296
después de esta linea: ;extensions.conf => sqlite,asterisk,ast_config se pone: musiconhold.conf => odbc,asterisk,ast_config Se guardan los cambios. El nombre asterisk que aparece en la linea se refiere al nombre de la etiqueta con que inicia la configuración de la conexión en res_odbc.conf. Gráficamente: odbc.ini
res_odbc.conf
extconfig.conf
Ahora que se ha configurado la música de espera en Realtime se renombra el archivo de texto: mv /etc/asterisk/musiconhold.conf /etc/asterisk/musiconhold.conf.old Se reinicia Asterisk: service asterisk restart Se entra en la consola: asterisk -rvvvvvvvvvvvvvv se averigua que la conexión en Realtime esté activa (desde el lado Asterisk): CLI> odbc show all ODBC DSN Settings ----------------Name: asterisk 297
DSN: asterisk Last connection attempt: 1969-12-31 19:00:00 Pooled: No Connected: Yes se mira la configuración de la música de espera: CLI> moh show classes Class: default Mode: files Directory: /var/lib/asterisk/moh Class: mp3 Mode: files Directory: /var/lib/asterisk/mohmp3 Parece que todo está bien. Desde la extensión 1000 se marca el numero 200 para probar la música de espera MP3 en Realtime. 12.2 Realtime Dinamico El Realtime dinámico permite guardar objetos en una base de datos. Estos objetos pueden ser: extensiones, colas de espera, agentes, buzones de voz, etc. Cuando se realiza un cambio en la base de datos, Asterisk actualizará la configuración en tiempo real. A diferencia del Realtime estático, los objetos creados en la base de datos “conviven” con aquellos presentes en los archivos de configuración. Ejemplo: se pueden configurar las extensiones en el sip.conf y al mismo tiempo en la base de datos. Al recargar la configuración SIP, funcionarán ambas. 12.2.1 Extensiones SIP en Realtime La parte más complicada de la configuración de SIP en Realtime, es la creación de la tabla donde almacenar los parámetros de las extensiones SIP. Algunos campos de la tabla son opcionales mientras otros son obligatorios. Una tabla base debe contener por lo menos estos parámetro: • • • • • • • • • •
type name secret context host ipaddr port regseconds defaultuser fulcontact 298
• • •
regserver useragent lastms
Para crear una tabla más completa, se puede tomar como referencia el resultado de este comando: CLI> sip show peer 1000 * Name : 1000 Description : Secret : MD5Secret : Remote Secret: Context : externas Record On feature : automixmon Record Off feature : automixmon Subscr.Cont. : subscribe Language : es Tonezone : es Accountcode : 1000 AMA flags : Unknown Transfer mode: open CallingPres : Presentation Allowed, Not Screened Callgroup : 1 Pickupgroup : 1 Named Callgr : Nam. Pickupgr: MOH Suggest : default Mailbox : 1000@default VM Extension : asterisk LastMsgsSent : 0/0 Call limit : 2147483647 Max forwards : 0 Dynamic : Yes Callerid : "Fulano" <1000> MaxCallBR : 384 kbps Expire : 3563 Insecure : no Force rport : Yes Symmetric RTP: Yes ACL : No DirectMedACL : No T.38 support : Yes T.38 EC mode : FEC T.38 MaxDtgrm: 400 DirectMedia : No 299
PromiscRedir : No User=Phone : No Video Support: Yes Text Support : No Ign SDP ver : No Trust RPID : Yes Send RPID : Yes TrustIDOutbnd: Legacy Subscriptions: Yes Overlap dial : Yes DTMFmode : rfc2833 Timer T1 : 500 Timer B : 32000 ToHost : Addr->IP : 87.7.52.17:57725 Defaddr->IP : (null) Prim.Transp. : UDP Allowed.Trsp : UDP Def. Username: 1000 SIP Options : outbound path Codecs : (alaw|g729|g722|h263) Codec Order : (alaw:20,g722:20,g729:20,h263:0) Auto-Framing : No Status : OK (239 ms) Useragent : Reg. Contact : sip:[email protected]:57725 Qualify Freq : 60000 ms Keepalive : 60000 ms Sess-Timers : Originate Sess-Refresh : uas Sess-Expires : 600 secs Min-Sess : 90 secs RTP Engine : asterisk Parkinglot : Use Reason : Yes Encryption : No Todos los parámetros que aparecen en la lista, se pueden configurar en la tabla. CLI> quit Ya se puede crear la tabla teniendo en cuenta los parámetros disponibles para la configuración de una extensión: mysql -u root -psesamo mysql> use asterisk 300
mysql> CREATE TABLE `sipexten` ( `name` varchar(40) NOT NULL default ' ', `secret` varchar(40) default NULL, `md5secret` varchar(40) default NULL, `remotesecret` varchar(40) default NULL, `callbackextension` varchar(30) default NULL, `type` varchar(10) NOT NULL default ' ', `defaultuser` varchar(40) default NULL, `fromuser` varchar(40) default NULL, `fromdomain` varchar(40) default NULL, `auth` varchar(10) default NULL, `mailbox` varchar(20) default NULL, `subscribemwi` varchar(10) default NULL, `vmexten` varchar(20) default NULL, `callerid` varchar(40) default NULL, `cid_number` varchar(40) default NULL, `callingpres` varchar(20) default NULL, `usereqphone` varchar(10) default NULL, `language` varchar(10) default NULL, `context` varchar(40) NOT NULL default ' ', `subscribecontext` varchar(40) default NULL, `amaflags` varchar(20) default NULL, `accountcode` varchar(20) default NULL, `allowtransfer` varchar(20) default NULL, `callgroup` varchar(20) default NULL, `pickupgroup` varchar(20) default NULL, `autoframing` varchar(10) default NULL, `disallow` varchar(20) default 'all', `allow` varchar(20) default NULL, `maxcallbitrate` varchar(15) default NULL, `host` varchar(40) default 'dynamic', `outboundproxy` varchar(40) default NULL, `ipaddr` varchar(45) NOT NULL default ' ', `defaultip` varchar(20) NOT NULL default '0.0.0.0', `port` int(6) NOT NULL default '0', `fullcontact` varchar(60) default NULL, `insecure` varchar(20) default NULL, `qualify` varchar(15) default NULL, `regseconds` int(11) NOT NULL default '0', `regexten` varchar(20) default NULL, `regserver` varchar(20) default NULL, `rtptimeout` varchar(15) default NULL, `rtpholdtimeout` varchar(15) default NULL, `rtpkeepalive` varchar(15) default NULL, `lastms` int(11) NOT NULL default '-1', `setvar` varchar(200) default NULL, 301
`nat` varchar(20) NOT NULL, `useragent` varchar(40) default NULL, `Directmedia` varchar(3) default 'no', `Deny` varchar(31) default '', `Permit` varchar(31) default NULL, `transport` varchar(3) default 'udp', `encryption` varchar(3) default 'no', PRIMARY KEY (`name`), KEY `host` (`host`,`port`), KEY `ipaddr` (`ipaddr`,`port`) ); Query OK, 0 rows affected (0.01 sec) Se sale del cliente MySQL mysql> quit Bye En este caso como la base de datos es la misma del Realtime estático, no hay que modificar ni el odbc.ini, ni el res_odbc.ini. El único archivo que hay que modificar es el extconfig.conf nano /etc/asterisk/extconfig.conf Se modifica esta linea: ;sippeers => odbc,asterisk para que quede: sippeers => odbc,asterisk,sipexten Se guardan los cambios y se actualiza la configuración de Asterisk: /etc/init.d/asterisk reload Ahora se puede configurar la primera extensión SIP en Realtime. Para volver más sencillo el trabajo con las bases de datos, se pueden utilizar distintos programas, entre otros: webmin e phpadmin. En este caso se ha optado por Webmin. Se instalan unas dependencias (para las conexiones seguras): yum install perl-Net-SSLeay -y Se descarga el paquete: cd /usr/src wget http://prdownloads.sourceforge.net/webadmin/webmin-1.740-1.noarch.rpm
302
y se instala rpm -ivh webmin-1.740-1.noarch.rpm advertencia:webmin-1.740-1.noarch.rpm: CabeceraV3 DSA/SHA1 Signature, ID de clave 11f63c51: NOKEY Preparando... ########################################### [100%] Operating system is CentOS Linux 1:webmin ########################################### [100%] Webmin install complete. You can now login to https://sip1.voztovoice.net:10000/ as root with your root password. Antes de entrar en la pagina de administración de Webmin hay que abrir el puerto 10000 en el firewall: nano /etc/sysconfig/iptables Después de esta linea: -A INPUT -p udp -m udp --dport 10000:20000 -j ACCEPT se pone: # Webmin -A INPUT -p tcp -m state --state NEW -m tcp --dport 10000 -j ACCEPT Se guardan los cambios y se reinicia iptables: service iptables restart Ahora desde un navegador Web se pone la dirección para entrar en Webmin. Si es un servidor Linode se pone el nombre de dominio del Linode sino la IP: https://IPservidor:10000
En Username se pone root y en Password la contraseña del usuario root de Linux. En la pagina que aparece, en la derecha se escoge el menú “Servers” y luego “MySQL Database Server”:
303
En Login se pone root (el usuario MySQL) y como contraseña sesamo:
Se selecciona la base de datos Asterisk y luego la tabla Sipexten. Al fondo de la nueva pagina se presiona el botón “View Data” y luego “Add Row”. Se puede empezar a crear la primera extensión en Realtime:
304
Al terminar se presiona el botón "Save". Si desde la consola de Asterisk se escribe el comando: asterisk -rvvvvvvvvvvvv 305
CLI> sip show peers la nueva extensión configurada no aparecerá. Para ver la configuración de la nueva extensión hay que utilizar el siguiente comando: CLI> sip show peer 1004 load Para la parte user: CLI> sip show user 1004 load IMPORTANTE: Si por cualquier motivo la configuración de la extensión no aparece, revisar la configuración en Webmin. A veces en algunos campus es presente un espacio inicial que hay que quitar Se configura el X-lite para conectarse a la extensión 1004. En la consola de Asterisk aparecerá:
Si se quiere ver el estado de la extensión en la consola de Asterisk como si fuera configurada en el archivo sip.conf y conocer su estado hay que modificar dos parámetros: • •
qualify=yes en la configuración de la extensión rtcachefriends=yes en la parte general del archivo sip.conf IMPORTANTE: si se utiliza el parámetro rtcachefriends=yes la configuración de las extensiones se cargaran en una cache de memoria y si se modifica un parámetro de una extensión en la base de datos, habrá que actualizar la configuración con CLI> sip reload
Se recarga la configuración sip: CLI> sip reload y se mira si aparece: CLI> sip show peers like 1004
En la columna Realtime aparece “Cached RT” que significa que la extensión está configurada en Realtime y que se activó el parámetro rtcachefriends. Desde la extensión 1004 se marca 123 para probarla. 306
12.2.2 Extensiones IAX en Realtime La configuración de las extensiones IAX en realtime es bastante similar a la que se ha mostrado para las extensiones SIP. Primero hay que crear la tabla mysql -u root -psesamo mysql> use asterisk mysql> CREATE TABLE `iaxexten` ( `name` varchar(40) NOT NULL default '', `type` varchar(10) NOT NULL default 'friend', `username` varchar(40) NULL, `mailbox` varchar(40) NULL, `secret` varchar(40) NULL, `dbsecret` varchar(40) NULL, `context` varchar(40) NULL, `regcontext` varchar(40) NULL, `host` varchar(40) NULL default 'dynamic', `ipaddr` varchar(20) NULL, `port` int(5) NULL, `defaultip` varchar(20) NULL, `sourceaddress` varchar(20) NULL, `mask` varchar(20) NULL, `regexten` varchar(40) NULL, `regseconds` int(11) NULL, `accountcode` varchar(20) NULL, `mohinterpret` varchar(20) NULL, `mohsuggest` varchar(20) NULL, `inkeys` varchar(40) NULL, `outkey` varchar(40) NULL, `language` varchar(10) NULL, `callerid` varchar(100) NULL, `cid_number` varchar(40) NULL, `sendani` varchar(10) NULL, `fullname` varchar(40) NULL, `trunk` varchar(3) NULL, `auth` varchar(20) NULL, `maxauthreq` varchar(5) NULL, `requirecalltoken` varchar(4) NULL, `encryption` varchar(20) NULL, `transfer` varchar(10) NULL, `jitterbuffer` varchar(3) NULL, `forcejitterbuffer` varchar(3) NULL, `disallow` varchar(40) NULL, 307
`allow` varchar(40) NULL, `codecpriority` varchar(40) NULL, `qualify` varchar(10) NULL, `qualifysmoothing` varchar(10) NULL, `qualifyfreqok` varchar(10) NULL, `qualifyfreqnotok` varchar(10) NULL, `timezone` varchar(20) NULL, `adsi` varchar(10) NULL, `amaflags` varchar(20) NULL, `setvar` varchar(200) NULL, PRIMARY KEY (`name`), INDEX name (name, host), INDEX name2 (name, ipaddr, port), INDEX ipaddr (ipaddr, port), INDEX host (host, port) ); mysql> quit Luego se modifica el archivo extconfig.conf: nano /etc/asterisk/extconfig.conf se cambian estas dos lineas: ;iaxusers => odbc,asterisk ;iaxpeers => odbc,asterisk para que queden: iaxusers => odbc,asterisk,iaxexten iaxpeers => odbc,asterisk,iaxexten se guarda la configuración y se crea una extensión IAX en Realtime desde Webmin entrando en la tabla iaxexten:
308
309
Al terminar se presiona el botón “Save”. Como para el protocolo SIP se cambia el parámetro rtcachefriends en el iax.conf: nano /etc/asterisk/iax.conf rtcachefriends=no para que quede: rtcachefriends=yes Se guarda la configuración y se actualiza Asterisk: service asterisk reload En el cliente Zoiper se configura el usuario marko2 y se mira en la consola de Asterisk si está registrado: asterisk -rvvvvvvvvvvvvvv CLI> iax2 show peers
Para terminar hay que modificar el dialplan para que se pueda marcar a las extensiones creadas en Realtime: CLI> quit nano /etc/asterisk/extensions.conf 310
Se modifica este bloque: exten => _100[0-2],1,Gosub(disponible,s,1(${EXTEN})) same => n,gosub(calendario,s,1(${EXTEN})) same => n,Dial(SIP/${EXTEN},45,hHkKtTwWxX) same => n,Hangup para que quede: exten => _100[0-2,4],1,Gosub(disponible,s,1(${EXTEN})) same => n,gosub(calendario,s,1(${EXTEN})) same => n,Dial(SIP/${EXTEN},45,hHkKtTwWxX) same => n,Hangup siempre en el contexto internas se pone: exten => 1235,1,Dial(IAX2/marko2,30) same => n,Hangup para terminar en el contexto subscribe se añade: exten => 1004,hint,SIP/1004 exten => marko2,hint,IAX2/marko2 Se guarda los cambios y se recarga el dialplan: asterisk -rx "dialplan reload" 10.2.3 Dialplan en Realtime dinamico Entre los objetos que se pueden guardar en Realtime dinámico, está el dialplan. De esta forma se pueden crear distintos dialplan para distintos servidores Asterisk conectados en Realtime a la base de datos. Esta puede ser una optima solución cuando se quieren compartir partes de dialplan entre distintos servidores Asterisk o cuando se quiere tener el motor de la base de datos en otro servidor. Para iniciar se crea la tabla para guardar el dialplan en la base de datos: mysql -u root -psesamo mysql> use asterisk mysql> CREATE TABLE `dialplan` ( `id` int(11) NOT NULL auto_increment, `context` varchar(20) NOT NULL default '', `exten` varchar(20) NOT NULL default '', 311
`priority` tinyint(4) NOT NULL default '0', `app` varchar(20) NOT NULL default '', `appdata` varchar(128) NOT NULL default '', PRIMARY KEY (`context`,`exten`,`priority`), KEY `id` (`id`) ); ahora se crea en la tabla una extensión muy sencilla: mysql> INSERT INTO dialplan (context,exten,priority,app,appdata) VALUES ('test','70','1','Answer','0'); mysql> INSERT INTO dialplan (context,exten,priority,app,appdata) VALUES ('test','70','2','Playback','demo-congrats'); mysql> INSERT INTO dialplan (context,exten,priority,app,appdata) VALUES ('test','70','3','Hangup','0'); el resultado será: mysql> select * from dialplan;
Se sale del cliente MySQL y se modifica el archivo extconfig.conf: mysql> quit nano /etc/asterisk/extconfig.conf Se busca esta linea: ;extensions => odbc,asterisk y se modifica para que quede: extensions => odbc,asterisk,dialplan Se guardan los cambios y se pasa al dialplan
312
nano /etc/asterisk/extensions.conf Antes del contexto internas se añade este bloque que configura Asterisk para que busque el contexto test en la base de datos: [test] switch => Realtime y se añade las lineas en negrita en los dos bloques que siguen: [externas] include => internas include => internacio include => parkedcalls include => test [locales] include => internas include => auten include => parkedcalls include => test De esta forma las extensiones que tengan acceso al contexto externas o locales, tendrán acceso también al contexto test. Se guardan los cambios y se reinicia Asterisk: service asterisk restart Desde la extensión 1000 se marca el numero 70 y se prueba el nuevo contexto creado en Realtime. Para averiguar que cuando se modifique el dialplan en realtime, este sea activo en seguida, se cambia el numero de extensión presente en la tabla: mysql -u root -psesamo mysql> use asterisk mysql> update dialplan set exten=80 where exten='70'; mysql> select * from dialplan;
313
Se sale del cliente MySQL: mysql> quit Sin actualizar el dialplan desde la extensión 1000 se marca el numero 80: asterisk -rvvvvvvvvvvvvv -- Executing [80@externas:1] Answer("SIP/1004-00000002", "0") -- Executing [80@externas:2] Playback("SIP/1004-00000002", "demo-congrats") -- Playing 'demo-congrats.g722' (language 'es')
314
Capitulo XIII IVR avanzados – func_odbc.conf La función func_odbc permite realizar consultas en base de datos directamente desde el dialplan. Al mismo tiempo es posible actualizar o modificar entradas de la base de datos. El archivo que se utiliza para este tipo de configuración es el func_odbc.conf. En este modulo, se ilustrarán cuatro diferentes escenarios: • • • •
Buscar el nombre de un empleado en base a su numero de matricula Guardar los resultados de una encuesta telefónica en una base de datos Bolsa de minutos Consultas que devuelven más de un resultado
13.1 Empleados La tabla de los empleados contendrá solamente dos campos: 1. numero de matricula 2. nombre Se crea la tabla en la base de datos Asterisk: mysql -u root -psesamo mysql> use asterisk mysql> CREATE TABLE `empleados` ( `id` int(11) NOT NULL auto_increment, `nombre` varchar(20) NOT NULL, `matricula` int(4) NOT NULL, PRIMARY KEY (`nombre`), KEY `id` (`id`) ); Se añaden a la tablas cuatro empleados: mysql> INSERT INTO empleados (nombre,matricula) VALUES ('fulano','1234'), ('zutano','1235'),('mengano','1236'),('perengano','1237'); el resultado: mysql> select * from empleados;
mysql> quit Ahora se crea el archivo func_odbc.conf. Primero se renombra el predefinido: mv /etc/asterisk/func_odbc.conf /etc/asterisk/func_odbc.conf.old se crea el nuevo: nano /etc/asterisk/func_odbc.conf y se copian las siguientes lineas: [Empleados] dsn=asterisk readsql=SELECT nombre FROM empleados WHERE matricula='${SQL_ESC(${ARG1})}' • • •
[Empleados] – El nombre de la función que se está creando dsn – el nombre de la etiqueta definida al inicio del bloque configurado en el archivo res_odbc.conf para la base de datos asterisk readsql=SELECT nombre FROM empleados WHERE matricula='${SQL_ESC(${ARG1})}' – la sentencia SQL para realizar consultas en la base de datos asterisk (en este caso la tabla empleados)
Para interaccionar con el usuario que llame para consultar la base de datos, se utilizará otro sistema de TTS (text to Speech); en este caso Festival. En Asterisk hay un modulo dedicado a la conexión con un servidor Festival. Lo único que hace falta es su configuración. Primero se averigua si el modulo está compilado y funcionando: asterisk -rvvvvvvvvvvvvvvv CLI> module unload app_festival.so CLI> module load app_festival.so == Parsing '/etc/asterisk/festival.conf': == Found == Registered application 'Festival' Loaded app_festival.so => (Simple Festival Interface) CLI> quit 317
Festival viene con el inglés como idioma predefinido. Para configurarlo con el idioma español se siguen estos pasos: se modifica el archivo de configuración de festival: nano /usr/share/festival/lib/festival.scm se añaden estas líneas antes de la ultima linea del archivo: ;(language__spanish) (set! voice_default 'voice_JuntaDeAndalucia_es_sf_diphone) (define (tts_textasterisk string mode) "(tts_textasterisk STRING MODE) Apply tts to STRING. This function is specifically designed for use in server mode so a single function call may synthesize the string. This function name may be added to the server safe functions." (let ((wholeutt (utt.synth (eval (list 'Utterance 'Text string))))) (utt.wave.resample wholeutt 8000) (utt.wave.rescale wholeutt 5) (utt.send.wave.client wholeutt))) Se guardan los cambios y se modifica el archivo de configuración de festival en Asterisk: mv /etc/asterisk/festival.conf /etc/asterisk/festival.conf.old nano /etc/asterisk/festival.conf estas son las líneas que hay que añadir: [general] host=localhost port=1314 festivalcommand=(tts_textasterisk "%s" 'file)(quit)\n Se guardan las modificaciones. Se actualiza la configuración de Asterisk: /etc/init.d/asterisk reload Para iniciar el servidor Festival en automático: nano /etc/rc.local al final del archivo se añade esta linea: /usr/bin/festival_server > /dev/null &
318
Se inicia el servidor festival; /usr/bin/festival_server > /dev/null & Se averigua que esté corriendo: ps aux | grep festival root 24071 0.0 0.2 4600 1096 pts/1 S 13:36 0:00 /bin/sh /usr/bin/festival_server root 24077 0.4 3.6 23464 19324 pts/1 S 13:36 0:00 festival --server ./festival_server.scm root 24081 0.0 0.1 4028 688 pts/1 S+ 13:36 0:00 grep festival Se modifica el Dialplan para crear una extensión que permita efectuar una prueba del servidor Festival: nano /etc/asterisk/extensions.conf en el contexto internas se pone: exten => 650,1,Answer() same => n,Festival(Asterisk y Festival trabajan junto. Chevere!!!) same => n,Hangup() Se actualiza el dialplan desde la consola: asterisk -rvvvvvvvvvvvvvvvvv CLI> dialplan reload Desde la extensión 1000 se marca la extensión 650 para escuchar la frase que se acaba de configurar en el dialplan. CLI> quit Terminada la configuración y la prueba de Festival se construye el dialplan para realizar consultas a la tabla empleados: nano /etc/asterisk/extensions.conf en el contexto internas se pone: exten => 660,1,Answer same => n,Wait(2) same => n,Festival(Por favor ingrese los 4 digitos de la matricula del empleado.) same => n,Read(EMPNUM,beep,4) same => n,Set(EMPNAME=${ODBC_Empleados(${EMPNUM})}) same => n,GotoIf($[${EXISTS(${EMPNAME})}]?nombre) same => n,Festival(Ningun empleado encontrado. Hasta luego.) same => n,Hangup 319
same => n(nombre),Festival(El nombre del empleado es ${EMPNAME}. Hasta luego.) same => n,Hangup Una explicación de las lineas: • • • • • • • • • •
Linea1 – se contesta la llamada Linea2 – se esperan dos segundos Linea3 – Se usa Festival para leer el texto y enviarlo como audio Linea 4 – Con la aplicación Read se espera que el llamante digite 4 números y se guardan en la variable EMPNUM Linea 5 – Se realiza la consulta en la tabla Empleados como configurado en el archivo func_odbc. Desde la lógica de MySQL sería: select nombre from empleados where matricula='$ {EMPNUM}'; Linea6 – Si la consulta devuelve un valor se va a la etiqueta (nombre), si la consulta no devuelve ningún valor se continua en el dialplan (la función EXIST permite averiguar si una determinada variable contiene un valor o está vacía) Linea7 – En el caso la consulta no haya tenido éxito, se anuncia al llamante que no se ha encontrado ningún empleado que tenga ese numero de matricula Linea8 – se termina la llamada Linea9 – Si la consulta ha tenido éxito, se anuncia al llamante el nombre del empleado Linea10 – se termina la llamada
Se guardan los cambios y se recarga el dialplan: asterisk -rvvvvvvvvvvvvvvvvvvvvvvvv CLI> dialplan reload Desde la extensión 1000 se marca 660 y se efectúan diferentes pruebas. En la consola: Executing [660@externas:1] Answer("SIP/1000-00000010", "") in new stack -- Executing [660@externas:2] Wait("SIP/1000-00000010", "2") in new stack -- Executing [660@externas:3] Festival("SIP/1000-00000010", "Por favor ingrese los 4 digitos de la matricula del empleado.") in new stack == Parsing '/etc/asterisk/festival.conf': == Found -- Executing [660@externas:4] Read("SIP/1000-00000010", "EMPNUM,beep,4") in new stack -- Accepting a maximum of 4 digits. -- Playing 'beep.alaw' (language 'es') -- User entered '1234' -- Executing [660@externas:5] Set("SIP/1000-00000010", "EMPNAME=fulano") in new stack -- Executing [660@externas:6] GotoIf("SIP/1000-00000010", "1?nombre") in new stack -- Goto (externas,660,9) -- Executing [660@externas:9] Festival("SIP/1000-00000010", "El nombre del empleado es fulano. Hasta luego.") in new stack == Parsing '/etc/asterisk/festival.conf': == Found 320
-- Executing [660@externas:10] Hangup("SIP/1000-00000010", "") in new stack == Spawn extension (externas, 660, 10) exited non-zero on 'SIP/1000-00000010' 13.2 Encuesta Se quiere suministrar una encuesta a los clientes de la empresa para medir el grado de satisfacción de los mismos. La encuesta está compuesta por 4 preguntas. Las preguntas se pueden grabar o, como en este caso, se utilizará Festival. Los pasos a seguir son: • • •
crear la tabla para la encuesta crear un nuevo bloque en el archivo func_odbc.conf crear un nuevo bloque de dialplan
Se inicia creando la tabla: mysql -u root -psesamo mysql> use asterisk mysql> CREATE TABLE `encuesta` ( `id` bigint(20) NOT NULL auto_increment, `fecha` datetime default NULL, `resp1` int(1) default NULL, `resp2` int(1) default NULL, `resp3` int(1) default NULL, `resp4` int(1) default NULL, PRIMARY KEY (`id`) ); se sale del cliente mysql: mysql> quit se abre el archivo func_odbc.conf nano /etc/asterisk/func_odbc.conf al final del archivo se añade el siguiente bloque: [Encuesta] dsn=asterisk writesql=insert into encuesta (Fecha,resp1,resp2,resp3,resp4) values ("${SQL_ESC(${VAL1})}","$ {SQL_ESC(${VAL2})}","${SQL_ESC(${VAL3})}","${SQL_ESC(${VAL4})}","${SQL_ESC($ {VAL5})}")
321
IMPORTANTE: El contenido de la sentencia writesql tiene que estar en la misma linea. Para terminar se modifica el dialplan: nano /etc/asterisk/extensions.conf en el contexto internas se pone: exten => 670,1,Goto(encuesta,s,1) same => n,Hangup y después del contexto internas se pone el siguiente bloque: [encuesta] exten => s,1,Answer same => n,Wait(2) same => n,Festival(Pregunta uno) same => n,Read(var1,,1,,10) same => n,Festival(Pregunta dos) same => n,Read(var2,,1,,10) same => n,Festival(Pregunta tres) same => n,Read(var3,,1,,10) same => n,Festival(Pregunta cuatro) same => n,Read(var4,,1,,10) same => n,Set(ODBC_Encuesta()=${STRFTIME(${EPOCH},,%y%m%d%H%M%S)},${var1},${var2},${var3},${var4})
same => n,Playback(thank-you-cooperation) same => n,Hangup El bloque de dialplan es bastante comprensible. Se presentan las cuatros preguntas. Se guardan los dígitos en 4 variables distintas y al terminar la encuesta se guardan los resultados en la tabla encuesta a través de la función ODBC_Encuesta que se acaba de crear en el archivo func_odbc.conf. Se guardan las modificaciones y se actualiza Asterisk: service asterisk reload Desde unas de las extensiones conectadas a Asterisk se marca el 670 y se contestan las preguntas. Se repite la operación 3-4 veces. Para ver los resultados: mysql -u root -psesamo mysql> use asterisk mysql> select * from encuesta;
322
Los resultados aparecen ordenados por ID y fecha. 13.3 Bolsa de minutos Se quiere limitar las llamadas a celulares que realizan las extensiones sobre base mensual; por ejemplo las extensiones tienen 300 minutos mensuales disponibles para llamar celulares. Para este caso también se puede utilizar la función func_odbc y crear la consulta en la tabla CDR que contiene todos los registros de las llamadas. En el plan de marcado se controlará los minutos que una extensión ha consumido para llamadas a celulares y, si supera los admitidos, se le comunicará. Lo primero que hay que hacer es crear una nueva conexión a la base de datos asteriskcdr en ODBC: nano /etc/odbc.ini se copian las siguientes lineas: [asteriskcdr] Description = MySQL AsteriskCDR Driver = MySQL Database = asteriskcdr Server = localhost User = asterisk Password = sesamo Port = 3306 Option = 3 Se guardan los cambios y se averigua que la conexión esté funcionando: isql asteriskcdr asterisk sesamo +---------------------------------------+ | Connected! | | | | sql-statement | | help [tablename] | | quit | 323
| | +---------------------------------------+ Perfecto. Ya se puede salir del programa: SQL> quit Ahora, como se ha hecho para el Asterisk Realtime, si crea un nuevo bloque en el archivo res_odbc.conf: nano /etc/asterisk/res_odbc.conf al final de archivo, se añade el siguiente bloque: [cdr] enabled => yes dsn => asteriskcdr username => asterisk password => sesamo pre-connect => yes sanitysql => select 1 idlecheck => 3600 connect_timeout => 10 Se guardan los cambios y se crea la query (consulta) en el archivo func_odbc.conf: nano /etc/asterisk/func_odbc.conf al final del archivo se añaden las siguientes lineas: [CDR] dsn=cdr readsql=select sum(billsec) from cdr where calldate like '${SQL_ESC(${ARG1})}%' and src='$ {SQL_ESC(${ARG2})}' and dst like '00573%' El campo billsec de la tabla CDR contiene la duración de la llamada desde que ha sido contestada. La función sum de MySQL permite sumar todos los valores encontrados en el campo billsec por el mes seleccionado. La consulta sería: suma todos los segundos de conversación efectuados por la extensión X en el mes Y (normalmente el mes corriente) para las llamadas hacia números que empiecen por 00573 (en este caso los celulares de Colombia). Una vez creada la consulta hacia la base de datos se puede crear un nuevo bloque en el dialplan para efectuar la consulta y utilizar el valor restituido para definir el tipo de comportamiento. Se abre el archivo del plan de marcado: 324
nano /etc/asterisk/extensions.conf y en el contesto internacio se crea un nuevo bloque: exten => _00573.,1,Noop same => n,Set(fecha=${STRFTIME(epoch,,%Y-%m)}%) same => n,Set(consumo=${ODBC_CDR(${fecha},${CALLERID(num)})}) same => n,Set(minutos=${MATH(${consumo} / 60,int)}) same => n,Noop(Segundos ${consumo} Minutos ${minutos}) same => n,Gotoif($[${minutos} > 300]?acaba) same => n,Dial(SIP/voztovoice/${EXTEN}) same => n,Hangup same => n(acaba),Festival(Estimado. No tienes más minutos de llamadas a celulares disponibles. Contacte el administrador) same => n,Hangup Este bloque se utilizará solamente para las llamadas a celulares (de Colombia). Asterisk antes de efectuar la llamada consulta la tabla CDR y suma todos los segundos utilizados por la extensión que está llamando a celulares. El valor se divide por 60 y del resultado se saca el numero entero (con la función MATH). Si los minutos utilizados son más de 300 se comunica a la extensión, de lo contrario se efectúa la llamada. Se recarga la configuración de Asterisk: service asterisk reload y se realiza una llamada a un celular de Colombia. En la consola de Asterisk: Executing [00573163435746@externas:1] NoOp("SIP/1000-00000013", "") in new stack Executing [00573163435746@externas:2] Set("SIP/1000-00000013", "fecha=2013-03%") in new stack Executing [00573163435746@externas:3] Set("SIP/1000-00000013", "consumo=5") in new stack Executing [00573163435746@externas:4] Set("SIP/1000-00000013", "minutos=0") in new stack Executing [00573163435746@externas:5] NoOp("SIP/1000-00000013", "Segundos 5 Minutos 0") in new stack
Executing [00573163435746@externas:6] GotoIf("SIP/1000-00000013", "0?acaba") in new stack Executing [00573163435746@externas:7] Dial("SIP/1000-00000013", "SIP/voztovoice/00573163435746") in new stack
13.4 Consultas con respuestas múltiples A veces se necesita realizar consultas en una base de datos que devuelven más de un resultado. Un ejemplo podría ser averiguar cuantas veces un determinado numero de teléfono está presente en una determinada tabla. En este párrafo se mostrará como efectuar una consulta de este tipo en la tabla CDR de la base de datos Asterisk y anunciar al llamante la duración de cada llamada. 325
Como en el párrafo anterior ya se ha creado una conexión a la tabla CDR de la base de datos Asterisk, lo único que hace falta es configurar el archivo func_odbc.conf. Se abre: nano /etc/asterisk/func_odbc.conf Al final se añade: [llamada] dsn=cdr mode=multirow readsql=select billsec from cdr where dst='${SQL_ESC(${ARG1})}' El parámetro mode=multirow permite realizar consultas que pueden devolver más de un resultado. La sentencia sería: selecciona el campo billsec (la duración de la llamada desde el momento en que se contesta) desde la tabla cdr donde el campo dst (que contiene el numero llamado) es igual a la variable que luego se pasará a través del dialplan. Se guardan los cambios y se crea un nuevo bloque de dialplan para efectuar la consulta: nano /etc/asterisk/extensions.conf En el bloque internas se pone: exten => 680,1,Answer same => n,Festival(Por favor ingrese el numero de teléfono a buscar y presione la tecla numero.) same => n,Read(TELNUM,beep,20) same => n,Set(ID=${ODBC_llamada(${TELNUM})}) same => n,NoOP(Columnas ${ODBCROWS} ID ${ID}) same => n,Set(contar=${ODBCROWS}) same => n,While($[${contar} > 0]) same => n,Set(durac=${ODBC_FETCH(${ID})}) same => n,Festival(Llamada de ${durac} segundos) same => n,Set(contar=($[${contar} - 1])) same => n,Endwhile same => n,OdbcFinish same => n,Hangup Una explicación del bloque: • • • • •
Linea 1 – se contesta la llamada Linea 2 – Se solicita al llamante que ingrese el numero de teléfono a buscar Linea 3 – Se utiliza la aplicación Read para almacenar el numero digitado en la variable TELNUM Linea 4 – Cuando se realiza una consulta que puede devolver más de un resultado, la aplicación devuelve un numero (ID) que contiene todos los resultados encontrados Linea 5 – Se devuelve a la consola de Asterisk el numero de resultados encontrados a través de 326
• • • • • • • •
la variable ${ODBCROWS} y el ID asignado a la consulta Linea 6 – se asigna la variable contar el numero de resultados encontrados Linea 7 – Hasta que la variable contar sea mayor que cero, se ejecutará el ciclo que sigue Linea 8 – se asigna la variable durac el valor de la duración de la llamada del primer resultado encontrado. ${ODBC_FETCH(${ID})}) Esta función permite sacar el primer resultado encontrado. Linea 9 – Se anuncia la duración del primer resultado encontrado Linea 10 – Se asocia a la variable contar su valor menos 1 Linea 11 – Se cierra el ciclo y se vuelve a la linea del While. Si el valor de la variable contar es todavía mayor que cero, se procesa el ciclo nuevamente. Linea 12 – Cuando el ciclo termine con la aplicación ODBCFinish se “limpia” el resultado de la consulta efectuada. Linea 13 – Se termina la llamada.
Se guardan los cambios y si actualiza Asterisk: service asterisk reload Ahora se puede efectuar una prueba llamando la extensión 680 y digitando el numero 005714013434 que en teoría se ha marcado más de una vez. Claramente este es un ejemplo muy sencillo de este tipo de consultas pero es un buen punto de partida para escenario más complejos.
327
Capitulo XIV Buzón de voz – voicemail.conf En el archivo voicemail.conf es donde se configura todo lo relacionado con el buzón de voz. Si se recibe una llamada y no se contesta o la línea está ocupada, siempre y cuando se configure el dialplan oportunamente, entrará en función el buzón de voz, grabará el mensaje de voz dejado por quien llama y enviará una notificación por correo electrónico al llamado. Anexo al correo electrónico es posible enviar el mensaje de voz en distintos formatos audio. A través de la configuración de este archivo es posible, además, crear distintos grupos de buzones de voz (distintas empresa) y configurar distintas zonas horarias. 14.1 voicemail.conf Como para los demás archivos de configuración, en la tabla a seguir se indicarán los parámetros que se van a configurar con una breve descripción. En negrita los valores de cada parámetro. Al final de la tabla, la configuración completa del archivo. Parámetro
Descripción
[general]
Inicia la parte general
format
Los formatos audio en que se grabará cada mensaje de voz. Valor wav49|gsm|wav IMPORTANTE: si se cambian los formatos audios en un sistema que ya contiene mensajes de voz guardados, habrá que entrar en la carpeta de cada usuario y modificar el formato audio manualmente en uno de los nuevos formatos. Se aconseja no modificar este parámetro en un sistema en producción.
serveremail
Dirección de correo electrónico del remitente en la notificaciones de la presencia de un nuevo mensaje de voz. Valor [email protected]. Un ejemplo para Linode: [email protected] Personalizar
attach
yes = se anexa al correo electrónico el archivo audio que contiene el mensaje de voz.
maxmsg
Numero máximo de mensajes de voz guardados para cada buzón de voz. Valor 100
maxsecs
Numero máximo de segundos que puede durar un mensaje de voz. Valor 500
minsecs
Numero mínimo de segundos para que un mensaje de voz sea reconocido como tal y enviado al buzón de voz del destinatario. Valor 3
maxgreet
Duración máxima, en segundos, del mensaje de bienvenida que cada propietario de un buzón de voz puede grabar para
Parámetro
Descripción presentarse. Valor 180
skipms
Cuando se escuchan los mensaje de voz, se puede utilizar el teclado numérico del teléfono para adelantar o devolver el mensaje. Este valor se define en mili segundos y representa de cuanto se adelantará/devolverá el mensaje de voz. Valor 3000
maxsilence
Si mientras se deja un mensaje en el buzón de voz hay un silencio mayor al numero de segundos indicados en este parámetro, se termina la grabación. Valor 2 Tienes que ser un valor inferior del parámetro minsecs
silencethreshold
El numero indicado en este parámetro indica el nivel de ruido y sirve para definir que se considera silencio. Más bajo el número, más sensible al ruido. Valor 128
maxlogins
Numero máximo de intentos permitidos para marcar la clave asociada al buzón de voz personal. Valor 3
moveheard
yes = una vez escuchados los nuevos mensajes de voz, se mueven a la carpeta OLD (viejos) en automático; si se configura en no, hay que hacerlo desde el menú del buzón de voz
forward_urgent_auto
yes = cada mensaje de voz reenviado se considerará urgente. Valor no
;externnotify=/usr/bin/myapp
si se quiere ejecutar una aplicación cada vez que llega un nuevo mensaje de voz, hay que definirla en este parámetro. Se deja comentado
;externpass=/usr/bin/myapp
cada vez que se cambie la contraseña de un buzón de voz, es posible ejecutar un script externo. Se deja comentado
;externpassnotify=/usr/bin/myapp
Cada vez que se cambie la contraseña de un buzón de voz y se configure el nombre de un script en este parámetro, las variables contexto, mailbox y nueva contraseña se pasarán al script; si el parámetro anterior se ha configurado, este no será tomado en cuenta.
directoryintro
La locución de introducción de la aplicación directory. Se explicará más adelante que es y como funciona. Valor dir-intro
charset
El estándar ISO para los correo electrónicos que se enviarán para notificar la llegada de un nuevo mensaje de voz. Valor ISO-8859-1
pbxskip
yes = quita la sigla [PBX] en el asunto de los correos electrónicos de notifica
fromstring
Nombre del remitente del los correos electrónicos. Valor Buzón de Voz
330
Parámetro
Descripción
usedirectory
yes = los mensajes de voz que se reciben se pueden reenviar a otros usuarios/extensiones del servidor Asterisk. También se pueden dejar directamente mensajes de voz a otros buzones. Este parámetro permite buscar en el directorio la persona a la que se quiere dejar o reenviar el mensaje de voz
;odbcstorage
Se pueden guardar los mensajes de voz en un base de datos usando el conector ODBC. En este parámetro se define el nombre de la base de datos. Valor asterisk (se deja comentado)
;mensajes
El nombre de la tabla de la base de datos donde guardar los mensaje de voz. Valor: mensajes (se deja comentado)
emailsubject
Asunto del correo electrónico de notificación. Valor. Nuevo mensaje de voz ${VM_MSGNUM} en el buzón de voz $ {VM_MAILBOX}
emailbody
Contenido del correo electrónico. Tiene que estar todo en la misma linea. Valor: Estimado ${VM_NAME}:\n\n\t le estamos enviando este correo para avisarle que ha recibido un nuevo mensaje de voz de ${VM_DUR} segundos (numero $ {VM_MSGNUM})\n\n buzon de voz ${VM_MAILBOX} del numero ${VM_CALLERID}, el ${VM_DATE}.\n\n Llame su buzon de voz para escucharlo. Gracias!\n\n\t\t\t\t.Tu Buzon de Voz\n Nombre empresa Personalizar según sus necesidades
emaildateformat
Formato de la hora y fecha del correo electrónico. Valor %A, %d %B %Y at %H:%M:%S
mailcmd
comando Linux para enviar el correo electrónico. En este caso se utiliza Sendmail. Valor /usr/sbin/sendmail -t
tz
zona horaria predefinida para indicar fecha y hora de llegada del mensaje de voz. Valor central A partir de este parámetro inicia la configuración avanzada del archivo.
locale
Desde la versión 1.8 de Asterisk es posible configurar el idioma para el formato de la fecha que aparece en el mensaje de notificación. Se pone el mismo valor configurado para el idioma del sistema operativo (para Colombia): es_CO.iso88591
attach
yes = se envían los nuevos mensajes de voz anexos al correo electrónico de notificación.
attachfmt
de los tres formatos audio en que se grabarán los mensaje de voz (definidos en el parámetro format), se escoge él que se utilizará para anexar el audio al correo electrónico. Valor wav
331
Parámetro
Descripción
saycid
yes = antes de escuchar el mensaje de voz se anuncia el CallerID del llamante
cidinternalcontexts
nombre del contexto del dialplan donde buscar el contexto de los buzones de voz para anunciar en lugar del numero de extensión el nombre de la persona que dejó el mensaje. Valor internas
sayduration
yes = anuncia la duración del mensaje de voz
saydurationm
define la duración mínima del mensaje de voz para que sea anunciado (en minutos). Valor 2
dialout
nombre del contexto del dialplan para efectuar llamadas salientes desde el menú del buzón de voz (opción 4 del menú avanzado). Valor externas
sendvoicemail
Permitir o no de enviar el mensaje de voz a otra extensión desde el menú del buzón de voz. (opción 5 del menú avanzado). Valor yes
;callback=fromvm
Nombre del contexto del dialplan para poder llamar el remitente del mensaje de voz. Se deja comentado
:exitcontext=fromvm
Nombre del contexto donde enviar el llamante si presiona una tecla antes de dejar un mensaje. Se deja comentado
review
yes = Permite al llamante escuchar el mensaje de voz que ha grabado antes de enviarlo
;operador=yes
permite al llamante presionar la tecla 0 para hablar con un operador mientras se encuentra en el buzón de voz. Se deja comentado
envelope
yes = antes de reproducir un mensaje de voz, se anuncian todos los datos del mensaje mismo (fecha, hora, etc.)
delete
no = no se borra el mensaje de voz una vez que se ha enviado anexo al correo electrónico de notificación.
volgain
permite subir el volumen de grabación de los mensajes de voz. Para que funcione se necesita que SOX sea instalado en el servidor. Valor 0.0
nextaftercmd
yes = en el caso en que hay más de un mensaje de voz presente en el buzón de voz, permite pasar al mensaje siguiente presionando las teclas 7 o 9 (borrar/guardar el mensaje respectivamente)
forcename
yes = obliga cada usuario con un buzón de voz configurado a grabar su nombre la primera vez que accede. Un usuario se considera nuevo si la contraseña del buzón de voz coincide con el numero de extensión 332
Parámetro
Descripción
forcegreeting
no = obliga un nuevo usuario a grabar un mensaje de bienvenida para su buzón de voz
hidefromdir
no = el usuario aparecerá en el directorio. yes = el usuario no aparecerá en el directorio
tempgreetwarn
yes = recuerda al usuario que el mensaje de bienvenida que está utilizando es temporal hasta que no grabe uno personalizado.
passwordlocation
Es posible definir donde se guardarán las contraseñas para cada buzón de voz. Posibles valores: – voicemail.conf - Se guardarán en este archivo – spooldir – la contraseñas de cada usuario se guardarán en un archivo de texto (secret.conf) en la carpeta /var/spool/asterisk/voicemail/contexto/usuario donde contexto es el nombre del contexto al que pertenece el buzón de voz y usuario es el numero del buzón de voz de la extensión
messagewrap
yes = Mientras se están escuchando los mensajes de voz, permite presionando la tecla 6 pasar del ultimo mensaje escuchado al primero, presionando 4 del primer mensaje ir al ultimo.
minpassword
define una longitud mínima para la contraseña del buzón de voz (el numero de cifras). Valor 4
;vm-password=custom_sound estos parámetros permiten personalizar las locuciones. Se ;vm-newpassword=custom_sound dejan comentadas ;vm-passchanged=custom_sound ;vm-reenterpassword=custom_sound ;vm-mismatch=custom_sound ;vm-invalid-password=custom_sound ;vm-pls-try-again=custom_sound listen-control-forward-key
# = tecla para el avance rápido del mensaje
listen-control-reverse
* = tecla para rebobinar el mensaje
listen-control-pause-key
0 = tecla numérica para poner en pausa/reanudar el mensaje
listen-control-restart-key
2 = tecla numérica para volver a escuchar el mensaje desde el inicio
listen-control-stop-key
13456789 = teclas numéricas para terminar la escucha de un mensaje de voz (todas, menos las ya configuradas)
backupdeleted
50 = numero máximo de mensajes de voz permitidos en la carpeta de borrados
333
Parámetro
Descripción
[zonemessages]
a partir de esta etiqueta se configuran las distintas zona horarias que se podrán configurar para cada buzón de voz. De esta forma el propietario de cada buzón de voz, escuchará la fecha y la hora en que se dejó el mensaje de voz según el país en que se encuentre. Lo mismo pasará con el correo electrónico de notificación. Siguen algunos ejemplos
eastern
America/New_York|'vm-received' Q 'digits/at' IMp
central
America/Chicago|'vm-received' Q 'digits/at' IMp
european
Europe/Copenhagen|'vm-received' a d b 'digits/at' HM
colombia
America/Bogota|'vm-received' aebY 'digits/at' HM
mexico
America/Mexico_City|'vm-received' aebY 'digits/at' HM
[default]
a partir de esta etiqueta se configuran los contextos para los buzones de voz. En el configuración de las extensiones en el sip.conf para el parámetro mailbox se ha puesto como valor “default”. Ese el el contexto que hay que configurar en el voicemail.conf y la etiqueta lo define. Después del contexto, se configuran todos los buzones de voz, uno por linea, siguiendo la sintaxis: Numero extensión => contraseña, nombre apellido, correo electrónico, correo pager,opciones
1000 =>
1000,fulano de tal,[email protected],,tz=colombia
1001 =>
1001,fulano de pascual,[email protected],,tz=colombia
1002 =>
1002,zutano pelado,[email protected],,tz=european
1234 =>
1234,marko,[email protected],,tz=mexico
1235 =>
1235,marko2,[email protected],,tz=central
IMPORTANTE: Todos los datos (nombre, correo electrónico y zona horaria presentes en el archivo, van personalizados. De esta forma se han definidos los buzones de voz para todas las extensiones configuradas en Asterisk menos la 1004. Como la contraseña es igual al numero de extensión, la primera vez que el usuario acceda a su buzón de voz, se le pedirá de cambiar la contraseña y configurar su buzón de voz. Ahora se puede crear el archivo. Se renombra el predefinido: mv /etc/asterisk/voicemail.conf /etc/asterisk/voicemail.conf.old se crea uno nuevo: nano /etc/asterisk/voicemail.conf
334
se copian las siguientes lineas: [general] format=wav49|gsm|wav [email protected] attach=yes maxmsg=100 maxsecs=500 minsecs=3 maxgreet=180 skipms=3000 maxsilence=2 silencethreshold=128 maxlogins=3 moveheard=yes forward_urgent_auto=no ;externnotify=/usr/bin/myapp ;externpass=/usr/bin/myapp ;externpassnotify=/usr/bin/myapp directoryintro=dir-intro charset=ISO-8859-1 pbxskip=yes fromstring=Buzon de Voz usedirectory=yes ;odbcstorage=asterisk ;odbctable=mensajes emailsubject=Nuevo mensaje de voz ${VM_MSGNUM} en el buzon de voz ${VM_MAILBOX} emailbody=Estimado ${VM_NAME}:\n\n\t le estamos enviando este correo para avisarle que ha recibido un nuevo mensaje de voz de ${VM_DUR} segundos (numero ${VM_MSGNUM})\n\n buzon de voz $ {VM_MAILBOX} del numero ${VM_CALLERID}, el ${VM_DATE}.\n\n Llame su buzon de voz para escucharlo. Gracias!\n\n\t\t\t\t.Tu Buzon de Voz\n Nombre empresa ; todo el texto del parametro "emailbody" tiene que estar en la misma linea emaildateformat=%A, %d %B %Y at %H:%M:%S mailcmd=/usr/sbin/sendmail -t tz=central locale=es_CO.iso88591 attach=yes attachfmt=wav saycid=yes cidinternalcontexts=internas sayduration=yes saydurationm=2 dialout=externas 335
sendvoicemail=yes ;callback=fromvm :exitcontext=fromvm review=yes ;operador=yes envelope=yes delete=no volgain=0.0 nextaftercmd=yes forcename=yes forcegreeting=no hidefromdir=no tempgreetwarn=yes passwordlocation=voicemail.conf messagewrap=yes minpassword=4 ;vm-password=custom_sound ;vm-newpassword=custom_sound ;vm-passchanged=custom_sound ;vm-reenterpassword=custom_sound ;vm-mismatch=custom_sound ;vm-invalid-password=custom_sound ;vm-pls-try-again=custom_sound listen-control-forward-key=# listen-control-reverse=* listen-control-pause-key=0 listen-control-restart-key=2 listen-control-stop-key=13456789 backupdeleted=50 [zonemessages] ; Supported values: ; 'filename' filename of a soundfile (single ticks around the filename ; required) ; ${VAR} variable substitution ; A or a Day of week (Saturday, Sunday, ...) ; B or b or h Month name (January, February, ...) ; d or e numeric day of month (first, second, ..., thirty-first) ;Y Year ; I or l Hour, 12 hour clock ;H Hour, 24 hour clock (single digit hours preceded by "oh") ;k Hour, 24 hour clock (single digit hours NOT preceded by "oh") ;M Minute, with 00 pronounced as "o'clock" ;N Minute, with 00 pronounced as "hundred" (US military time) ; P or p AM or PM ;Q "today", "yesterday" or ABdY ; (*note: not standard strftime value) 336
;q "" (for today), "yesterday", weekday, or ABdY ; (*note: not standard strftime value) ;R 24 hour time, including minute eastern=America/New_York|'vm-received' Q 'digits/at' IMp central=America/Chicago|'vm-received' Q 'digits/at' IMp european=Europe/Copenhagen|'vm-received' a d b 'digits/at' HM colombia=America/Bogota|'vm-received' aebY 'digits/at' HM mexico=America/Mexico_City|'vm-received' aebY 'digits/at' HM [default] ; personalizar nombres, apellidos, correos electrónicos y zona horaria 1000 => 1000,fulano de tal,[email protected],,tz=colombia 1001 => 1001,fulano de pascual,[email protected],,tz=colombia 1002 => 1002,zutano pelado,[email protected],,tz=european 1234 => 1234,marko,[email protected],,tz=mexico 1235 => 1235,marko2,[email protected],,tz=central IMPORTANTE: personalizar el parámetro serveremail con su nombre de dominio y los parámetros nombre, correo electrónico y zona horaria de cada buzón de voz. Se guardan los cambios y se recarga la configuración del voicemail.conf: asterisk -rvvvvvvvvvvvvvvvv CLI> voicemail reload Para ver los usuarios configurados y los mensajes de voz presentes: CLI> voicemail show users Context Mbox User Zone NewMsg default general New User 0 default 1000 fulano de tal colombia 0 default 1001 fulano de pascual colombia 0 default 1002 zutano de tal european 0 default 1234 marko mexico 0 default 1235 marko2 central 0 Para ver la zonas horarias configuradas: CLI> voicemail show zones Zone Timezone Message Format mexico America/Mexico_City 'vm-received' aebY 'digits/at' HM colombia America/Bogota 'vm-received' aebY 'digits/at' HM european Europe/Copenhagen 'vm-received' a d b 'digits/at' HM central America/Chicago 'vm-received' Q 'digits/at' IMp eastern America/New_York 'vm-received' Q 'digits/at' IMp
337
Se sale la consola: CLI> quit Para que una llamada, si no es contestada o si la extensión está ocupada, se envíe al buzón de voz, hay que modificar el dialplan. Como esta parte es igual para todas las extensiones, se creará una Subrutina. Se abre el archivo del dialplan: nano /etc/asterisk/extensions.conf Primero se añade la parte para llamar el buzón de voz en el contexto internas: exten => 97,1,Answer same => n,VoiceMailMain(${CALLERID(num)}@default) same => n,Hangup • • •
Linea1 – contesta la llamada Linea2 – envía la llamada al buzón de voz del llamante (CALLERID(num) y al contexto default (configurado en voicemail.conf) Linea2 – cuelga la llamada
Para entrar al buzón de voz general y luego digitar numero de buzón y contraseña: exten => 98,1,VoicemailMain same => n,Hangup Para buscar un usuario en el directorio: exten => 99,1,Directory(default,internas,e) same => n,Hangup se modifica estos tres bloques para que queden: exten => _100[0-2,4],1,Gosub(disponible,s,1(${EXTEN})) same => n,Gosub(calendario,s,1(${EXTEN})) same => n,Dial(SIP/${EXTEN},45,hHkKtTwWxX) same => n,Hangup exten => 1234,1,Dial(IAX2/marko,30) same => n,Hangup exten => 1235,1,Dial(IAX2/marko2,30) same => n,Hangup para que queden: 338
exten => _100[0-2,4],1,Dial(SIP/${EXTEN},45,hHkKtTwWxX) same => n,Gosub(voicemail,s,1(${EXTEN})) same => n,Hangup exten => 1234,1,Dial(IAX2/marko,30) same => n,Gosub(voicemail,s,1(${EXTEN})) same => n,Hangup exten => 1235,1,Dial(IAX2/marko2,30) same => n,Gosub(voicemail,s,1(${EXTEN})) same => n,Hangup Luego al final del archivo se crea la macro: [voicemail] exten => s,1,Goto(s-${DIALSTATUS},1) exten => s-BUSY,1,Voicemail(${ARG1}@default,b) same => n,Hangup exten => s-CANCEL,1,Hangup exten => s-CONGESTION,1,Congestion same => n,Hangup exten => _s-.,1,Voicemail(${ARG1}@default,u) same => n,Hangup La aplicación dial genera la variable DIALSTATUS que contiene uno de los siguientes valores: • • • • • • • •
CHANUNAVAIL CONGESTION NOANSWER BUSY ANSWER CANCEL DONTCALL TORTURE
En base al valor se enviará la llamada a un determinado punto de la subrutina, por ejemplo, si el valor es BUSY, la llamada se transferirá al buzón de voz anunciando al llamante que la extensión se encuentra ocupada. Se guardan los cambios y se recarga el dialplan: asterisk -rvvvvvvvvvvvvvvv CLI> dialplan reload 339
La primera operación es la de configurar el buzón de voz de la extensión 1000. Desde esa extensión se marca el numero 97 y se siguen los pasos indicados por las locuciones. Terminada esta operación se marca desde la extensión 1000 el numero 99 para probar el directorio. En el directorio se busca una persona digitando en el teclado del teléfono las primeras tres letras del apellido. Si el apellido existe, se podrá llamar directamente desde esta aplicación. Realizar la prueba marcando el apellido (como configurado en el voicemail.conf) de la extensión 1002. Como ultima prueba, desde la extensión 1001 se marca la extensión 1000 y no se contesta la llamada. La extensión 1001 será transferida al buzón de voz de la extensión 1000 donde se dejará un mensaje. En la interfaz de X-Lite (extensión 1000), aparecerá:
La parte evidenciada indica que hay un mensaje en el buzón de voz de la extensión 1000. Se puede comprobar también desde la consola: CLI> voicemail show users Context Mbox User Zone NewMsg default 1000 fulano de tal colombia 1 default 1001 fulano de pascual colombia 0 default 1002 zutano pelado european 0 default 1234 marko mexico 0 default 1235 marko2 central 0 7 voicemail users configured. y con el correo electrónico recibido:
340
El anexo es el archivo audio con el mensaje de voz. Se puede escuchar el mensaje llamando también el numero 97. Los tres archivos audio (en los tres formatos definidos en voicemail.conf) se encontrarán en la carpeta: ls -l /var/spool/asterisk/voicemail/default/1000/INBOX/ -rw-r--r-- 1 root root 17127 Oct 19 20:37 msg0000.gsm -rw-rw-rw- 1 root root 271 Oct 19 20:37 msg0000.txt -rw-r--r-- 1 root root 166124 Oct 19 20:37 msg0000.wav -rw-r--r-- 1 root root 16895 Oct 19 20:37 msg0000.WAV El archivo msg0000.txt contiene toda la información relacionada con el mensaje de voz: ; ; Message Information file ; [message] origmailbox=1000 context=voicemail macrocontext= exten=s-NOANSWER rdnis=unknown priority=1 callerchan=SIP/1001-00000002 callerid="zutano" <1001> origdate=Mon Apr 14 02:35:43 PM UTC 2014 origtime=1397486143 category= msg_id=1397486143-00000001 flag= duration=9 14.2 Mensajes de voz en una base de datos Los mensaje de voz, ademas de guardarse en la carpeta indicada en el párrafo anterior, pueden guardarse en una base de datos. Esto permite implementar aplicaciones que desde la Web permitan escuchar los mensajes de voz y revisar todos los datos de los mismos. Esta configuración se basa en el conector ODBC y una base de datos (en este caso MySQL). Para que funcione, hay que volver a compilar Asterisk con el soporte ODBC para el buzón de voz. Se entra en la carpeta de las fuentes de Asterisk y se siguen estos pasos: cd /usr/src/asterisk-11.17.1 make distclean 341
./configure --libdir=/usr/lib64 make menuselect En el menú “Voicemail Build Options” seleccionar “ODBC_STORAGE”:
En el menú “Compiler flags” se deselecciona nuevamente el parámetro BUILD_NATIVE:
Se guardan los cambios y se compila Asterisk: make Antes de instalar nuevamente los modulo de Asterisk, se para el servicio: service asterisk stop Luego se instala: make install WARNING WARNING WARNING Your Asterisk modules directory, located at /usr/lib64/asterisk/modules contains modules that were not installed by this version of Asterisk. Please ensure that these modules are compatible with this version before attempting to run Asterisk. app_meetme.so app_mysql.so app_saycountpl.so cdr_mysql.so 342
codec_g729-ast110-gcc4-glibc-x86_64-barcelona.so format_mp3.so res_config_mysql.so WARNING WARNING WARNING Ahora, para guardar los mensaje de voz en la base de datos, hay que crear la tabla. En algunos casos los datos de las tablas se encuentran en la carpeta contrib/realtime/mysql de las fuentes de Asterisk como es el caso de la tabla para los mensajes de voz. mysql -u root -psesamo asterisk < contrib/realtime/mysql/voicemail_messages.sql Creada la tabla hay que modificar dos parámetros en el archivo voicemail.conf: nano /etc/asterisk/voicemail.conf modificar estas dos lineas: ;odbcstorage=asterisk ;odbctable=mensajes para que queden: odbcstorage=asterisk odbctable=voicemail_messages Se guardan los cambios y se inicia Asterisk: service asterisk start Se entra en la consola de Asterisk y se averigua que el modulo esté funcionando con ODBC Storage: asterisk -rvvvvvvvvvvvvvvvvvv CLI> module unload app_voicemail.so == Unregistered application 'VoiceMail' == Unregistered application 'VoiceMailMain' == Unregistered application 'MailboxExists' == Unregistered application 'VMAuthenticate' == Unregistered application 'VoiceMailPlayMsg' == Unregistered application 'VMSayName' == Unregistered custom function MAILBOX_EXISTS == Unregistered custom function VM_INFO == Manager unregistered action VoicemailUsersListt CLI> module load app_voicemail.so == Parsing '/etc/asterisk/voicemail.conf': Found 343
== Parsing '/etc/asterisk/users.conf': Found == Registered application 'VoiceMail' == Registered application 'VoiceMailMain' == Registered application 'MailboxExists' == Registered application 'VMAuthenticate' == Registered application 'VoiceMailPlayMsg' == Registered application 'VMSayName' == Registered custom function 'MAILBOX_EXISTS' == Registered custom function 'VM_INFO' == Manager registered action VoicemailUsersList Loaded app_voicemail.so => (Comedian Mail (Voicemail System) with ODBC Storage)) Por lo que aparece en negrita parece que si. Para probarlo, desde la extensión 1001 o 1002 se llama la extensión 1000 y se deja un mensaje en el buzón de voz. Para averiguar que el mensaje ha sido guardado en la tabla: mysql -u root -psesamo mysql> use asterisk mysql> select dir,msgnum,context,callerid from voicemail_messages; +--------------------------------------------------+--------+-----------+-----------------+ | dir | msgnum | context | callerid | +--------------------------------------------------+--------+-----------+-----------------+ | /var/spool/asterisk/voicemail/default/1000/INBOX | 0 | voicemail | "zutano" <1001> | +--------------------------------------------------+--------+-----------+-----------------+ 1 row in set (0.00 sec) Perfecto!! 14.3 Buzones de voz en una base de datos Además de los mensajes de voz, también los buzones de voz se pueden guardar en una base de datos. En este caso se utilizará el Realtime dinámico. La ventaja, como ya se ha dicho anteriormente, es que esto permite modificar los valores directamente desde la base de datos o desde una aplicación Web que trabaje con la base de datos.. Los pasos a seguir son: • • •
crear la tabla en la base de datos configurar el realtime dinámico reiniciar asterisk
344
Como para la tabla de los mensajes de voz, se utilizará la tabla presente en las fuentes de Asterisk: cd /usr/src/asterisk-11.17.1/contrib/realtime/mysql/ mysql -u root -psesamo asterisk < voicemail.sql Creada la tabla se configura el realtime dinámico: nano /etc/asterisk/extconfig.conf Se modifica esta linea: ;voicemail => odbc,asterisk para que quede: voicemail => odbc,asterisk,voicemail Se guardan los cambios y se reinicia Asterisk: service asterisk reload Ahora se configura el buzón de voz de la extensión 1004 (la extensión configurada en SIP realtime) en la tabla voicemail a través de Webmin:
345
En la tabla aparecen todas las opciones que se pueden configurar para un buzón de voz. Se termina 346
presionando el botón “Save” y desde la extensión 1004 se marca el 97 para probar la configuración. Si todo funciona, ya se ha terminado con la configuración de los buzones de voz.
347
Capitulo XV Las conferencias audio En Asterisk una funcionalidad bastante interesante es la de las conferencias audio. Para utilizar esta funcionalidad, existen dos aplicaciones: • •
meetme confbridge
La primera es la más conocida y ha sido implementada en Asterisk desde las primeras versiones. MeetMe se apoya en DAHDI para generar la sincronización de los canales audios presentes en la conferencia creando una canal pseudo-DAHDI para cada una. Sin DAHDI instalado, MeetMe no funciona. Confbridge en la versión 11 ha sido totalmente reescrita superando en opciones y características la “vieja” meetme que ya se puede considerar obsoleta. Otra característica muy interesante de la aplicación ConfBridge es que permite videoconferencias aunque la parte vídeo enviada es solamente de la persona que está hablando. Como veremos en este capitulo, también la aplicación Page ya no necesita DAHDI para funcionar ya que ha sido enlazada a la aplicación ConfBridge. La configuración de ambas aplicaciones se realiza a partir de un archivo de configuración dedicado. Se inicia con MeetMe 15.1 meetme.conf Como para los demás archivos de configuración de Asterisk, se presentan los parámetros con una breve descripción. En negrita los valores que se asignarán. Al final de la tabla el archivo completo. Parámetro
Descripción
[general]
Inicia la parte general de configuración
audiobuffers
Numero de paquetes audio de 20ms que serán guardados en un buffer de memoria cuando pertenecen a canales que no son DADHI. Esto permite sincronizar el audio de los distintos participantes y evitar retrasos. Puede ser un valor entre 2 y 32. Valor 32
schedule
Este parámetro va configurado en yes solamente si se utilizan las conferencias en realtime (ARA). En caso contrario hay que dejarlo en no
logmembercount
Si las conferencias están configuradas en Realtime este parámetro actualiza la tabla cada vez que un usuario entre o salga de la conferencia. Valor yes
fuzzystart
Hay una conferencia programada a las 8 de la mañana. Este parámetro se utiliza para definir si un usuario puede o no entrar en la conferencia si
Parámetro
Descripción ésta no ha empezado. 300 es el número de segundos. Ejemplo. Si el usuario entra a la 7:55 será aceptado porque puede entrar hasta 5 minutos (300 segundos) antes del comienzo de la conferencia. Si entra a las 7:50 será rechazado. Funciona solamente en Realtime
earlyalert
Este valor (siempre en segundos) define si al usuario que intenta entrar en una conferencia programada le será anunciado o no que la conferencia todavía no ha empezado. Con el valor en 3600, si entra cuando falta menos de una hora recibirá este aviso. Si entra más de una hora antes se le anunciará que la conferencia no existe.
endalert
Cuando falten los segundos indicados en este parámetro para que termine una conferencia programada, a los usuario se les presentará un aviso. Valor 120
[rooms]
a partir de esta etiqueta inicia la configuración de las conferencias. La sintaxis es: conf => confno[,pin][,adminpin]
conf => 3500
Se configura la primera sala de conferencia sin PIN de usuario y PIN de administrador
conf => 3501,1234
Se configura la segunda sala de conferencia con PIN de usuario 1234 y sin PIN de administrador
conf => 3502,1234,5678
Se configura una tercera sala de conferencia con PIN de usuario 1234 y PIN de administrador 5678
Se renombra el archivo predefinido: mv /etc/asterisk/meetme.conf /etc/asterisk/meetme.conf.old y se crea uno nuevo con los parámetros indicados en la tabla: nano /etc/asterisk/meetme.conf [general] audiobuffers=32 schedule=no logmembercount=yes fuzzystart=300 earlyalert=3600 endalert=120 350
[rooms] conf => 3500 conf => 3501,1234 conf => 3502,1234,5678 Se guardan los cambios y se entra en la consola de Asterisk: asterisk -rvvvvvvvvvvvvvvvvvvvv se recarga el modulo app_meetme CLI> module reload app_meetme.so se revisa la sintaxis de la aplicación meetme: CLI> core show application meetme Como se puede ver hay muchos parámetros y opciones que se pueden configurar. Hay otras aplicaciones relacionadas con las conferencias: CLI> core show application meetme (más la tecla tabulador) MeetMe MeetMeAdmin MeetMeChannelAdmin MeetMeCount Las aplicaciones disponibles son cuatro. La primera es para entrar en una conferencia, la segunda para administrarla, la tercera es para controlar un canal de la conferencia y la tercera para conocer el numero de usuarios presentes en una conferencia. CLI> quit Ahora se modifica el dialplan para utilizar las conferencias configuradas en el archivo meetme.conf: nano /etc/asterisk/extensions.conf después del contexto internas se añade un nuevo contexto: [conferencias] exten => _350[012],1,Meetme(${EXTEN},scM(default)) same => n,Hangup Llamando la extensión 3500,3501 o 3502 se entrará en el cuarto de conferencia (como configurado en meetme.conf) Las tres opciones:
351
• • •
s - Con esta opción se activa el menú del cuarto de conferencias para usuarios y administradores. Marcando la tecla asterisco se escuchará el menú c - Al entrar en un cuarto de conferencia se le anunciará al usuario el número de personas presentes M(default) - Cuando en el cuarto de conferencia es presente solamente una persona, ésta escuchara la música de espera de la clase default”
Existe la posibilidad de crear cuartos de conferencias de forma dinámica (sin tener que configurarlos en el archivo meetme.conf). A seguir un ejemplo que se va a añadir al dialplan en el contexto conferencias: exten => 3510,1,Meetme(,DM(default)) same => n,Hangup Primero no se indica el número del cuarto de conferencias y se utiliza la opción D que permite definir la extensión 3510 como cuarto de la conferencia y un PIN para entrar. El PIN de la conferencia será el digitado por la primera persona que entre. Si en lugar de la opción D se pone la opción d no se necesitará digitar un PIN para el cuarto de conferencia. Otro ejemplo que se puede añadir al dialplan es crear una conferencia y definir como numero máximo de participantes 10. Esto se hace con una Subrutina. En el contexto conferencias se pone: exten => 3520,1,Set(confmax=10) same => n,Gosub(meetme,s,1(${confmax},${EXTEN})) same => n,Hangup y al final del archivo se añade la subrutina: [meetme] exten => s,1,MeetMeCount(${ARG2},count) same => n,Gotoif($[${count} > ${ARG1}]?llena) same => n,MeetMe(${ARG2},D) same => n,Hangup same => n(llena),Playback(conf-invalid) same => n,Hangup Una explicación. Primero se asocia a la variable confmax el numero 10 (el numero máximo de participantes permitidos en la conferencia) y luego se llama la subrutina meetme. Con la primera línea de la subrutina se controla con la aplicación MeetmeCount cuantos usuarios están en la conferencia 3520 y se asocia ese valor a la variable count. Si el numero contenido en la variable count es mayor al numero contenido en la variable confmax (10), variable ${ARG1} enviada a la subrutina, se va a la línea con la etiqueta (llena) donde se comunicará que la conferencia no es valida y se colgará la llamada; si es menor el usuario podrá entrar al cuarto de conferencias. Para terminar la configuración del dialplan, para que las extensiones tengan acceso al contexto conferencias hay que añadir la linea en negrita al contexto externas y locales: 352
[externas] include => internas include => internacio include => parkedcalls include => test include => conferencias [locales] include => internas include => auten include => parkedcalls include => test include => conferencias Se guardan los cambios y se actualiza el dialplan: asterisk -rvvvvvvvvvvvv CLI> dialplan reload Ahora desde las extensiones 1000 y 1001 se marca el numero 3500 para entrar en la primera conferencia configurada en el archivo meetme.conf. Para ver las extensiones presentes en la conferencia: CLI> meetme list 3500 User #: 01 1000 Fulano User #: 02 1001 zutano 2 users in that conference.
Channel: SIP/1000-00000005 Channel: SIP/1001-00000006
(unmonitored) 00:00:08 (unmonitored) 00:00:03
Para sacar un usuario de la conferencia: CLI> meetme kick 3500 1 == Setting global variable 'MEETMEADMINSTATUS' to 'OK' -- Playing 'conf-kicked.alaw' (language 'es') -- Executing [3500@externas:2] Hangup("SIP/1000-00000003", "") in new stack Quedará: CLI> meetme list 3500 User #: 02 1001 zutano 1 users in that conference.
Channel: SIP/1001-00000001
(unmonitored) 00:00:57
CLI> quit Para probar la Macro desde la extensión 1000 se marca 3520. 353
15.2 Aplicación ConfBridge Como se ha dicho en la introducción de este capitulo, también la aplicación ConfBridge se basa en un archivo de configuración dedicado. Si se mira la sintaxis de la aplicación: asterisk -rvvvvvvvvvvvvvvvvv CLI> core show application ConfBridge ConfBridge(conference[,bridge_profile[,user_profile[,menu]]]) Esto quiere decir que cuando se configura la aplicación en el dialplan será posible indicar: • •
•
•
conference: un nombre o un numero para la conferencia bridge_profile: un perfil de la conferencia (ya se verá que tipo de parámetros contiene). Se configura en el archivo confbridge.conf. Si no se indica uno especifico, se utilizará el [default_bridge] si presente en el archivo de configuración predefinido o un perfil creado dinámicamente en el dialplan utilizando la función CONFBRIDGE antes de la aplicación ConfBridge user_profile: un perfil de usuario que también se configura en el archivo confbridge.conf. Si no se indica uno especifico, se utilizará el [default_user] si presente en el archivo de configuración predefinido o un perfil creado dinámicamente en el dialplan utilizando la función CONFBRIDGE antes de la aplicación ConfBridge menu: un menú de opciones disponibles dentro de la conferencia. Normalmente se activa con la tecla asterisco (*)
El archivo se divide en tres partes que se pueden repetir según la configuración que se necesite. A parte la etiqueta [general] todas las etiquetas que se definen sucesivamente pueden hacer referencias a un perfil bridge, a un perfil de usuario o a un menú. El parámetro que permite definir el tipo de perfil que se va a configurar es type y acepta tres valores: • • •
user bridge menu
A seguir se presentan los distintos parámetros con una breve descripción. En negrita los valores que se utilizarán: Parámetro
Descripción
[general]
Etiqueta que da inicio a la configuración general del archivo. Todavía no se utiliza.
[usuario]
La etiqueta que define el primer perfil 354
Parámetro
Descripción
type
Puede ser: • user (se configura un perfil de usuario) • bridge • menu
admin
Si se configura con yes será un perfil para los administradores de la conferencia, con no, usuarios normales
marked
Si se configura con yes todos los usuarios que entrarán en la conferencia serán marcados (una especie de flag). Si se configura con no, no serán marcados. Valor: no
startmuted
Define si los usuarios que entrarán en la conferencias tendrán de forma predefinida el micrófono desactivado (no podrán hablar). Valor: no
music_on_hold_when_empty
Define si cuando haya un solo usuario en la conferencia escuchará o no la música de espera. Con yes la escuchará, con no, no la escuchará Valor: yes
music_on_hold_class
Clase de la música en espera che escuchará el usuario si el parámetro anterior está configurado con yes. Valor: default
quiet
Si el valor es yes, a los usuarios presentes en la conferencia no se le enviará un anuncio cada vez que un usuario entre o salga de la conferencia. Con no se le anunciará. Valor: no
announce_user_count
Con yes se anunciará al nuevo usuario que entra en la conferencia, el numero de personas presentes. Con no, no se realizará el anuncio. Valor: yes
announce_user_count_all
Con yes el numero de usuarios presentes en la conferencia se anunciará a todos los usuarios cuando entre uno nuevo. Con no, no se anunciará. Si se especifica un numero (ejemplo: 10), el anuncio se realizará solamente cuando el numero de usuarios presentes en la conferencia sea mayor (ejemplo: 11). Valor: yes
announce_only_user
Con yes cuando un usuario entra en la conferencia y es el único usuario presente, se le anunciará esa condición. Con no, no se efectuará el anuncio. Valor: yes 355
Parámetro
Descripción
wait_marked
Con yes un usuario para poder acceder a una conferencia tiene que esperar que un usuario marcado esté presente. Con no, no hace falta que esté presente un usuario marcado. Opción útil en el caso que se quiera que una conferencia esté activa solamente si un usuario marcado haya entrado (ejemplo un administrador). Valor: no
end_marked
Con yes cuando el ultimo usuario marcado sale de la conferencia, todos los demás usuarios que tengan en su perfil este parámetro en yes, serán “expulsados” de la conferencia. Con no, no serán expulsados. Valor: no
dsp_drop_silence
Con yes, todo lo que Asterisk considere silencio (o ruido de fondo) no será enviado a la conferencia. Esta opción activada aumenta la calidad del audio de la conferencia especialmente para conferencia con un numero elevado de usuarios. Con no se desactiva. Valor: yes
dsp_talking_threshold
El tiempo, en mili segundos que tardará Asterisk para calibrar el audio de un usuario para definir si está hablando o está en silencio. Se pueden verificar tres escenarios: 1. si el valor es demasiado alto, cada vez que un usuario inicie a hablar, escuchará un retorno de su voz hasta que Asterisk no empiece a enviar el audio a la conferencia. 2. Cuando la detección del audio está activada en los eventos del AMI y el valor es demasiado bajo, es posibles que se generen eventos causados por el ruido de fondo 3. Como el parámetro anterior depende de este, si el valor es demasiado alto, cuando el usuario inicia a hablar es posible que una parte de su audio sea cortada. Posibles valores: de 1 a 2^31. Valor: 160
dsp_silence_threshold
El tiempo, en mili segundos para que Asterisk decida si el que está hablando ha dejado de hablar. Esto en base a lo que Asterisk considera silencio. La mejor forma de configurar este parámetro es tener en consideración las pausas de silencio que puede realizar un usuario cuando esté hablando. Posibles valores: de 1 a 2^31. Valor: 2500 356
Parámetro
Descripción
talk_detection_events
Con yes se generarán los eventos en el AMI de Asterisk cada vez que se detecte audio en la conferencia. Con no, no se generarán. Valor: yes
denoise
Con yes se activa un filtro en el audio producido antes de enviarlo a la conferencia. Para que funcione el modulo func_speex tiene que estar compilado y activado. Valor: yes
jitterbuffer
Con yes se activa un buffer en el flujo audio del usuario antes de realizar la mezcla del flujo con la conferencia. Es altamente aconsejado activarlo aunque pueda crear un pequeño retraso en el flujo audio. Valor: yes
pin
Este parámetro, si presente, contiene un PIN numérico que el usuario tendrá que digitar para acceder a la conferencia. Valor: 1234
announce_join_leave
Con yes el usuario, antes de entrar en la conferencia, tendrá que grabar su nombre que será anunciado en la conferencia al momento de entrar.
dtmf_passthrough
Con yes los tonos DTMF serán enviados a la conferencia. Valor: yes
;announcement
A cada usuario que acceda a la conferencia se presentará la locución del file audio configurado. Valor: /tmp/anuncio.wav. Se deja comentado.
[conferencia]
La etiqueta que define un segundo perfil
type
Puede ser: • user • bridge (se conferencia) • menu
configura
un
perfil
de
max_members
Numero máximo de participantes aceptados en la conferencia. Un usuario admin puede acceder a la conferencia aunque se haya alcanzado el numero máximo de participantes. Valor: 10
record_conference
Con yes se activa la grabación de la conferencia desde que el primer usuario acceda hasta que el ultimo salga. El archivo se guardará en el formato slinear en la carpeta definida para las grabaciones en el archivo asterisk.conf. Normalmente /var/spool/asterisk/monitor. El nombre predefinido para el archivo será confbridge-nombre-del-perfil357
Parámetro
Descripción de-la-conferencia-fechadeinicio. Valor: no
;record_file
Se el parámetro anterior es configurado con yes, en este es posible definir la carpeta y el nombre de archivo donde se grabará la conferencia. Como el mismo perfil puedes ser utilizado por distintas conferencias, pueden haber problemas. La recomendación es utilizar este parámetro solamente a través de la función CONFBRIDGE directamente desde el dialplann. Valor: /tmp/conferencia Se deja comentado.
internal_sample_rate
Este parámetro permite configurar la frecuencia de muestreo del audio de la conferencia. Puede ser auto o un valor entre 8000 y 19200. Valor: auto
mixing_interval
Con este parámetro se configura la duración de cada paquete audio que se enviará a la conferencia. Posibles valores: 10, 20, 40,80. Un valor alto aumentará el retraso del flujo audio de la conferencia. Valor: 40
video_mode
Con este parámetro se define si se activa el flujo vídeo en la conferencia y de que fuente se tomará. Para que los participantes puedan recibir/enviar el flujo vídeo, tendrán que configurar el mismo codec vídeo en su SIP Phone. Cuando se activa el video en la conferencia hay que deshabilitar el parámetro jitterbuffer para evitar que se pierda la sincronización entre audio y vídeo. Posibles valores: • none. No existe una fuente vídeo predefinida aunque se puede activar a través de la AMI de Asterisk o utilizando los tonos DTMF si previsto por la configuración del menu • follow_talker. La fuente vídeo procederá de la persona que está hablando siempre y cuando haya activado el envío de vídeo en su SIP Phone. • last_marked. La fuente vídeo será tomada del ultimo usuario marcado que ha accedido a la conferencia. Si este usuario deja la conferencia, la fuente vídeo será tomada del ultimo usuario marcado que ha accedido a la conferencia y que todavía está presente en la conferencia. 358
Parámetro
Descripción •
first_marked. El primer usuario marcado que ha accedido a la conferencia será la fuente del flujo vídeo. Si el usuario deja la conferencia su lugar será tomado del usuario que accedió después de él. Valor: none language
Idioma para las locuciones que se utilizarán en la conferencia. Valor: es
;sound_join ;sound_leave ;sound_has_joined ;sound_has_left ;sound_kicked ;sound_muted ;sound_unmuted ;sound_only_person ;sound_only_one ;sound_there_are ;sound_other_in_party ;sound_place_into_conference ;sound_wait_for_leader ;sound_leader_has_left ;sound_get_pin ;sound_invalid_pin ;sound_locked ;sound_locked_now ;sound_unlocked_now ;sound_error_menu
Todas las lineas indicadas se utiliza para configurar locuciones personalizadas para el perfil de la conferencia. Si el parámetro no se configura, se utilizarán las locuciones predefinidas. Se dejan todas comentadas.
[menu]
La etiqueta que define un tercer perfil
type
Puede ser: • user • bridge • menu (menú de opciones disponible en la conferencia) Las distintas opciones se indican con el dígito que hay que utilizar para activarlas/utilizarlas.
playback
Envía las locuciones presentes en este parámetro al usuario que ha seleccionado esta opción. Normalmente se utiliza para anunciar las distintas opciones disponibles en el menú. Las locuciones se indican en la misma linea juntandolas con el 359
Parámetro
Descripción carácter &. El usuario tendrá que esperar que termine la presentación de las locuciones para poder escoger una opción entre las indicadas.
playback_and_continue
Al contrario del parámetro anterior, el usuario podrá escoger una opción mientras esté escuchando las distintas locuciones.
toggle_mute
Seleccionando esta opción el usuario pondrá en silencio su micrófono pero podrá seguir escuchando el audio de la conferencia.
no_op
Esta opción no ejecuta ningún comando y es presente para dejar una opción personalizable.
decrease_listening_volume
Esta opción permite al usuario aumentar el volumen del audio de escucha de la conferencia.
increase_listening_volume
Esta opción permite al usuario bajar el volumen de escucha del audio de la conferencia.
reset_listening_volume
Esta opción permite al usuario cambiar el volumen de escucha del audio de la conferencia a su valor predefinido.
decrease_talking_volume
Esta opción permite al usuario bajar el volumen del audio que está enviando a la conferencia.
increase_talking_volume
Esta opción permite al usuario subir el volumen del audio que está enviando a la conferencia.
reset_talking_volume
Esta opción permite al usuario cambiar el volumen del audio que está enviando a la conferencia a su valor predefinido.
dialplan_exec
Permite al usuario “saltar” a un contexto, extensión, prioridad presente en el dialplan. Terminada su ejecución el usuario volverá a la conferencia.
leave_conference
Esta opción permite al usuario salir de la conferencia y continuar en las siguientes lineas presentes en el dialplan.
admin_kick_last
Esta opción permite a un administrador sacar de la conferencia el ultimo usuario que ha accedido.
admin_toggle_conference_lock
Esta opción permite a un administrador bloquear/desbloquear la conferencia
set_as_single_video_src
Esta opción permite a un usuario activarse como la nueva fuente del flujo vídeo. Esta opción tiene la prioridad sobre el parámetro video_mode 360
Parámetro
Descripción
release_as_single_video_src
Esta opción permite al usuario dejar de ser la fuente del flujo vídeo enviado a la conferencia.
admin_toggle_mute_participants
Esta opción permite a un administrador poner en silencio todos los participante de la conferencia menos los demás administradores.
participant_count
Esta opción devuelve el numero de participantes presentes en la conferencia.
[menuusuario] type=menu *=playback_and_continue(conf-usermenu) *1=toggle_mute 1=toggle_mute *4=decrease_listening_volume 4=decrease_listening_volume *6=increase_listening_volume 6=increase_listening_volume *7=decrease_talking_volume 7=decrease_talking_volume *8=leave_conference 8=leave_conference *9=increase_talking_volume 9=increase_talking_volume
Un ejemplo de menú para los usuarios.
[menuadmin] type=menu *=playback_and_continue(conf-adminmenu) *1=toggle_mute 1=toggle_mute *2=admin_toggle_conference_lock 2=admin_toggle_conference_lock *3=admin_kick_last 3=admin_kick_last *4=decrease_listening_volume 4=decrease_listening_volume *6=increase_listening_volume 6=increase_listening_volume *7=decrease_talking_volume 7=decrease_talking_volume *8=leave_conference 8=leave_conference *9=increase_talking_volume 9=increase_talking_volume
Un ejemplo de menú para los administradores.
Se renombra el archivo predefinido: 361
mv /etc/asterisk/confbridge.conf /etc/asterisk/confbridge.conf.old se crea uno nuevo: nano /etc/asterisk/confbridge.conf Se copian las lineas que siguen: [general] [usuario] type=user admin=no marked=no startmuted=no music_on_hold_when_empty=yes music_on_hold_class=default quiet=no announce_user_count=yes announce_user_count_all=yes announce_only_user=yes wait_marked=no end_marked=no dsp_drop_silence=yes dsp_talking_threshold=160 dsp_silence_threshold=2500 talk_detection_events=yes denoise=yes jitterbuffer=yes pin=1234 announce_join_leave=yes dtmf_passthrough=yes ;announcement=/tmp/anuncio.wav [conferencia] type=bridge max_members=10 record_conference=no ;record_file=/tmp/conferencia internal_sample_rate=auto mixing_interval=40 video_mode=none language=es ;sound_join ;sound_leave ;sound_has_joined 362
;sound_has_left ;sound_kicked ;sound_muted ;sound_unmuted ;sound_only_person ;sound_only_one ;sound_there_are ;sound_other_in_party ;sound_place_into_conference ;sound_wait_for_leader ;sound_leader_has_left ;sound_get_pin ;sound_invalid_pin ;sound_locked ;sound_locked_now ;sound_unlocked_now ;sound_error_menu [menuusuario] type=menu *=playback_and_continue(conf-usermenu) *1=toggle_mute 1=toggle_mute *4=decrease_listening_volume 4=decrease_listening_volume *6=increase_listening_volume 6=increase_listening_volume *7=decrease_talking_volume 7=decrease_talking_volume *8=leave_conference 8=leave_conference *9=increase_talking_volume 9=increase_talking_volume [menuadmin] type=menu *=playback_and_continue(conf-adminmenu) *1=toggle_mute 1=toggle_mute *2=admin_toggle_conference_lock 2=admin_toggle_conference_lock *3=admin_kick_last 3=admin_kick_last *4=decrease_listening_volume 4=decrease_listening_volume *6=increase_listening_volume 6=increase_listening_volume 363
*7=decrease_talking_volume 7=decrease_talking_volume *8=leave_conference 8=leave_conference *9=increase_talking_volume 9=increase_talking_volume se guardan los cambios y se entra en la consola de Asterisk: asterisk -rvvvvvvvvvvvvvvv Se desactiva y se vuelve a activar el modulo de la aplicación ConfBridge: CLI> module unload app_confbridge.so Unloaded app_confbridge.so == Unregistered application 'ConfBridge' == Unregistered custom function CONFBRIDGE == Unregistered custom function CONFBRIDGE_INFO == Unregistered channel type 'ConfBridgeRec' == Manager unregistered action ConfbridgeList == Manager unregistered action ConfbridgeListRooms == Manager unregistered action ConfbridgeMute == Manager unregistered action ConfbridgeUnmute == Manager unregistered action ConfbridgeKick == Manager unregistered action ConfbridgeUnlock == Manager unregistered action ConfbridgeLock == Manager unregistered action ConfbridgeStartRecord == Manager unregistered action ConfbridgeStopRecord == Manager unregistered action ConfbridgeSetSingleVideoSrc CLI> module load app_confbridge.so Parsing '/etc/asterisk/confbridge.conf': Found == Registered custom function 'CONFBRIDGE' == Registered custom function 'CONFBRIDGE_INFO' == Registered channel type 'ConfBridgeRec' (Conference Bridge Recording Channel) == Registered application 'ConfBridge' == Manager registered action ConfbridgeList == Manager registered action ConfbridgeListRooms == Manager registered action ConfbridgeMute == Manager registered action ConfbridgeUnmute == Manager registered action ConfbridgeKick == Manager registered action ConfbridgeUnlock == Manager registered action ConfbridgeLock == Manager registered action ConfbridgeStartRecord == Manager registered action ConfbridgeStopRecord == Manager registered action ConfbridgeSetSingleVideoSrc 364
Loaded app_confbridge.so => (Conference Bridge Application) CLI> quit Ahora se puede modificar el dialplan para crear la primera conferencia utilizando la aplicación ConfBridge: nano /etc/asterisk/extensions.conf bajo el contexto conferencias se añade el siguiente bloque: exten => 3530,1,Confbridge(reuniones,conferencia,usuario,menuusuario) same => n,hangup Los datos: • • • •
reuniones: el nombre de la conferencia conferencia: el perfil de configuración de la conferencia usuario: el perfil de configuración de los usuarios menuusuario: el menú al que tendrán acceso los usuarios cuando estén en la conferencia
Se guardan los cambios y se recarga el diaplan: asterisk -rvvvvvvvvvvvvvvv CLI> dialplan reload Ahora desde la extensión 1000 se marca la extensión 3530. Al usuario se le solicitará el PIN de la conferencia (1234) y que grabe su nombre. Luego el sistema anunciará que es el único usuario presente en la conferencia y empezará a escuchar la música de espera (clase default). En la consola de Asterisk: CLI> confbridge list Conference Bridge Name Users Marked Locked? ================================ reuniones 1 0 unlocked CLI> confbridge list reuniones confbridge list reuniones Channel User Profile Bridge Profile Menu CallerID Muted ============================== ======================== SIP/1000-00000009 usuario conferencia menuusuario 1000 No Para una lista completa de los comandos disponibles: CLI> help confbridge confbridge kick Kick participants out of conference bridges. 365
confbridge list List conference bridges and participants. confbridge lock Lock a conference. confbridge mute Mute a participant. confbridge record start Start recording a conference confbridge record stop Stop recording a conference. confbridge show menu Show a conference menu confbridge show menus Show a list of conference menus confbridge show profile bridge Show a conference bridge profile. confbridge show profile bridge Show a list of conference bridge profiles. confbridge show profile user Show a conference user profile. confbridge show profile users Show a list of conference user profiles. confbridge unlock Unlock a conference. confbridge unmute Unmute a participant. Si se marca el * se debería escuchar el menú de opciones. Luego se cuelga. Hasta ahora no se ha creado un perfil de usuario para los administradores. Para hacerlo, se modifica el archivo de configuración de la aplicación ConfBridge: nano /etc/asterisk/confbridge.conf después del bloque [usuario] se añade el siguiente bloque: [admin] type=user admin=yes marked=yes startmuted=no music_on_hold_when_empty=yes music_on_hold_class=default quiet=no announce_user_count=yes announce_user_count_all=yes announce_only_user=yes wait_marked=no end_marked=no dsp_drop_silence=yes dsp_talking_threshold=160 dsp_silence_threshold=2500 talk_detection_events=yes denoise=yes jitterbuffer=yes pin=5678 announce_join_leave=yes dtmf_passthrough=yes ;announcement=/tmp/anuncio.wav
366
Los parámetros que se han modificado son: • • •
admin=yes marked=yes PIN=5678
Para que los administradores puedan acceder a la conferencia utilizando el perfil que se acaba de crear, habrá que modificar el dialplan y crear un nuevo bloque en el contexto [conferencias] nano /etc/asterisk/extensions.conf en el contexto conferencias, se añade el siguiente bloque: exten => 3531,1,Confbridge(reuniones,conferencia,admin,menuadmin) same => n,hangup Se pone como perfil de usuario admin y come perfil de menu menuadmin. Se guardan los cambios y desde la consola de Asterisk se recarga el dialplan y la configuración de ConfBridge: asterisk -rvvvvvvvvvvvvvvvvvvvv CLI> dialplan reload CLI> module reload app_confbridge.so Ahora desde la extensión 1000 se marca 3530. Una vez que el usuario esté en la conferencia, desde la extensión 1001 se marca 3531. En la consola de Asterisk: CLI> confbridge list Conference Bridge Name Users Marked Locked? ================================ ====== ====== ======== reuniones 2 1 unlocked Como se puede ver en la conferencia reuniones hay dos usuarios, uno está marcado (el administrador): *CLI> confbridge list reuniones Channel User Profile Bridge Profile Menu CallerID ============================== SIP/1000-00000000 usuario conferencia menuusuario 1000 SIP/1001-00000001 admin conferencia menuadmin 1001
Muted No No
en la lista de usuarios uno aparecerá como usuario y uno como administrador; cada uno con su menú personalizado. Ahora si el usuario de la extensión 1001 marca el asterisco, escuchará el menú de administrador configurado. Escogiendo la opción 2, el administrador bloqueará el acceso a la conferencia (en negrita): 367
CLI> confbridge list Conference Bridge Name Users Marked Locked? ================================ ====== reuniones 2 1 locked Ahora si desde la extensión 1002 se marca 3530, el usuario no podrá acceder a la conferencia (en negrita): Executing [3530@locales:1] ConfBridge("SIP/1002-00000002", "reuniones,conferencia,usuario,menuusuario") in new stack > 0x7fba30119200 -- Probation passed - setting RTP source address to 79.44.192.186:8000 -- Playing 'conf-getpin.alaw' (language 'es') > 0x7fba30119200 -- Probation passed - setting RTP source address to 79.44.192.186:8000 -- Playing 'vm-rec-name.alaw' (language 'es') -- Playing 'beep.alaw' (language 'es') -- x=0, open writing: /var/spool/asterisk/confbridge/confbridge-name-reuniones-1397660152.4 format: sln, 0x7fb9a8001818 -- User ended message by pressing # -- Playing 'auth-thankyou.alaw' (language 'es') -- Playing 'conf-locked.alaw' (language 'es') Como se ha visto a lo largo de la configuración del archivo confbridge.conf es posible activar en el menú una opción que permite al usuario que la activa ir a un punto especifico del dialplan. Se utilizará esa opción para invitar un nuevo usuario en la conferencia llamándolo a su numero fijo/celular. Se abre nuevamente el archivo de configuración: nano /etc/asterisk/confbridge.conf y en el bloque [menuadmin] se modifican estas dos lineas: *8=leave_conference 8=leave_conference para que queden: *8=dialplan_exec(internas,10,1) 8=dialplan_exec(internas,10,1) Se guardan los cambios y se crea la extensión 10, contexto internas en el dialplan: nano /etc/asterisk/extensions.conf se copian las siguientes lineas: exten => 10,1,NoOp(invitar usuario a la conferencia) 368
same => n,Read(num,beep,20,,1,15) same => n,Originate(SIP/voztovoice/${num},exten,conferencias,3532,1) La aplicación Read ya se ha presentado mientras la aplicación Originate es nueva. Esta aplicación permite llamar una extensión local o un numero de teléfono y cuando el llamado conteste, ejecutar una aplicación o enviar el llamado a un contexto, extensión, prioridad determinados. En este caso se enviará el llamado al contexto conferencias, extensión 3532, prioridad uno. Como no existe, en el contexto conferencias se crea un nuevo bloque: exten => 3532,1,Confbridge(reuniones,conferencia,invitado,menuadmin) same => n,hangup Como se puede ver el llamado utilizará un nuevo perfil de usuario cuyo nombre es invitado. Se abre el archivo de configuración de ConfBrdge nano /etc/asterisk/confbridge.conf después del bloque [admin] se añade: [invitado] type=user admin=no marked=no startmuted=no music_on_hold_when_empty=yes music_on_hold_class=default quiet=no announce_user_count=yes announce_user_count_all=yes announce_only_user=yes wait_marked=no end_marked=no dsp_drop_silence=yes dsp_talking_threshold=160 dsp_silence_threshold=2500 talk_detection_events=yes denoise=yes jitterbuffer=yes announce_join_leave=yes dtmf_passthrough=yes ;announcement=/tmp/anuncio.wav Se ha quitado el parámetro PIN (al invitado no se solicitará). Se guardan los cambios y se recarga la configuración de Asterisk: service asterisk reload
369
Ahora desde la extensión 1000 se marca 3531 y una vez dentro de la conferencia se activa el menú (tecla asterisco) y luego se digita el 8. Después del beep se digitará el usuario que se quiere invitar (numero fijo o celular) y una vez que el llamado conteste, la extensión 1000 regresará a la conferencia y el nuevo usuario podrá acceder sin tener que marcar el PIN. Una solución muy útil cuando se quiera invitar un “externo” a una conferencia. 15.2.1 La función CONFBRIDGE Como se ha explicado a lo largo de la configuración de la aplicación ConfBridge es posible crear perfiles dinámicos de conferencias y de usuarios utilizando la aplicación CONFBRIDGE. La sintaxis de la función es: CONFBRIDGE(type,option) • •
type: el tipo de parámetro que se va a configurar (user o bridge) option: la opción que se va a configurar entre las disponibles para el perfil.
Para mostrar como funciona la función se creará un perfil de usuario que luego se utilizará en lugar de los configurados en el archivo confbridge.conf. Se abre el dialplan: nano /etc/asterisk/extensions.conf y en el contexto conferencias se añade el bloque que sigue: exten => 3533,1,Set(CONFBRIDGE(user,admin)=no) same => n,Set(CONFBRIDGE(user,startmuted)=yes) same => n,Set(CONFBRIDGE(user,marked)=no) same => n,Set(CONFBRIDGE(user,quiet)=yes) same => n,Set(CONFBRIDGE(user,pin)=7777) same => n,Confbridge(reuniones,conferencia,,menuusuario) same => n,Hangup El usuario que utilizará este perfil no será administrador, accederá sin poder hablar, no será marcado, no escuchará los anuncios relacionados con usuarios que entran y salen de la conferencia y tendrá que digitar el PIN 7777. En la linea donde se llama la aplicación ConfBridge, no se indicará un perfil de usuario ya que se utilizará el configurado con la función CONFBRIDGE. Se guardan los cambios y se recarga el dialplan: asterisk -rvvvvvvvvvvvvvvvv CLI> dialplan reload Ahora desde la extensión 1000 se marca 3533 y se averigua si efectivamente los parámetros configurados son los que serán asociados al nuevo usuario.
370
La función CONFBRIDGE se puede utilizar también para modificar parámetros ya presentes en un determinado perfil. De esta forma se aplicará el perfil indicado pero con los parámetros modificados. Se abre nuevamente el dialplan: nano /etc/asterisk/extensions.conf y en el contexto conferencias se añade el bloque que sigue: exten => 3534,1,Set(CONFBRIDGE(user,template)=usuario) same => n,Set(CONFBRIDGE(user,admin)=yes) same => n,Set(CONFBRIDGE(user,marked)=yes) same => n,Confbridge(reuniones,conferencia,usuario,menuusuario) same => n,Hangup Con esta configuración los usuario que accederán a la conferencia marcando 3534 utilizarán el perfil de usuario “usuario” pero con los dos parámetros configurados modificados; serán administradores y serán marcados. Se guarda la configuración y se recarga el dialplan: asterisk -rvvvvvvvvvvvvvvvvvvvv CLI> dialplan reload Ahora desde la extensión 1000 se marca el numero 3534 y se averigua si el nuevo usuario efectivamente es un administrador (en negrita): CLI> confbridge list Conference Bridge Name Users Marked Locked? ================================ ====== reuniones 1 1 unlocked 15.3 Meetme en Realtime Dinámico Como se ha comentado anteriormente, es posible configurar las conferencias en Realtime dinámico. Lo primero es crear la tabla en la base de datos Asterisk: mysql -u root -psesamo mysql> use asterisk mysql> CREATE TABLE `meetme` ( `confno` char(80) NOT NULL default '0', `starttime` datetime NOT NULL default '0000-00-00 00:00:00', `endtime` datetime default NULL, 371
`pin` char(20) default NULL, `opts` char(100) default NULL, `adminpin` char(20) default NULL, `adminopts` char(100) default NULL, `members` int(11) NOT NULL default '0', `maxusers` int(11) NOT NULL default '0', PRIMARY KEY (`confno`,`starttime`) ); mysql> quit Creada la tabla, se modifica el archivo extconfig.conf nano /etc/asterisk/extconfig.conf se busca esta linea: ;meetme => mysql,general y se modifica para que quede: meetme => odbc,asterisk,meetme Se guardan los cambios y se modifica el parámetro schedule del archivo meetme.conf para permitir la creación de conferencias programadas en Realtime: nano /etc/asterisk/meetme.conf schedule= no se cambia a: schedule=yes Se guardan los cambios y se recarga toda la configuración de Asterisk: service asterisk reload Como algunas locuciones para las conferencias programadas no existen en la instalación estándar de Asterisk, hay que descargarlas: cd /tmp wget http://www.voztovoice.org/tmp/confprompts.tar descomprimir el paquete:
372
tar -xf confprompts.tar y moverlas en la carpeta de la locuciones en ingles: mv *.wav /var/lib/asterisk/sounds/en Se borra el archivo descargado: rm -fr confprompts.tar Ahora para la prueba se configuran dos conferencias a través de Webmin. La idea es crear una que inicie dentro de 50 minutos y otra que inicie dentro de 5 minutos y que las dos tengan una duración de una hora.
Las opciones que aparecen en las dos conferencias para los usuarios: • •
c – anuncia los usuarios presentes en la conferencia I – obliga al usuario que entra a la conferencia a grabar su nombre 373
•
s – se activa la tecla “*” para entrar en un menú que permite modificar algunos parámetros personales (volumen de la conferencia, volumen del micrófono, etcétera).
La única diferencia con las opciones del administrador es la opción a que activa el modo administrador. Para terminar hay que añadir las dos conferencias en el dialplan nano /etc/asterisk/extensions.conf en el contexto conferencias se añade el siguiente bloque: exten => _500[01],1,Meetme(${EXTEN}) same => n,Hangup Se guardan los cambios y se actualiza la configuración asterisk -rvvvvvvvvvvvvvvvvvv CLI> dialplan reload Ahora se hace una prueba llamando primero la conferencia 5000 y luego la 5001. En el primer caso un anuncio avisará que la conferencia no ha empezado, en el segundo, como faltan menos de 5 minutos para que empiece, deja entrar el usuario (como configurado en el parámetro fuzzystart, 300 segundos). 15.4 Aplicación Page La aplicación Page se utiliza para crear conferencias instantáneas llamando un grupo de extensiones simultáneamente. Como se ha explicado en la introducción de este capitulo, esta aplicación ya no depende de DAHDI para funcionar ya que ha sido enlazada a la aplicación ConfBridge. Dependiendo del tipo de opciones configuradas, se podrán crear distintos tipos de escenarios: • • •
solamente quien ha iniciado la llamada podrá hablar todas las extensiones podrán hablar como sistema de intercomunicación para comunicar breves mensajes a la persona llamada (el teléfono del destinatario abrirá la linea en automático)
La sintaxis de la aplicación es: Page(Technology/Resource[&Technology2/Resource2[&...]][,options[,timeout]]) y las opciones disponibles: • •
d – audio en ambas direcciones i – no se tomarán en cuenta intentos de transferir la llamada
374
• • • • •
q – modo silencioso, el llamante no escuchará un beep r – se grabará la conferencia en un archivo audio s – solo se intentará incluir en las conferencias las extensiones cuyo estado sea “NOT_INUSE” A(x) – envía un anuncio a todos los participantes de la conferencia. x es el nombre del archivo audio que contiene la locución n – no envía un anuncio a todos los participantes de la conferencia. Implica que A(x) sea presente
Una prima forma de probar la aplicación es: exten => 501,1,Page(SIP/1001&SIP/1002) same => n,Hangup Una vez que las dos extensiones contesten, solamente la 1000 tendrá activado el audio. Una variación de este bloque es: exten => 502,1,Page(SIP/1001&SIP/1002,d) same => n,Hangup En este caso todas las extensiones tendrán el micrófono activado. Utilizar Page como sistema de intercomunicación puede ser muy útil, por ejemplo, en una empresa donde se quiera comunicar a todos los empleados un anuncio. En este caso se conecta a Asterisk una ATA tipo el PA1 de SNOM, que a su vez se puede conectar a un sistema de amplificación audio. Llamando la extensión asociada al PA1, este contestará la llamada en automático y el anuncio será difundido por el sistema de parlantes conectados al ATA. El mismo sistema se utiliza con los teléfonos SIP. Dependiendo de la marca hay que enviar una cabecera especifica en el INVITE para que el teléfono mismo la reconozca y conteste la llamada en automático activando el parlante (alta voz) del teléfono. Las cabeceras se añaden a través de la aplicación Sipaddheader de Asterisk Estas cabeceras cambian según la marca de los teléfonos. Algunos ejemplos: • • • • •
Aastra - SIPAddHeader(Alert-Info: info=alert-autoanswer) Polycom - SIPAddHeader(Alert-Info: Ring Answer) Snom - SIPAddHeader(Call-Info: sip:domain.com\;answer-after=0) Cisco SPA - SIPAddHeader(Call-Info:\;answer-after=0) Yealink - SIPAddHeader (P-Auto-answer: normal)
Ahora in una hipotética oficina donde el gerente quiera realizar una anuncio a la secretaria y ambos están utilizando teléfonos Yealink cuya extensiones son 1000 para el gerente y 1001 para la secretaria, el dialplan sería:
375
exten => 503,1,SIPAddHeader (P-Auto-answer: normal) same => n,Page(SIP/1001,i) same => hangup El gerente marca 503 y efectúa el anuncio a la secretaria cuyo teléfono habrá contestado en automático activando el parlante. Para terminar este párrafo se modifica el dialplan: nano /etc/asterisk/extensions.conf y en el contexto conferencias se añaden los dos bloques que siguen: exten => 501,1,Page(SIP/1001&SIP/1002) same => n,Hangup exten => 502,1,Page(SIP/1001&SIP/1002,d) same => n,Hangup Se guardan los cambios y se actualiza el dialplan: asterisk -rvvvvvvvvvvvv CLI> dialplan reload Desde la extensión 1000 se marca primero el numero 501 y luego el 502 para probar la configuración
376
Capitulo XVI Distribución automática de llamadas – Colas de espera Cuando se llama un centro de atención al cliente, sin saberlo, se está adentro de un sistema de distribución automática de llamadas. ¿Cómo funciona? Cada llamada que llega se pone en una cola de espera respetando la prioridad con que ha llegado. Cuando uno de los operadores que atienden las llamadas está libre, la llamada sera transferida a ese operador. A lo largo de la espera, según la configuración, el llamante escuchará distintos anuncios (que posición tiene en la cola, el tiempo estimado de espera y un largo etcétera). Quizás este es el servicio más importante y estratégico para una empresa. En base a su calidad y el tiempo promedio de espera, los clientes estarán evaluando la misma empresa. En Asterisk la configuración de las colas de espera se puede realizar de dos formas distintas: • •
con agentes/operadores estáticos con agentes/operadores dinámicos
La primera opción ya se ha vuelto obsoleta porque obliga el agente a estar permanentemente conectado a la cola sin poder efectuar otro tipo de actividad. En las configuraciones actuales, se utilizan casi exclusivamente agente dinámicos. Las diferencias entre las dos soluciones se presentarán en los próximos párrafos. Se empieza este capitulo con una configuración para agentes estáticos que se realiza en el archivo agent.conf. 16.1 Los Agentes Para configurar los agentes que atenderán las llamadas entrantes a las distintas colas hay que modificar el archivo agents.conf. En la tabla que sigue los distintos parámetros con una breve descripción. En negrita el valor asociado a cada parámetro. Al final del la tabla el archivo completo de configuración. Parámetro
Descripción
[general]
etiqueta que da inicio a la parte general del archivo
[agents]
A partir de esta etiqueta inicia la configuración de los agentes
maxlogintries
Numero de intentos permitidos a un agente para autenticarse. Valor 3
autologoff
Numero de segundos que un agente tiene para contestar una llamada entrante. Si no contesta dentro de ese tiempo, será desconectado de la cola. Valor 15
autologoffunavail
yes = si la extensión desde la cual el agente se
Parámetro
Descripción conecta se vuelve no disponible, automáticamente el agente será desconectado de la cola
ackcall
Para atender una llamada un agente tiene que presionar la tecla configurada en el próximo parámetro. Valor no (no tiene que presionarla)
acceptdtmf
#
endcall
yes = permite al agente terminar una llamada presionando la tecla configurada en el próximo parámetro
enddtmf
*
wrapuptime
Numero de mili segundos que Asterisk esperará antes de volver a llamar un agente que acaba de atender una llamada. Valor 5000
musiconhold
Música de espera predefinida para el agente. Valor default
updatecdr
Actualizar o no el CDR con el nombre del agente. Valor no
;group
obsoleto. No usar
recordagentcalls
grabar o no las llamadas de los agentes. Valor no
recordformat
Formato audio de las llamadas grabadas. Valor wav
;urlprefix=http://localhost/calls/
el prefijo del nombre del los archivos grabados. Puede ser una URL. Ejemplo http://www.voztovoice.org/calls. Se deja comentado
;savecallsin=/var/calls
De manera predefinida las llamadas grabadas se guardan en la carpeta: /var/spool/asterisk/monitor Si se quiere personalizar la carpeta se indica en este parámetro. Se deja comentado
custom_beep
Avisa al agente que está conectado permanentemente a la cola, de la llegada de una llamada. Valor beep
agent
Ahora se configuran los agentes. Las sintaxis es: agent => agentid,agentpassword,name Valor: 2000,1234,Fulano
agent
2001,1235,Zutano
agent
2002,1236 Mengano
379
Se renombra el archivo predefinido: mv /etc/asterisk/agents.conf /etc/asterisk/agents.conf.old se crea uno nuevo: nano /etc/asterisk/agents.conf y se añaden los parámetros de la tabla: [general] [agents] maxlogintries=3 autologoff=15 autologoffunavail=yes ackcall=no acceptdtmf=# endcall=yes enddtmf=* wrapuptime=5000 musiconhold=default updatecdr=yes ;group recordagentcalls=no recordformat=wav ;urlprefix=http://localhost/calls/ ;savecallsin=/var/calls custom_beep=beep agent => 2000,1234,Fulano agent => 2001,1235,Zutano agent => 2002,1236,Mengano Se guardan los cambios. Se entra en la consola de Asterisk y se recarga el modulo chan_agent.so: asterisk -rvvvvvvvvvvvvvv CLI> module reload chan_agent.so Para ver la lista de los agentes configurados: CLI> agent show 2000 (Fulano) not logged in (musiconhold is 'default') 2001 (Zutano) not logged in (musiconhold is 'default') 2002 (Mengano) not logged in (musiconhold is 'default') 3 agents configured [0 online , 3 offline] 380
CLI> quit Para que los agentes puedan autenticarse y atender las colas de que son miembros, se utiliza en el dialplan la aplicación Agentlogin: nano /etc/asterisk/extensions.conf en el contexto internas, se añade el siguiente bloque: exten => _200[012],1,Agentlogin(${EXTEN}) same => n,Hangup Se guardan los cambios y se actualiza el dialplan. asterisk -rvvvvvvvvvvvvvvvvvvvv CLI> dialplan reload Ahora desde la extensión 1000 se marca el numero 2000, y cuando el sistema lo pide, se ingresa la clave del agente 2000 (1234) seguida por la tecla numero #. Una vez autenticado, el agente empezará a escuchar la música de espera predefinida, esperando de atender los clientes. CLI> agent show 2000 (Fulano) logged in on SIP/1000-00000001 is idle (musiconhold is 'default') 2001 (Zutano) not logged in (musiconhold is 'default') 2002 (Mengano) not logged in (musiconhold is 'default') 3 agents configured [1 online , 2 offline] Es poco productivo tener un agente conectado permanentemente a una cola además utilizando parte de la banda disponible. Es mucho más lógico conectar los agentes de forma dinámica y que mientras esperen las llamadas de los clientes, puedan utilizar el teléfono para otro tipo de actividad. Esta parte se verá en el ultimo párrafo de este capitulo. Es hora de configurar las colas. 16.2 Las colas de espera – queue.conf En el archivo queues.conf se configuran las distintas colas de espera. En la tabla que sigue los distintos parámetros con una breve descripción. En negrita el valor asociado a cada parámetro. Al final de la tabla el archivo completo. Parámetro
Descripción
[general]
Etiqueta que define la parte general del archivo
persistentmembers
yes = se guardan los datos de los miembros activos de la cola en la base de datos interna de Asterisk. Si se
381
Parámetro
Descripción reinicia la PBX los miembros serán reasignados a las colas correspondientes. Valido solamente para agentes dinámicos
autofill
Normalmente una cola funciona de la siguiente manera. Hay unos cuantos usuarios esperando por ser atendidos por los agentes. Cuando el usuario que está de primero en la cola viene atendido el segundo se vuelve primero e será atendido por el primer agente disponible. Este comportamiento no tiene en cuenta que pueden haber muchos agentes disponibles que podrían atender los clientes sin esperar que llegarán a ser los primeros de la cola de espera. Con este parámetro se define otro tipo de comportamiento. Los clientes serán atendidos de manera paralela hasta que haya agentes disponibles. De esta forma se reducen considerablemente los tiempos de espera. Valor yes
monitor-type
el tipo de aplicación utilizada para grabar las conversaciones de una cola. Puede ser Mixmonitor o monitor
updatecdr
Actualiza o no el valor del campo dstchannel del CDR (el registro de las llamadas) con el nombre del agente. Valor no
shared_lastcall
Si un agente es parte de más de una cola y se ha definido su tiempo de descanso entre una llamada y otra (el parámetro wraptime), con este parámetro se define si ese tiempo va respetado entre las distintas colas de que el agente es miembro. Valor yes
negative_penalty_invalid
A los agentes que atienden las colas se pueden aplicar penalidades según su rendimiento y las llamadas que han contestado. Si este parámetro se configura con yes y un agente tiene un valor de penalidad negativo, se tratará como si fuera desconectado de la cola. Valor: no
log_membername_as_agent
Si este parámetro se configura con yes, en los registros de la cola, en los eventos ADDMEMBER y REMOVEMEMBER aparecerá el nombre del agente en lugar de la extensión de la que se conectó. Valor: no
[ventas]
con esta etiqueta se define la primera cola de espera que tendrá como nombre ventas
musiclass
La música de espera para los clientes en la cola. Valor default
;announce=queue-ventas
Este parámetro permite crear un anuncio para que los 382
Parámetro
Descripción agentes que pertenecen a más de una cola sepan, antes de atender una llamada, de que cola procede el cliente. Se deja comentado
strategy
En este parámetro se define la lógica con que se transferirán las llamadas presentes en una cola a los agentes: • leastrecent: Asigna la siguiente llamada al agente que más tiempo lleva conectado a la cola • fewestcalls: Asigna la siguiente llamada al agente que menos llamadas ha atendido en la cola • random: Asigna la siguiente llamada aleatoriamente a cualquier agente disponible. • ringall: Llama todos los agentes disponibles a la vez hasta que uno conteste. • rrmemory: Distribuye las llamadas “por turnos” entre los agentes disponibles y “recuerda” el último agente al que intentó llamar. • rrordered: parecido a rrmemory con la única diferencia que se respetará el orden de los agentes presentes en este archivo de configuración • linear: Llama los agentes siguiendo el orden definido en este archivo de configuración. Si son agentes dinámicos según el orden con que se han registrado a la cola • wrandom: asigna la llamada aleatoriamente usando una métrica basada en penalidades.
servicelevel
Parámetro utilizado para la estadísticas de la cola. En base al numero de segundos configurados en este parámetro, en los reportes aparecerá el numero de llamadas contestadas dentro del tiempo definido. Valor 120
context
Si el cliente en la cola antes de ser atendido presiona una tecla del teléfono será enviado al contexto definido en este parámetro y a la prioridad correspondiente al dígito que ha marcado. Valor ventas-exit
penaltymemberslimit
El sistema de penalidades se aplicará solamente si los agentes conectados a la cola son más que el numero indicado en este parámetro. Valor: 0
timeout
En la cola se pueden configurar dos distintos tipos de
383
Parámetro
Descripción tiempos de espera. Uno a nivel de aplicación (dialplan) define el tiempo máximo que un cliente podrá quedar en la cola. Pasado ese tiempo sin ser atendido, el cliente saldrá de la cola y se ejecutara la siguiente prioridad presente en el dialplan. El segundo es el tiempo máximo que timbrará la extensión de un agente antes de considerarlo no disponible y pasar al siguiente. Este parámetro y los siguientes dos se utilizan para definir que tipo de tiempo de espera tendrá prioridad. Este primer parámetro define por cuantos segundos timbrará la extensión del agente. Valor: 15
retry
numero de segundos de espera antes de llamar otro agente si el primero no ha contestado dentro de los 15 segundos definidos en el parámetro anterior. Valor: 4
timeoutpriority
En este parámetro se define si se toma en consideración el tiempo de espera definido a nivel de aplicación o a nivel de archivo de configuración. Valor app (aplicación)
weight
El peso de la cola. Más alto el valor, más prioridad tendrá la cola. Si hay agentes que atienden más de una cola, las colas con peso más alto serán atendidas con mayor prioridad respecto a las colas con peso más bajo. Valor 0
wrapuptime
Tiempo de descanso de un agente entre una llamada y otra (en segundos) Valor 15
autofill
El mismo parámetro de la parte general del archivo se puede configurar por cada cola separadamente. Valor yes
autopause
yes = los agentes que no atenderán una llamada serán puestos en pausa all=el agente será puesto en pausa en todas las colas a que pertenece.
autopausedelay
Retrasa la puesta en pausa de los agentes que no han contestado una llamada por el numero de segundos indicados en este parámetro. Valor: 60
autopausebusy
Un agente será puesto en pausa automáticamente si su extensión aparece como ocupada. Valor: no
autopauseunavail
Parecido al anterior si su extensión no se encuentra disponible. Valor: no
maxlen
Numero máximo de personas que pueden estar esperando en la cola. Valor 50 Si se pone 0 no se fijará 384
Parámetro
Descripción ningún limite
setinterfacevar
yes = una serie de variables serán creadas justo antes de conectar un miembro de la cola con un cliente (véase archivo predefinido queues.conf)
setqueueentryvar
yes = otra serie de variables serán creadas justo antes de conectar un miembro de la cola con un cliente (véase archivo predefinido queues.conf)
setqueuevar
yes = otra serie de variables relacionadas con la cola serán creadas justo antes de conectar un miembro de la cola con un cliente (véase archivo predefinido queues.conf)
;membermacro=macro
Antes de conectar el agente con el cliente se puede ejecutar la macro indicada en este parámetro. Se deja comentado
;membergosub=gosub
Antes de conectar el agente con el cliente se puede ejecutar la subrutina indicada en este parámetro. Se deja comentado
announce-frequency
Cada cuanto segundos anunciar al cliente en la cola su posición y tiempo estimado de espera. Valor 90
min-announce-frequency
Para evitar que cada vez que la posición y/o el tiempo estimado de espera de un cliente cambie se le presente un anuncio, este parámetro define un tiempo (en segundos) que se esperará antes de comunicarle su nueva posición/tiempo estimado. Valor 15
;periodic-announce-frequency=60
Cada cuantos segundos presentar un anuncio personalizado al cliente en la cola de espera. Se deja comentado
;random-periodic-announce=no
Los anuncios pueden ser presentados según un orden aleatorio. Se deja comentado
relative-periodic-announce
Si se configura en yes la periodicidad de los anuncios (parámetro periodic-announce-frequency) empezará a contar desde que el anuncio ha terminado. Con no, desde que el anuncio ha empezado. Valor: yes
announce-holdtime
anunciar junto a la posición en la cola el tiempo estimado de espera. Puede ser yes, no, u once (una sola vez)
announce-position
Anuncia al cliente su posición en la cola. Valores: • yes – si • no – no se le anuncia
385
Parámetro
Descripción •
•
more - si la posición del cliente en la cola de espera es más alta del numero especificado en el próximo parámetro, se le anunciará que hay más de “valor del próximo parámetro” clientes esperando en la cola limit – solo los clientes con una posición en la cola de espera menor o igual al valor del parámetro que sigue, escucharán el anuncio de su posición en la cola de espera
announce-position-limit
5
announce-round-seconds
Con este parámetro se redondea los minutos y los segundos de espera anunciados al cliente. Valor 20
;queue-youarenext=queue-youarenext
A partir de esta linea se pueden personalizar las locuciones predefinidas de la cola de espera.
;queue-thereare=queue-thereare ;queue-callswaiting=queue-callswaiting ;queue-holdtime=queue-holdtime ;queue-minute=queue-minute ;queue-minutes=queue-minutes ;queue-seconds=queue-seconds ;queue-thankyou=queue-thankyou ;queue-reporthold=queue-reporthold ;periodic-announce=queue-periodicannounce ;periodic-announce=anuncio1,anuncio2
en este parámetro se definen los anuncios periódicos personalizados separados por una coma. Se deja comentado
;monitor-format=gsm|wav|wav49
formatos audio en que se grabarán las conversaciones de la cola de espera (si se deja comentado, no se grabaran)
monitor-type
Se define la aplicación para grabar la conversaciones. Puede ser monitor y mixmonitor
joinempty
Este parámetro con el que sigue, son los más importantes en la configuración de la cola. Aquí se define si un cliente puede o no entrar a una cola de espera si no hay agentes disponibles. Los distintos valores que se pueden utilizar, separados por una coma, son: 386
Parámetro
Descripción • •
• • • • • •
paused – un agente es considerado no disponible si está en pausa penalty – un agente es considerado no disponible si el valor de su penalidad es menor al valor asociado a la variable QUEUE_MAX_PENALTY inuse – un agente es considerado no disponible si el estado de su extensión es INUSE ringing – un agente es considerado no disponible si su extensión está timbrando unavailable - un agente es considerado no disponible si el estado de su extensión es UNAVAILABLE invalid - un agente es considerado no disponible si el estado de su extensión es INVALID unknown – un agente es considerado no disponible si el estado de su extensión es UNKNOWN wrapup - un agente es considerado no disponible si está en su tiempo de descanso (wraptime) después de haber atendido una llamada
Valor: paused,unavailable,invalid,unknown leavewhenempty
este parámetro aplica a los clientes que ya están en la cola de espera y en base a los valores indicados, si todos los agentes se vuelven no disponibles, el cliente será sacado de la cola. Valor paused,unavailable,invalid,unknown
;eventwhencalled = yes ;eventmemberstatus = yes
Estos dos parámetros configurados en yes, generan una serie de eventos, relacionados con la cola, en el AMI de Asterisk
reportholdtime
yes = Se anuncia al agente, antes de contestar la llamada, cuanto tiempo el cliente ha esperado en la cola
ringinuse
no = no se envían las llamadas a agentes cuyo estado de la extensión es INUSE
memberdelay
tiempo en segundos que el sistema esperará antes de conectar el agente con el cliente. De esta forma aunque hayan agentes disponibles, el cliente esperará ese tiempo antes de ser conectado con un agente. Valor 5
387
Parámetro
Descripción
timeoutrestart
yes = el tiempo de espera para que un agente conteste una llamada se resetea si el estado de la extensión es BUSY o CONGESTION
;defaultrule=myrule
en el archivo queuerules.conf se configuran distintos escenarios para manejar las colas con el sistema de penalidades. En el caso que se haya configurado un escenario para esta cola, en este parámetro se define el nombre. Se deja comentado
member => Agent/2000 member => Agent/2001 member => Agent/2002
a partir de esta linea se definen los miembros de la cola. La sintaxis es: member => tecnología/extensión,penalidad,nombre,extensión Se ponen los tres agentes configurados en el archivo agent.conf
Ahora se guardan los valores de la tabla en el archivo de configuración de las colas. Se renombra el predefinido: mv /etc/asterisk/queues.conf /etc/asterisk/queues.conf.old Se crea uno nuevo: nano /etc/asterisk/queues.conf se añaden las siguientes lineas: [general] persistentmembers=yes autofill=yes monitor-type=mixmonitor updatecdr=no shared_lastcall=yes negative_penalty_invalid=no log_membername_as_agent=no [ventas] musicclass=default ;announce=queue-ventas strategy=ringall servicelevel=120 context=ventas-exit penaltymemberslimit=0 timeout=15 retry=4 388
timeoutpriority=app weight=0 wrapuptime=15 autofill=yes autopause=yes autopausedelay=60 autopausebusy=no autopauseunavail=no maxlen=50 setinterfacevar=yes setqueueentryvar=yes setqueuevar=yes ;membermacro=macro ;membergosub=gosub announce-frequency=90 min-announce-frequency=15 ;periodic-announce-frequency=60 ;random-periodic-announce=no relative-periodic-announce=yes announce-holdtime=once announce-position=more announce-position-limit=5 announce-round-seconds=30 ;queue-youarenext=queue-youarenext ;queue-thereare=queue-thereare ;queue-callswaiting=queue-callswaiting ;queue-holdtime=queue-holdtime ;queue-minute=queue-minute ;queue-minutes=queue-minutes ;queue-seconds=queue-seconds ;queue-thankyou=queue-thankyou ;queue-reporthold=queue-reporthold ;periodic-announce=anuncio1,anuncio2 ;monitor-format=gsm|wav|wav49 monitor-type=mixmonitor joinempty=paused,unavailable,invalid,unknown leavewhenempty=paused,unavailable,invalid,unknown ;eventwhencalled = yes ;eventmemberstatus = yes reportholdtime=yes ringinuse=no memberdelay=5 timeoutrestart=yes ;defaultrule=myrule member => Agent/2000 member => Agent/2001 member => Agent/2002 389
Se guardan los cambios y se recarga el modulo de la aplicación de las colas en espera: asterisk -rvvvvvvvvvvvvvvvvvvvvv CLI> module reload app_queue.so CLI> queue show ventas ventas has 0 calls (max 50) in 'ringall' strategy (0s holdtime, 0s talktime), W:0, C:0, A:0, SL:0.0% within 120s Members: Agent/2002 (Unavailable) has taken no calls yet Agent/2000 (Unavailable) has taken no calls yet Agent/2001 (Unavailable) has taken no calls yet No Callers Con queue show ventas se muestran los datos de las colas. Los comandos asociados a la aplicación queue: CLI> help queue queue add member Add a channel to a specified queue queue reload {parameters|membe Reload queues, members, queue rules, or parameters queue remove member Removes a channel from a specified queue queue reset stats Reset statistics for a queue queue set penalty Set penalty for a channel of a specified queue queue set ringinuse Set ringinuse for a channel of a specified queue queue show Show status of a specified queue queue show rules Show the rules defined in queuerules.conf queue {pause|unpause} member Pause or unpause a queue member CLI> quit Se sale de la consola y se pasa al dialplan: nano /etc/asterisk/extensions.conf en el contexto internas se ponen las siguientes lineas: exten => 3000,1,Answer same => n,Queue(ventas,R) same => n,Hangup Con la opción R, cuando la llamada es enviada a un agente, el cliente dejará de escuchar la música de espera y en su lugar escuchará el tono de timbrado. Se guardan los cambios y se recarga el dialplan:
390
asterisk -rx "dialplan reload" Desde la extensión 1000 conectada a Asterisk, se marca la extensión 3000. Como no hay agentes disponibles la llamada terminará (parte en negrita): -- Executing [3000@externas:1] Answer("SIP/1000-00000005", "") in new stack -- Executing [3000@externas:2] Queue("SIP/1000-00000005", "ventas,R") in new stack WARNING[22025]: app_queue.c:6202 queue_exec: Unable to join queue 'ventas' -- Executing [3000@externas:3] Hangup("SIP/1000-00000005", "") in new stack Ahora desde la extensión 1000 se marca el numero 2000 (para conectarse como agente a las colas de espera). Una vez conectado se entra a la consola de Asterisk: asterisk -rvvvvvvvvvvvvvvv CLI> queue show ventas ventas has 0 calls (max 50) in 'ringall' strategy (0s holdtime, 0s talktime), W:0, C:0, A:0, SL:0.0% within 120s Members: Agent/2002 (Unavailable) has taken no calls yet Agent/2000 (Not in use) has taken no calls yet Agent/2001 (Unavailable) has taken no calls yet No Callers El agente 2000 está disponible. Desde la extensión 1001 se marca el numero 3000. Cuando el agente (la extensión 1000) reciba la llamada del cliente (la extensión 1001), el estado de la cola de espera será: CLI> queue show ventas ventas has 0 calls (max 50) in 'ringall' strategy (0s holdtime, 0s talktime), W:0, C:0, A:0, SL:0.0% within 120s Members: Agent/2002 (Unavailable) has taken no calls yet Agent/2000 (Busy) has taken no calls yet Agent/2001 (Unavailable) has taken no calls yet No Callers y al terminar la llamada: CLI> queue show ventas ventas has 0 calls (max 50) in 'ringall' strategy (0s holdtime, 28s talktime), W:0, C:1, A:0, SL:100.0% within 120s Members: Agent/2002 (Unavailable) has taken no calls yet Agent/2000 (Not in use) has taken 1 calls (last was 27 secs ago) Agent/2001 (Unavailable) has taken no calls yet No Callers 391
Como se ha visto, si no hay agentes disponibles no se deja entrar el cliente a la cola. Como se ha dicho el llamante se envía a la prioridad que sigue. Se puede crear otro escenario de este tipo: nano /etc/asterisk/extensions.conf en el contexto internas se pone exten => 3001,1,Answer same => n,Queue(ventas) same => n,Voicemail(1000@default) same => n,Hangup De esta forma el llamante tendrá la oportunidad de dejar un mensaje en el buzón de voz. Se guardan los cambios y se recarga el dialplan. asterisk -rvvvvvvvvvvvv CLI> dialplan reload Desde la extensión 1000 se marca el 3001 (sin agentes conectados). Executing [3001@externas:1] Answer("SIP/1000-00000017", "") in new stack Executing [3001@externas:2] Queue("SIP/1000-00000017", "ventas") in new stack [Oct 21 16:58:49] WARNING[15270]: app_queue.c:5160 queue_exec: Unable to join queue 'ventas' Executing [3001@externas:3] VoiceMail("SIP/1000-00000017", "1000@default") in new stack Como no hay agentes disponibles, la llamada será enviada al buzón de voz. 16.3 Agentes dinámicos En Asterisk hay dos aplicaciones para añadir y quitar un miembro de una cola. Estas dos aplicaciones son: • AddQueueMember • RemoveQueueMember ¿Cual es la diferencia con la aplicación Agentlogin? La aplicación Agentlogin es pensada para call center de grandes dimensiones. En el caso de una pequeña empresa que quiera tener un pequeño call center y no quiera que los empleados estén todo el tiempo conectados como agentes sino que puedan desarrollar su normal actividad y al mismo tiempo atender las llamadas de la cola, la aplicación addQueueMember es mucho más funcional. En el plan de marcado, contexto internas, se añaden estos dos bloques: 392
nano /etc/asterisk/extensions.conf exten => *70,1,Addqueuemember(ventas,SIP/${CALLERID(num)}) same => n,Playback(agent-loginok) same => n,Hangup exten => *71,1,Removequeuemember(ventas,SIP/${CALLERID(num)}) same => n,Playback(agent-loggedoff) same => n,Hangup Con el primer bloque las extensiones se añaden a la cola ventas, con el segundo se quitan. Hay dos aplicaciones más que permiten a los agentes dinámicos ponerse en pausa y no atender las llamadas para luego, después del “descanso” volver a atender la cola. Hay que acordarse que cuando un agente se pone en pausa, por como se ha configurado la cola, el agente será considerado como no disponible. Estas dos aplicaciones se pueden añadir al plan de marcado de la siguiente forma: exten => *72,1,PauseQueueMember(ventas,SIP/${CALLERID(num)}) same => n,Playback(beep) same => n,Hangup exten => *73,1,UnpauseQueueMember(ventas,SIP/${CALLERID(num)}) same => n,Playback(beep) same => n,Hangup Todos los datos de las conexiones de los agentes dinámicos se guardan en la base de datos interna de Asterisk. Se guardan los cambios y se recarga el plan de marcado: asterisk -rvvvvvvvvvvvvv CLI> dialplan reload Ahora desde la extensión 1000 se llama el numero *70 y se mira lo que aparece en la base de datos de Asterisk y en la cola ventas: CLI> database show /Queue/PersistentMembers/ventas
: SIP/1000;0;0;SIP/1000;SIP/1000
CLI> queue show ventas ventas has 0 calls (max 50) in 'ringall' strategy (0s holdtime, 1s talktime), W:0, C:1, A:0, SL:100.0% within 120s Members: Agent/2002 (Unavailable) has taken no calls yet Agent/2000 (Unavailable) has taken 1 calls (last was 394 secs ago) 393
Agent/2001 (Unavailable) has taken no calls yet SIP/1000 (dynamic) (Not in use) has taken no calls yet No Callers CLI> quit Como en el archivos de las colas de espera se ha configurado el parámetro persistentmembers=yes, si se reinicia Asterisk, los datos del agente deben permanecer en la base de datos. service asterisk restart asterisk -rvvvvvvvvvvvvvvvvvvvvvvv CLI> database show /Queue/PersistentMembers/ventas
: SIP/1000;0;0;SIP/1000;SIP/1000
El agente no se ha borrado de la cola de espera. Para probarlo desde la extensión 1001 se marca el numero 3001. Como el agente dinámico quiere almorzar, se pone en pausa marcando el numero *72 Si se mira el estado de la cola: CLI> queue show ventas ventas has 0 calls (max 50) in 'ringall' strategy (2s holdtime, 2s talktime), W:0, C:1, A:0, SL:100.0% within 120s Members: Agent/2002 (Unavailable) has taken no calls yet Agent/2000 (Unavailable) has taken no calls yet Agent/2001 (Unavailable) has taken no calls yet SIP/1000 (dynamic) (paused) (Not in use) has taken no calls yet No Callers Se podrá comprobar que efectivamente el agente dinámico está en pausa. Para volver activo desde la extensión 1000 se marca el numero *73. El resultado: CLI> queue show ventas ventas has 0 calls (max 50) in 'ringall' strategy (2s holdtime, 2s talktime), W:0, C:1, A:0, SL:100.0% within 120s Members: Agent/2002 (Unavailable) has taken no calls yet Agent/2000 (Unavailable) has taken no calls yet Agent/2001 (Unavailable) has taken no calls yet SIP/1000 (dynamic) (Not in use) has taken no calls yet No Callers Terminada la prueba se quita la extensión 1000 de la cola de espera llamando desde esa extensión el 394
numero: *71 Se averigua en la base de datos de Asterisk que efectivamente el agente ya no está registrado: CLI> database show Ya no aparece la linea: /Queue/PersistentMembers/ventas
: SIP/1000;0;0;SIP/1000;SIP/1000
16.4 Estadísticas de las colas Por defecto todas las estadísticas de las colas se guardan en el archivo predefinido queue_log presente en la carpeta /var/log/asterisk. La mayoría de los programas que permiten obtener gráficos de estas estadísticas, leen ese archivo. Entre ellos, se pueden citar los dos más reconocidos (el primero con una versión Lite gratuita disponible y el segundo comercial) • •
Asternic Call Center Stats QueueMetrics
¿Cómo se interpretan los datos presentes en este archivo? Cada linea del archivo puede contener hasta 10 campos distintos separados por un pipe | Estos son: • • • • • •
fecha y hora en formado EPOCH identificador único de la llamada nombre de la cola nombre del agente evento que se ha presentado campos de datos (hasta 5) que contienen los valores devueltos por los eventos de la cola.
En el caso que el evento no incluya todos los campos, en lugar de los datos aparecerá el valor NONE. Los eventos que se pueden presentar son: •
ABANDON: cuando un cliente abandona la cola sin ser atendido. Junto al evento aparecerá el nombre de la cola, la posición que tenía el cliente cuando abandonó la cola, la posición que tenía al momento de entrar en la cola y el tiempo que esperó antes de colgar.
•
ADDMEMBER: cuando se añade un agente dinámico a la cola. Junto al evento aparecerá la variable UNIQUEID de la llamada, el nombre de la cola a la que se registró el agente y la extensión con la que se registró.
Ejemplo: 1323691008|1323691008.7|ventas|SIP/1000|ADDMEMBER| 395
•
AGENTDUMP: el agente ha rechazado la llamada mientras el cliente estaba escuchando el anuncio de la cola y antes de ser conectado con el cliente
•
AGENTLOGIN: cuando un agente se conecta utilizando la aplicación Agentlogin. Junto al evento aparecerá la variable UNIQUEID de la llamada, El numero del agente y el canal utilizado para el registro.
Ejemplo: 1323689794|1323689785.3|NONE|Agent/2000|AGENTLOGIN|SIP/1000-00000003 •
AGENTLOGOFF: cuando un agente se desconecta. Junto al evento aparecerá la variable UNIQUEID de la llamada, el numero del agente, el canal utilizado cuando se registró y el tiempo en segundos que ha quedado conectado.
Ejemplo: 1323689825|1323689785.3|NONE|Agent/2000|AGENTLOGOFF|SIP/1000-00000003|31 •
COMPLETEAGENT: cuando un agente que ha atendido una llamada cuelga. Junto al evento aparecerá la variable UNIQUEID, el nombre de cola, la extensión del agente, el tiempo que esperó el cliente antes de ser atendido, la duración de la llamada y la posición que tenía el cliente al entrar en la cola.
Ejemplo: 1323690712|1323690653.4|ventas|Agent/2000|COMPLETEAGENT|9|50|1 •
COMPLETECALLER: cuando un cliente atendido por un agente cuelga la llamada. Junto al evento aparecerá , la variable UNIQUEID, el nombre de la cola, la extensión del agente, el tiempo que esperó el cliente antes de ser atendido, la duración de la llamada y la posición inicial que tenía el cliente al entrar en la cola.
Ejemplo: 1323695800|1323694274.2|ventas|SIP/1000|COMPLETECALLER|16|27|1 •
CONFIGRELOAD: cuando se recarga la configuración de Asterisk.
Ejemplo: 1323531449|NONE|NONE|NONE|CONFIGRELOAD| •
CONNECT: cuando un cliente es atendido por un agente. Junto al evento aparecerá, el UNIQUEID de la llamada del cliente, el nombre de la cola, la extensión del agente que ha atendido el cliente, el tiempo que ha esperado el cliente antes de ser atendido, el UNIQUEID de la llamada entre cliente y agente, y el tiempo que timbró la extensión del agente.
Ejemplo: 1323690662|1323690653.4|ventas|Agent/2000|CONNECT|9|1323690653.5|0 •
ENTERQUEUE: cuando un cliente entra en la cola. Junto al evento aparecerá, el UNIQUEID de la llamada, el nombre de la cola, la URL (si aplica) y el CALLERID del cliente.
Ejemplo: 1323690653|1323690653.4|ventas|NONE|ENTERQUEUE||1001 396
•
EXITEMPTY: cuando un cliente viene desconectado de la cola porque no hay agentes disponibles. Junto al evento aparecerá el UNIQUEID de la llamada, el nombre de la cola, posición inicial y final del cliente en la cola, y el tiempo que ha esperado en la cola antes de ser desconectado.
Ejemplo: 1323710320|1323710281.17|ventas|NONE|EXITEMPTY|1|1|38 •
EXITWITHKEY: el cliente mientras esperaba en la cola ha presionado una tecla. Junto al evento aparecerá el UNIQUEID de la llamada, el nombre de la cola, el numero de la tecla presionada (en este caso 8), y la posición del cliente en la cola antes de presionar la tecla.
Ejemplo: 1323710850|1323710844.23|ventas|NONE|EXITWITHKEY|8|1 •
EXITWITHTIMEOUT: el cliente ha sido desconectado de la cola porque después del tiempo máximo permitido de espera, ningún agente lo ha atendido. Junto al evento aparecerá el UNIQUEID de la llamada, el nombre de la cola, la posición final y inicial del cliente en la cola, y el tiempo que éste ha esperado antes de ser desconectado
•
PAUSE: cuando un agente se pone en pausa utilizando la aplicación PauseQueueMember de Asterisk. Junto al evento aparecerá el nombre de la cola y la extensión del agente. Si el agente ha sido desconectado de la cola porque no ha atendido una llamada antes del tiempo configurado, aparecerá también el valor Auto-Pause
Ejemplo1: 1323712960|NONE|ventas|SIP/1000|PAUSE| Ejemplo2: 1323710541|NONE|ventas|SIP/1000|PAUSE|Auto-Pause •
QUEUESTART: cuando Asterisk ha sido reiniciado
Ejemplo: 1323447241|NONE|NONE|NONE|QUEUESTART| •
REMOVEMEMBER: cuando una agente se desconecta de la cola con la aplicación Removequeuemember. Junto al evento aparecerá el UNIQUEID de la llamada, el nombre de la cola y la extensión del agente.
•
RINGNOANSWER: cuando la extensión de un agente timbra y al agente no contesta dentro del tiempo configurado. Junto al evento aparecerá el UNIQUEID de la llamada, el nombre de la cola, la extensión del agente que no ha contestado la llamada y el tiempo (en mili segundos) que ha timbrado la extensión del agente:
Ejemplo: 1323711528|1323711480.31|ventas|SIP/1000|RINGNOANSWER|45000 •
SYSCOMPAT: la llamada ha sido contestada por un agente pero ha terminado porque los dos canales (cliente y agente) no eran compatibles.
397
•
TRANSFER: cuando el cliente, atendido por un agente, ha sido transferido a otra extensión. Junto al evento aparecerá el UNIQUEID de la llamada, el nombre de la cola, la extensión del agente que ha atendido la llamada, el numero de la extensión donde ha sido transferida la llamada, el contexto utilizado para la transferencia, el tiempo que ha esperado el cliente en la cola, el tiempo de duración de la llamada antes de la transferencia y la posición del cliente al entrar en la cola.
Ejemplo: 1323712663|1323712627.34|ventas|SIP/1000|TRANSFER|1002|externas|12|24|1 •
UNPAUSE: cuando un agente vuelve a conectarse a la cola utilizando la aplicación UnpauseQueueMember. Junto al evento aparecerá el nombre de la cola y la extensión del agente.
16.5 Colas, agentes y estadísticas en Realtime dinámico Como para las extensiones, las conferencias, los buzones de voz, también para las colas es posible trabajar en Realtime. En este caso se puede guardar en Realtime: • • •
la configuración de las colas los agentes las estadísticas de la cola
Como queda claro por lo arriba mencionado, hay que crear tres tablas distintas, una para cada tipo de objectos que se guardarán. Se inicia con la configuración de las colas. En esta tabla se pueden configurar todos los valores presentes para la definición de la cola, aunque el único obligatorio es el nombre de la cola misma. se entra en MySQL mysql -u root -psesamo se escoge la base de datos asterisk: mysql> use asterisk se crea la tabla para las colas: mysql> CREATE TABLE `queue_table` ( `name` varchar(128) NOT NULL, `musiconhold` varchar(128) default NULL, `announce` varchar(128) default NULL, `context` varchar(128) default NULL, `strategy` varchar(128) default NULL, `servicelevel` int(11) default NULL, `penaltymemberslimit` int(11) default NULL, 398
`timeout` int(11) default NULL, `retry` int(11) default NULL, `timeoutpriority` varchar(128) default NULL, `weight` int(11) default NULL, `wrapuptime` int(11) default NULL, `autofill` varchar(128) default NULL, `autopause` varchar(128) default NULL, `autopausedelay` INT(4) default 60, `autopausebusy` varchar(3) default NULL, `autopauseunavail` varchar(3) default NULL, `maxlen` int(11) default NULL, `setinterfacevar` varchar(3) default NULL, `setqueueentryvar` varchar(3) default NULL, `setqueuevar` varchar(3) default NULL, `membermacro` varchar(128) default NULL, `announce-frequency` int(11) default NULL, `min-announce-frequency` int(11) default NULL, `periodic-announce-frequency` int(11) default NULL, `random-periodic-announce` varchar(3) default NULL, `relative-periodic-announce` varchar(3) default NULL, `announce-holdtime` varchar(4) default NULL, `announce-position` varchar(3) default NULL, `announce-position-limit` int(11) default NULL, `announce-round-seconds` int(11) default NULL, `queue-youarenext` varchar(128) default NULL, `queue-thereare` varchar(128) default NULL, `queue-callswaiting` varchar(128) default NULL, `queue-holdtime` varchar(128) default NULL, `queue-minute` varchar(128) default NULL, `queue-minutes` varchar(128) default NULL, `queue-seconds` varchar(128) default NULL, `queue-thankyou` varchar(128) default NULL, `queue-reporthold` varchar(128) default NULL, `periodic-announce` varchar(512) default NULL, `monitor-format` varchar(128) default NULL, `monitor-type` varchar(128) default NULL, `joinempty` varchar(128) default NULL, `leavewhenempty` varchar(128) default NULL, `eventwhencalled` varchar(128) default NULL, `eventmemberstatus` varchar(128) default NULL, `reportholdtime` varchar(128) default NULL, `ringinuse` varchar(3) default NULL, `memberdelay` int(11) default NULL, `timeoutrestart` varchar(128) default NULL, `defaultrule` varchar(128) default NULL, PRIMARY KEY (`name`) ); 399
Se crea la tabla para los agentes de las colas: mysql> CREATE TABLE queue_member_table ( uniqueid INT(10) UNSIGNED PRIMARY KEY AUTO_INCREMENT, membername varchar(40), queue_name varchar(128), interface varchar(128), penalty INT(11), paused INT(11), UNIQUE KEY queue_interface (queue_name, interface) ); y por ultimo se crea la tabla para guardar las estadísticas de las colas: mysql> CREATE TABLE queue_log ( time datetime, callid char(50), queuename char(50), agent char(50), event char(20), data1 char(50), data2 char(50), data3 char(50), data4 char(50), data5 char(50), index bydate (time), index qname (queuename,time) ); Se sale de MySQL y se modifica el archivo del realtime: mysql> quit nano /etc/asterisk/extconfig.conf se modifican estas tres lineas: ;queues => odbc,asterisk ;queue_members => odbc,asterisk ;queue_log => mysql,genera para que queden: queues => odbc,asterisk,queue_table queue_members => odbc,asterisk,queue_member_table queue_log => odbc,asterisk,queue_log 400
Se guardan los cambios y se reinicia Asterisk: service asterisk restart Ahora para probar el log de las colas en realtime, desde la extensión 1000 se marca *70 para conectarse a la cola ventas como agente dinámico y luego desde las demás extensiones se marca el 3001. En la base de datos: mysql -u root -psesamo mysql> use asterisk mysql> select time,queuename,agent,event,data1,data2,data3 from queue_log; El resultado:
Se sale del cliente MySQL: mysql> quit Como segunda prueba se crea otra cola en realtime. Desde Webmin se entra a la tabla queue_table y se rellenan los campos:
401
402
Se guarda la configuración presionando el botón “Save”. Se vuelve a la consola de Asterisk donde aparecerá la nueva cola: CLI> queue show compras compras has 0 calls (max 50) in 'ringall' strategy (0s holdtime, 0s talktime), W:1, C:0, A:0, SL:0.0% within 120s No Members No Callers
403
que todavía no tienes agentes configurados. Desde el Webmin se pasa a la tabla queue_member_table y se añaden dos agentes a la cola creada:
Se vuelve nuevamente a la consola de Asterisk: CLI> queue show compras compras has 0 calls (max 50) in 'ringall' strategy (0s holdtime, 0s talktime), W:1, C:0, A:0, SL:0.0% within 120s Members: Fulano (Agent/2000 from Agent/2000) (ringinuse disabled) (realtime) (Unavailable) has taken no calls yet Sutano (Agent/2001 from Agent/2001) (ringinuse disabled) (realtime) (Unavailable) has taken no calls yet
No Callers Para terminar si desde la extensión 1000 se marca 2000 para conectarse como agente 2000. Una vez conectado en la consola de Asterisk: CLI> queue show queue show compras has 0 calls (max 50) in 'ringall' strategy (0s holdtime, 0s talktime), W:1, C:0, A:0, SL:0.0% within 120s Members: Fulano (Agent/2000 from Agent/2000) (ringinuse disabled) (realtime) (Not in use) has taken no calls yet Sutano (Agent/2001 from Agent/2001) (ringinuse disabled) (realtime) (Unavailable) has taken no calls yet
No Callers ventas has 0 calls (max 50) in 'ringall' strategy (0s holdtime, 0s talktime), W:0, C:0, A:2, SL:0.0% within 120s 404
Members: Agent/2002 (ringinuse disabled) (Unavailable) has taken no calls yet Agent/2000 (ringinuse disabled) (Not in use) has taken no calls yet Agent/2001 (ringinuse disabled) (Unavailable) has taken no calls yet No Callers El agente estará conectado a las dos colas creadas (en negrita). 16.6 La aplicación Chan_Spy La aplicación chan_spy es una funcionalidad que permite escuchar las conversaciones activas en la centralita Asterisk. Según la configuración permite escuchar sin que los canales espiados se den cuenta, hablar con el canal espiado sin que el otro interlocutor pueda escuchar la conversación, hablar con los dos “canales” de la llamada. Como se puede entender, es una aplicación muy útil para ser implementada en los Call Center ya que permite poder controlar la calidad de las llamadas y al mismo tiempo formar los operadores y/o ayudarlos en su quehacer cotidiano. La sintaxis de la aplicación es: CLI> core show application ChanSpy ChanSpy([chanprefix][,options]) Las opciones: • • • •
• • • • •
b – espía solamente los canales que están en una conversación B – en lugar de hablar solamente con el canal espiado, esta opción permite hablar con ambos c(digit) – normalmente para pasar de un canal espiado a otro se utiliza la tecla * (asterisco). Si se quiere modificar la tecla predefinida, se indica en este parámetro d – remplaza los dígitos predefinidos para pasar de un canal espiado a otro y los dígitos predefinidos para cambiar el modo de espiado: • 4 – modo espiar • 5 – modo susurrar al canal espiado • 6 – modo hablar con ambos canales e(ext) – con esta opción se podrán espiar solamente las extensiones que aparecen en esta opción separadas por los dos puntos (ejemplo: e(1000:1001:1002) E – termina la llamada cuando el canal espiado cuelga g(grp) – será permitido espiar solamente los canales que están presentes en el grupo definido a través de la variable ${SPYGROUP} n([mailbox][@context]) – al canal que está espiando se le anunciará el nombre del canal espiado si este ha grabado su nombre cuando ha configurado su buzón de voz. o – quien está espiando escuchará solamente el audio del canal espiado y no el audio de ambos canales presentes en la conversación
405
• • • • • • • • •
q – no se enviará un beep al canal espiado cuando se empieza a espiarlo r(basename) – con está opción se graba la llamada espiada y se guarda en la carpeta /var/spool/asterisk/monitor si se indica un prefijo (basename), con ese prefijo empezará el nombre del archivo donde se grabó la llamada. Predefinido es chanspy s – no se anuncia el tipo de canal espiado (SIP, IAX2) cuando se anuncia el nombre asociado al canal S – se termina el modo espiar cuando no hay más canales disponibles para espiar v(value) – ajusta el volumen del canal espiado. Puede ser un valor que va de -4 a 4 w – activa el modo susurrar. De esta forma el canal que está espiando puede hablar con el canal espiado W – activa el modo “susurrar privado”. De esta forma el canal que está espiando puede hablar con el canal espiado pero no puede escuchar la conversación x(digit) – permite configurar un dígito que puede ser utilizado para salir de la aplicación X – permite al canal que está espiando, digitando una tecla, salir de la aplicación y continuar en el mismo contexto, numero de extensión correspondiente a la tecla digitada. Si se quiere enviar el canal en otro contexto, hay que especificarlo antes de utilizar la aplicación ChanSpy.
La opciones son muchas y a lo largo de este párrafo se verá como utilizarlas. Para empezar, se configura la aplicación en la forma más sencilla: nano /etc/asterisk/extensions.conf después del contexto internas, se crea un nuevo contexto con la primera extensión: [espiar] exten => 11,1,NoOp(contexto ChanSpy) same => n,ChanSpy(all) same => n,Hangup Se podrá espiar cualquier extensión que esté efectuando, recibiendo una llamada. Además de esta forma se puede decidir que extensiones tienen acceso al contexto espiar y que por ende pueden utilizar la aplicación ChanSpy. En este caso este contexto se añade a los dos existentes: [externas] include => internas include => internacio include => parkedcalls include => test include => conferencias include => espiar [locales] include => internas include => auten include => parkedcalls 406
include => test include => conferencias include => espiar Se guardan los cambios y se recarga el dialplan: asterisk -rvvvvvvvvvvvvvvvvvvvvvv CLI> dialplan reload Ahora desde la extensión 1001 se llama la extensión 1002. Cuando las dos extensiones están hablando, desde la extensión 1000 se marca el numero 11. En la consola de Asterisk: - Executing [11@externas:1] NoOp("SIP/1000-00000009", "contexto ChanSpy") in new stack -- Executing [11@externas:2] ChanSpy("SIP/1000-00000009", "all") in new stack > 0x7f15e8035c80 -- Probation passed - setting RTP source address to 79.44.192.186:53742 -- Playing 'beep.alaw' (language 'es') > 0x7f15e8035c80 -- Probation passed - setting RTP source address to 79.44.192.186:53742 -- Playing 'spy-sip.alaw' (language 'es') -- Playing 'digits/1.alaw' (language 'es') -- Playing 'digits/0.alaw' (language 'es') -- Playing 'digits/0.alaw' (language 'es') -- Playing 'digits/2.alaw' (language 'es') == Spying on channel SIP/1002-00000008 Se anunciará el tipo de canal espiado (SIP) y el numero de extensión (1001). Para pasar de un canal espiado a otro se utiliza la tecla *. Si se presiona: == Done Spying on channel SIP/1002-00000008 -- Playing 'spy-sip.alaw' (language 'es') -- Playing 'digits/1.alaw' (language 'es') -- Playing 'digits/0.alaw' (language 'es') -- Playing 'digits/0.alaw' (language 'es') -- Playing 'digits/1.alaw' (language 'es') == Spying on channel SIP/1001-00000007 Se pasa a espiar del canal 1002 al canal 1001 (que al final es la misma llamada). Si no se quiere que el canal espiado escuche un beep que le anuncie que el canal está siendo espiado, el mismo bloque del dialplan sería (opción q): exten => 12,1,NoOp(contexto ChanSpy) same => n,ChanSpy(all,q) same => n,Hangup Si se quiere espiar solamente canales que estén ya en una conversación (opción b):
407
exten => 13,1,NoOp(contexto ChanSpy) same => n,ChanSpy(all,qb) same => n,Hangup Si se quiere espiar solamente canales SIP: exten => 14,1,NoOp(contexto ChanSpy) same => n,ChanSpy(SIP,qb) same => n,Hangup Si se quiere espiar solamente los agentes configurados en el archivo agent.conf y al mismo tiempo poder hablar con ellos sin que el otro interlocutor pueda escuchar la conversación: exten => 15,1,NoOp(contexto ChanSpy) same => n,ChanSpy(Agent,qbw) same => n,Hangup Estos cuatros bloques se añaden al contexto [espiar]. Entre las distintas opciones disponibles hay una que permite a la extensión que está espiando de presionar una tecla y “saltar” a ese numero de extensión en el mismo contexto. Para probar la opción, se añade al contexto espiar el siguiente bloque: exten => 16,1,NoOp(contexto ChanSpy) same => n,ChanSpy(all,qbX) same => n,Hangup exten => 5,1,Playback(goodbye) same => n,hangup El resultado en la consola de Asterisk: Executing [16@externas:1] NoOp("SIP/1000-0000000a", "contexto ChanSpy") in new stack -- Executing [16@externas:2] ChanSpy("SIP/1000-0000000a", "all,qbX") in new stack > 0x7f15e8073c80 -- Probation passed - setting RTP source address to 79.44.192.186:63236 > 0x7f15e8073c80 -- Probation passed - setting RTP source address to 79.44.192.186:63236 == Spying on channel SIP/1002-00000008 [Apr 17 10:39:57] NOTICE[24536][C-00000008]: app_chanspy.c:487 start_spying: Attaching SIP/1000-0000000a to SIP/1002-00000008 == Done Spying on channel SIP/1002-00000008 -- Executing [5@externas:1] Playback("SIP/1000-0000000a", "goodbye") in new stack -- Playing 'goodbye.alaw' (language 'es') -- Executing [5@externas:2] Hangup("SIP/1000-0000000a", "") in new stack Otra opción interesante de la aplicación ChanSpy es la posibilidad de definir la variable ${SPYGROUP} que permite espiar solamente los canales que pertenecen a ese grupo. Si, por ejemplo, se quiere espiar solamente los canales de una determinada cola de espera, se modifica el dialplan:
408
nano /etc/asterisk/extensions.conf Se crea un nuevo bloque para la cola de espera compras: exten => 3002,1,Answer same => n,Set(SPYGROUP=ventas) same => n,Queue(ventas,R) same => n,Hangup y luego en el contexto espiar se añade el siguiente bloque: exten => 17,1,NoOp(contexto ChanSpy) same => n,ChanSpy(SIP,qbg(ventas)) same => n,Hangup Se guardan los cambios y se recarga el dialplan: asterisk -rvvvvvvvvvvvvv CLI> dialplan reload De esta forma llamando la extensión 16 se podrán espiar solamente los canales de la cola de espera ventas (g(ventas)). Para terminar este párrafo, otra forma de espiar los canales es digitando directamente el canal que se quiere espiar. Se añade al contesto espiar el siguiente bloque: exten => _*10XXXX,1,NoOp(contexto ChanSpy) same => n,ChanSpy(SIP/${EXTEN:3},qS) same => n,Hangup De esta forma se espiará el canal digitado después de *10. Ejemplo: si se digita *101001 el canal espiado sera SIP/1001 ya que los primeros tres dígitos marcados serán eliminados de la variable $ {EXTEN}: Executing [*101001@externas:1] NoOp("SIP/1000-0000000b", "contexto ChanSpy") in new stack -- Executing [*101001@externas:2] ChanSpy("SIP/1000-0000000b", "SIP/1001,qS") in new stack > 0x7f15e8034e30 -- Probation passed - setting RTP source address to 79.44.192.186:64374 > 0x7f15e8034e30 -- Probation passed - setting RTP source address to 79.44.192.186:64374 == Spying on channel SIP/1001-00000007 Con la opción S si el canal no está activo, la llamada será terminada.
409
Capitulo XVII Asterisk y los FAX En Asterisk la recepción y trasmisión de FAX se basa en dos módulos: • •
res_fax res_fax_spandsp
Estos dos módulos se apoyan en las librerías SpanDSP y permiten la recepción y envío de FAX a través de dos protocolos: T30 (audio) y T38 (FoIP – Fax over IP). En este capitulo se presentará primero una solución basada en la combinación del programa IAXmodem con el servidor de FAX Hylafax, para luego abordar el tema del protocolo T38. 17.1 IAXmodem IAXmodem es un módem software, escrito en lenguaje C que utiliza un canal IAX2 en lugar de una línea telefónica y un DSP software (SpanDSP) en lugar de un chip DSP (Digital Signal Processing). Se descargan las fuentes de IAXmodem: cd /usr/src wget http://switch.dl.sourceforge.net/sourceforge/iaxmodem/iaxmodem-1.2.0.tar.gz Se descomprime el archivo tar -xf iaxmodem-1.2.0.tar.gz Se entra en la carpeta: cd iaxmodem-1.2.0 Se compila: ./configure make Se copia el programa compilado en la siguiente carpeta: cp iaxmodem /usr/local/sbin Como se van a crear dos módem IAX2, se crean algunas carpetas y archivos para el correcto funcionamiento de IAXmodem: mkdir /etc/iaxmodem
mkdir /var/log/iaxmodem touch /var/log/iaxmodem/ttyIAX1 touch /var/log/iaxmodem/ttyIAX2 touch /var/log/iaxmodem/iaxmodem En la carpeta de las fuentes de IAXmodem hay un archivo de configuración predefinido para la creación de un módem IAX. Se puede tomar como referencia para la creación de los dos módem IAX que se utilizarán para la recepción y envío de FAX con Asterisk. Se configura el primero: cd /etc/iaxmodem nano ttyIAX1 La lineas son: device /dev/ttyIAX1 owner uucp:uucp mode 660 port 4570 refresh 60 server 127.0.0.1 peername iaxmodem1 secret pbx5050 cidname VozToVoice cidnumber XXXXXXXXXX codec alaw Se guardan los cambios. Esta configuración es valida si IAXmodem está instalado en el mismo servidor donde se instaló Asterisk. En el caso de dos servidores distintos hay que indicar en la línea server la dirección IP del servidor Asterisk. Se pone la contraseña en secret y en cidname y cidnumber nombre y numero telefónico que usará IAXmodem para presentarse a Asterisk. Para configurar distintos IAXmodem hay que modificar en la primera línea el nombre del device, en port el puerto y en peername el nombre de la troncal. IMPORTANTE: en la linea codec hay que indicar un codec audio que no utilice algoritmos de compresión. Esto porque el protocolo T30 funciona solamente con canales audio no comprimidos. Para el segundo IAXmodem la configuración será: nano ttyIAX2 device /dev/ttyIAX2 412
owner uucp:uucp mode 660 port 4571 refresh 60 server 127.0.0.1 peername iaxmodem2 secret pbx5051 cidname VozToVoice cidnumber XXXXXXXXXX codec alaw Se guardan los cambios. Ahora hay que modificar la configuración de Asterisk para añadir las dos extensiones IAX (iaxmodem1 y iaxmodem2) en el archivo iax.conf nano /etc/asterisk/iax.conf Al final del archivo se añaden los dos bloques que siguen: [iaxmodem1] type=friend context=fax disallow=all allow=alaw username=iaxmodem1 secret=pbx5050 qualify=yes notransfer=yes host=dynamic requirecalltoken=auto [iaxmodem2] type=friend context=fax disallow=all allow=alaw username=iaxmodem2 secret=pbx5051 qualify=yes notransfer=yes host=dynamic requirecalltoken=auto Se guardan los cambios y se actualiza la configuración de IAX2 en Asterisk asterisk -rvvvvvvvvvvvvvvvvvvv 413
CLI> iax2 reload Se abre otra ventana terminal o se crea otra sesión de PuTTy y se realiza una prueba para ver si la conexión entre IAXmodem y Asterisk funciona: cd /usr/local/sbin ./iaxmodem ttyIAX1 debe aparecer: [2011-10-24 09:44:37] Modem started [2011-10-24 09:44:37] Setting device = '/dev/ttyIAX1' [2011-10-24 09:44:37] Setting owner = 'uucp:uucp' [2011-10-24 09:44:37] Setting mode = '660' [2011-10-24 09:44:37] Setting port = 4570 [2011-10-24 09:44:37] Setting refresh = 60 [2011-10-24 09:44:37] Setting server = '127.0.0.1' [2011-10-24 09:44:37] Setting peername = 'iaxmodem1' [2011-10-24 09:44:37] Setting secret = 'pbx5050' [2011-10-24 09:44:37] Setting cidname = 'VozToVoice' [2011-10-24 09:44:37] Setting cidnumber = 'XXXXXXXX' [2011-10-24 09:44:37] Setting codec = ulaw [2011-10-24 09:44:37] Opened pty, slave device: /dev/pts/4 [2011-10-24 09:44:37] Created /dev/ttyIAX1 symbolic link Ignoring unknown information element 'Unknown IE' (54) of length 0 [2011-10-24 09:44:37] Registration completed successfully. Se controla que en la consola de Asterisk aparezca la conexión de IAXmodem (volviendo a la otra ventana Terminal abierta):
Para iniciar IAXmodem en automático se instala el script presente en la carpeta de las fuentes de IAXmodem: cd /usr/src/iaxmodem-1.2.0 cp iaxmodem.init.fedora /etc/init.d/iaxmodem se vuelve ejecutable: chmod +x /etc/init.d/iaxmodem e se configura para el inicio automático: 414
chkconfig --add iaxmodem chkconfig iaxmodem on Se inicia el programa: /etc/init.d/iaxmodem start Volviendo a la consola de Asterisk, las dos extensiones deben estar registradas: CLI> iax2 show peers Name/Username Host Mask Port Status Description marko 79.44.192.186 (D) 255.255.255.255 4569 (E) OK (241 ms) marko2/marko2 79.44.192.186 (D) 255.255.255.255 4569 (E) OK (244 ms) iaxmodem1/iaxmo 127.0.0.1 (D) 255.255.255.255 4570 (E) OK (3 ms) iaxmodem2/iaxmo 127.0.0.1 (D) 255.255.255.255 4571 (E) OK (3 ms) 4 iax2 peers [4 online, 0 offline, 0 unmonitored] Ahora que IAXmodem ha sido instalado y configurado, se puede continuar con la instalación y configuración de Hylafax. 17.2 Hylafax Hylafax es un servidor FAX diseñado para sistemas Linux que se basa en un sistema cliente-servidor. Un cliente (FAX) se conecta al servidor (Hylafax) y a través de él envía el FAX. Hay que empezar instalando algunas (dependencias) requeridas por Hylafax: yum install ghostscript ghostscript-devel sharutils ghostscript-fonts -y En la pagina de Hylafax están presentes los paquetes para las distintas distribuciones de Linux: Se descargan los paquetes para CentOS (cliente y servidor): cd /usr/src wget ftp://ftp.hylafax.org/binary/linux/redhat/6.0.6/hylafax-client-6.0.6-1rhel6.x86_64.rpm wget ftp://ftp.hylafax.org/binary/linux/redhat/6.0.6/hylafax-server-6.0.6-1rhel6.x86_64.rpm Se instalan: rpm -ivh hylafax*.rpm El paso a seguir es la configuración de de Hylafax. Esto se hace a través de la utilidad faxsetup: 415
faxsetup Should an entry be added for the FaxMaster to /etc/aliases [yes]? no Update /var/spool/hylafax/status/any.info. HylaFAX configuration parameters are: [1] Init script starts faxq: [2] Init script starts hfaxd [3] Start paging protocol: Are these ok [yes]? yes
yes yes no
Se contesta yes. Luego inicia la configuración de Hylafax. Hay que indicar los parámetros como aparecen personalizando el numero de teléfono y el prefijo del país. En negrita los datos que se van insertando desde el teclado. Modem support functions written to /var/spool/hylafax/etc/setup.modem. Configuration parameters written to /var/spool/hylafax/etc/setup.cache. No scheduler config file exists, creating one from scratch. Country code [1]? 57 Area code []? 5 Long distance dialing prefix [1]? 0 International dialing prefix [011]? 00 Dial string rules file (relative to /var/spool/hylafax) ["etc/dialrules"]? Tracing during normal server operation [1]? Default tracing during send and receive sessions [0xffffffff]? Continuation cover page (relative to /var/spool/hylafax) []? Timeout when converting PostScript documents (secs) [180]? Maximum number of concurrent jobs to a destination [1]? Define a group of modems []? Time of day restrictions for outbound jobs ["Any"]? Timeout before purging a stale UUCP lock file (secs) [30]? Max number of pages to permit in an outbound job [0xffffffff]? Syslog facility name for ServerTracing messages [daemon]? The non-default scheduler parameters are: CountryCode: 57 AreaCode: 5 LongDistancePrefix: 0 InternationalPrefix: 00
416
Are these ok [yes]? yes Creating new configuration file /var/spool/hylafax/etc/config... Restarting HylaFAX server processes. Should I restart the HylaFAX server processes [yes]? yes /etc/rc.d/init.d/hylafax start Starting HylaFAX queue manager (faxq): [ OK ] Starting HylaFAX server (hfaxd): [ OK ] Restarting HylaFAX modem manager (faxgetty): [ OK ] You do not appear to have any modems configured for use. Modems are configured for use with HylaFAX with the faxaddmodem(8C) command. Desde la linea que sigue se configura el primer FAX (ttyIAX1) Do you want to run faxaddmodem to configure a modem [yes]? yes Serial port that modem is connected to []? ttyIAX1 Ok, time to setup a configuration file for the modem. The manual page config(5F) may be useful during this process. Also be aware that at any time you can safely interrupt this procedure. Reading scheduler config file /var/spool/hylafax/etc/config. No existing configuration, let's do this from scratch. Country code [57]? Area code [5]? Phone number of fax modem [+1.999.555.1212]? +5753850962 Local identification string (for TSI/CIG) ["NothingSetup"]? LibroAsterisk Long distance dialing prefix [1]? 0 International dialing prefix [011]? 00 Dial string rules file (relative to /var/spool/hylafax) [etc/dialrules]? Tracing during normal server operation [1]? Tracing during send and receive sessions [11]? Protection mode for received facsimile [0600]? Protection mode for session logs [0600]? Protection mode for ttyIAX1 [0600]? Rings to wait before answering [1]? 2 Modem speaker volume [off]? Command line arguments to getty program ["-h %l dx_%s"]? Pathname of TSI access control list file (relative to /var/spool/hylafax) [""]? Pathname of Caller-ID access control list file (relative to /var/spool/hylafax) [""]? Tag line font file (relative to /var/spool/hylafax) [etc/lutRS18.pcf]? 417
Tag line format string ["From %%l|%c|Page %%P of %%T"]? Time before purging a stale UUCP lock file (secs) [30]? Hold UUCP lockfile during inbound data calls [Yes]? Hold UUCP lockfile during inbound voice calls [Yes]? Percent good lines to accept during copy quality checking [95]? Max consecutive bad lines to accept during copy quality checking [5]? Max number of pages to accept in a received facsimile [25]? Syslog facility name for ServerTracing messages [daemon]? Set UID to 0 to manipulate CLOCAL [""]? Use available priority job scheduling mechanism [""]? The non-default server configuration parameters are: CountryCode: 57 AreaCode: 5 FAXNumber: +5753850962 LongDistancePrefix: 0 InternationalPrefix: 00 DialStringRules: etc/dialrules SessionTracing: 11 RingsBeforeAnswer: 2 SpeakerVolume: off GettyArgs: "-h %l dx_%s" LocalIdentifier: CursoAsterisk TagLineFont: etc/lutRS18.pcf TagLineFormat: "From %%l|%c|Page %%P of %%T" MaxRecvPages: 25 Are these ok [yes]? yes Now we are going to probe the tty port to figure out the type of modem that is attached. This takes a few seconds, so be patient. Note that if you do not have the modem cabled to the port, or the modem is turned off, this may hang (just go and cable up the modem or turn it on, or whatever). Probing for best speed to talk to modem: 38400 OK. About fax classes: The difference between fax classes has to do with how HylaFAX interacts with the modem and the fax protocol features that are used when sending or receiving faxes. One class isn't inherently better than another; however, one probably will suit a user's needs better than others. Class 1 relies on HylaFAX to perform the bulk of the fax protocol. 418
Class 2 relies on the modem to perform the bulk of the fax protocol. Class 2.0 is similar to Class 2 but may include more features. Class 1.0 is similar to Class 1 but may add V.34-fax capability. Class 2.1 is similar to Class 2.0 but adds V.34-fax capability. HylaFAX generally will have more features when using Class 1/1.0 than when using most modems' Class 2 or Class 2.0 implementations. Generally any problems encountered in Class 1/1.0 can be resolved by modifications to HylaFAX, but usually any problems encountered in Class 2/2.0/2.1 will require the modem manufacturer to resolve it. Use Class 1 unless you have a good reason not to. This modem looks to have support for Class 1.0 and 1. How should it be configured [1.0]? Hmm, this looks like a Class 1.0 modem. Product code (ATI0) is "spandsp". Other information (ATI3) is "www.soft-switch.org". DTE-DCE flow control scheme [default]? Modem manufacturer is "Unknown". Modem model is "Unknown". Using prototype configuration file class1.0... There is no prototype configuration file for your modem, so we will have to fill in the appropriate parameters by hand. You will need the manual for how to program your modem to do this task. In case you are uncertain of the meaning of a configuration parameter you should consult the config(5F) manual page for an explanation. Note that modem commands must be specified exactly as they are to be sent to the modem. Note also that quote marks (") will not be displayed and will automatically be deleted. You can use this facility to supply null parameters as "". Finally, beware that the set of parameters is long. If you prefer to use your favorite editor instead of this script you should fill things in here as best you can and then edit the configuration file "/var/spool/hylafax/etc/config.ttyIAX1" after completing this procedure. Command to enter Class 1 [AT+FCLASS=1.0]? Command to stop and wait prior to sending PPM [AT+FTS=7]? 419
Command to stop and wait prior to sending TCF [AT+FTS=7]? Command to stop and wait prior to sending EOP [AT+FTS=9]? Extra bytes in a received HDLC frame [4]? Maximum time to wait for OK after aborting a receive (ms) [200]? Maximum wait for initial identification frame (ms) [40000]? Command to ensure silence after receiving HDLC and before sending [AT+FRS=7]? The modem configuration parameters are: Class1Cmd: AT+FCLASS=1.0 Class1PPMWaitCmd: AT+FTS=7 Class1TCFWaitCmd: AT+FTS=7 Class1EOPWaitCmd: AT+FTS=9 Class1FrameOverhead: 4 Class1RecvAbortOK: 200 Class1RecvIdentTimer: 40000 Class1SwitchingCmd: AT+FRS=7 Class1TCFMaxNonZero: 10 Class1TCFMinRun: 1000 Are these ok [yes]? yes Creating new configuration file /var/spool/hylafax/etc/config... ...saving current file as /var/spool/hylafax/etc/config.sav. Don't forget to run faxmodem(8C) (if you have a send-only environment) or configure init to run faxgetty on ttyIAX1. Terminada la configuración del primer módem, el servidor Hyalafax preguntará si se quiere instalar otro. Se contesta con yes y se configura el segundo módem (ttyIAX2) Do you want to run faxaddmodem to configure another modem [yes]? yes Serial port that modem is connected to []? ttyIAX2 Ok, time to setup a configuration file for the modem. The manual page config(5F) may be useful during this process. Also be aware that at any time you can safely interrupt this procedure. Reading scheduler config file /var/spool/hylafax/etc/config. No existing configuration, let's do this from scratch. Country code [57]? Area code [5]? Phone number of fax modem [+1.999.555.1212]? +5753850962 Local identification string (for TSI/CIG) ["NothingSetup"]? LibroAsterisk 420
Long distance dialing prefix [1]? 0 International dialing prefix [011]? 00 Dial string rules file (relative to /var/spool/hylafax) [etc/dialrules]? Tracing during normal server operation [1]? Tracing during send and receive sessions [11]? Protection mode for received facsimile [0600]? Protection mode for session logs [0600]? Protection mode for ttyIAX2 [0600]? Rings to wait before answering [1]? 2 Modem speaker volume [off]? Command line arguments to getty program ["-h %l dx_%s"]? Pathname of TSI access control list file (relative to /var/spool/hylafax) [""]? Pathname of Caller-ID access control list file (relative to /var/spool/hylafax) [""]? Tag line font file (relative to /var/spool/hylafax) [etc/lutRS18.pcf]? Tag line format string ["From %%l|%c|Page %%P of %%T"]? Time before purging a stale UUCP lock file (secs) [30]? Hold UUCP lockfile during inbound data calls [Yes]? Hold UUCP lockfile during inbound voice calls [Yes]? Percent good lines to accept during copy quality checking [95]? Max consecutive bad lines to accept during copy quality checking [5]? Max number of pages to accept in a received facsimile [25]? Syslog facility name for ServerTracing messages [daemon]? Set UID to 0 to manipulate CLOCAL [""]? Use available priority job scheduling mechanism [""]? The non-default server configuration parameters are: CountryCode: 57 AreaCode: 5 FAXNumber: +5753850962 LongDistancePrefix: 0 InternationalPrefix: 00 DialStringRules: etc/dialrules SessionTracing: 11 RingsBeforeAnswer: 2 SpeakerVolume: off GettyArgs: "-h %l dx_%s" LocalIdentifier: CursoAsterisk TagLineFont: etc/lutRS18.pcf TagLineFormat: "From %%l|%c|Page %%P of %%T" MaxRecvPages: 25 Are these ok [yes]? yes Now we are going to probe the tty port to figure out the type of modem that is attached. This takes a few seconds, so be patient. 421
Note that if you do not have the modem cabled to the port, or the modem is turned off, this may hang (just go and cable up the modem or turn it on, or whatever). Probing for best speed to talk to modem: 38400 OK. About fax classes: The difference between fax classes has to do with how HylaFAX interacts with the modem and the fax protocol features that are used when sending or receiving faxes. One class isn't inherently better than another; however, one probably will suit a user's needs better than others. Class 1 relies on HylaFAX to perform the bulk of the fax protocol. Class 2 relies on the modem to perform the bulk of the fax protocol. Class 2.0 is similar to Class 2 but may include more features. Class 1.0 is similar to Class 1 but may add V.34-fax capability. Class 2.1 is similar to Class 2.0 but adds V.34-fax capability. HylaFAX generally will have more features when using Class 1/1.0 than when using most modems' Class 2 or Class 2.0 implementations. Generally any problems encountered in Class 1/1.0 can be resolved by modifications to HylaFAX, but usually any problems encountered in Class 2/2.0/2.1 will require the modem manufacturer to resolve it. Use Class 1 unless you have a good reason not to. This modem looks to have support for Class 1.0 and 1. How should it be configured [1.0]? Hmm, this looks like a Class 1.0 modem. Product code (ATI0) is "spandsp". Other information (ATI3) is "www.soft-switch.org". DTE-DCE flow control scheme [default]? Modem manufacturer is "Unknown". Modem model is "Unknown". Using prototype configuration file class1.0... There is no prototype configuration file for your modem, so we will have to fill in the appropriate parameters by hand. You will need the manual for how to program your modem to do this task. In case you are uncertain of the meaning of a configuration parameter you should consult the config(5F) manual page for an explanation. Note that modem commands must be specified exactly as they are to be 422
sent to the modem. Note also that quote marks (") will not be displayed and will automatically be deleted. You can use this facility to supply null parameters as "". Finally, beware that the set of parameters is long. If you prefer to use your favorite editor instead of this script you should fill things in here as best you can and then edit the configuration file "/var/spool/hylafax/etc/config.ttyIAX2" after completing this procedure. Command to enter Class 1 [AT+FCLASS=1.0]? Command to stop and wait prior to sending PPM [AT+FTS=7]? Command to stop and wait prior to sending TCF [AT+FTS=7]? Command to stop and wait prior to sending EOP [AT+FTS=9]? Extra bytes in a received HDLC frame [4]? Maximum time to wait for OK after aborting a receive (ms) [200]? Maximum wait for initial identification frame (ms) [40000]? Command to ensure silence after receiving HDLC and before sending [AT+FRS=7]? The modem configuration parameters are: Class1Cmd: AT+FCLASS=1.0 Class1PPMWaitCmd: AT+FTS=7 Class1TCFWaitCmd: AT+FTS=7 Class1EOPWaitCmd: AT+FTS=9 Class1FrameOverhead: 4 Class1RecvAbortOK: 200 Class1RecvIdentTimer: 40000 Class1SwitchingCmd: AT+FRS=7 Class1TCFMaxNonZero: 10 Class1TCFMinRun: 1000 Are these ok [yes]? yes Creating new configuration file /var/spool/hylafax/etc/config.ttyIAX2... Creating fifo /var/spool/hylafax/FIFO.ttyIAX2 for faxgetty... done. Done setting up the modem configuration. Checking /var/spool/hylafax/etc/config for consistency... ...everything looks ok; leaving existing file unchanged. Don't forget to run faxmodem(8C) (if you have a send-only environment) or configure init to run faxgetty on ttyIAX2.
423
Hylafax preguntará si se quiere configurar otro módem: Do you want to run faxaddmodem to configure another modem [yes]? no Se contesta no. El servidor de FAX avisará que para que las llamadas sean contestadas en automático hay que configurar faxgetty (la utilidad que se encarga de esta tarea) y si se quiere iniciar faxmodem para los dos FAX configurados (se contesta yes): You do not appear to be using faxgetty to notify the HylaFAX scheduler about new modems and/or their status. This means that you must use the faxmodem program to inform the new faxq process about the modems you want to have scheduled by HylaFAX. Beware that if you have modems that require non-default capabilities specified to faxmodem then you should read faxmodem(8C) manual page and do this work yourself (since this script is not intelligent enough to automatically figure out the modem capabilities and supply the appropriate arguments). Should I run faxmodem for each configured modem [yes]? yes /usr/sbin/faxmodem ttyIAX1 /usr/sbin/faxmodem ttyIAX2 Done verifying system setup. La configuración de los dos módem ha terminado. Ahora se configura faxgetty en CentOS de forma que la utilidad se inicie al arrancar el servidor Linux: nano /etc/init/faxgetty1.conf se pegan las siguientes lineas: start on runlevel [2345] stop on runlevel [016] respawn exec /usr/sbin/faxgetty ttyIAX1 Se sigue en mismo procedimiento para el segundo FAX: nano /etc/init/faxgetty2.conf start on runlevel [2345] stop on runlevel [016] respawn exec /usr/sbin/faxgetty ttyIAX2 Se inician los dos:
424
initctl start faxgetty1 faxgetty1 start/running, process 11865 initctl start faxgetty2 faxgetty2 start/running, process 11867 Se averigua que faxgetty este corriendo para los dos FAX: ps aux | grep ttyIAX
Se reinicia Hylafax /etc/init.d/hylafax restart Shutting down HylaFAX queue manager (faxq): [ OK ] Shutting down HylaFAX server (hfaxd): [ OK ] Starting HylaFAX queue manager (faxq): [ OK ] Starting HylaFAX server (hfaxd): [ OK ] Restarting HylaFAX modem manager (faxgetty): [ OK ] Shutting down HylaFAX queue manager (faxq): [ OK ] Todos los archivos de configuración que se crearán a lo largo del proceso de configuración de Hylafax se guardaran en las carpeta /var/spool/hylafax/etc y /etc/hylafax Para controlar el estado de Hylafax y de los FAX configurados se utiliza este comando: faxstat El resultado es: HylaFAX scheduler on li370-135.members.linode.com: Running Modem ttyIAX2 (+5753850962): Running and idle Modem ttyIAX1 (+5753850962): Running and idle Para mejorar la recepción y envío de los FAX, se añade un pequeño retraso en la configuración de los módem de forma que si se pierde la conexión, se intentará reajustarla: nano /var/spool/hylafax/etc/config.ttyIAX1 al final del archivo se añade esta linea: Class1SwitchingCmd: "" Lo mismo se hace con el módem ttyIAX2: 425
nano /var/spool/hylafax/etc/config.ttyIAX2 al final del archivo se añade esta linea: Class1SwitchingCmd: "" Para recibir una notificación si el fax ha sido enviado hay que modificar el archivo de configuración de Hylafax (la recibirá el usuario root): nano /etc/hylafax/hyla.conf si cambia esta linea: #Notify: Done para que quede Notify: Done Para recibir los FAX entrantes a una dirección de correo electrónico externa al servidor: nano /var/spool/hylafax/etc/FaxDispatch se cambia esta linea: SENDTO=FaxMaster para que quede (personalizar la dirección de correo electrónico): [email protected] Se reinicia Hylafax: /etc/init.d/hylafax restart Por ultimo se indica que todos los mensajes de correo electrónico para el usuario Faxmaster se envíen al usuario root: nano /etc/aliases después de esta linea: support: postmaster se pone: FaxMaster:
root
426
Se guardan los cambios y se recarga la configuración: newaliases Prueba envío. Para el envío de los FAX se crea en extension.conf un contesto [fax] (el mismo que se ha configurado para las dos extensiones iaxmodem en iax.conf) antes del contexto internas, con las siguientes líneas: nano /etc/asterisk/extensions.conf [fax] exten => _X.,1,Dial(SIP/voztovoice/${EXTEN}) same => n,Hangup exten => 1234,1,Dial(IAX2/iaxmodem2) same => n,hangup El primer bloque es para enviar FAX a números externos, el segundo es para probar el fax en local. En la parte general del archivo sip.conf, se ha configurado el parámetro faxdetect en yes; esto significa que si el sistema detecta que la llamada está llegando desde un FAX, automáticamente “saltará”, si existe, a la extensión fax. Para probarlo, en el mismo contexto fax se añade otro bloque: exten => 1235,1,Answer same => n,Wait(6) same => n,Dial(SIP/1000,45) exten => fax,1,Dial(IAX2/iaxmodem2) same => n,hangup El flujo del dialplan es: se contesta la llamada entrante, se esperan 4 segundos para permitir a Asterisk reconocer si la llamada procede de un fax. Si procede de un fax se va a la extensión fax, prioridad 1 donde se contestará con el modem FAX iaxmodem2, sino se llamará la extensión 1000. Se guardan los cambios y actualiza el dialplan: /etc/init.d/asterisk reload Para enviar un fax con el cliente Hylafax la sintaxis es: sendfax -h modem -n -d Se crea el archivo de texto que se enviará: nano /tmp/pruebafax.txt y se pone: 427
Libro Asterisk 11.X Nombre Apellido Se guardan los cambios. En este caso con el módem ttyIAX1 se enviará el FAX y con el módem ttyIAX2 se recibe. Hay que tener en cuenta que cuanto se trabaja con pura lineas VoIP el envío y la recepción de los FAX no siempre funciona bien. Por eso se realiza esta prueba. sendfax -h ttyIAX1@localhost -n -d numerolocal /tmp/pruebafax.txt Utilizando el numero local sería: sendfax -h ttyIAX1@localhost -n -d 1234 /tmp/pruebafax.txt En lugar de “numerolocal” se pone el numero definido en el contexto [fax] para la prueba en local. Si sale este error: Usage: /usr/sbin/textfmt [-1] [-2] [-B] [-c] [-D] [-f fontname] [-F fontdir(s)] [-m N] [-o #] [-p #] [-r] [-U] [-Ml=#,r=#,t=#,b=#] [-V #] files... >out.ps Default options: -f Courier -1 -p 11bp -o 0 Se ha producido un error al convertir el documento; el comando fue "/usr/sbin/textfmt -B -f CourierBold -Ml=0.4in -p 11 -s default >'/tmp//sndfaxlBau98' <'/tmp/pruebafax.txt'" es porque hay un problema con los fonts de Ghostscrpt. Para solucionarlo se abre el siguiente archivo: nano +92 /usr/share/ghostscript/8.70/Resource/Init/Fontmap.GS y se modifica la linea 92: /Courier-Bold
/NimbusMonL-Bold
;
Para que quede: /Courier-Bold
(n022004l.pfa)
;
Se guardan los cambios y se vuelve a enviar el fax: sendfax -h ttyIAX1@localhost -n -d 1234 /tmp/pruebafax.txt request id is 1 (group id 1) for host localhost (1 file) Se puede controlar el estado del envío con el siguiente comando: faxstat -s HylaFAX scheduler on li374-112.members.linode.com: Running Modem ttyIAX2 (+5753850962): Running and idle 428
Modem ttyIAX1 (+5753850962): Initializing server JID Pri S Owner Number Pages Dials TTS Status 1 127 R root 1234 0:1 0:12 Se entra en la consola de Asterisk y se mira que aparece: asterisk -rvvvvvvvvvvvvv cuando termine la llamada se sale de la consola: CLI> quit y se controla que ha pasado: faxstat -s HylaFAX scheduler on li374-112.members.linode.com: Running Modem ttyIAX2 (+5753850962): Running and idle Modem ttyIAX1 (+5753850962): Running and idle Los registros del envío de FAX con Halyfax se encuentran en la carpeta /var/spool/hylafax/log y una vez enviado el fax, deberían estar presentes dos archvos: ls -l /var/spool/hylafax/log total 16 -rw------- 1 uucp uucp 5017 Mar 24 11:29 c000000001 -rw------- 1 uucp uucp 4022 Mar 24 11:29 c000000002 -rw------- 1 uucp uucp 1 Mar 24 11:29 seqf El primero es el log del modem ttyIAX1 y el segundo del modem ttyIAX2. Si se abren se podrá averiguar que el fax se ha enviado. ¿Cómo puedo comprobarlo? Abriendo el correo del usuario root (desde terminal o Webmin):
429
y comprobando que el fax enviado ha llegado al correo electrónico definido a lo largo de la configuración de Hylafax:
430
Abriendo el PDF:
Si se quiere utilizar un cliente con interfaz gráfica para el envío de fax, una buena solución es YajHFC (Yet another Java HylaFAX Client) que siendo escrito completamente en JAVA funciona con cualquier sistema operativo. Otra solución más elaborada es AvantFAX. En este libro se mostrará como instalar y configurar WinPrint Hylafax para Windows7. Para que el cliente pueda conectarse al servidor hay que abrir el puerto 4559 TCP (donde el servidor hylafax espera recibir las conexiones) y un rango de puertos TCP para los datos. Se abre la configuración de IPtables: nano /etc/sysconfig/iptables y después de esta linea: -A INPUT -p udp -m udp --dport 10000:20000 -j ACCEPT se añade: # Hylafax 431
-A INPUT -p tcp -m state --state NEW -m tcp --dport 4559 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 40000:60000 -j ACCEPT Se guardan los cambios y se reinicia IPtables: service iptables restart Además para que el cliente pueda conectarse al servidor, hay que crear las credenciales de acceso (usuario y contraseña). Esta operación se realiza con una utilidad presente en la instalación de Hylafax: faxadduser -p sesamo campus Se crea el usuario campus cuya contraseña será sesamo. Estos datos se guardan automáticamente en el archivo: nano /var/spool/hylafax/etc/hosts.hfaxd ^campus@::aczqwbGw8jPm2 La contraseña será cifrada. Terminada esta primera parte de la configuración, en el computador con Windows7 instalado, se descarga el programa y se instala: http://sourceforge.net/projects/wphfforwin7/files/WinPrintHylafax-for-Windows7/setup/wphfxwin7_setup_1.4.3.0.exe
A lo largo de la instalación aparecerá esta ventana:
432
Hylafax server: IP del servidor Linode o del servidor donde está instalado Hylafax Username: nombre del usuario que se ha creado con la utilidad faxadduser Password: contraseña del usuario que se ha creado con la utilidad faxadduser Email: correo electrónico donde recibir la notificaciones del éxito o fracaso del envío del fax Modem: se indica el modem IAX que se quiere utilizar (ttyIAX1) Address Book Directory: una carpeta donde guardar el directorio de los clientes (números de FAX) Page Size: el formato de la pagina Resolution: la calidad de los FAX enviados. Una vez terminada la configuración se presiona el botón “Aceptar”. Se sigue con los pasos indicados por el programa para terminar la instalación y luego se pasa a la configuración de la impresora virtual. En Windows7 se va a Inicio → Dispositivos e impresoras y en la nueva pagina se selecciona:
En la nueva ventana se selecciona “Agregar una impresora local” y en la siguiente pagina:
433
Se selecciona “Usar un puerto existente” y en el menú desplegable se selecciona “HFAX1: (WinPrint Hylafax Port). Se continua presionando el botón “Siguiente”:
Se selecciona una impresora PostScript (en este caso una Xerox Phaser 6120 PS) y se presiona el botón “Siguiente”:
En la siguiente pagina se le asigna un nombre a la impresora y se presiona el botón “Siguiente”:
Se selecciona “No compartir esta impresora” y se presiona el botón “Siguiente”:
434
Se termina la configuración presionando el Botón “Finalizar”. A partir de este momento se puede utilizar la impresora para enviar FAX a cualquier numero de teléfono utilizando el servidor Hylafax. Para efectuar una prueba, se crea un nuevo documento con el programa preferido y luego se manda a imprimir. En la lista de impresoras disponibles, se escoge “Hylafax ttyIAX1”
En Número de FAX se pone 1234 (la extensión configurada en Asterisk para recibir los fax con el modem ttyIAX2) y se presiona el botón “Enviar FAX”. Al correo electrónico indicado a lo largo de la instalación, se recibirá un correo electrónico indicando si el fax se ha enviado o no con éxito:
435
Al correo electrónico configurado en el archivo /var/spool/hylafax/etc/FaxDispatch el mensaje con anexo el FAX recibido:
En el caso que se quiera instalar el cliente en distintos computadores de una empresa habrá que crear más fax IAXmodem en el servidor Linux y realizar la configuración con la utilidad faxaddmodem de Hylafax. Luego si se quiere diferenciar la dirección de correo electrónico según el módem IAXmodem donde se ha recibido el fax, hay que modificar la configuración del archivo FaxDispatch: nano /var/spool/hylafax/etc/FaxDispatch Primero se comenta esta linea: [email protected] 436
para que quede: #[email protected] Luego al final del archivo se pone: case "$DEVICE" in ttyIAX1) ttyIAX2) esac
[email protected] [email protected]
Se guarda la configuración y se reinicia Hylafax: /etc/init.d/hylafax restart Para que esta configuración funcione, cada FAX debería tener su numero geográfico asociado para tener la certeza que el FAX se reciba en el módem correcto. Otra solución podría ser configurar un IVR para la recepción de FAX que diga “Para enviar un FAX a administración, presione 1, para enviarlo a ventas, presione 2”. Mayores informaciones y guías para WinPrint Hylafax para Windows7, se encuentran en esta pagina: http://wphfforwin7.sourceforge.net/ 17.3 Protocolo T38 Se pone una hoja en la “maquina”, se marca el numero de teléfono de destino y se espera que salga un OK por algún lado. Esta sencilla operación es la que se realiza cuando se quiere enviar un FAX. Todo lo que pasa en el “mientras” es totalmente transparente. Las dos maquinas FAX negocian todos los pasajes y para hacerlo utilizan un protocolo. Ese protocolo ha sido definido por la “International Telecommunication Union” y tomó como sigla T.30 En 1998 la misma organización define un nuevo protocolo que permite recibir y enviar fax usando una red a paquetes (Internet). La sigla de este protocolo es T.38. ¿Cómo funciona el protocolo T.38? Quizás la imagen que sigue ayuda para entender:
437
El FAX está conectado a la línea telefónica y también a un Gateway con soporte T.38. Ese Gateway se encarga de transformar el FAX en el formato requerido para ser enviado a través de la red Internet. En el lado opuesto otro Gateway T.38 se encarga de “decodificar” los paquetes que lleguen para luego pasar el resultado al fax de destinación. Un Gateway T.38 clásico funciona como se muestra en la imagen que sigue:
Los datos del FAX T.30 se analizan y se transforman en paquetes (IFP). Los paquetes se pueden enviar usando tres protocolos de transporte: UDPTL, TCP o RTP. Será tarea de los Gateway T.38 negociar el protocolo de trasporte. En el caso de Asterisk el único protocolo de trasporte admitido es UDPTL que funciona de la siguiente forma: 438
Cada paquete UDPTL contiene encapsulado el paquete IFP (que contiene los datos del fax que se está enviando y un sistema de corrección de errores – FEC [forward error correction]). Para repetir los paquetes perdidos y controlar que lleguen en el justo orden hay disponibles dos sistemas: • •
Con el primero se repite el ultimo paquete enviado como FEC para el paquete que se está enviando Con el segundo se crea un paquete de paridad para un numero determinado de paquetes IFP y se incluye esta información en el paquete UDPTL corriente.
El paquete UDPTL está encapsulado en un paquete UDP (protocolo de trasporte) que a su vez está encapsulado en un paquete IP (protocolo que permite al paquete llegar a su destino). Asterisk 11.X soporta el protocolo T.38 como pasarela y como Gateway, esto quiere decir que si a un lado de la trasmisión hay otro Gateway T.38, Asterisk podrá enviar/recibir el fax utilizando este protocolo. En Asterisk el envío y recepción de faxes es posible a través de la librería SpanDSP y el modulo res_fax. Desde la consola: asterisk -rvvvvvvvvvvvvvvvv Se controla la sintaxis de las dos aplicaciones que se activan con el modulo res_fax: CLI> core show application ReceiveFax -= Info about application 'ReceiveFAX' =[Synopsis] Receive a FAX and save as a TIFF/F file. [Description] 439
This application is provided by res_fax, which is a FAX technology agnostic module that utilizes FAX technology resource modules to complete a FAX transmission. Session arguments can be set by the FAXOPT function and to check results of the ReceiveFax() application. [Syntax] ReceiveFAX(filename[,options]) [Arguments] options d: Enable FAX debugging. f: Allow audio fallback FAX transfer on T.38 capable channels. F: Force usage of audio mode on T.38 capable channels. s: Send progress Manager events (overrides statusevents setting in res_fax.conf). CLI> core show application SendFax -= Info about application 'SendFAX' =[Synopsis] Sends a specified TIFF/F file as a FAX. [Description] This application is provided by res_fax, which is a FAX technology agnostic module that utilizes FAX technology resource modules to complete a FAX transmission. Session arguments can be set by the FAXOPT function and to check results of the SendFax() application. [Syntax] SendFAX([filename2[&...]][,options]) [Arguments] filename2 TIFF file to send as a FAX. options d: Enable FAX debugging. f: Allow audio fallback FAX transfer on T.38 capable channels. F: Force usage of audio mode on T.38 capable channels. s: Send progress Manager events (overrides statusevents setting in 440
res_fax.conf). z: Initiate a T.38 reinvite on the channel if the remote end does not. y la función (en negrita la opción que permite activar el Gateway T.38): CLI> core show function FAXOPT [Synopsis] Gets/sets various pieces of information about a fax session. [Description] FAXOPT can be used to override the settings for a FAX session listed in " res_fax.conf", it can also be used to retreive information about a FAX session that has finished eg. pages/status. [Syntax] FAXOPT(item) [Arguments] item ecm - R/W Error Correction Mode (ECM) enable with 'yes', disable with 'no'. error - R/O FAX transmission error code upon failure. filename - R/O Filename of the first file of the FAX transmission. filenames - R/O Filenames of all of the files in the FAX transmission (comma separated). headerinfo - R/W FAX header information. localstationid - R/W Local Station Identification. minrate - R/W Minimum transfer rate set before transmission. maxrate - R/W Maximum transfer rate set before transmission. modem - R/W Modem type (v17/v27/v29). gateway - R/W T38 fax gateway, with optional fax activity timeout in seconds (yes[,timeout]/no) faxdetect - R/W Enable FAX detect with optional timeout in seconds (yes,t38,cng[,timeout]/no) pages - R/O Number of pages transferred. rate - R/O Negotiated transmission rate. remotestationid - R/O Remote Station Identification after transm ission. resolution - R/O Negotiated image resolution after transmission. sessionid - R/O Session ID of the FAX transmission. status - R/O Result Status of the FAX transmission. statusstr - R/O Verbose Result Status of the FAX transmission. Algunos ATA comercializados soportan el protocolo T.38. En Voip-info aparece una lista (aunque no 441
muy actualizada). Para el soporte T.38 en Asterisk hay que modificar este archivo: mv /etc/asterisk/udptl.conf /etc/asterisk/udptl.conf.old nano /etc/asterisk/udptl.conf Se pone: [general] udptlstart=4000 udptlend=4099 udptlchecksums=yes udptlfecentries = 3 udptlfecspan = 3 use_even_ports = no Se guardan los cambios y se vuelve a iniciar Asterisk: /etc/init.d/asterisk restart 17.3.1 Aplicación ReceiveFax Para el test que se va a realizar hay que modificar el dialplan: nano /etc/asterisk/extensions.conf en el contexto [fax] se modifica este bloque: exten => 1234,1,Dial(IAX2/iaxmodem2) same => n,hangup Para que quede: exten => 1234,1,Answer same => n,Receivefax(/tmp/${UNIQUEID}.tif,df) same => n,Hangup exten => h,1,Noop(FAXSTATUS ${FAXOPT(status)}, FAXERROR ${FAXOPT(error)}) same => n,Hangup Se guardan los cambios. Como se ha activado la opción de debug (d), para ver los datos en la consola de Asterisk hay que modificar el archivo logger.conf que es donde se configuran los distintos registros de Asterisk. Se abordará la configuración del archivo de forma más detallada en el capitulo 20. nano /etc/asterisk/logger.conf 442
se modifica esta linea: console => notice,warning,error para que quede: console => notice,warning,error,fax Se guardan los cambios y se actualiza la configuración de Asterisk: service asterisk reload Se envía el mismo archivo txt utilizado anteriormente: sendfax -h ttyIAX1@localhost -n -d 1234 /tmp/pruebafax.txt entrando en la consola de Asterisk se miran los resultados del envío: asterisk -rvvvvvvvvvvvvvvvvv Encontraremos todo el debug de la recepción del fax con el protocolo T30. Las ultimas lineas: [Mar 23 07:18:03] FAX[11707]: res_fax.c:655 ast_fax_log: FLOW T.30 Send complete in phase T30_PHASE_E, state 2 [Mar 23 07:18:03] FAX[11707]: res_fax.c:655 ast_fax_log: FLOW T.30 Changing from state 2 to 32 [Mar 23 07:18:03] FAX[11707]: res_fax.c:655 ast_fax_log: FLOW T.30 Changing from phase T30_PHASE_E to T30_PHASE_CALL_FINISHED [Mar 23 07:18:03] FAX[11707]: res_fax.c:655 ast_fax_log: FLOW FAX Set rx type 9 [Mar 23 07:18:03] FAX[11707]: res_fax.c:655 ast_fax_log: FLOW FAX FAX exchange complete [Mar 23 07:18:03] FAX[11707]: res_fax.c:655 ast_fax_log: FLOW FAX Set tx type 9 [Mar 23 07:18:03] FAX[11707]: res_fax.c:655 ast_fax_log: FLOW FAX FAX exchange complete -- Executing [1234@fax:3] Hangup("IAX2/iaxmodem1-3347", "") in new stack == Spawn extension (fax, 1234, 3) exited non-zero on 'IAX2/iaxmodem1-3347' -- Executing [h@fax:1] NoOp("IAX2/iaxmodem1-3347", "FAXSTATUS SUCCESS, FAXERROR ") in new stack -- Executing [h@fax:2] Hangup("IAX2/iaxmodem1-3347", "") in new stack El fax, como indica la parte en negrita, se ha recibido con éxito. Se entra en la carpeta /tmp y se mira si efectivamente está presente un archivo tiff: ls /tmp 1332505066.0.tif
443
17.3.2 Applicación SendFax Como se ha visto en el párrafo 17.3, la aplicación para enviar FAX en Asterisk es SendFax. La sintaxis es muy sencilla: SendFAX([filename2[&...]][,options]) El problema es que con esta aplicación no se puede llamar directamente un FAX en cuanto no hay posibilidad de indicar el numero a marcar. Para solucionar este problema hay que hacer uso de un callfile. Un callfile es un archivo de texto donde se definen unas cuantas acciones que Asterisk ejecuta; una vez preparado se mueve (no se copia) en la carpeta /var/spool/asterisk/outgoing. Asterisk controla periódicamente esta carpeta a través del modulo pbx_spool.so y si hay un archivo de este tipo lo procesa. En el escenario que se va a presentar se llamará el numero de destino usando el chan_local. Una vez que el destinatario conteste se enviará el archivo tiff (la aplicación SendFax solo acepta archivos tiff). El callfile que se va a utilizar: Channel: Local/1234@fax ;el canal que se va a usar para efectuar la llamada y el numero a llamar. El canal Local es un pseudo canal que permite llamar una extensión y un determinado contexto y, cuando la extensión conteste, pasar el procesamiento del dialplan a esa extensión. En este caso se llamará la extensión 1234, contexto fax que es donde se ha configurado la aplicación para recibir los FAX. Callerid: "FAX" ; el identificativo del llamante WaitTime: 30 ;Se espera un respuesta por 30 segundos Maxretries:3 :se intentará llamar el numero tres veces RetryTime: 300 ; entre un intento y otro se esperarán 300 segundos Account: 1000 ; en el registro de las llamadas (CDR) se contabilizará la llamada a la extensión 1000 Application: SendFax ; una vez que el destinatario conteste se ejecuta la aplicación sendfax Data: /tmp/1329843102.10.tif ;el nombre del archivo que se enviará (cambiar el nombre con el que hay en la carpeta /tmp)
444
El resultado del archivo sin los comentarios será: cd /tmp nano enviofax Channel: Local/1234@fax Callerid: "FAX" WaitTime: 30 Maxretries:3 RetryTime: 300 Account: 1000 Application: SendFax Data: /tmp/1332505066.0.tif,dz Ahora se mueve el archivo en la carpeta /var/spool/asteisk/outgoning mv enviofax /var/spool/asterisk/outgoing Se entra en la consola de Asterisk: asterisk -rvvvvvvvvvvvvvvv Mar 23 07:26:51] FAX[11883]: res_fax.c:655 ast_fax_log: FLOW T.30 Send complete in phase T30_PHASE_E, state 2 [Mar 23 07:26:51] FAX[11883]: res_fax.c:655 ast_fax_log: FLOW T.30 Changing from state 2 to 32 [Mar 23 07:26:51] FAX[11883]: res_fax.c:655 ast_fax_log: FLOW T.30 Changing from phase T30_PHASE_E to T30_PHASE_CALL_FINISHED [Mar 23 07:26:51] FAX[11883]: res_fax.c:655 ast_fax_log: FLOW FAX Set rx type 9 [Mar 23 07:26:51] FAX[11883]: res_fax.c:655 ast_fax_log: FLOW FAX FAX exchange complete [Mar 23 07:26:51] FAX[11883]: res_fax.c:655 ast_fax_log: FLOW FAX Set tx type 9 [Mar 23 07:26:51] FAX[11883]: res_fax.c:655 ast_fax_log: FLOW FAX FAX exchange complete -- Executing [1234@fax:3] Hangup("Local/1234@fax-ee6a;2", "") in new stack == Spawn extension (fax, 1234, 3) exited non-zero on 'Local/1234@fax-ee6a;2' -- Executing [h@fax:1] NoOp("Local/1234@fax-ee6a;2", "FAXSTATUS SUCCESS, FAXERROR ") in new stack -- Executing [h@fax:2] Hangup("Local/1234@fax-ee6a;2", "") in new stack Esto significa que el fax se ha enviado con éxito utilizando el protocolo T30. Si se quiere probar el envío con el protocolo T38, hay que utilizar un proveedor VoIP que lo soporte, cosa que no hace VozToVoice como se puede ver con esta prueba: nano enviofax Channel: SIP/voztovoice/003907331870494 Callerid: "FAX" WaitTime: 30 445
Maxretries:3 RetryTime: 300 Account: 1000 Application: SendFax Data: /tmp/1332505066.0.tif,dz mv enviofax /var/spool/asterisk/outgoing El resultado en la consola de Asterisk (la parte en negrita): -- Attempting call on SIP/justvoip/003907331875163 for application SendFax(/tmp/1332505066.0.tif,d) (Retry 1) == Using SIP RTP CoS mark 5 > Channel SIP/justvoip-00000001 was answered. > Launching SendFax(/tmp/1332505066.0.tif,d) on SIP/justvoip-00000001 -- Channel 'SIP/justvoip-00000001' sending FAX: -- /tmp/1332505066.0.tif [Mar 23 07:33:58] WARNING[11945]: res_fax.c:1996 sendfax_t38_init: Audio FAX not allowed on channel 'SIP/voztovoice-00000001' and T.38 negotiation failed; aborting. [Mar 23 07:33:58] ERROR[11945]: res_fax.c:2225 sendfax_exec: error initializing channel 'SIP/justvoip-00000001' in T.38 mode [Mar 23 07:33:58] NOTICE[11945]: pbx_spool.c:366 attempt_thread: Call completed to SIP/justvoip/003907331875163 El discurso cambia si para recibir FAX se utilizan las normales lineas telefónicas. La calidad es mucho mejor. En la configuración del chan_dahdi.conf, hay unos parámetro relacionados con los FAX: ; For fax detection, uncomment one of the following lines. The default is *OFF* ; ;faxdetect=both ;faxdetect=incoming ;faxdetect=outgoing ;faxdetect=no ; When 'faxdetect' is used, one could use 'faxbuffers' to configure the DAHDI ; transmit buffer policy. The default is *OFF*. When this configuration ; option is used, the faxbuffer policy will be used for the life of the call ; after a fax tone is detected. The faxbuffer policy is reverted after the ; call is torn down. The sample below will result in 6 buffers and a full ; buffer policy. ; ;faxbuffers=>6,full De esta forma, para cada canal se puede definir si tiene que reconocer los FAX en las llamadas entrantes, salientes o desactivar la opción.
446
Capitulo XVIII Conexiones entre servidores Asterisk Este capitulo es dedicado a las conexiones entre servidores Asterisk. Un escenario típico de este tipo de configuración es cuando una empresa tiene sedes en distintos lugares y quiere que las extensiones de una sede puedan comunicarse con las extensiones de la otra. Además, si en una de las sedes están instalados Gateway/Tarjetas FXO, desde la otra sede se podrán sacar las llamadas utilizando esos Gateway/Tarjetas. Se presentarán cinco tipos de conexiones: • • • • •
Conexiones SIP con nombre de usuario y contraseña Conexiones IAX2 con autentificación sobre IP Conexiones distribuidas con el protocolo DUNDi Conexiones SIP con autentificación sobre IP vía OpenVPN Conexiones SIP con protocolo SIP TLS y audio cifrado (SRTP)
18.1 Conectar dos servidores Asterisk con el protocolo SIP Hay dos servidores Asterisk, A y B que se quieren conectar entre ellos utilizando el protocolo SIP para llamar desde A las extensiones de B y desde B las extensiones de A. Las extensiones del servidor A son de 4 cifras y empiezan por 1, en el servidor B son de 4 cifras y empiezan por el mismo numero 1. Servidor A nano /etc/asterisk/sip.conf En el bloque register se añade: register => serverA:pass1@IPserverB/serverB En lugar del IPserverB se pone la dirección IP del servidor B. Al final del archivo: [serverB] type=friend remotesecret=pass2 context=internas qualify=yes host=dynamic language=es disallow=all allow=gsm allow=ulaw allow=alaw
Con la línea de register, se conecta el servidor serverA al servidor serverB. Con las líneas que están después de la etiqueta [serverB] se define una extensión SIP que será aquella usada por el servidor B para conectarse al servidor A. Con contexto=internas, el servidor B tendrá acceso a todo el dialplan definido en ese contexto. Si se quiere que el servidor B tenga acceso solamente a un determinado contexto, se modifica la linea context poniendo un nombre de contexto y, si no existe, se crea ese contexto en el dialplan. IMPORTANTE: cuando se conectan dos servidores Asterisk entre ellos, en la configuración de la extensión no se utiliza el parámetro secret sino el parámetro remotesecret Se guardan los cambios y se pasa al servidor B. Servidor B nano /etc/asterisk/sip.conf En el bloque register se añade:: register => serverB:pass2@IPserverA/serverA al final del archivo: [serverA] type=friend remotesecret=pass1 context=internas host=dynamic language=es qualify=yes disallow=all allow=gsm allow=ulaw allow=alaw Ahora que los dos servidores están configurados hay que reiniciarlos. En los dos se escribe el comando: /etc/init.d/asterisk restart Desde la consola se averigua que haya conexión entre los dos servidores: asterisk -rvvvvvvvvvvvvvv para el servidor A: CLI> sip show registry 449
Host 173.255.203.178:5060 15:23:58 1 SIP registrations.
dnsmgr Username N serverA
CLI> sip show peers serverB/serverA 69.164.196.73
D N
Refresh State 105 Registered
5060
Reg.Time Fri, 18 Apr 2014
OK (1 ms)
para el servidor B: CLI> sip show registry Host 72.14.178.214:5060 1 SIP registrations.
dnsmgr Username N serverB
CLI> sip show peers serverA/serverB 96.126.121.135 D
5060
Refresh State 105 Registered
Reg.Time Fri, 18 Apr 2014 15:23:42
OK (2 ms)
Ahora lo único que hace falta es modificar el archivo extensions.conf de ambos servidores. Servidor A nano /etc/asterisk/extensions.conf En el contexto internas (para las llamadas a extensiones del servidor B) se añade: exten => _*1XXX,1,NoOp() same => n,Dial(SIP/serverB/${EXTEN:1},30) same => n,Hangup() Con estas líneas se configura Asterisk para que todas las llamadas con destino las extensiones cuyo numero empiece por 1 y sean de 4 cifras sean redirigidas hacia el servidor B. Para diferenciarlas de las llamadas entre las extensiones locales del servidor A se añade un * delante de las cuatro cifras a marcar. Ejemplo: para marcar a la extensión 1000 del servidor B, hay que marcar el siguiente numero: *1000 Servidor B nano /etc/asterisk/extensions.conf En el contexto internas (para las llamadas a extensiones del servidor A) se añade: exten => _*1XXX,1,NoOp() same => n,Dial(SIP/serverA/${EXTEN:1},30) same => n,Hangup() Con estas líneas se configura Asterisk para que todas las llamadas con destino las extensiones cuyo numero empiece por 1 y sean de 4 cifras sean redirigidas hacia el servidor B. Para diferenciarlas de las 450
llamadas entre las extensiones locales del servidor A se añade un * delante de las cuatro cifras a marcar. Se actualiza la configuración en los dos servidores: asterisk -rvvvvvvvvvvvvvvv CLI> dialplan reload Prueba Desde la extensión 1000 del servidor A se marca *1000 para llamar la extensión 1000 del servidor B y se mira lo que pasa en la consola de Asterisk del servidor B: Executing [*1000@externas:1] NoOp("SIP/1000-00000000", "") in new stack -- Executing [*1000@externas:2] Dial("SIP/1000-00000000", "SIP/serverB/1000,30") in new stack == Using SIP RTP CoS mark 5 -- Called SIP/serverB/1000 -- SIP/serverB-00000001 is ringing -- SIP/serverB-00000001 answered SIP/1000-00000000 La llamada funciona sin problemas. 18.2 Conectar dos servidores Asterisk con el protocolo IAX2 En este párrafo se ilustrará como conectar dos servidor Asterisk a través del protocolo IAX2 y la autentificación sobre IP. La ventaja de IAX2 está en su característica, llamada trunking, que utiliza el mismo trunk para el envío del audio de todas las llamadas. De esta forma cuando hay un numero considerable de llamadas que estén pasando por la troncal IAX2, hay un notable ahorro de banda. Esta conexión se implementará utilizando las direcciones IP publicas de los Servidores. Suponiendo que la direcciones IP publicas sean: Servidor A: IP: 96.126.125.112 nome trunk: servera Extensiones: 1000-1001-1002 Servidor B: IP: 66.228.49.216 nome trunk: serverb Extensiones: 1000-1001-1002 Servidor A Si abre el archivo iax.conf
451
nano /etc/asterisk/iax.conf al final del archivo se añaden las siguientes lineas: [serverb] type=friend host=66.228.49.216 trunk=yes context=internas qualify=yes Es importante destacar que la IP que se define es la del servidor B; además se utilizará en la configuración la funcionalidad del trunkink IAX2 El mismo procedimiento se ejecuta en el servidor B. Servidorr B nano /etc/asterisk/iax.conf se añaden las lineas: [servera] type=friend host=96.126.125.112 trunk=yes context=internas qualify=yes Se actualiza la configuración en ambos servidores: asterisk -rvvvvvvvvv CLI> iax2 reload Se averigua que haya conexión entre los servidores (servidor A): CLI> iax2 show peers serverb 66.228.49.216 (S) 255.255.255.255 4569 (T) (E) OK (1 ms) Servidor B: CLI> iax2 show peers servera 96.126.125.112 (S) 255.255.255.255 4569 (T) (E) OK (1 ms) CLI> quit
452
En el dialplan se crea un nuevo bloque que permita llamar de un servidor a otro: Servidor A nano /etc/asterisk/extensions.conf se añaden las siguientes lineas en el contexto internas: exten => _*1100X,1,Dial(IAX2/serverb/${EXTEN:2}) same => n,Hangup se actualiza el dialplan: asterisk -rx "dialplan reload" Servidor B nano /etc/asterisk/extensions.conf se añaden las siguientes lineas en el contexto internas: exten => _*1100X,1,Dial(IAX2/servera/${EXTEN:2}) same => n,Hangup se actualiza el dialplan: asterisk -rx "dialplan reload" Ahora se pueden efectuar las pruebas. Desde la extensión 1000 del servidor A, se marca el numero *11000 y se averigua en la consola de Asterisk que la llamada sea cursada correctamente al servidor B.. En la consola Asterisk del servidor A aparecerá: Executing [*11000@externas:1] Dial("SIP/1000-00000002", "IAX2/serverb/1000") in new stack -- Called IAX2/serverb/1000 -- Call accepted by 173.255.203.178 (format alaw) -- Format for call is (alaw) -- IAX2/serverb-17904 is ringing -- IAX2/serverb-17904 answered SIP/1000-00000002 La llamada ha funcionado perfectamente. 18.3 El protocolo DUNDi Cuando hay que conectar un numero considerable de servidores Asterisk y compartir las rutas y las extensiones configuradas en cada uno de ellos, la solución más funcional es el protocolo DUNDi. 453
DUNDi (Distributed Universal Number Discovery) es un protocolo que permite buscar y compartir dialplan entre servidores Asterisk. Esto por medio de una red Peer-to-peer (punto-a-punto) en la cual no existen roles fijos de clientes y servidores, sino que los servidores pueden asumir uno u otro rol según el contexto. A lo largo de la configuración se puede decidir si compartir contextos ya configurados en el Dialplan o crear nuevos definiendo las extensiones que se volverán disponibles a los demás servidores.. Aunque la configuración y puesta en marcha pueda parecer un poco complicada, con algo de practica se irán aclarando las ideas y los conceptos claves. El puerto predefino para el protocolo DUNDi es el 4520 UDP. Hay que abrirlo en el cortafuego de los servidores donde se va a utilizar DUNDi: nano /etc/sysconfig/iptables antes de esta linea: -A INPUT -p udp -m udp --dport 4569 -j ACCEPT se añade: # DUNDi -A INPUT -p udp -m udp --dport 4520 -j ACCEPT Se guardan los cambios y se reinicia Iptables: service iptables restart En el escenario que se presenta en este párrafo hay dos servidores Asterisk con estas características: Servidor A: IP: 192.168.129.142 usuario: server1 Extensiones: 1000-1001-1002 MAC Tarjeta de red: F2:3C:91:DF:5B:3E Servidor B: IP: 192.168.182.236 usuario: server2 Extensiones: 1000-1001-1002 MAC Tarjeta de red: FE:FD:45:A4:C4:49 Los dos servidores están en la misma LAN pero pueden estar ubicados en cualquier punto de la red Internet. El protocolo DUNDi se configura en el archivo dundi.conf. Es en este archivo que se definen los parámetros de conexión entre los servidores Asterisk y los contextos que se van a compartir. En el 454
mismo archivo se define el tipo de protocolo que los dos servidores utilizarán para efectuar y recibir llamadas (puede ser IAX2, SIP o H323). Terminada la configuración de dundi.conf, se modifica el dialplan para definir cuales son las rutas o contextos que se quieren compartir. Servidor A En la tabla que sigue se indican los parámetros que se configuran en el archivo dundi.conf con una breve descripción para cada uno de ellos. En la columna descripción, en negrita el valor de cada parámetro. Parámetro [general]
Descripción inicia la configuración general del archivo
department=EmpresaA En estos parámetros se indican los datos de la empresa. organization=EmpresaA locality=Santa Marta stateprov=Magdalena country=Colombia [email protected] phone=+57XXXXXXXXXX bindaddr
Dirección IP que se quiere utilizar con el protocolo DUNDi. Con 0.0.0.0 todas las direcciones IPv4 disponibles en el servidor Linux
port
Puerto para las conexiones DUNDi (4520 predefinido)
entityid
El MAC address de la tarjeta de red utilizada para las conexiones DUNDi. Personalizar con el valor real (comando ifconfig). Un ejemplo: F2:3C:91:DF:5B:3E
cachetime
Cuando se envía un solicitud para conocer la disponibilidad de una ruta y se encuentra una disponible, el resultado se guardará en la base de datos interna del Asterisk que envió la solicitud por el tiempo definido en este parámetro (en segundos). Valor 3600
ttl
Time to Live es un numero que representa el tiempo de vida de la solicitud. Más alto el numero más nodos se alcanzará a consultar. Valor 32
autokill
yes = si no se recibe una respuesta dentro de 2000 ms, se anulará la solicitud. Esto permite evitar que las solicitudes queden abiertas por un tiempo indeterminado
secretpath
El modulo pbx_dundi crea una clave, con el nombre definido en este parámetro, que rotará de manera automática y que se guardará en la base de datos interna de Asterisk. Valor dundi
storehistory
yes = mantiene un registro de las ultimas solicitudes efectuadas con los tiempos de respuesta de cada una. De esta forma es posible 455
Parámetro
Descripción averiguar cuales son los nodos lentos dentro de la red DUNDi
[mappings]
a partir de esta etiqueta se definen los contextos que se va a compartir con los demás servidores Asterisk. Las sintaxis de un contexto es: dundi_context => local_context,weight,tech,dest[,options]] • • •
• •
•
servera =>
dundi_context - el contexto DUNDi que se quiere compartir con los demás nodos de la red DUNDi local_context – el contexto local definido en el dialplan donde se configuran las rutas o extensiones que se quieren compartir weight – el peso que se asigna a las rutas que se comparten. Si son extensiones locales se pone 0, si son rutas para las cuales no hay una conexión directa o de alta calidad se pone un numero más alto. Al momento de efectuar una solicitud, si para el mismo numero requerido existen distintas rutas, se escogerá la ruta con menor peso tech – protocolo usado para la conexión entre servidores Asterisk (se usará IAX2) dest – cuando se realiza una solicitud desde el servidor B y se encuentra una ruta en el Servidor A, el Servidor A utilizará esa destinación para recibir la llamada. Simplificando: se crea un user en el iax.conf del servidor Asterisk A y dest representa los paramentos para conectarse a ese user options – son las distintas opciones que se pueden añadir a cada contexto DUNDi: 1. nounsolicited – llamadas de cualquier tipo que no sean solicitadas no son permitidas en esta ruta 2. nocomunsolicit – llamadas comerciales no solicitadas no son permitidas en esta ruta 3. residential – el numero es de una residencia 4. commercial – el numero es de una empresa 5. mobile – el numero es un celular 6. nopartial – no se harán búsquedas por números incompletos
servera-local,0,IAX2,server1:${SECRET}@192.168.129.142/${NUMBER}
El que aparece arriba es el contexto que se va a definir: • • • •
servera => - el contexto DUNDi que se va a compartir servera-local - el contexto definido en el dialplan que contendrá todas las rutas que se van a compartir IAX2 - la tecnología usada (protocolo) para las llamadas server1 - usuario que se configurará en el el archivo iax.conf 456
Parámetro
Descripción • • •
${SECRET} - es la variable que contiene la clave que el modulo DUNDi crea en automático y que se usará para autenticar el usuario server1 192.168.129.142 - dirección IP del Servidor A (personalizar) ${NUMBER}: la variable que contendrá el numero que ha sido solicitado
Para terminar con la configuración del archivo dundi.conf se definen los servidores Asterisk con los que se va a tener una conexión directa: [FE:FD:45:A4:C4:49] model = symmetric host = 192.168.182.236 inkey = server2 outkey = server1 include = all permit = servera qualify = yes • •
• • • • • •
FE:FD:45:A4:C4:49: MAC address de la tarjeta de red del Servidor Asterisk B con el que se crea la conexión (personalizar) model: puede ser: 1. inbound: recibe solamente solicitudes 2. outbound: solo efectúa solicitudes pero no las recibe 3. symmetric: recibe y efectúa solicitudes host: dirección IP o nombre de dominio del servidor Asterisk B inkey: clave RSA usada para autenticarse con el servidor Asterisk B outkey: clave RSA usada por el Servidor Asterisk B para autenticarse con el Servidor Asterisk A include: incluye esta conexión para todas las solicitudes efectuadas en el Servidor Asterisk A permit: se definen los contextos DUNDi a los que tendrá acceso este nodo qualify: se controlará periódicamente que la conexión con el nodo esté activa
Se crea el archivo dundi.conf. Primero se renombra el predefinido: mv /etc/asterisk/dundi.conf /etc/asterisk/dundi.conf.old se crea uno nuevo: nano /etc/asterisk/dundi.conf y se copian los datos de configuración: [general] 457
department=EmpresaA organization=EmpresaA locality=Santa Marta stateprov=Magdalena country=Colombia [email protected] phone=+57XXXXXXXXXX bindaddr=0.0.0.0 port=4520 entityid=F2:3C:91:DF:5B:3E cachetime=3600 ttl=32 autokill=yes secretpath=dundi storehistory=yes [mappings] servera => servera-local,0,IAX2,server1:${SECRET}@192.168.129.142/${NUMBER} [F2:3C:91:96:EC:A3] model = symmetric host = 192.168.182.236 inkey = server2 outkey = server1 include = all permit = servera qualify = yes IMPORTANTE: Personalizar los siguientes parámetros: entityid, la dirección IP local presente bajo la etiqueta [mappings], el mac address de la tarjeta del servidor B contenido entre corchetes y la dirección ip local del servidor B en host Se guardan los cambios y se crea la clave RSA para autenticar el Servidor Asterisk B. Para crear la clave se utilizará una utilidad que viene con la instalación de Asterisk. Primero se entra en la carpeta donde se guardarán las claves: cd /var/lib/asterisk/keys Se crea la clave: astgenkey -n server1 This script generates an RSA private and public key pair in PEM format for use by Asterisk. You will be asked to enter a passcode for your key multiple times. Please enter the same code each time. The resulting files will need to be moved to /var/lib/asterisk/keys if you want 458
to use them, and any private keys (.key files) will need to be initialized at runtime either by running Asterisk with the '-i' option, or with the 'init keys' command once Asterisk is running. Press ENTER to continue or ^C to cancel. Generating SSL key 'server1': Generating RSA private key, 1024 bit long modulus .......++++++ ..............................................................++++++ e is 65537 (0x10001) writing RSA key Key creation successful. Public key: server1.pub Private key: server1.key Se crearán dos archivos; uno contiene la clave publica y uno la clave privada. La publica se copia en el Servidor Asterisk B: scp server1.pub [email protected]:/var/lib/asterisk/keys Personalizar la dirección IP local del servidor B. Ahora se puede añadir el usuario server1 al archivo iax.conf nano /etc/asterisk/iax.conf Se añaden las siguientes lineas al final del archivo: [server1] type=user dbsecret=dundi/secret context=servera-local qualify=yes disallow=all allow=ulaw allow=alaw Importante definir el parámetro context con el valor del contexto que se ha definido en nuestra ruta (servera-local) El ultimo archivo que hay que modificar es el dialplan: nano /etc/asterisk/extensions.conf Antes del contexto internas se define el contexto servera-local y se incluyen las rutas/extensiones que se quiere compartir con el servidor B 459
[servera-local] exten => 20,1,Answer() exten => 20,n,Playback(hello-world) exten => 20,n,Hangup() Para las solicitudes remotas se crea otro contexto: [dundi-remoto] switch => DUNDi/serverb De esta forma cuando se marca un numero y ese numero no está presente en ningún contexto del dialplan, Asterisk consultará el servidor remoto con que tiene una conexión DUNDi. El nombre serverb es el contexto DUNDi que luego se creará en el archivo dundi.conf del Servidor Asterisk B. Añadimos el contexto dundi-remoto a la lista de contextos disponibles para la extensiones configuradas en el Servidor Asterisk A (en negrita los cambios): [externas] include => internas include => internacio include => parkedcalls include => test include => conferencias include => espiar include => dundi-remoto [locales] include => internas include => auten include => parkedcalls include => test include => conferencias include => espiar include => dundi-remoto Se guardan los cambios y se continúa con la configuración del Servidor Asterisk B Servidor B mv /etc/asterisk/dundi.conf /etc/asterisk/dundi.conf.old nano /etc/asterisk/dundi.conf Con los oportunos cambios, la configuración del servidor B será:
460
[general] department=EmpresaB organization=EmpresaB locality=Santa Marta stateprov=Magdalena country=Colombia [email protected] phone=+57XXXXXXXX bindaddr=0.0.0.0 port=4520 entityid=F2:3C:91:96:EC:A3 cachetime=3600 ttl=32 autokill=yes secretpath=dundi storehistory=yes [mappings] serverb => serverb-local,0,IAX2,server2:${SECRET}@192.168.182.236/${NUMBER} [F2:3C:91:DF:5B:3E] model = symmetric host = 192.168.129.142 inkey = server1 outkey = server2 include = all permit = serverb qualify = yes IMPORTANTE: Personalizar los siguientes parámetros: entityid, la dirección IP local presente bajo la etiqueta [mappings],el mac address de la tarjeta del servidor B contenido entre corchetes y la dirección ip local del servidor B en host Se crea la clave RSA para el servidor B: cd /var/lib/asterisk/keys astgenkey -n server2 This script generates an RSA private and public key pair in PEM format for use by Asterisk. You will be asked to enter a passcode for your key multiple times. Please enter the same code each time. The resulting files will need to be moved to /var/lib/asterisk/keys if you want to use them, and any private keys (.key files) will need to be initialized at runtime either by running Asterisk with the '-i' option, or with the 'init keys' 461
command once Asterisk is running. Press ENTER to continue or ^C to cancel. Generating SSL key 'server2': Generating RSA private key, 1024 bit long modulus ...................++++++ ...............................++++++ e is 65537 (0x10001) writing RSA key Key creation successful. Public key: server2.pub Private key: server2.key Se copia la clave publica en el Servidor Asterisk A scp server2.pub [email protected]:/var/lib/asterisk/keys Personalizar la dirección IP local del servidor A. Se crea el usuario IAX2 nano /etc/asterisk/iax.conf [server2] type=user qualify=yes dbsecret=dundi/secret context=serverb-local disallow=all allow=ulaw allow=alaw Para terminar se modifica el plan de marcado: nano /etc/asterisk/extensions.conf [serverb-local] exten => 40,1,Answer() exten => 40,n,Playback(hello-world) exten => 40,n,Hangup() [dundi-remoto] switch => DUNDi/servera Se incluye el contexto dundi-remoto de forma que sea accesible a las extensiones: [externas] include => internas 462
include => internacio include => parkedcalls include => test include => conferencias include => espiar include => dundi-remoto [locales] include => internas include => auten include => parkedcalls include => test include => conferencias include => espiar include => dundi-remoto Una vez terminada la configuración del Servidor Asterisk B en ambos se reinicia la PBX: /etc/init.d/asterisk restart Se entra en la consola del servidor Asterisk A: asterisk -rvvvvvvvvvvvv se mira la lista de comandos disponibles para DUNDi CLI> help dundi dundi flush [stats] Flush DUNDi cache dundi lookup Lookup a number in DUNDi dundi precache Precache a number in DUNDi dundi query Query a DUNDi EID dundi set debug {on|off} Enable/Disable DUNDi debugging dundi show cache Show DUNDi cache dundi show entityid Display Global Entity ID dundi show hints Show DUNDi hints in the cache dundi show mappings Show DUNDi mappings dundi show peers [registered|i Show defined DUNDi peers dundi show peer Show info on a specific DUNDi peer dundi show precache Show DUNDi precache dundi show requests Show DUNDi requests dundi show trans Show active DUNDi transactions dundi store history {on|off} Enable/Disable DUNDi historic records Se controla que haya conexión entre los dos servidores: CLI> dundi show peers EID Host
Port Model
AvgTime Status 463
f2:3c:91:96:ec:a3 192.168.182.236 (S) 4520 Symmetric Unavail OK (1 ms) 1 dundi peers [1 online, 0 offline, 0 unmonitored] Con el comando: CLI> database show /dundi/secret : qotQe+Vp1B2G7S9yoizlPA==;3obGb1QtvkUeciZs7rH5CA== /dundi/secretexpiry : 1259212403 aparecerá la clave creada por el modulo pbx_dundi y el tiempo que falta para que caduque. Ahora se puede realizar la primera consulta para controlar que efectivamente las rutas se están compartiendo: CLI> dundi lookup 40@serverb 1. 0 IAX2/server2:[email protected]/40 (EXISTS|CANMATCH) from f2:3c:91:96:ec:a3, expires in 3600 s DUNDi lookup completed in 45 ms En el servidor Asterisk B las extensión compartidas es la 40 y efectivamente enviando la solicitud, la respuesta es que la extensión existe. En el comando ademas de la extensión va indicado el contexto como se ha definido en el bloque mappings del dundi.conf del servidor Asterisk B. Si se envía una solicitud para una ruta que no existe la respuesta será: CLI> dundi lookup 20@serverb DUNDi lookup returned no results. DUNDi lookup completed in 3 ms Se efectúa otra solicitud de prueba desde el Servidor Asterisk B CLI> dundi lookup 20@servera 1. 0 IAX2/server1:[email protected]/20 (EXISTS|CANMATCH) from f2:3c:91:df:5b:3e, expires in 3600 s DUNDi lookup completed in 7 ms Para terminar las pruebas se conecta un softphone al servidor Asterisk B y se intenta llamar la extensión 20 (que es presente en el servidor Asterisk A); luego desde una extensión del servidor A se marca el numero 40. Como se ha podido ver, las potencialidades del protocolo DUNDi son realmente grandes. Este párrafo es una pequeña guía para que se pueda empezar a implementarlas. 18.4 Conectar dos servidores Asterisk con OpenVPN Aunque en la versión 11.X de Asterisk se ha mejorado el soporte del cifrado de la señalización SIP y 464
del flujo media, todavía hay muchos problemas de compatibilidad entre Asterisk y las distintas marcas/modelos de teléfonos actualmente en el mercado. Por este motivo, en algunos casos, puede ser más funcional crear una red VPN entre servidores Linux y luego utilizarla para configurar troncales en Asterisk. En este párrafo se verá como instalar y configurar OpenVPN en dos servidores Asterisk y como crear una conexión VPN entre los dos. Servidor A Primero se instala LZO, una librería de compresión datos requerida por OpenVPN: cd /usr/src Se descarga: wget http://www.oberhumer.com/opensource/lzo/download/lzo-2.09.tar.gz Se descomprime y se instala: tar -xf lzo-2.09.tar.gz cd lzo-2.09 ./configure --prefix=/usr --libdir=/usr/lib64 make make install Ahora se puede instalar la ultima versión disponible de OpenVPN pero primero se instala una dependencia: yum install pam-devel -y cd /usr/src se descarga: wget http://swupdate.openvpn.org/community/releases/openvpn-2.3.6.tar.gz se descomprime: tar -xf openvpn-2.3.6.tar.gz se entra en la carpeta creada: cd openvpn-2.3.6 se compila: ./configure --libdir=/usr/lib64 465
make make install Para preparar el servidor Linux creando las distintas claves (CA, servidor, cliente), se descargan unas utilidades: wget https://github.com/OpenVPN/easy-rsa/archive/release/2.x.zip unzip 2.x.zip cd easy-rsa-release-2.x/easy-rsa/2.0/ Se crea la carpeta donde se guardarán las distintas claves: mkdir /usr/local/sbin/keys nano vars Se modifican las líneas que siguen. Esto datos serán los predefinidos que se usaran al momento de la generación de las claves. Personalizar los datos de los parámetros que siguen: export KEY_DIR=/usr/local/sbin/keys export KEY_COUNTRY="CO" export KEY_PROVINCE="MAG" export KEY_CITY="SantaMarta" export KEY_ORG="VozToVoice" export KEY_EMAIL="[email protected]" export KEY_OU="PBXA" Se guardan los cambios y se prepara el programa para la generación de las claves: . ./vars NOTE: If you run ./clean-all, I will be doing a rm -rf on /usr/local/sbin/keys IMPORTANTE: entre el primer punto y el segundo hay un espacio ./clean-all Ahora se puede empezar a generar las claves empezando con la CA (Certificate Authority): ./build-ca Generating a 2048 bit RSA private key .................................................................+++ ..............................................................................................................+++ 466
writing new private key to 'ca.key' ----You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----Country Name (2 letter code) [CO]: State or Province Name (full name) [MAG]: Locality Name (eg, city) [SantaMarta]: Organization Name (eg, company) [VozToVoice]: Organizational Unit Name (eg, section) [PBXA]: Common Name (eg, your name or your server's hostname) [VozToVoice CA]:li204-236.members.linode.com Name [EasyRSA]: Email Address [[email protected]]: En “Common Name” se pone el nombre de dominio de Linode o del servidor Linux que se está utilizando. Se continua con la clave del servidor: ./build-key-server server Generating a 2048 bit RSA private key .................................................................+++ .....................+++ writing new private key to 'server.key' ----You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----Country Name (2 letter code) [CO]: State or Province Name (full name) [MAG]: Locality Name (eg, city) [SantaMarta]: Organization Name (eg, company) [VozToVoice]: Organizational Unit Name (eg, section) [PBXA]: Common Name (eg, your name or your server's hostname) [server]:li204-236.members.linode.com Name [EasyRSA]: Email Address [[email protected]]: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: 467
An optional company name []: Using configuration from /usr/src/openvpn-2.3.2/easy-rsa/easy-rsa/2.0/openssl-1.0.0.cnf Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows countryName :PRINTABLE:'CO' stateOrProvinceName :PRINTABLE:'Magdalena' localityName :PRINTABLE:'SantaMarta' organizationName :PRINTABLE:'VozToVoice' organizationalUnitName:PRINTABLE:'PBXA' commonName :PRINTABLE:'li374-118.members.linode.com' name :PRINTABLE:'EasyRSA' emailAddress :IA5STRING:'[email protected]' Certificate is to be certified until Sep 30 21:54:50 2023 GMT (3650 days) Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Updated Para terminar se crea una clave para el cliente (el servidor Asterisk B): ./build-key clienteb Generating a 2048 bit RSA private key .....................................................+++ ...............................+++ writing new private key to 'clienteb.key' ----You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----Country Name (2 letter code) [CO]: State or Province Name (full name) [MAG]: Locality Name (eg, city) [SantaMarta]: Organization Name (eg, company) [VozToVoice]: Organizational Unit Name (eg, section) [PBXA]: Common Name (eg, your name or your server's hostname) [clienteb]: Name [EasyRSA]: Email Address [[email protected]]: Please enter the following 'extra' attributes 468
to be sent with your certificate request A challenge password []: An optional company name []: Using configuration from /usr/src/openvpn-2.3.2/easy-rsa/easy-rsa/2.0/openssl-1.0.0.cnf Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows countryName :PRINTABLE:'CO' stateOrProvinceName :PRINTABLE:'Magdalena' localityName :PRINTABLE:'SantaMarta' organizationName :PRINTABLE:'VozToVoice' organizationalUnitName:PRINTABLE:'PBXA' commonName :PRINTABLE:'clienteb' name :PRINTABLE:'EasyRSA' emailAddress :IA5STRING:'[email protected]' Certificate is to be certified until Sep 30 21:55:46 2023 GMT (3650 days) Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Updated Si se tiene planeado utilizar la conexión para conectar teléfonos IP y/o Softphone, se crean otras claves cliente. Se termina con la generación del parámetro Diffie Hellman ./build-dh Generating DH parameters, 2048 bit long safe prime, generator 2 This is going to take a long time OpenVPN utiliza como puerto predefinido el 1194 (puede ser UDP o TCP según la configuración). Hay que abrirlo en Iptables solamente para la IP del servidor B. Suponiendo que la IP del servidor B es 66.228.49.216, se añaden las siguientes lineas en la configuración: nano /etc/sysconfig/iptables después de esta linea: -A INPUT -p tcp -m state --state NEW -m tcp --dport 15000 -j ACCEPT se pone: # OpenVPN -A INPUT -p tcp -m state --state NEW -m tcp -s 66.228.49.216 --dport 1194 -j ACCEPT -A INPUT -p udp -m udp -s 66.228.49.216 --dport 1194 -j ACCEPT Se guardan los cambios y se reinicia iptables: 469
service iptables restart Lo siguiente es instalar el script de arranque presente en las fuentes de OpenVPN: cd /usr/src/openvpn-2.3.6/distro/rpm cp openvpn.init.d.rhel /etc/rc.d/init.d/openvpn chkconfig --add openvpn chkconfig openvpn on Se crea la carpeta donde se guardarán los archivos de configuración de OpenVPN: mkdir /etc/openvpn Se crea el archivo de configuración para el servidor: cd /etc/openvpn nano server.conf Se copian las siguientes lineas: port 1194 proto udp dev tun ca /usr/local/sbin/keys/ca.crt cert /usr/local/sbin/keys/server.crt key /usr/local/sbin/keys/server.key dh /usr/local/sbin/keys/dh2048.pem server 10.8.0.0 255.255.255.0 ifconfig-pool-persist ipp.txt keepalive 10 120 comp-lzo max-clients 30 persist-key persist-tun log openvpn.log log-append openvpn.log verb 3 management localhost 7505 Para más informaciones sobre estos parámetros: http://openvpn.net/index.php/open-source/documentation/howto.html#examples 470
Se guardan los cambios y se inicia OpenVPN /etc/init.d/openvpn start En la configuración de red del servidor aparecerá un nuevo dispositivo: ifconfig
Servidor B Se sigue el mismo procedimiento para el servidor B: cd /usr/src Se descarga: wget http://www.oberhumer.com/opensource/lzo/download/lzo-2.09.tar.gz Se descomprime y se instala: tar -xf lzo-2.09.tar.gz cd lzo-2.09 ./configure --prefix=/usr --libdir=/usr/lib64 make make install Ahora se puede instalar la ultima versión disponible de OpenVPN: yum install pam-devel -y cd /usr/src se descarga: wget http://swupdate.openvpn.org/community/releases/openvpn-2.3.6.tar.gz se descomprime: 471
tar -xf openvpn-2.3.6.tar.gz se entra en la carpeta creada: cd openvpn-2.3.6 se compila: ./configure --libdir=/usr/lib64 make make install Para preparar el servidor Linux para crear las distintas claves (CA, servidor, cliente), se descargan unas utilidades: wget https://github.com/OpenVPN/easy-rsa/archive/release/2.x.zip unzip 2.x.zip cd easy-rsa-release-2.x/easy-rsa/2.0/ Se crea la carpeta donde se guardarán las distintas claves: mkdir /usr/local/sbin/keys nano vars Se modifican las líneas que siguen. Esto datos serán los que se usaran como predefinidos al momento de la generación de las claves. Personalizar los datos desde la segunda linea en adelante: export KEY_DIR=/usr/local/sbin/keys export KEY_COUNTRY="CO" export KEY_PROVINCE="MAG" export KEY_CITY="SantaMarta" export KEY_ORG="VozToVoice" export KEY_EMAIL="[email protected]" export KEY_OU="PBXB" Se guardan los cambios y se prepara el programa para la generación de las claves: . ./vars IMPORTANTE: entre el primer punto y el segundo hay un espacio ./clean-all 472
Ahora se puede empezar a generar las claves empezando con la CA (Certificate Authority): ./build-ca Generating a 2048 bit RSA private key ...............+++ ...........................+++ writing new private key to 'ca.key' ----You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----Country Name (2 letter code) [CO]: State or Province Name (full name) [MAG]: Locality Name (eg, city) [SantaMarta]: Organization Name (eg, company) [VozToVoice]: Organizational Unit Name (eg, section) [PBXB]: Common Name (eg, your name or your server's hostname) [VozToVoice CA]:li659-203.members.linode.com
Name [EasyRSA]: Email Address [[email protected]]: En “Common Name” se pone el nombre de dominio de Linode o del servidor Linux que se está utilizando. Se continua con la clave del servidor: ./build-key-server server Generating a 2048 bit RSA private key ...............................+++ .....................................................................+++ writing new private key to 'server.key' ----You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----Country Name (2 letter code) [CO]: State or Province Name (full name) [MAG]: Locality Name (eg, city) [SantaMarta]: Organization Name (eg, company) [VozToVoice]: 473
Organizational Unit Name (eg, section) [PBXB]: Common Name (eg, your name or your server's hostname) [server]:li659-203.members.linode.com Name [EasyRSA]: Email Address [[email protected]]: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: Using configuration from /usr/src/openvpn-2.3.2/easy-rsa/easy-rsa/2.0/openssl-1.0.0.cnf Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows countryName :PRINTABLE:'CO' stateOrProvinceName :PRINTABLE:'MAG' localityName :PRINTABLE:'SantaMarta' organizationName :PRINTABLE:'VozToVoice' organizationalUnitName:PRINTABLE:'PBXB' commonName :PRINTABLE:'server' name :PRINTABLE:'EasyRSA' emailAddress :IA5STRING:'[email protected]' Certificate is to be certified until Sep 30 22:09:41 2023 GMT (3650 days) Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Updated Para terminar se crea una clave para el cliente (el servidor Asterisk B): ./build-key clientea Generating a 2048 bit RSA private key .................+++ ............................+++ writing new private key to 'clientea.key' ----You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----Country Name (2 letter code) [CO]: State or Province Name (full name) [MAG]: 474
Locality Name (eg, city) [SantaMarta]: Organization Name (eg, company) [VozToVoice]: Organizational Unit Name (eg, section) [PBXB]: Common Name (eg, your name or your server's hostname) [clientea]: Name [EasyRSA]: Email Address [[email protected]]: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: Using configuration from /usr/src/openvpn-2.3.2/easy-rsa/easy-rsa/2.0/openssl-1.0.0.cnf Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows countryName :PRINTABLE:'CO' stateOrProvinceName :PRINTABLE:'MAG' localityName :PRINTABLE:'SantaMarta' organizationName :PRINTABLE:'VozToVoice' organizationalUnitName:PRINTABLE:'PBXB' commonName :PRINTABLE:'clientea' name :PRINTABLE:'EasyRSA' emailAddress :IA5STRING:'[email protected]' Certificate is to be certified until Sep 30 22:10:51 2023 GMT (3650 days) Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Updated Se termina con la generación del parámetro Diffie Hellman ./build-dh Generating DH parameters, 2048 bit long safe prime, generator 2 This is going to take a long time Como para el servidor A, se abren los puertos en iptables para la IP del servidor A nano /etc/sysconfig/iptables después de esta linea: -A INPUT -p tcp -m state --state NEW -m tcp --dport 15000 -j ACCEPT se añade:
475
# OpenVPN -A INPUT -p tcp -m state --state NEW -m tcp -s 69.164.201.178 --dport 1194 -j ACCEPT -A INPUT -p udp -m udp -s 69.164.201.178 --dport 1194 -j ACCEPT Se guardan los cambios y se reinicia iptables: service iptables restart Lo siguiente es instalar el script de arranque presente en las fuentes de OpenVPN: cd /usr/src/openvpn-2.3.6/distro/rpm cp openvpn.init.d.rhel /etc/rc.d/init.d/openvpn chkconfig --add openvpn chkconfig openvpn on Se crea la carpeta donde se guardarán los archivos de configuración de OpenVPN: mkdir /etc/openvpn Se crea el archivo de configuración para el servidor: cd /etc/openvpn nano server.conf Se copian las siguientes lineas: port 1194 proto udp dev tun ca /usr/local/sbin/keys/ca.crt cert /usr/local/sbin/keys/server.crt key /usr/local/sbin/keys/server.key dh /usr/local/sbin/keys/dh2048.pem server 10.10.0.0 255.255.255.0 ifconfig-pool-persist ipp.txt keepalive 10 120 comp-lzo max-clients 30 persist-key persist-tun log openvpn.log log-append openvpn.log verb 3 476
management localhost 7505 Se guardan los cambios. La diferencia con el archivo del Servidor A es que se utiliza otro rango de IP local. Se inicia OpenVPN /etc/init.d/openvpn start En la configuración de red del servidor aparecerá un nuevo dispositivo: ifconfig
Ahora que los dos servidores están configurados, hay que crear una conexión cliente en cada uno. Para eso hay que copiar las siguientes claves de un servidor a otro: Servidor A → Servidor B: • • •
ca.crt clienteb.crt clienteb.key
La claves se copian en la carpeta /etc/openvpn del servidor B. Servidor B → Servidor A: • • •
ca.crt clientea.crt clientea.key
La claves se copian en la carpeta /etc/openvpn del servidor A. Ahora en el servidor A se crea el archivo de configuración cliente para conectarse al servidor B: cd /etc/openvpn nano client.conf se copian las siguientes lineas: client 477
dev tun proto udp remote 66.228.49.216 1194 resolv-retry infinite nobind persist-key persist-tun ca /etc/openvpn/ca.crt cert /etc/openvpn/clientea.crt key /etc/openvpn/clientea.key comp-lzo verb 3 ns-cert-type server route-method exe route-delay 2 En la linea 4 se pone la dirección IP del servidor B y el puerto (1194). Se guardan los cambios y se reinicia OpenVPN: service openvpn restart Si todo ha salido bien, tendremos un nuevo dispositivo de red:
Para que las llamadas puedan ser enrutadas correctamente por Asterisk, hay que añadir estas dos nuevas redes en la configuración del sip.conf: nano /etc/asterisk/sip.conf Después del primer parámetro localnet se añade: localnet=10.8.0.0/255.255.255.0 localnet=10.10.0.0/255.255.255.0 Se recarga la configuración SIP: asterisk -rx "sip reload" 478
Se sigue el mismo procedimiento para el servidor B: cd /etc/openvpn nano client.conf se copian las siguientes lineas: client dev tun proto udp remote 96.126.125.112 1194 resolv-retry infinite nobind persist-key persist-tun ca /etc/openvpn/ca.crt cert /etc/openvpn/clienteb.crt key /etc/openvpn/clienteb.key comp-lzo verb 3 ns-cert-type server route-method exe route-delay 2 Se guardan los cambios y se reinicia OpenVPN: service openvpn restart Si todo ha salido bien, tendremos un nuevo dispositivo de red:
Para que las llamadas puedan ser enrutadas correctamente por Asterisk, hay que añadir estas dos nuevas redes en la configuración del sip.conf: 479
nano /etc/asterisk/sip.conf Después del primer parámetro localnet se añade: localnet=10.8.0.0/255.255.255.0 localnet=10.10.0.0/255.255.255.0 Se recarga la configuración SIP: asterisk -rx "sip reload" Una vez terminada la configuración y la conexión OpenVPN entre los dos servidores, se crea una nueva troncal SIP entre los dos. Esta vez utilizando la autentificación por IP. Para crear la troncal podemos utilizar o el rango de IP 10.8.0.1 o el rango de IP 10.10.0.1 Servidor A nano /etc/asterisk/sip.conf al final del archivo se pone: [serverbvpn] type=peer context=vpn host=10.8.0.6 disallow=all allow=g729 allow=alaw language=es qualify=yes dtmfmode = rfc2833 Importante destacar la dirección IP VPN del servidor B en el parámetro host y el contexto (vpn). Se guarda los cambios y se pasa al servidor B. Servidor B nano /etc/asterisk/sip.conf al final del archivo se pone: [serveravpn] type=peer context=vpn host=10.8.0.1 disallow=all 480
allow=g729 allow=alaw language=es qualify=yes dtmfmode = rfc2833 Se recarga la configuración SIP en ambos servidores: asterisk -rx "sip reload" Se entra en la consola de ambos servidores y se averigua que la conexión este funcionando: asterisk -rvvvvvvvvvv Servidor A: CLI> sip show peers like serverbvpn Name/username Host Dyn Nat ACL Port Status Realtime serverbvpn 10.8.0.6 N 5060 OK (2 ms) 1 sip peers [Monitored: 1 online, 0 offline Unmonitored: 0 online, 0 offline] Servidor B: CLI> sip show peers like serveravpn Name/username Host Dyn Nat ACL Port Status Realtime serveravpn 10.8.0.1 N 5060 OK (2 ms) 1 sip peers [Monitored: 1 online, 0 offline Unmonitored: 0 online, 0 offline] Perfecto!! Para probar las llamadas entre los servidores, utilizando la red OpenVPN, se modifica el dialplan acordándose que el contexto que se ha definido en la troncal es vpn. Servidor A nano /etc/asterisk/extensions.conf antes del contexto internas, se crea el nuevo contexto vpn y se añaden las siguientes lineas: [vpn] exten => 70,1,Answer same => n,Playback(demo-congrats) same => n,Hangup y en el contexto internas se pone: exten => 70,1,Set(CALLERID(num)=ServerAVPN) 481
same => n,Dial(SIP/serverbvpn/${EXTEN}) same => n,hangup Servidor B nano /etc/asterisk/extensions.conf antes del contexto internas, se crea el nuevo contexto vpn y se añaden las siguientes lineas: [vpn] exten => 70,1,Answer same => n,Playback(demo-congrats) same => n,Hangup y en el contexto internas se pone: exten => 70,1,Set(CALLERID(num)=ServerBVPN) same => n,Dial(SIP/serveravpn/${EXTEN}) same => n,hangup Se guardan los cambios en ambos servidores y se recarga el dialplan asterisk -rx "dialplan reload" Para terminar, se realiza una prueba marcando desde la extensión 1000 del servidor A la extensión 70. En la consola de Asterisk de servidor A debería aparecer: Executing [70@externas:1] Set("SIP/1000-0000001d", "CALLERID(num)=ServerAVPN") in new stack
-- Executing [70@externas:2] Dial("SIP/1000-0000001d", "SIP/serverbvpn/70") in new stack == Using SIP RTP CoS mark 5 -- Called SIP/serverbvpn/70 -- SIP/serverbvpn-0000001e answered SIP/1000-0000001d La comodidad de tener las dos redes VPN es que se pueden configurar otros clientes OpenVPN en los computadores donde tenemos instalados los SoftPhone o los teléfonos que soportan este protocolo (ejemplo Yealink desde el modelo T21 para arriba). 18.5 Conectar dos Servidores Asterisk con TLS y SRTP En esta párrafo se verá como configurar una conexión SIP entre dos servidores Asterisk y utilizar el protocolo TLS para la señalización SIP y el cifrado media con el protocolo SRTP. Primero hay que crear los certificados para el servidor A y el servidor B. Esto se realiza con una utilidad presente en las fuentes de Asterisk. Desde el servidor A: mkdir /etc/asterisk/keyspbx 482
Primero se crea el certificado CA y el certificado para el servidorA: cd /usr/src/asterisk-11.17.1/contrib/scripts ./ast_tls_cert -d certs -C li215-240.members.linode.com -o serverA No config file specified, creating 'certs/tmp.cfg' You can use this config file to create additional certs without re-entering the information for the fields in the certificate Creating CA key certs/ca.key Generating RSA private key, 4096 bit long modulus ..................................................................................................................................................................... ...................................................................................................++ ..............++ e is 65537 (0x10001) Enter pass phrase for certs/ca.key: Verifying - Enter pass phrase for certs/ca.key: Creating CA certificate certs/ca.crt Enter pass phrase for certs/ca.key: Creating certificate certs/serverA.key Generating RSA private key, 1024 bit long modulus ............................................++++++ ............++++++ e is 65537 (0x10001) Creating signing request certs/serverA.csr Creating certificate certs/serverA.crt Signature ok subject=/CN=li490-88.members.linode.com/O=Asterisk Getting CA Private Key Enter pass phrase for certs/ca.key: Combining key and crt into certs/serverA.pem En la opción -C se pone el nombre de dominio del servidor A y cuando el script lo pide se ingresa una contraseña (por ejemplo servera) Luego se crea el certificado para el servidorB ./ast_tls_cert -d certs -C li291-216.members.linode.com -o serverB No config file specified, creating 'certs/tmp.cfg' You can use this config file to create additional certs without re-entering the information for the fields in the certificate Creating CA key certs/ca.key Generating RSA private key, 4096 bit long modulus ..................................................................................................................................................................... ...............................................++ 483
..................................................................................................++ e is 65537 (0x10001) Enter pass phrase for certs/ca.key: Verifying - Enter pass phrase for certs/ca.key: Creating CA certificate certs/ca.crt Enter pass phrase for certs/ca.key: Creating certificate certs/serverB.key Generating RSA private key, 1024 bit long modulus ........................................++++++ .................................................++++++ e is 65537 (0x10001) Creating signing request certs/serverB.csr Creating certificate certs/serverB.crt Signature ok subject=/CN=li659-203.members.linode.com/O=Asterisk Getting CA Private Key Enter pass phrase for certs/ca.key: Combining key and crt into certs/serverB.pem Cuando el script pide la contraseña, se pone la misma que se ha utilizado para crear las claves del servidorA (servera) Ahora se copian los siguientes archivos en la carpeta /etc/asterisk/keys del servidorA: cd certs cp ca.crt /etc/asterisk/keyspbx/ cp serverA.pem /etc/asterisk/keyspbx/ Para terminar se modifica la configuración del archivo sip.conf para activar el protocolo TLS y se crea la troncal para el servidorB con autentificación sobre IP: nano /etc/asterisk/sip.conf al final de la parte general se pone: tlsenable=yes tlsbindaddr=96.126.125.112 tlscertfile=/etc/asterisk/keyspbx/serverA.pem tlscafile=/etc/asterisk/keyspbx/ca.crt tlscapath=/etc/asterisk/keyspbx tlsdontverifyserver=yes en tlsbindaddr se pone la dirección IP del servidorA al final del archivo se configura la troncal para el servidorB
484
[serverbtls] type=peer context=from-tls host=66.228.49.216 disallow=all allow=alaw language=es qualify=yes transport=tls encryption=yes Los parámetros importantes: • • • •
context: nombre del contexto donde entrarán las llamadas del servidoB host: la dirección IP del servidorB transport: de define como trasporte de la señalización SIP el protocolo TLS encryption: se activa el cifrado del flujo media (protocolo SRTP)
El protocolo TLS en Asterisk, utiliza el puerto predefinido 5061 TCP. Hay que abrirlo en el firewall para la IP del servidorB nano /etc/sysconfig/iptables después de esta linea: -A INPUT -p tcp -m state --state NEW -m tcp --dport 5060 -j ACCEPT se pone: -A INPUT -p tcp -m state --state NEW -m tcp -s 66.228.49.216 --dport 5061 -j ACCEPT Se guardan los cambios y se reinicia iptables: service iptables restart En el dialplan se crea el nuevo contexto antes del contexto internas: nano /etc/asterisk/extensions.conf [from-tls] exten => 71,1,Answer same => n,Noop(TLS = ${CHANNEL(secure_signaling)}, SRTP = ${CHANNEL(secure_media)}) same => n,Playback(tt-monkeys) same => n,Hangup
485
Con la segunda linea se lee la variable CHANNEL para el cifrado de la señalización y del flujo media. Si el valor es 1 significa que se están utilizando, si el valor es 0, significa que no están activos en el canal en uso. En el contexto internas se añade. exten => 71,1,Set(CALLERID(num)=serveratls) same => n,Dial(SIP/serverbtls/${EXTEN}) same => n,hangup
Servidor B Se crea la carpeta para los certificados: mkdir /etc/asterisk/keyspbx Se vuelve al servidor A y se copian las dos claves: scp ca.crt [email protected]:/etc/asterisk/keyspbx scp serverB.pem [email protected]:/etc/asterisk/keyspbx Esto suponiendo que la IP publica del servidorB sea 66.228.49.216 Se abre el archivos sip.conf: nano /etc/asterisk/sip.conf y al final de la parte general se pone: tlsenable=yes tlsbindaddr=66.228.49.216 tlscertfile=/etc/asterisk/keyspbx/serverB.pem tlscafile=/etc/asterisk/keyspbx/ca.crt tlscapath=/etc/asterisk/keyspbx tlsdontverifyserver=yes en tlsbindaddr se pone la dirección IP del servidorB. Al final del archivo se configura la troncal para el servidorA: [serveratls] type=peer context=from-tls host=96.126.125.112 disallow=all allow=alaw 486
language=es qualify=yes transport=tls encryption=yes Los parámetros importantes: • • • •
context: nombre del contexto donde entrarán las llamadas del servidoB host: la dirección IP del servidorB transport: de define como trasporte de la señalización SIP el protocolo TLS encryption: se activa el cifrado del flujo media (protocolo SRTP)
Se abre el puerto 5061 TCP en el firewall para la IP del servidorA nano /etc/sysconfig/iptables después de esta linea: -A INPUT -p tcp -m state --state NEW -m tcp --dport 5060 -j ACCEPT se pone: -A INPUT -p tcp -m state --state NEW -m tcp -s 96.126.125.112 --dport 5061 -j ACCEPT Se guardan los cambios y se reinicia iptables: service iptables restart Se pasa al dialplan: nano /etc/asterisk/extensions.conf Antes del contexto internas se pone: [from-tls] exten => 71,1,Answer same => n,Noop(TLS = ${CHANNEL(secure_signaling)}, SRTP = ${CHANNEL(secure_media)}) same => n,Playback(tt-monkeys) same => n,Hangup En el contexto internas se pone: exten => 71,1,Set(CALLERID(num)=serverbtls) same => n,Dial(SIP/serveratls/${EXTEN}) same => n,hangup
487
Se guardan los cambios y se recarga la configuración de ambos servidores: service asterisk reload Se averigua en el servidorA que el servidorB esté conectado: asterisk -rvvvvvvvvvvvvvvv CLI> sip show peers serverbtls 66.228.49.216
N
5061
OK (1 ms)
N
5061
OK (2 ms)
Se hace la misma operación en el servidorB: CLI> sip show peers serveratls 96.126.125.112
Ahora desde la extensión 1000 del servidorA se marca el numero 71 y se mira que pasa en la consola de ambos servidores: Servidor A: Executing [71@externas:1] Set("SIP/1000-00000022", "CALLERID(num)=serveratls") in new stack -- Executing [71@externas:2] Dial("SIP/1000-00000022", "SIP/serverbtls/71") in new stack Servidor B: Executing [71@from-tls:1] Answer("SIP/serveratls-00000015", "") in new stack -- Executing [71@from-tls:2] NoOp("SIP/serveratls-00000015", "TLS = 1, SRTP = 1") in new stack -- Executing [71@from-tls:3] Playback("SIP/serveratls-00000015", "tt-monkeys") in new stack -- Playing 'tt-monkeys.ulaw' (language 'es') -- Executing [71@from-tls:4] Hangup("SIP/serveratls-00000015", "") in new stack Como se puede ver en la consola del servidorB la llamada que llega tiene activado el protocolo TLS (1) y el protocolo SRTP(1). Esto quiere decir que la señalización y el flojo media serán cifrados. Otra forma de averiguarlo es activar con Ngrep la captura en el puerto 5061 en uno de los dos servidores: ngrep -W byline port 5061 Aparecerán puros bloques cifrados.
488
Capitulo XIX AMI y AGI 19.1 AMI (Asterisk Manager Interface) AMI (Asterisk Manager Interface) es una interfaz de monitoreo y gestión que interacciona con la PBX recibiendo eventos y/o enviando acciones que el sistema ejecutará. Para conectarse a la AMI, como cliente, se puede utilizar un socket TCP (puerto predefinido 5038) o el protocolo HTTP (puerto predefinido 8088). El AMI se configura en el archivo de configuración manager.conf y en el caso que se quiera utilizar también el protocolo HTTP, el archivo http.conf. En la tabla a seguir se indicarán los parámetros que se van a configurar con una breve descripción. En negrita los valores de cada parámetro. Al final de la tabla, la configuración completa del archivo.
Parámetro
Descripción
[general]
Etiqueta que indica el inicio de la configuración general del archivo
enabled
yes – Se activa el acceso a la AMI
webenabled
yes = se activa el acceso a la AMI vía HTTP
port
5038 – el puerto predefinido para la conexión a la AMI de Asterisk vía TCP
bindaddr
Dirección IP donde la AMI aceptará conexiones. Valor 0.0.0.0 todas las direcciones IP presentes en el servidor
;tlsenable=no ;tlsbindport=5039 ;tlsbindaddr=0.0.0.0 ;tlscertfile=/tmp/asterisk.pem ;tlsprivatekey=/tmp/private.pem
Es posible configurar la AMI para que utilice el protocolo TLS. Este tipo de configuración es aconsejado en el caso que se permita el acceso a la interfaz desde remoto. Los parámetros presentes son parecidos a la configuración del protocolo TLS en el archivo sip.conf. Se dejan comentados.
allowmultiplelogin
Este parámetro define si por un usuario configurado en este archivo se aceptan una o más conexiones simultaneas. Valor yes se aceptan
displayconnects
yes – En la consola de Asterisk cada vez que un usuario configurado en el manager.conf se conecte o se desconecte aparecerá una linea que lo notificará.
timestampevents
yes – añade una fecha en formato EPOCH a cada evento
;channelvars = var1,var2,var3
permite configurar unas variables que aparecerán cada vez que se genere un evento relacionado con un canal. De deja comentado
debug
no – no se activa el debug de la AMI de forma predefinida. Es posible activarlo y desactivarlo en cualquier momento desde la
Parámetro
Descripción consola de Asterisk
authtimeout
es el tiempo, expresado en segundos, que tiene un cliente para autenticarse. Valor 60
authlimit
define el numero máximo de sesiones simultaneas no autenticadas que aceptará la AMI. Valor: 20
httptimeout
define tres condiciones: 1. el tiempo máximo de vida del cookie http generado por la AMI 2. el tiempo que esperará el servidor web de la AMI al recibir una acción de tipo “waitevent” antes de cerrar la solicitud 3. tiempo que la AMI esperará antes de cerrar la sesión con un cliente después de haber enviado una respuesta a la solicitud recibida Valor: 60
[admin]
a partir de esta etiqueta se define el primer usuario que tendrá acceso a la AMI de Asterisk. El valor entre corchetes es el nombre del usuario.
secret
La contraseña que el usuario utilizará para conectarse a la AMI de Asterisk. Utilizar siempre contraseñas fuertes. Para esta configuración de prueba el valor es sesamo
deny
con este parámetro se define un rango de IP que no podrán acceder a la AMI de Asterisk con las credenciales del usuario configurado. Valor 0.0.0.0/0.0.0.0 (todas)
permit
con este parámetro se define un rango de IP que tendrán acceso a la AMI de Asterisk con las credenciales del usuario configurado. Valor 127.0.0.1/255.255.255.255 En este caso solamente desde local.
;eventfilter=Event: Newchannel ;eventfilter=!Channel: DAHDI*
El parámetro eventfilter permite filtrar los eventos que recibirá el usuario una vez que esté conectado a la AMI de Asterisk. Para los eventos se pueden crear dos tipos de configuraciones: 1. si el nombre del evento no empieza con un punto exclamativo, el tipo de evento se enviará 2. si el nombre del evento empieza con un punto exclamativo, se filtrará y no será enviado al cliente conectado a la AMI de Asterisk Se dejan comentadas.
writetimeout
Valor en mili segundos que esperará Asterisk para enviar los datos al cliente conectado a la AMI. Se utiliza en el caso que el cliente pierda la conexión con la AMI. Valor: 100
491
Una vez configurado el usuario, falta definir los permisos que el mismo usuario tendrá al conectarse con la AMI de Asterisk. Estos permisos son de dos tipos: • •
lectura escritura
En la tabla que sigue la lista completa y el significado de cada uno de ellos: Parámetro
Read
Write
all
El usuario puede leer todos los eventos de la AMI
El usuario tiene acceso a todas las acciones de la AMI
system
El usuario recibe todos los eventos relacionados con el funcionamiento de la PBX
El usuario puede enviar acciones de sistema (reiniciar la PBX, recargar la configuración, etc)
call
Permite al usuario recibir informaciones relacionadas con los canales de la PBX
Permite al usuario modificar, crear canales en la PBX
agent
permite al usuario acceder a todos los datos Permite al usuario enviar acciones para relacionados con las colas de espera y los gestionar y monitorear el estado de las agentes colas y los agentes
user
Recibe eventos relacionados con las extensiones y los usuarios Jabber (XMPP)
Permite generar eventos relacionados con las extensiones configuradas
config
Solo escritura
Permite al usuario leer, actualizar y recargar los archivos de configuración de Asterisk
command
Solo escritura
Permite al usuario ejecutar comandos de la consola de Asterisk
DTMF
permite al usuario recibir los eventos relacionados con los tonos
Solo lectura
reporting
permite al usuario recibir reportes de la calidad de las llamadas
permite al usuario ejecutar acciones para recibir estadísticas y reportes del sistema
cdr
permite al usuario recibir eventos Solo lectura relacionados con el registro de las llamadas según la configuración del archivo cdr_manager.conf
dialplan
permite al usuario recibir eventos cuando se modifica una variable o se crea una nueva extensión en el dialplan
Solo lectura
originate
Solo escritura
Permite al usuario crear una nueva llamada utilizando la acción Originate de la AMI
agi
permite al usuario recibir eventos generados por la ejecución de un AGI
Permite al usuario generar acciones para la gestión de los canales creados por un AGI 492
en modo asíncrono cc
permite al usuario recibir eventos relacionados con el sistema CCSS (rellamada)
Solo lectura
aoc
permite al usuario recibir eventos relacionados con AOC (advice of charge) es decir el costo de la llamada corriente Más Informaciones en la wiki de Asterisk
permite al usuario generar un mensaje AOC para una determinada llamada.
Ahora se puede crear el archivo manager.conf. Se renombra el predefinido: mv /etc/asterisk/manager.conf /etc/asterisk/manager.conf.old se crea uno nuevo: nano /etc/asterisk/manager.conf y se copian las siguientes lineas: [general] enabled=yes webenabled=yes port=5038 bindaddr=0.0.0.0 ;tlsenable=no ;tlsbindport=5039 ;tlsbindaddr=0.0.0.0 ;tlscertfile=/tmp/asterisk.pem ;tlsprivatekey=/tmp/private.pem allowmultiplelogin=yes displayconnects=yes timestampevents=yes ;channelvars = var1,var2,var3 debug=no authtimeout=60 authlimit=20 httptimeout=60 [admin] secret=sesamo deny=0.0.0.0/0.0.0.0 permit=127.0.0.1/255.255.255.255 ;eventfilter=Event: Newchannel ;eventfilter=!Channel: DAHDI* writetimeout=100 493
read=system,call,agent,user,dtmf,reporting,cdr,dialplan,agi,cc,aoc write=system,call,agent,user,config,command,reporting,otiginate,agi,aoc En las dos lineas read y write, se ponen todos los valores posibles. Se guardan los cambios y se entra en la consola de Asterisk: asterisk -rvvvvvvvvvvvvvvvvv Los comandos relacionados con la AMI de Asterisk: CLI> help manager manager reload Reload manager configurations manager set debug [on|off] Show, enable, disable debugging of the manager code manager show command Show a manager interface command manager show commands List manager interface commands manager show connected List connected manager interface users manager show eventq List manager interface queued events manager show events List manager interface events manager show event Show a manager interface event manager show settings Show manager global settings manager show users List configured manager users manager show user Display information on a specific manager user Primero se recarga la configuración: CLI> manager reload luego se controla que el usuario configurado aparezca:: CLI> manager show users username -------admin ------------------1 manager users configured. El usuario admin está presente. Con el comando: CLI> manager show commands aparecerá una lista de todos los comandos que se pueden utilizar desde la AMI de Asterisk. Por cada comando, en la columna Privilege, aparecen los privilegios que se necesitan para ejecutarlo. Entre ellos está el comando Login que permite conectarse a la AMI de Asterisk y es el que se utilizará para realizar la primera prueba. Para conocer la sintaxis: CLI> manager show command Login 494
[Syntax] Action: Login [ActionID:] Username: [Secret:] [Synopsis] Login Manager. [Description] Login Manager. [Arguments] ActionID ActionID for this transaction. Will be returned. Username Username to login with as specified in manager.conf. Secret Secret to login with as specified in manager.conf. [See Also] Not available Para conectarse a la AMI de Asterisk se utilizará el programa Telnet. Se abre otra consola de Linux y se instala telnet: yum install telnet -y Se inicia el programa: telnet y se crea la conexión a la AMI de Asterisk: telnet> o localhost 5038 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. Asterisk Call Manager/1.1 Action: Login Username: admin Secret: sesamo Events: Off Después de cada linea, para pasar a la siguiente se presiona la tecla envío. Después de la ultima linea la 495
tecla envío se presiona dos veces. El resultado será: Response: Success Message: Authentication accepted Para salir de la AMI: Action: Logoff Response: Goodbye Message: Thanks for all the fish. Connection closed by foreign host. En la consola de Asterisk aparecerá: == Manager 'admin' logged on from 127.0.0.1 == Manager 'admin' logged off from 127.0.0.1 Otra prueba que se se puede hacer es ver la configuración de la extensión 1000 telnet telnet> o localhost 5038 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. Asterisk Call Manager/1.1 Action: Login Username: admin Secret: sesamo Events: On Response: Success Message: Authentication accepted Event: FullyBooted Privilege: system,all Status: Fully Booted En este caso, con Events:On, se activa la recepción de todos los eventos generados por la AMI. Luego se ejecuta la acción para ver la configuración de la extensión 1000 Action: SIPshowpeer Peer: 1000
496
Response: Success Channeltype: SIP ObjectName: 1000 ChanObjectType: peer SecretExist: Y RemoteSecretExist: N MD5SecretExist: N Context: externas Language: es ToneZone: es Accountcode: 1000 AMAflags: Unknown CID-CallingPres: Presentation Allowed, Not Screened Callgroup: 1 Pickupgroup: 1 Named Callgroup: Named Pickupgroup: MOHSuggest: default VoiceMailbox: 1000@default TransferMode: open LastMsgsSent: 65536 Maxforwards: 0 Call-limit: 2147483647 Busy-level: 0 MaxCallBR: 384 kbps Dynamic: Y Callerid: "callerid=Fulano" <1000> RegExpire: 2870 seconds SIP-AuthInsecure: no SIP-Forcerport: Y SIP-Comedia: Y ACL: N SIP-CanReinvite: N SIP-DirectMedia: N SIP-PromiscRedir: N SIP-UserPhone: N SIP-VideoSupport: Y SIP-TextSupport: N SIP-T.38Support: Y SIP-T.38EC: FEC SIP-T.38MaxDtgrm: 400 SIP-Sess-Timers: Originate SIP-Sess-Refresh: uas SIP-Sess-Expires: 600 SIP-Sess-Min: 90 SIP-RTP-Engine: asterisk SIP-Encryption: N 497
SIP-DTMFmode: rfc2833 ToHost: Address-IP: 79.44.192.186 Address-Port: 6000 Default-addr-IP: (null) Default-addr-port: 0 Default-Username: 1000 Codecs: (alaw|g729|g722|h263) CodecOrder: alaw,g722,g729,h263 Status: OK (250 ms) SIP-Useragent: X-Lite release 4.5.4 stamp 70866 Reg-Contact: sip:[email protected]:6000;rinstance=7f359a2313f6b8bb QualifyFreq: 60000 ms Parkinglot: SIP-Use-Reason-Header: Y Action: Logoff Connection closed by foreign host. Una ultima prueba es conectarse a la AMI y mirar cuales eventos se generan a lo largo de una llamada entre la extensión 1000 y la extensión 1001: telnet localhost 5038 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. Asterisk Call Manager/1.1 Action: Login Username: admin Secret: sesamo Events: On Response: Success Message: Authentication accepted Event: FullyBooted Privilege: system,all Status: Fully Booted Una vez conectado a la AMI desde la extensión 1000 se llama la extensión 1001 y se mira lo que aparece en la consola de Linux. Se verán toda una serie de informaciones relacionadas con la llamada; además aparecerán los eventos relacionados con el CCSS. Ya se puede salir de la AMI: Action:Logoff 498
Response: Goodbye Message: Thanks for all the fish. Connection closed by foreign host. Claramente utilizar la AMI de esta forma es poco practico. Normalmente se hace escribiendo código en distintos lenguajes de programación, desde script bash hasta script en Ruby. De hecho existen muchas librerías que simplifican está operación: Entre ellas: • • • • •
PHP: PHPagi Python: Starpy Perl: Asterisk-perl Java: Asterisk-java Ruby: Adhearsion
Como se ha dicho al inicio de este párrafo, es posible interaccionar con la AMI de Asterisk vía HTTP. De hecho hay soluciones que utilizan este tipo de conexión. Entre ellas hay que citar la GUI para Asterisk de Digium, cuya instalación se explicará en el capitulo XXVI, y FOP2 (Flash Operator Panel 2) que es un sistema que permite monitorear las actividad de las llamadas de Asterisk y al mismo tiempo efectuar algunas acciones entre las cuales: transferir una llamada, espiar una llamada, ver la actividad de una cola. Por ultimo, WebRTC que es una novedad de la versión 11 de Asterisk, funcionalidad de la que se ha hablado en el párrafo 7.9. 19.2 AGI (Asterisk Gateway Interface) El Asterisk Gateway Interface (AGI) permite desarrollar aplicaciones externas que pueden interaccionar con Asterisk. Estas aplicaciones pueden estar escritas en distintos lenguajes de programación y de hecho existen librerías en Perl, PHP, Python, Ruby que simplifican su escritura. Como para la AMI, también para el AGI es posible conocer los comandos disponibles desde la consola de Asterisk: asterisk -rvvvvvvvvvvvvvvv y se escribe: CLI> help agi agi dump html Dumps a list of AGI commands in HTML format agi exec Add AGI command to a channel in Async AGI agi set debug [on|off] Enable/Disable AGI debugging agi show commands [topic] List AGI commands or specific help Para una lista de los comandos que se pueden utilizar en un AGI: CLI> agi show commands 499
¿Cómo Funciona? La comunicación entre Asterisk y el AGI se apoya a los “files descriptors” del sistema operativo Linux que permiten una comunicación entre el Kernel y la aplicación que quiere acceder a un determinado archivo/programa. En Linux. Los tres estándar que se utilizan son: • • •
STDIN STDOUT STDERR
Visto de forma gráfica:
Esto permite, como ya se ha dicho, escribir el AGI utilizando prácticamente cualquier lenguaje de programación. Para los ejemplos a seguir, se utilizarán la librería PHPAGI y PHP. Para PHPAGI, primero se instala php: yum install php-* luego de descarga la librería: cd /usr/src wget http://downloads.sourceforge.net/project/phpagi/phpagi/2.20/phpagi-2.20.tgz Se descomprime: tar -xf phpagi-2.20.tgz se entra en la carpeta creada: 500
cd phpagi-2.20 y se copian las dos librerías AGI en la carpeta agi-bin de Asterisk: cp phpagi.php /var/lib/asterisk/agi-bin cp phpagi-asmanager.php /var/lib/asterisk/agi-bin se vuelven los archivos ejecutables: chmod 755 /var/lib/asterisk/agi-bin/phpagi.php chmod 755 /var/lib/asterisk/agi-bin/phpagi-asmanager.php PHPAGI se apoya a un archivo de configuración que hay que crear en la carpeta /etc/asterisk. nano /etc/asterisk/phpagi.conf se copian las siguientes lineas: [phpagi] debug=false error_handler=true [email protected] hostname=li204-236.members.linode.com tempdir=/var/spool/asterisk/tmp/ [asmanager] server=localhost port=5038 username=admin secret=sesamo [fastagi] setuid=true basedir=/var/lib/asterisk/agi-bin/ [festival] text2wave=/usr/bin/text2wave El primer bloque del archivo es dedicado al la configuración de PHPAGI para la ejecución de scripts AGI. Personalizar los parámetros admin con un correo electrónico real y hostname con el nombre de dominio o la IP del servidor Linux. En en segundo bloque [asmanager], se configura los datos de acceso a la AMI de Asterisk para el usuario admin anteriormente creado. El tercer bloque es para la configuración de FastAGI (cuando se ejecutan los script AGI sobre una 501
conexión TCP) Por ultimo, para utilizar Festival como sistema de texto a voz, se indica la ubicación del archivo text2wave. Se guardan los cambios y se crea el primer AGI: nano /var/lib/asterisk/agi-bin/pruebaudio.php #!/usr/bin/php -q answer(); $agi-> stream_file('demo-congrats'); $agi-> hangup(); ?> Se vuelve ejecutable el archivo: chmod +x /var/lib/asterisk/agi-bin/pruebaudio.php Se modifica el dialplan para añadir el AGI: nano /etc/asterisk/extensions.conf en el contexto internas se añade: exten => 250,1,Agi(pruebaudio.php) same => n,Hangup Se guardan los cambios, se entra en la consola de Asterisk y se recarga el dialplan: asterisk -rvvvvvvvvvvvv CLI> dialplan reload la sintaxis de la aplicación AGI: CLI> core show application agi [Syntax] AGI(command[,arg1[,arg2[,...]]]) Desde la extensión 1000 se marca el numero 250. En la consola aparecerá: -- Executing [250@externas:1] AGI("SIP/1000-00000050", "pruebaudio.php") in new stack 502
-- Launched AGI Script /var/lib/asterisk/agi-bin/pruebaudio.php -- Playing 'demo-congrats' (escape_digits=) (sample_offset 0) -- AGI Script pruebaudio.php completed, returning 4 == Spawn extension (externas, 250, 1) exited non-zero on 'SIP/1000-00000050' Si se activa el debug agi: CLI> agi set debug on El resultado será: -- Executing [250@externas:1] AGI("SIP/1000-00000051", "pruebaudio.php") in new stack -- Launched AGI Script /var/lib/asterisk/agi-bin/pruebaudio.php AGI Tx >> agi_request: pruebaudio.php AGI Tx >> agi_channel: SIP/1000-00000051 AGI Tx >> agi_language: es AGI Tx >> agi_type: SIP AGI Tx >> agi_uniqueid: 1331227067.81 AGI Tx >> agi_version: 1.8.8.2 AGI Tx >> agi_callerid: 1000 AGI Tx >> agi_calleridname: callerid=Fulano AGI Tx >> agi_callingpres: 0 AGI Tx >> agi_callingani2: 0 AGI Tx >> agi_callington: 0 AGI Tx >> agi_callingtns: 0 AGI Tx >> agi_dnid: 250 AGI Tx >> agi_rdnis: unknown AGI Tx >> agi_context: externas AGI Tx >> agi_extension: 250 AGI Tx >> agi_priority: 1 AGI Tx >> agi_enhanced: 0.0 AGI Tx >> agi_accountcode: 1000 AGI Tx >> agi_threadid: -1229980784 AGI Tx >> AGI Rx << ANSWER AGI Tx >> 200 result=0 AGI Rx << STREAM FILE demo-congrats "" 0 -- Playing 'demo-congrats' (escape_digits=) (sample_offset 0) AGI Tx >> 200 result=0 endpos=313776 AGI Rx << HANGUP AGI Tx >> 200 result=1 -- AGI Script pruebaudio.php completed, returning 4 == Spawn extension (externas, 250, 1) exited non-zero on 'SIP/1000-00000051' Asterisk, antes de procesar el agi, envía todas las variables relacionadas con el canal. Otro ejemplo podría ser devolver al llamante su CallerID
503
nano /var/lib/asterisk/agi-bin/callerid.php #!/usr/bin/php -q answer(); $callerid = $agi->request['agi_callerid']; $agi->text2wav("Hola extension $callerid"); $agi-> hangup(); ?> chmod +x /var/lib/asterisk/agi-bin/callerid.php nano /etc/asterisk/extensions.conf exten => 251,1,Agi(callerid.php) same => n,Hangup asterisk -rvvvvvvvvvvvv CLI> dialplan reload Desde la extensión 1000 se marca 251. El ultimo ejemplo es un despertador que no utiliza la librería PHPAGI sino PHP “puro”: cd /usr/src wget http://www.voztovoice.org/tmp/wakeup.2.0.tar Se descomprime: tar -xf wakeup.2.0.tar Se entra en la carpeta: cd wakeup.2.0 Se vuelve ejecutable el archivo wakeup.php: chmod +x wakeup.php se copia en la carpeta agi-bin de asterisk: cp wakeup.php /var/lib/asterisk/agi-bin/ 504
Terminada esta primera parte se modifica el Dialplan para crear una nueva extensión que se usará para programar el despertador nano /etc/asterisk/extensions.conf Se añaden las siguientes dos líneas en el contexto internas: exten => 77,1,Set(CHANNEL(language)=es) same => n,agi(wakeup.php) same=> n,Hangup Se guarda el archivo y se recarga el dialplan: asterisk -rvvvvvvvvvvv CLI> dialplan reload Ahora desde un extensión 1000 se marca el numero 77 y se siguen las instrucciones para programar el despertador. Una vez programado si desde la misma extensión se marca otra vez la extensión 77 se tendrá la posibilidad de poder modificar la hora del despertador. Cuando llega la llamada del despertador, en el softphone aparecerá:
19.3 Las variantes AGI Ademas de la aplicación AGI que se acaba de ilustrar, existen una variantes que se utilizan en algunos escenarios muy específicos. Estas son: • • •
EAGI FastAGI Async AGI
Hasta la versión 1.4.X de Asterisk existía también la aplicación DeadAGI que normalmente se utilizaba en un canal que había sido terminado. Esta aplicación ya es “deprecated” y va sustituida con la normal aplicación AGI
505
19.3.1 EAGI La gran diferencia entre AGI y EAGI es que el segundo, ademas de comunicarse con Asterisk a través de STDIN y STDOUT, utiliza un file descriptor para la creación de un flujo audio procedente del canal que ha llamado la aplicación. Algunos datos: CLI> core show application EAGI -= Info about application 'EAGI' =[Synopsis] Executes an EAGI compliant application. [Description] Using 'EAGI' provides enhanced AGI, with incoming audio available out of band on file descriptor 3. Executes an Asterisk Gateway Interface compliant program on a channel. AGI allows Asterisk to launch external programs written in any language to control a telephony channel, play audio, read DTMF digits, etc. by communicating with the AGI protocol on *stdin* and *stdout*. As of '1.6.0', this channel will not stop dialplan execution on hangup inside of this application. Dialplan execution will continue normally, even upon hangup until the AGI application signals a desire to stop (either by exiting or, in the case of a net script, by closing the connection). A locally executed AGI script will receive SIGHUP on hangup from the channel except when using DeadAGI. A fast AGI server will correspondingly receive a HANGUP inline with the command dialog. Both of theses signals may be disabled by setting the ${AGISIGHUP} channel variable to 'no' before executing the AGI application. Use the CLI command 'agi show commands' to list available agi commands. This application sets the following channel variable upon completion: ${AGISTATUS}: The status of the attempt to the run the AGI script text string, one of: SUCCESS FAILURE NOTFOUND HANGUP [Syntax] EAGI(command[,arg1[,arg2[,...]]]) [Arguments] Not available [See Also] AGI(), DeadAGI() 506
19.3.2 FastAGI FastAGI trabaja sobre una conexión TCP que se realiza con un servidor FastAGI. El control sobre el canal se realiza vía TCP y no requiere iniciar un nuevo proceso para cada llamada. La sintaxis es: AGI(agi://IPservidorFastAGI:puerto) El puerto predefinido es el 4573 En las fuentes de Asterisk es presente un servidor FastAGI para efectuar una prueba. Primero se modifica el dialplan: nano /etc/asterisk/extensions.conf En el contexto internas se añade el siguiente bloque: exten => 252,1,Noop same => n,AGI(agi://127.0.0.1:4573) same => n,Hangup Se guardan los cambios y se recarga el dialplan: asterisk -rvvvvvvvvvvvvv CLI> dialplan reload Se cambian los permisos del servidor FastAGI: chmod 755 /usr/src/asterisk-11.17.1/agi/fastagi-test y se inicia: /usr/src/asterisk-1112.0/agi/fastagi-test Desde la extensión 1000 se marca el numero 252. Aparecerá: Consola Asterisk: -- Executing [253@externas:1] NoOp("SIP/1000-00000011", "") in new stack -- Executing [253@externas:2] AGI("SIP/1000-00000011", "agi://127.0.0.1:4573") in new stack -- AGI Script agi://127.0.0.1:4573 completed, returning 0 -- Executing [253@externas:3] Hangup("SIP/1000-00000011", "") in new stack == Spawn extension (externas, 253, 3) exited non-zero on 'SIP/1000-00000011'
507
Consola del servidor FastAgi: AGI Environment Dump from 59836 --- accountcode = 1000 -- callerid = 1000 -- calleridname = callerid=Fulano -- callingani2 = 0 -- callingpres = 0 -- callingtns = 0 -- callington = 0 -- channel = SIP/1000-00000011 -- context = externas -- dnid = 253 -- enhanced = 0.0 -- extension = 253 -- language = es -- network = yes -- priority = 2 -- rdnis = unknown -- request = agi://127.0.0.1:4573 -- threadid = -1224852592 -- type = SIP -- uniqueid = 1331242231.21 -- version = 1.8.8.2 1. Testing 'sendfile'...PASS (0) 2. Testing 'sendtext'...PASS (0) 3. Testing 'sendimage'...PASS (0) 4. Testing 'saynumber'...PASS (0) 5. Testing 'waitdtmf'...PASS (0) 6. Testing 'record'...PASS (0) 6a. Testing 'record' playback...PASS (0) ================== Complete ====================== 7 tests completed, 7 passed, 0 failed ================================================== Un “framework” que utiliza FastAGI es Adhearsion. 19.3.3 Async AGI Async AGI permite el envío de los comandos a través de la AMI de Asterisk. De esta forma es posible abrir un canal y luego desde la AMI enviar los comandos al canal abierto. Desde el punto de vista del dialplan la sintaxis es muy sencilla: AGI(agi:async)
508
Para poder enviar las acciones AGI a la AMI de Asterisk, el usuario configurado en el manager.conf deber tener los permisos de lectura y escritura para el parámetro agi, cosa que se hizo cuando se configuró el usuario admin en el manager.conf. Para probar la funcionalidad de modifica el dialplan: nano /etc/asterisk/extensions.conf y se añade el bloque que sigue: exten => 253,1,Noop same => n,AGI(agi:async) same => n,Hangup Se guardan los cambios y se recarga el dialplan: asterisk -rvvvvvvvvvvvv CLI> dialplan reload Antes de marcar la extensión 253, se abre otra ventana terminal y se crea una conexión manual a la AMI de Asterisk: telnet localhost 5038 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. Asterisk Call Manager/1.1 Se autentica el usuario admin: Action:login Username:admin Secret:sesamo Events:off Response: Success Message: Authentication accepted Se ejecuta la primera acción agi para contestar el canal (el numero de canal aparece en la consola de Asterisk): Action:Agi Channel:SIP/1000-00000017 Command:Answer Response: Success 509
Message: Added AGI command to queue Se envía la música de espera al canal: Action:Agi Channel:SIP/1000-00000017 Command:Exec startmusiconhold Response: Success Message: Added AGI command to queue Se para la música de espera en el canal: Action:Agi Channel:SIP/1000-00000017 Command:Exec stopmusiconhold Response: Success Message: Added AGI command to queue Se termina la llamada: Action:Agi Channel:SIP/1000-00000017 Command:hangup Response: Success Message: Added AGI command to queue En la consola de Asterisk aparecerá: -- Executing [254@externas:1] NoOp("SIP/1000-00000017", "") in new stack -- Executing [254@externas:2] AGI("SIP/1000-00000017", "agi:async") in new stack AGI Tx >> agi_request: async AGI Tx >> agi_channel: SIP/1000-00000017 AGI Tx >> agi_language: es AGI Tx >> agi_type: SIP AGI Tx >> agi_uniqueid: 1331246894.27 AGI Tx >> agi_version: 1.8.8.2 AGI Tx >> agi_callerid: 1000 AGI Tx >> agi_calleridname: callerid=Fulano AGI Tx >> agi_callingpres: 0 AGI Tx >> agi_callingani2: 0 AGI Tx >> agi_callington: 0 AGI Tx >> agi_callingtns: 0 AGI Tx >> agi_dnid: 254 AGI Tx >> agi_rdnis: unknown 510
AGI Tx >> agi_context: externas AGI Tx >> agi_extension: 254 AGI Tx >> agi_priority: 2 AGI Tx >> agi_enhanced: 0.0 AGI Tx >> agi_accountcode: 1000 AGI Tx >> agi_threadid: -1225098352 AGI Tx >> AGI Tx >> 200 result=0 -- AGI Script Executing Application: (startmusiconhold) Options: () -- Started music on hold, class 'default', on SIP/1000-00000017 AGI Tx >> 200 result=0 -- AGI Script Executing Application: (stopmusiconhold) Options: () -- Stopped music on hold on SIP/1000-00000017 AGI Tx >> 200 result=0 AGI Tx >> 200 result=1 == Spawn extension (externas, 254, 2) exited non-zero on 'SIP/1000-00000017'
511
Capitulo XX Los registros en Asterisk Asterisk guarda toda una serie de registros relacionados con su actividad en distintos archivos. Una parte están relacionados con las llamadas y otra parte con el funcionamiento de la PBX. En este capitulo se hablará de: • • •
CDR (Call Detail Record) CEL (Channel Event Logging) Logger.conf
20.1 CDR (Call Detail Record) En el párrafo 1.7 se ha visto como crear una base de datos MySQL y una tabla (cdr) para guardar los registros de las llamadas. Mirando una entrada en la tabla CDR, se verán los siguientes datos:
En orden: • • • • • • • • • • • • • • • • •
calldate: fecha y hora de la llamada clid: callerID del llamante src: numero de la extensión que ha iniciado la llamada dst: numero de destino dcontext: contexto que se ha utilizado channel: nombre del canal de quien ha originado la llamada dstchannel: nombre del canal de destino lastapp: utima aplicación utilizada lastdata: opciones de la ultima aplicación utilizada duration: duración total de la llamada billsec: duración de la llamada desde que ha sido contestada disposition: resultado de la aplicación ejecutada (en este caso BUSY) amaflags: parámetro utilizado para la facturación de la llamada accountcode: numero de cuenta para la facturación de la llamada peeraccount: cuenta del usuario (lado peer) uniqueid: numero único que identifica la llamada linkedid: numero único que identifica la llamada y que mantiene el mismo valor en el caso la
•
llamada sea transferida, parqueada, enviada a una cola, etc.. Útil para hacerle seguimiento a la llamada userfield: campo personalizable por el usuario.
Una primera cosa que se puede hacer es utilizar el campo userfield para guardar la IP de donde se originó la llamada. Para esta configuración se utiliza la función CHANNEL que permite leer muchos datos de un determinado canal, entre ellos “peerip”. Se abre el dialplan: nano /etc/asterisk/extensions.conf y en el contexto internacio, después de esta linea: exten => _00X.,1,NoOp se añade: same => n,Set(CDR(userfield)=${CHANNEL(peerip)}) y después de esta linea: exten => _00573.,1,Noop se añade: same => n,Set(CDR(userfield)=${CHANNEL(peerip)}) Con estas lineas se asocia al campo userfield del CDR, la IP del canal que está originando la llamada. Se guardan los cambios y se recarga el dialplan: asterisk -rvvvvvvvvvvvvv CLI> dialplan reload Ahora desde la extensión 1000 se llama un numero de teléfono fijo/celular. Terminada la llamada se vuelve a Webmin y se mira la ultima entrada de la tabla CDR. En el campo userfield aparecerá la IP de donde se originó la llamada:
Este tipo de solución puede ser muy útil para conocer en cualquier momento de donde las extensiones están originando sus llamadas y de esta forma monitorear si se están presentando ataques exitosos a la PBX. 514
Los mismos datos se guardan también en distintos archivos CSV presentes en la la carpeta /var/log/asterisk.y algunas sub-carpetas (en negrita). ls -l /var/log/asterisk drwxr-xr-x 2 root root 4096 abr 8 13:21 cdr-csv drwxr-xr-x 2 root root 4096 abr 1 15:05 cdr-custom drwxr-xr-x 2 root root 4096 abr 1 15:05 cel-custom -rw-r--r-- 1 root root 413174 abr 20 09:30 messages -rw-r--r-- 1 root root 1477 abr 17 10:07 queue_log La carpeta cdr-csv contiene el archivo Master.csv, que contiene la lista de todas las llamadas efectuadas, y un archivo para cada extensión/cuenta. total 72 -rw-r--r-- 1 root root 18847 Mar 24 11:10 1000.csv -rw-r--r-- 1 root root 8055 Mar 22 17:44 1001.csv -rw-r--r-- 1 root root 1059 Mar 22 17:45 1002.csv -rw-r--r-- 1 root root 1113 Mar 23 16:26 marko2.csv -rw-r--r-- 1 root root 32149 Mar 24 11:10 Master.csv -rw-r--r-- 1 root root 261 Mar 21 11:09 Mengano.csv 20.1.1 cdr.conf Lo que se guarda y como se guardan los datos en el CDR depende de la configuración del archivo cdr.conf. En la tabla que sigue los distintos parámetros con una descripción. En negrita el valor asignado a cada parámetro.
Parámetro [general] enable
Descripción Etiqueta que indica el inicio de la parte general de la configuración yes = se habilita el registro CDR
unanswered
yes = reporta todas las llamadas no contestadas con múltiples destinos y una sola origen. Ejemplo: cuando desde una extensión se marca a un grupo de extensiones. no = reporta todas las llamadas incluyendo la no contestadas siempre y cuando el destino sea un solo numero/extensión
congestion
Con yes se reportan todas las llamadas fallidas por causa de congestión. Con no, no se reportan.
endbeforehexten
no = los datos se guardan en el CDR cuando ambos canales se hayan terminado. yes = se guardan antes de la extensión h (si presente).
initiatedseconds
Asterisk para determinar la duración de una llamada realiza un 515
Parámetro
Descripción calculo entre los segundos totales de la llamada menos los segundos desde que la llamada ha sido contestada. Ejemplo: segundos de la llamada 20 – segundos desde que se contestó 10 = tiempo de conversación 10 Esto porque a pesar de que guarde los datos en micro segundos, redondea a los números enteros. Con yes el calculo tendrá en cuenta los micro segundos. Ejemplo: segundos de la llamada 20,222222 – segundos desde que se contestó 10,111111 = tiempo de conversación 10,111111 redondeado = 11 Esto resuelve el desenlace que a veces se encuentra entre la duración de la llamada presente en el CDR y la duración que factura el proveedor VoIP. Valor: yes
batch
no = los datos se guardan en el CDR cada vez que una llamada termine. yes = los datos se guardan en un buffer de memoria y se escriben solamente cuando se alcance el numero o el tiempo definidos en el próximos dos parámetros. Si la PBX va en error o el proceso se termina, los datos en el buffer se perderán. Utilizar con cuidado.
;size=100
cuando en el buffer de memoria se alcancen 100 registros, estos se guardarán en los distintos archivos/base de datos. Se deja comentado.
;time=300
cada cuantos segundos guardar los registros del CDR presentes en el buffer de memoria. Este parámetro tiene prioridad sobre el parámetro size. Se deja comentado.
;scheduleronly=no
si el parámetro size es mayor que 10, este parámetro se pone igual a no. Para un valor inferior a 10 se pone igual a yes. se deja comentado.
;safeshutdown=yes
yes = si se para Asterisk, la PBX antes de cerrarse guardará los registros CDR presentes en el buffer de memoria
[csv]
En este bloque se define como se guardarán los registros CDR en los archivos csv.
usegmtime
no = no se guarda la hora en GMT sino en el huso horario configurado en el servidor
loguniqueid
yes = en el archivo csv se guarda el campo uniqueID
loguserfield
yes = en el archivo csv se guarda el campo userfield
accountlogs
yes = se creará un archivo para cada accountcode configurado en Asterisk.
Se renombra el archivo predefinido: mv /etc/asterisk/cdr.conf /etc/asterisk/cdr.conf.old
516
se crea uno nuevo: nano /etc/asterisk/cdr.conf y se copian las lineas que siguen: [general] enable=yes unanswered=no congestion=no endbeforehexten=no initiatedseconds=yes batch=no ;size=100 ;time=300 ;scheduleronly=no ;safeshutdown=yes [csv] usegmtime=no loguniqueid=yes loguserfield=yes accountlogs=yes Se guardan los cambios y se recarga la configuración de Asterisk: service asterisk reload Se entra en la consola de Asterisk: asterisk -rvvvvvvvvvvvvvvvvvvv y se revisa la configuración con el comando: CLI> cdr show status Call Detail Record (CDR) settings ---------------------------------Logging: Enabled Mode: Simple Log unanswered calls: No Log congestion: No * Registered Backends ------------------mysql Adaptive ODBC 517
cdr-custom csv 20.1.2 cdr_manager.conf Como se ha visto en el párrafo 19.1, en la configuración del los usuarios en el manager.conf, entre los permisos que se pueden configurar, hay el parámetro “cdr” que permite recibir, en la AMI de Asterisk, los eventos relacionados con los registros CDR. Por defecto esta funcionalidad no está activada. Para volverla disponible, se abre el siguiente archivo: nano /etc/asterisk/cdr_manager.conf y se modifica esta linea: enabled=no para que quede: enabled=yes Se guardan los cambios y se reinicia el modulo desde la consola de Asterisk: CLI> module reload cdr_manager.so Si se controla el estado del CDR se notará que la nueva funcionalidad está activada (en negrita): CLI> cdr show status Call Detail Record (CDR) settings ---------------------------------Logging: Enabled Mode: Simple Log unanswered calls: No Log congestion: No * Registered Backends ------------------cdr_manager mysql Adaptive ODBC cdr-custom csv Se puede realizar una prueba entrando en la AMI de asterisk: telnet localhost 5038 518
autenticándose: Action:Login Username:admin Secret:sesamo y efectuando una llamada desde la extensión 1000 a la extensión 1001. Al terminar la llamada, entre los distintos eventos, en la AMI aparecerá: Event: Cdr Privilege: cdr,all Timestamp: 1332542079.937863 AccountCode: 1000 Source: 1000 Destination: 1001 DestinationContext: externas CallerID: "callerid=Fulano" <1000> Channel: SIP/1000-00000008 DestinationChannel: SIP/1001-00000009 LastApplication: Dial LastData: SIP/1001,45,hHkKtTwWxX StartTime: 2012-03-23 17:34:26 AnswerTime: 2012-03-23 17:34:29 EndTime: 2012-03-23 17:34:39 Duration: 13 BillableSeconds: 11 Disposition: ANSWERED AMAFlags: DOCUMENTATION UniqueID: 1332542066.10 UserField: 20.1.3 CDR adaptive Como el modulo cdr-mysql ha sido etiquetado como “deprecated”, pronto ese modulo no estará disponible para la instalación. Para obviar este problema, una solución es utilizar el modulo cdr_adaptive_odbc que permite utilizar el conector ODBC para conectarse a una tabla de una base de datos y guardar los registros de las llamadas. Para probarlo, primero se crea una segunda tabla en la base de datos asteriskcdr: mysql -u root -psesamo mysql> use asteriskcdr mysql> CREATE TABLE cdr2 ( 519
id bigint(20) NOT NULL auto_increment, calldate datetime NOT NULL default '0000-00-00 00:00:00', clid varchar(80) NOT NULL default '', src varchar(80) NOT NULL default '', dst varchar(80) NOT NULL default '', dcontext varchar(80) NOT NULL default '', channel varchar(80) NOT NULL default '', dstchannel varchar(80) NOT NULL default '', lastapp varchar(80) NOT NULL default '', lastdata varchar(80) NOT NULL default '', duration int(11) NOT NULL default '0', billsec int(11) NOT NULL default '0', disposition varchar(45) NOT NULL default '', amaflags int(11) NOT NULL default '0', accountcode varchar(20) NOT NULL default '', peeraccount varchar(20) NOT NULL default '', uniqueid varchar(32) NOT NULL default '', linkedid varchar(80) NOT NULL default '', userfield varchar(255) NOT NULL default '', PRIMARY KEY (`id`), KEY callerid (clid) ); Se sale del cliente MySQL y se configura el odbc.ini: mysql> quit nano /etc/odbc.ini Al final del archivo se añaden las siguientes lineas(si ya no se ha hecho en el párrafo 13.3): [asteriskcdr] Description = MySQL AsteriskCDR Driver = MySQL Database = asteriskcdr Server = localhost User = asterisk Password = sesamo Port = 3306 Option = 3 Se pasa al archivo res_odbc: nano /etc/asterisk/res_odbc.conf y al final del archivo, se copian las siguientes lineas:
520
[asteriskcdr] enabled => yes dsn => asteriskcdr username => asterisk password => sesamo pre-connect => yes sanitysql => select 1 idlecheck => 3600 connect_timeout => 10 Por ultimo se configura el archivo cdr_adaptive_odbc.conf: mv /etc/asterisk/cdr_adaptive_odbc.conf /etc/asterisk/cdr_adaptive_odbc.conf.old se crea uno nuevo: nano /etc/asterisk/cdr_adaptive_odbc.conf y se copian las siguientes lineas: [cdr2] connection=asteriskcdr table=cdr2 alias start => calldate • • • •
[cdr2]: un nombre que se le asigna a la conexión connection=asteriskcdr: en este parámetro hay que poner la etiqueta que define el bloque creado en res_odbc.conf table=cdr2: la tabla MySQL donde se guardarán los datos alias start => calldate: en cdr_adaptive hay tres campos donde se guardan diferentes momentos de la llamada: cuando inicia, cuando se contesta y cuando termina. Los nombres de estos campos son respectivamente start, answer y end. El campo calldate no existe. Por este motivo para que este campo contenga un valor hay que escoger unos de los tres que crea cdr_adaptive. Esto se realiza indicando un alias y definiendo que el campo calldate contendrá el valor del campo start de cdr_adaptive (cuando la llamada inicia).
Se guardan los cambios y se entra en la consola de Asterisk: asterisk -rvvvvvvvvvvvvvvvvv se recarga el moudlo res_odbc y luego el modulo cdr adaptive: CLI> module reload res_odbc.so -- Reloading module 'res_odbc.so' (ODBC resource) == Parsing '/etc/asterisk/res_odbc.conf': == Found NOTICE[27191]: res_odbc.c:1531 odbc_obj_connect: Connecting asterisk 521
NOTICE[27191]: res_odbc.c:1563 odbc_obj_connect: res_odbc: Connected to asterisk [asterisk] NOTICE[27191]: res_odbc.c:920 load_odbc_config: Registered ODBC class 'asterisk' dsn->[asterisk] NOTICE[27191]: res_odbc.c:1531 odbc_obj_connect: Connecting cdr NOTICE[27191]: res_odbc.c:1563 odbc_obj_connect: res_odbc: Connected to cdr [asteriskcdr] NOTICE[27191]: res_odbc.c:920 load_odbc_config: Registered ODBC class 'cdr' dsn->[asteriskcdr] NOTICE[27191]: res_odbc.c:1531 odbc_obj_connect: Connecting asteriskcdr NOTICE[27191]: res_odbc.c:1563 odbc_obj_connect: res_odbc: Connected to asteriskcdr [asteriskcdr] NOTICE[27191]: res_odbc.c:920 load_odbc_config: Registered ODBC class 'asteriskcdr' dsn->[asteriskcdr]
CLI> module reload cdr_adaptive_odbc.so Reloading module 'cdr_adaptive_odbc.so' (Adaptive ODBC CDR backend) == Parsing '/etc/asterisk/cdr_adaptive_odbc.conf': == Found -- Found adaptive CDR table cdr2@asteriskcdr. > Found id column with type -5 with len 19, octetlen 19, and numlen (0,10) -- Found alias start for column calldate in cdr2@asteriskcdr > Found calldate column with type 93 with len 19, octetlen 19, and numlen (0,10) > Found clid column with type 12 with len 80, octetlen 80, and numlen (0,0) > Found src column with type 12 with len 80, octetlen 80, and numlen (0,0) > Found dst column with type 12 with len 80, octetlen 80, and numlen (0,0) > Found dcontext column with type 12 with len 80, octetlen 80, and numlen (0,0) > Found channel column with type 12 with len 80, octetlen 80, and numlen (0,0) > Found dstchannel column with type 12 with len 80, octetlen 80, and numlen (0,0) > Found lastapp column with type 12 with len 80, octetlen 80, and numlen (0,0) > Found lastdata column with type 12 with len 80, octetlen 80, and numlen (0,0) > Found duration column with type 4 with len 10, octetlen 10, and numlen (0,10) > Found billsec column with type 4 with len 10, octetlen 10, and numlen (0,10) > Found disposition column with type 12 with len 45, octetlen 45, and numlen (0,0) > Found amaflags column with type 4 with len 10, octetlen 10, and numlen (0,10) > Found accountcode column with type 12 with len 20, octetlen 20, and numlen (0,0) > Found peeraccount column with type 12 with len 20, octetlen 20, and numlen (0,0) > Found uniqueid column with type 12 with len 32, octetlen 32, and numlen (0,0) > Found linkedid column with type 12 with len 80, octetlen 80, and numlen (0,0) > Found userfield column with type 12 with len 255, octetlen 255, and numlen (0,0) Ahora se puede efectuar una primera prueba. Desde la extensión 1000 se marca a la extensión 1001. Al terminar la llamada, en la consola de Asterisk aparecerá: [INSERT INTO cdr2 (calldate,clid,src,dst,dcontext,channel,dstchannel,lastapp,lastdata,duration,billsec,disposition,amaflag s,accountcode,uniqueid,linkedid) VALUES ({ ts '2012-03-27 15:49:17' },'"callerid=Fulano" <1000>','1000','1001','externas','SIP/1000-0000000f','SIP/100100000010','Dial','SIP/1001,45,hHkKtTwWxX',12,10,'ANSWERED',3,'1000','1332881357.17','13328813 57.17')] Que indica que los datos de la llamada se han guardado en la tabla CDR2. En la tabla:
522
La misma entrada estará en la tabla CDR. Otra cosa que se puede hacer con el modulo CDR Adaptive es filtrar los datos que se van a guardar en la tabla. En el ejemplo que sigue se guardará en una nueva tabla solamente las llamadas originadas por la extensión 1000. mysql -u root -psesamo mysql> use asteriskcdr mysql> CREATE TABLE cdr3 ( id bigint(20) NOT NULL auto_increment, calldate datetime NOT NULL default '0000-00-00 00:00:00', clid varchar(80) NOT NULL default '', src varchar(80) NOT NULL default '', dst varchar(80) NOT NULL default '', dcontext varchar(80) NOT NULL default '', channel varchar(80) NOT NULL default '', dstchannel varchar(80) NOT NULL default '', lastapp varchar(80) NOT NULL default '', lastdata varchar(80) NOT NULL default '', duration int(11) NOT NULL default '0', billsec int(11) NOT NULL default '0', disposition varchar(45) NOT NULL default '', amaflags int(11) NOT NULL default '0', accountcode varchar(20) NOT NULL default '', peeraccount varchar(20) NOT NULL default '', uniqueid varchar(32) NOT NULL default '', linkedid varchar(80) NOT NULL default '', userfield varchar(255) NOT NULL default '', PRIMARY KEY (`id`), KEY callerid (clid) ); Se sale del cliente MySQL: mysql> quit Luego se modifica el archivo cdr_adaptive_odbc.conf:
523
nano /etc/asterisk/cdr_adaptive_odbc.conf Al final del archivo se añade el siguiente bloque: [cdr3] connection=asteriskcdr table=cdr3 alias start => calldate filter src => 1000 •
filter src => 1000: en la tabla se guardarán solamente los registros de las llamadas originadas por la extensión 1000
Se guardan los cambios y se entra en la consola de Asterisk: asterisk -rvvvvvvvvvvvvvvvvvvv En este caso se recarga solamente el modulo CDR adaptive: CLI> module reload cdr_adaptive_odbc.so Con la consola abierta desde la extensión 1001 se llama la extensión 1000. Al finalizar la llamada en la consola aparecerá: > CDR column 'src' with value '1001' does not match filter of '1000'. Cancelling this CDR. Como el campo src tiene como valor 1001 y el filtro se ha creado para el valor 1000, la llamada no se guardará en la tabla CDR3. Si ahora desde la extensión 1000 se llama la extensión 1001: [INSERT INTO cdr3 (calldate,clid,src,dst,dcontext,channel,dstchannel,lastapp,lastdata,duration,billsec,disposition,amaflag s,accountcode,uniqueid,linkedid) VALUES ({ ts '2012-03-27 16:01:52' },'"callerid=Fulano" <1000>','1000','1001','externas','SIP/1000-00000015','SIP/100100000016','Dial','SIP/1001,45,hHkKtTwWxX',11,8,'ANSWERED',3,'1000','1332882112.23','133288211 2.23')] Los datos de la llamada se guardarán en la tabla CDR3 20.2 CEL (Channel Event Logging) Aunque parezca que el CDR responda a todas las necesidades de los administradores de la PBX, tiene unas cuantas limitaciones. Esto porque su lógica se basa en tres eventos principales:
524
• • •
inicio de la llamada duración de la conversación terminación de la llamada
El tiempo que se facturará es la diferencia entre la duración total de la llamada y el duración de la conversación. El problema es que con este tipo de lógica, es muy complicado tener una traza de todos los eventos que se pueden presentar a lo largo de la llamada. Algunos ejemplos: • • • •
transferencia de la llamada a otra extensión transferencia de la llamada a una conferencia parqueo y/o captura de la llamada por otra extensión ejecución de un AGI a lo largo de la llamada.
Todos estos tipos de eventos, dificultan una correcta facturación y seguimiento de llamada. Es por eso que desde la versión 1.8 de Asterisk se ha añadido un nueva funcionalidad: el CEL (Channel Event Logging). El CEL, a diferencia del CDR, basa su lógica sobre el canal de la llamada y va guardando todos los eventos que se van generando desde ese canal. De esta forma es posible tener un registro mucho más detallado de las llamadas. El CEL, en su desarrollo actual, no sustituye el CDR, sin embargo la combinación de los dos permite un control y monitoreo de las llamadas muchos más detallado y completo. En este párrafo se ilustrará la configuración del modulo y como guardar los eventos en una tabla de una base de datos utilizando el conector ODBC. Lo primero es configurar el archivo cel.conf. En la tabla que sigue los distintos parámetros con una descripción. En negrita el valor asignado a cada parámetro.
Parámetro
Descripción
[general]
inicia la parte general de la configuración del archivo
enable
yes = se activa el registro de los eventos del modulo CEL
apps
en este parámetro se especifica la lista de las aplicaciones por las cuales se quiere recibir los eventos. Si se indica “all” se recibirán los eventos de todas las aplicaciones. Utilizar con cuidado ya que puede afectar el rendimiento de la PBX Valor: dial,park,queue,meetme
events
En este parámetro se indica una lista de eventos, separados por una coma, de los que se quieres tener traza Estos son: • ALL: todos • CHAN_START: fecha en que se ha creado el canal • CHAN_END: fecha en que el canal se ha terminado • ANSWER: fecha en que el canal ha sido contestado • HANGUP: fecha en que se ha presentado un Hangup (cierre del canal) • CONF_ENTER: fecha en que un canal ha sido enviado a una
525
Parámetro
Descripción conferencia audio • CONF_EXIT: fecha en que un canal ha salido de una conferencia audio • CONF_START: fecha en que el primer usuario ha entrado a una conferencia • CONF_END: fecha en que el ultimo usuario presente ha dejado una conferencia audio (y posiblemente apagado todas las luces :) • APP_START: fecha en que la aplicación se ha iniciado • APP_END: fecha en que la aplicación ha terminado • PARK_START: fecha en que el canal ha sido parqueado • PARK_END: fecha en que el canal ha sido sacado del “slot” de parqueo • BRIDGE_START: fecha en que el canal ha sido conectado con otro canal • BRIDGE_END: fecha en que ha terminado la conexión con otro canal • 3WAY_START: fecha en que ha iniciado una conferencia a 3 (normalmente con una transferencia asistida) • 3WAY_END: fecha en que una conferencia a 3 ha sido terminada • BLINDTRANSFER: fecha en que ha iniciado una transferencia ciega • ATTENDEDTRANSFER: fecha en que ha iniciado una transferencia asistida • TRANSFER: fecha en que se ha iniciado una transferencia • HOOKFLASH: fecha en que se ha iniciado un “descolgado relampago” en un canal DAHDI (normalmente utilizado para contestar llamadas en espera o para activar la conferencia a 3) • USER_DEFINED: evento personalizado que se puede enviar desde el dialpla a través de la aplicación CELGenUserEvent Para esta prueba se recibirán todos los eventos. Valor: All
dateformat
El formato de la fecha presente por cada evento. Valor: %F %T
[manager]
a partir de esta etiqueta inicia la configuración de CEL para la AMI de Asterisk
enabled
yes = se activa el envío de los eventos a la AMI de Asterisk
Con estos datos, se puede crear el archivo de configuración para CEL. Se renombra el predefinido: mv /etc/asterisk/cel.conf /etc/asterisk/cel.conf.old
526
se crea uno nuevo: nano /etc/asterisk/cel.conf y se añaden las siguientes lineas: [general] enable=yes apps=dial,park,queue,meetme events=all dateformat=%F %T [manager] enabled=yes Se guardan los cambios y se recarga la configuración de Asterisk: service asterisk reload Ahora falta crear la tabla y luego crear una conexión a la misma a través de ODBC. Se entra en cliente mysql: mysql -u root -psesamo Se crea la base de datos, la tabla y el usuario con los permisos: mysql> create database asteriskcel; mysql> use asteriskcel mysql> CREATE TABLE cel( eventtime TIMESTAMP NOT NULL , userdeftype VARCHAR( 255 ) NOT NULL , cid_name VARCHAR( 80 ) NOT NULL , cid_num VARCHAR( 80 ) NOT NULL , cid_ani VARCHAR( 80 ) NOT NULL , cid_rdnis VARCHAR( 80 ) NOT NULL , cid_dnid VARCHAR( 80 ) NOT NULL , exten VARCHAR( 80 ) NOT NULL , context VARCHAR( 80 ) NOT NULL , channame VARCHAR( 80 ) NOT NULL , appname VARCHAR( 80 ) NOT NULL , appdata VARCHAR( 80 ) NOT NULL , accountcode VARCHAR( 20 ) NOT NULL , peeraccount VARCHAR( 20 ) NOT NULL , uniqueid VARCHAR( 150 ) NOT NULL , linkedid VARCHAR( 150 ) NOT NULL , 527
amaflags INT NOT NULL , userfield VARCHAR( 255 ) NOT NULL , peer VARCHAR( 80 ) NOT NULL ); mysql> GRANT ALL PRIVILEGES ON asteriskcel.* TO 'asterisk'@'localhost' IDENTIFIED BY 'sesamo'; Se sale del cliente: mysql> quit Ahora los pasos a seguir son: • • •
Crear uno nuevo bloque en el archvo odbc.ini Crear un nuevo bloque en el archivo res_odbc.conf Configurar el archivo cel_odbc.conf
Se abre el archivo odbc.ini: nano /etc/odbc.ini y al final se añade el siguiente bloque: [asteriskcel] Description = MySQL AsteriskCEL Driver = MySQL Database = asteriskcel Server = localhost User = asterisk Password = sesamo Port = 3306 Option = 3 Se guarda los cambios y se prueba la nueva conexión: isql asteriskcel asterisk sesamo +---------------------------------------+ | Connected! | | | | sql-statement | | help [tablename] | | quit | | | +---------------------------------------+ SQL> quit 528
Se pasa al archivo res_odbc.conf: nano /etc/asterisk/res_odbc.conf se añade el siguiente bloque: [asteriskcel] enabled => yes dsn => asteriskcel username => asterisk password => sesamo pre-connect => yes sanitysql => select 1 idlecheck => 3600 connect_timeout => 10 El valor que aparece en el parámetro dns tiene que ser el mismo con que inicia el bloque que se acaba de configurar en el archivo odbc.ini Por ultimo se modifica el archivo cel_odbc.conf: mv /etc/asterisk/cel_odbc.conf /etc/asterisk/cel_odbc.conf.old nano /etc/asterisk/cel_odbc.conf Se copian las siguientes lineas: [CEL1] connection=asteriskcel table=cel • • •
CEL1:nombre que se quiere asignar a la conexión asteriskcel: tiene que ser el mismo valor con que inicia el bloque que se ha configurado en el archivo res_odbc.conf cel: nombre de la tabla que se ha creado y donde se guardarán los nuevos registros
Se guarda los cambios y se entra en la consola de Asteirsk: asterisk -rvvvvvvvvvvvv Se recarga primero el module res_odbc.so: CLI> module reload res_odbc.so Se averigua que haya conexión con ODBC: 529
CLI> odbc show ODBC DSN Settings ----------------Name: asterisk DSN: asterisk Last connection attempt: 1969-12-31 19:00:00 Pooled: No Connected: Yes Name: cdr DSN: asteriskcdr Last connection attempt: 1969-12-31 19:00:00 Pooled: No Connected: Yes Name: asteriskcdr DSN: asteriskcdr Last connection attempt: 1969-12-31 19:00:00 Pooled: No Connected: Yes Name: asteriskcel DSN: asteriskcel Last connection attempt: 1969-12-31 19:00:00 Pooled: No Connected: Yes Se recarga el modulo cel_odbc.so CLI> module reload cel_odbc.so Ahora desde la extensión 1001 se llama la extensión 1000 y utilizando el botón “Transfer” del softphone 3CX se transfiere la llamada a la conferencia numero 3500. Cuando la extensión 1000 esté en la conferencia, desde la extensión 1001 se marca el mismo numero de conferencia (3500). Una vez que las dos extensiones estén en la conferencia, primero cuelga la 1000 y luego la 1001. El resultado en la tabla CEL será: CLI> quit mysql -u root -psesamo mysql> use asteriskcel mysql> select eventtime,exten,context,channame,appname,appdata,uniqueid,linkedid from cel; 530
20.3 Logger.conf Además de las llamadas, es posible tener traza del funcionamiento de Asterisk (errores, advertencias) en archivos de texto que se guardan en la carpeta /var/log/asterisk. Que tipo de archivos y que tipo de registros se quieren guardar, se define en el archivo logger.conf. En la tabla que sigue los distintos parámetros con una descripción. En negrita el valor asignado a cada parámetro. Parámetro
Descripción
[general]
inicia la parte general de la configuración del archivo
dateformat
formato de la fecha. Predefinido ISO 8601 - %F %T
use_callids
Este parámetro se utiliza para definir si en los eventos se guardará también el CALLERID de cada llamada. Varlor: yes
appendhostname
si se quiere añadir o no al nombre del archivo el nombre del dominio del servidor. Valor no
queue_log
define si se quiere guardar o no las estadísticas de las colas de espera en un archivo. Valor yes
queue_log_name
El nombre del archivo donde guardar las estadísticas de la colas de espera. Valor queue_log
queue_log_to_file
yes = las estadísticas de las colas se siguen guardando en el archivo queue_log aunque estén configuradas en Realtime. 531
Parámetro
Descripción
rotatestrategy
Normalmente los archivos de Log pueden alcanzar un tamaño considerable que dificulta su consulta. Para evitarlo se pueden “rotar” y con este parámetro se define que tipo de rotación se va a utilizar: • secuential – se renombran los archivos siguiendo un orden donde el más reciente tendrá un numero más alto. • rotate – se renombran los archivos siguiendo un orden donde el más viejo tendrá el numero más alto • timestamp – se renombran los archivos añadiendo al nombre la fecha en que se archivaron
[logfiles]
esta etiqueta define el inicio de la configuración de los archivos de registro. Cada archivo puede contener los siguientes valores: • debug • notice • warning • error • verbose • dtmf • fax (desde la versión 1.8 de Asterisk) • security (desde la versión 11 de Asterisk)
debug =>
debug – se crea un archivo donde se guardará solamente el debug de la actividad de Asterisk
verbose =>
verbose – se crea un archivo donde guardar muy en detalle los registros de la actividad de Asterisk
fax =>
fax – se crea un archivo donde se guardarán los registros de actividad del envío/recepción de FAX
console =>
notice,warning,error,debug,dtmf,fax El archivo console no es propiamente un archivo. Se indica que tipo de registros aparecerán en la consola de Asterisk.
messages =>
notice,warning,dtmf En el archivo messages se guardarán solamente los registros relacionados con noticias, advertencias, DTMF y fax
error =>
error En el archivo error se guardarán solamente los errores.
security =>
security,notice En el archivo security se guardarán todos los registros de noticias y seguridad de la PBX. Este archivo es el que leerá Fail2ban para averiguar si se han presentado intentos de acceso no autorizados y de esta forma bloquear la IP de procedencia.
Para crear el nuevo archivo, se renombra el predefinido: mv /etc/asterisk/logger.conf /etc/asterisk/logger.conf.old
532
y se crea uno nuevo: nano /etc/asterisk/logger.conf Se copian las siguientes lineas: [general] dateformat=%F %T use_callids=yes appendhostname=no queue_log=yes queue_log_name=queue_log queue_log_to_file=yes rotatestrategy=rotate [logfiles] debug => debug verbose => verbose fax => fax console => notice,warning,error,debug,dtmf,fax messages => notice,warning,dtmf error => error security => security,notice Se guardan los cambios y se pasa a la definición de las política de rotación de los archivos de registro. Para definir estas políticas hay que instalar el programa Logrotate que se encarga de este tipo de tarea. yum install logrotate -y Una vez instalado se crea un nuevo archivo donde se va a definir la rotación de los archivos de Log de Asterisk: nano /etc/logrotate.d/asterisk Se copian las siguientes líneas: /var/log/asterisk/messages /var/log/asterisk/error /var/log/asterisk/debug /var/log/asterisk/verbose /var/log/asterisk/security { missingok rotate 7 daily postrotate /usr/sbin/asterisk -rx 'logger reload' > /dev/null 2> /dev/null endscript 533
} /var/log/asterisk/queue_log { missingok rotate 5 size=1000k postrotate /usr/sbin/asterisk -rx 'logger reload'> /dev/null 2> /dev/null endscript } El primer bloque define la rotación para los archivos messages, error, debug, verbose y security. La rotación será diaria y se crearán un máximo de 7 archivos secuenciales (archivo.1 archivo.2 , etc.). El más antiguo tendrá el numero secuencial más alto. Después de la rotación (postrotate) se actualiza la configuración del archivo logger.conf en asterisk. El segundo bloque define la política de rotación del archivo de registro queue_log (las estadísticas de las colas de espera). En este caso el archivo rotará cuando alcanzará un tamaño de 1000 Kbyte y se creerán un máximo de 5 archivos secuenciales. Para testar el archivo de configuración creado el procedimiento es: cd /etc/logrotate.d logrotate -fv asterisk Para aplicar los cambios desde la consola de Asterisk: asterisk -rvvvvvvvvvvvvvv se escribe: CLI> logger reload Para ver la configuración del archivo: CLI> logger show channels /var/log/asterisk/security File Enabled - NOTICE SECURITY /var/log/asterisk/error File Enabled - ERROR /var/log/asterisk/messages File Enabled - NOTICE WARNING DTMF Console Enabled - DEBUG NOTICE WARNING ERROR DTMF FAX /var/log/asterisk/fax File Enabled - FAX /var/log/asterisk/verbose File Enabled - VERBOSE /var/log/asterisk/debug File Enabled - DEBUG CLI> quit 534
Se reinicia Asterisk service asterisk restart En la carpeta /var/log/asterisk estarán presentes los archivos configurados en logger.conf y se podrán revisar los errores en el archivo error: nano /var/log/asterisk/error De esta forma en cualquier momento se tendrá bajo control el funcionamiento de Asterisk. 20.3.1 Debug Cuando algo no está funcionando en Asterisk, hay la posibilidad de aumentar el nivel de debug de la consola para buscar el problema que está afectando el funcionamiento de la PBX. Esto se realiza con un comando especifico: asterisk -rvvvvvvvvvvvvvvvvvvvvv CLI> core set debug 9 El nivel de debug va de 0 (ningún debug) a 9 (máximo debug). De esta forma las informaciones que se reciben acerca de las operaciones efectuadas por Asterisk son mucho más detalladas y en la mayoría de los casos permite solucionar el problema. Como en el logger.conf se ha definido que el debug se guardará en el archivo “debug”, ademas de la consola, se puede utilizar este archivo para encontrar eventuales errores. De hecho si se vuelve a desactivar el debug: CLI> core set debug 0 se sale de la consola de Asterisk: CLI> quit y se abre el archivo: nano /var/log/asterisk/debug se verá que ese archivo contiene todo el debug generado desde que se ha activado en la consola. La consulta de estos archivos puede ser bastante complicada ya que se generan una cantidad considerable de registros. Para buscar algo especifico se puede utilizar el programa “cat” junto al programa “grep”. El primero lee un archivo y devuelve su contenido en la ventana terminal de Linux, grep permite buscar una determinada palabra o frase en un archivo. Un ejemplo: 535
cat /var/log/asterisk/debug | grep odbc De esta forma todas la lineas del archivo debug que contengan la palabra odbc aparecerán en la ventana terminal. Si se quiere enviar el resultado a un archivo: cat /var/log/asterisk/debug | grep odbc > odbc En el caso el problema sea con la señalización SIP, desde la consola se puede activar el debug de este protocolo con el siguiente comando: asterisk -rvvvvvvvvvvvvvvvvvvvvv CLI> sip set debug on Si se quiere limitar el debug solamente a una determinada extensión, troncal: CLI> sip set debug peer voztovoice Como se ha visto en el párrafo 3.4 , se puede utilizar también la utilidad ngrep. Si el problema está relacionado con el audio (no hay audio en ambos canales o solamente uno) se puede utilizar el siguiente comando: CLI> rtp set debug on Este comando no es muy selectivo; es mucho mejor activarlo solamente para la IP del dispositivo que está teniendo problemas: CLI> rtp set debug ip 1.2.3.4 sustituir 1.2.3.4 con la IP del dispositivo. Para la calidad de las llamadas se utiliza el siguiente comando: CLI> rtcp set debug on a lo largo de una llamada se verán en la consola de Asterisk unos paquetes donde estarán presentes muchos datos relacionados con la llamada. Un ejemplo: * Sending RTCP RR to 186.112.196.77:10938 Our SSRC: 1887540840 Their SSRC: 4278190079 iFraction lost: 11 Cumulative loss: 8 IA jitter: 0.0000 Their last SR: 0 536
DLSR: 2184.3450 (sec) * Sent RTCP SR to 186.112.196.77:10941 Our SSRC: 2045970199 Sent(NTP): 1410402440.1427103744 Sent(RTP): 40000 Sent packets: 250 Sent octets: 40000 Report block: Fraction lost: 2 Cumulative loss: 2 IA jitter: 0.0013 Their last SR: 0 DLSR: 2184.3480 (sec) Se profundizará el tema el en capitulo 22
537
Capitulo XXI Seguridad en Asterisk 21.1 Reglas de oro Hay unas reglas de oro que se necesita seguir en la configuración de Asterisk. Estas reglas permiten mejorar la seguridad de la PBX y evitar ataques exitosos: 1. utilizar siempre contraseñas bastantes largas y difíciles de memorizar. 2. no utilizar la misma contraseña para todas las extensiones 3. no aceptar llamadas entrantes de invitados. Esto se configura con el parámetro allowguest=no en la parte general del sip.conf. Si se decide aceptar llamadas entrantes de invitados (sin autentificación), el contexto definido en la parte general del sip.conf no debe permitir el acceso a troncales SIP y/o lineas telefónicas tradicionales. 4. configurar en la parte general del sip.conf el parámetro alwaysauthreject=yes. De esta forma cualquier intento de registro sin éxito a extensiones existentes en la centralita, recibirá como respuesta que la extensión no existe, evitando dar trazas al atacante 5. No permitir el acceso al AMI de Asterisk desde remoto (teniendo cerrado el puerto 5038 TCP del servidor Linux. En el caso que se necesite utilizar el AMI desde remoto, configurar Iptables de modo que acepte el trafico solo desde determinadas direcciones IP. Un ejemplo es esta linea: -A INPUT -p tcp -m state --state NEW -m tcp --dport 5038 -s 192.168.142.200 -j ACCEPT Con esta linea se podrá conectar desde remoto al AMI de Asterisk solamente la maquina con IP 192.168.142.200. Otra forma es utilizar el protocolo TLS. 6. Utilizar números o nombres de extensiones largos y no fácilmente memorizables. 7. Utilizar las funciones GROUP y GRUP_COUNT para limitar las llamadas salientes de las extensiones. Ademas de estas 7 reglas, es posible instalar en el servidor Asterisk Fail2Ban., un programa que lee los registros de Asterisk del archivo /var/log/asterisk/messages y si hay un numero determinado de intentos de conexión sin éxito, bloquea la IP de donde se han originados, interactuando con iptables (cortafuegos). 21.2 Fail2ban Se descarga el programa: cd /usr/src wget https://github.com/fail2ban/fail2ban/archive/0.8.14.tar.gz se descomprime: tar -xf 0.8.14.tar.gz se entra en la carpeta creada:
cd fail2ban-0.8.14 y se instala: python setup.py install Se activa el script para el arranque como servicio: cp /usr/src/fail2ban-0.8.14/files/redhat-initd /etc/init.d/fail2ban chkconfig --add fail2ban chkconfig fail2ban on Se configura para que lea los registros de Asterisk: cd /etc/fail2ban/filter.d nano asterisk.conf La configuración presente es más que suficiente pero si se quiere se puede modificar. Se guardan los cambios y se termina modificando el archivo de configuración general de fail2ban: cd /etc/fail2ban nano jail.conf al final del archivo se añaden las lineas que siguen: [asterisk-iptables] enabled = true filter = asterisk action = iptables-allports[name=ASTERISK, protocol=all] sendmail-whois[name=ASTERISK, dest=root@localhost, [email protected]]
logpath = /var/log/asterisk/security maxretry = 5 bantime = 1800 En la línea logpath aparece el archivo de registros que fail2ban leerá para averiguar intentos frustrados de conexión a Asterisk. En la configuración hay que modificar la dirección de correo electrónico. En lugar de root@localhost se pone la dirección de correo electrónico donde se quiere recibir las notificaciones. En sender, en lugar de [email protected] se pone fail2ban@nombrededominio del servidor donde está instalado Asterisk. Para enviar los correos, fail2ban está configurado con Sendmail. Con esta configuración cuando se verifiquen 5 ataques del mismo tipo procedentes de la misma IP, Fail2ban bloqueará el IP insertando una nueva linea en el archivo de configuración de Iptables y la mantendrá bloqueada por 1800 segundos. 540
Para que funcione hay que averiguar que en el archivo de configuración de Asterisk nano /etc/asterisk/logger.conf este presente una linea que cree un archivo security que contiene los registros de noticias y seguridad. security => security,notice Se inicia fail2ban: /etc/init.d/fail2ban start Starting fail2ban: [ OK ] IMPORTANTE: cada vez que se reinicie Iptables, hay que reiniciar también el servicio de Fail2Ban: service iptables restart – service fail2ban restart Se averigua que no haya errores en el log de fail2ban: tail -f /var/log/fail2ban.log Si se quiere efectuar una prueba se configura en X-lite una extensión que no existe en el sistema y se intenta registrarla a Asterisk:
La IP de donde se está intentando registrarse será bloqueada. Accediendo a la consola del servidor remoto desde otra dirección IP con el comando: iptables -L se verá la IP bloqueada:
Desde el log de fail2ban:
541
Si por error se bloquea la IP del propio computador, la única forma de quitar el bloqueo es parar y reiniciar Iptables o reiniciar el servidor Linux. 21.3 Bloquear IP por países Normalmente las extensiones configuradas en la centralita son casi siempre de una determinada aérea geográfica o, de todas formas, siempre habrán países desde donde no se esperarán conexiones a la PBX. En estos caso, para mejorar la seguridad de Asterisk, es posible bloquear todas la IP de un determinado país y de esta forma evitar que se presenten ataques procedentes del país mismo. Este tipo de solución se apoya a una base de datos que contiene todas las IP del mundo, divididas por países, y Xtables-addons que contiene una serie de módulos adicionales para IPtables entre los cuales se encuentra él que permite interactuar con la base de datos. Los requerimientos para este tipo de instalación son: • • •
iptables >= 1.4.3 kernel-source >= 2.6.29 Perl
Primero se instalan algunos paquetes necesarios para la compilación de Xtables-addons: yum install xz iptables-devel zip unzip -y Para instalar el paquete perl-Text-CSV_XS se necesita tener los repositorios epel: cd /usr/src rpm -ivh http://ftp.rediris.es/mirror/fedora-epel/6/x86_64/epel-release-6-8.noarch.rpm Por defecto se desactiva. Se activará solamente cuando se necesiten instalar determinados paquetes: nano /etc/yum.repos.d/epel.repo se modifica en el primer bloque esta linea: enabled=1 542
para que quede: enabled=0 Ahora se instala el paquete activando el repositorio: yum --enablerepo=epel install perl-Text-CSV_XS -y La primera vez que se utiliza, aparecerà: warning: rpmts_HdrFromFdno: Header V3 RSA/SHA256 Signature, key ID 0608b895: NOKEY Retrieving key from file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6 Importing GPG key 0x0608B895: Userid : EPEL (6) Package: epel-release-6-7.noarch (installed) From : /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6 Is this ok [y/N]: y Se continua aceptando la clave del repositorio y luego se descargan las fuentes de Xtables-addons: cd /usr/src wget http://downloads.sourceforge.net/project/xtables-addons/Xtables-addons/1.47/xtables-addons-1.47.1.tar.xz
Se descomprime: tar -xf xtables-addons-1.47.1.tar.xz Se entra en la carpeta creada, se compila e instala: cd xtables-addons-1.47.1 ./configure --prefix=/usr --libdir=/usr/lib64 make si a lo largo del make aparece este error: /usr/src/xtables-addons-1.47.1/extensions/compat_xtables.c: En la función 'xtnu_ipv6_find_hdr': /usr/src/xtables-addons-1.47.1/extensions/compat_xtables.c:633: error: faltan argumentos para la función 'ipv6_find_hdr' make[4]: *** [/usr/src/xtables-addons-1.47.1/extensions/compat_xtables.o] Error 1 make[3]: *** [_module_/usr/src/xtables-addons-1.47.1/extensions] Error 2 make[3]: se sale del directorio `/usr/src/kernels/2.6.32-431.11.2.el6.x86_64' make[2]: *** [modules] Error 2 make[2]: se sale del directorio `/usr/src/xtables-addons-1.47.1/extensions' make[1]: *** [all-recursive] Error 1 make[1]: se sale del directorio `/usr/src/xtables-addons-1.47.1' 543
make: *** [all] Error 2 se corrige: nano /lib/modules/2.6.32-504.12.2.el6.x86_64/build/include/linux/autoconf.h se modifica esta linea: #define CONFIG_IP6_NF_IPTABLES_MODULE 1 para dejarla comentada: /* #define CONFIG_IP6_NF_IPTABLES_MODULE 1 */ Se guardan los cambios y se reinicia con la compilación: ./configure --prefix=/usr --libdir=/usr/lib64 make make install Se entra en la carpeta donde están presentes los script que permiten descargar la base de datos de GeoIP: cd geoip Se descarga la base de datos en formato CSV: ./xt_geoip_dl Desde la base de datos se crean los archivos de las IP por países: ./xt_geoip_build GeoIPCountryWhois.csv El resultado será la creación de dos carpetas que contienen las IP por países en el formato que IPtables puede leer. Se crea la carpeta predefinida donde IPtables buscará las IP: mkdir -p /usr/share/xt_geoip/ y se copian las dos carpetas: cp -r {BE,LE} /usr/share/xt_geoip/ Para bloquear las direcciones IP de un determinado país en IPtables, la sintaxis es: -A INPUT -m geoip --src-cc CN -j DROP CN es la sigla del país (en este caso China) 544
Se puede realizar una prueba bloqueando todas las IP de su proprio País (en este caso Colombia) para el puerto 5060. Se abre el archivo de configuración de IPtables: nano /etc/sysconfig/iptables antes de esta linea: -A INPUT -p udp -m udp --dport 5060 -j ACCEPT se pone: -A INPUT -p udp --dport 5060 -m geoip --src-cc CO -j DROP Personalizar con la sigla de su país. Se guardan las modificaciones y se reinicia IPtables: service iptables restart service fail2ban restart Ahora se intenta conectarse a Asterisk con las credenciales de unos de las extensiones configuradas en sip.conf. El registro no funcionará y en IPtables se verá, en la linea que se acaba de crear, que todos los paquetes han sidos rechazados iptables -L -v
Si se quiere invertir la configuración, es decir aceptar conexiones solamente desde Colombia, la linea cambiaría de: -A INPUT -p udp --dport 5060 -m geoip --src-cc CO -j DROP a -A INPUT -p udp --dport 5060 -m geoip --src-cc CO -j ACCEPT Claramente esto si los clientes y los proveedores VoIP son solamente de Colombia. En el caso que el proveedor VoIP sea de otro país (ejemplo Estados Unidos) habría que añadir otra linea después de la de 545
Colombia: -A INPUT -p udp --dport 5060 -m geoip --src-cc US -j ACCEPT Si se quiere actualizar la lista de las IP de GeoIP de forma automática cada primer día del mes: cd /root nano .bash_profile Al final del archivo se añade: export EDITOR=/usr/bin/nano Se guardan los cambios y se recarga la configuración de la shell bash: source .bash_profile Se crea el script en bash: nano /home/geoip.sh se copian las siguientes lineas: #!/bin/bash /usr/src/xtables-addons-1.43/geoip/xt_geoip_dl /usr/src/xtables-addons-1.43/geoip/xt_geoip_build GeoIPCountryWhois.csv \cp -rf {BE,LE} /usr/share/xt_geoip/ /etc/init.d/iptables restart /etc/init.d/fail2ban restart Se guardan los cambios y se vuelve ejecutable el archivo creado: chmod +x /home/geoip.sh Se configura un cronjob para que ejecute el script cada primer día del mes: crontab -e se añade la siguiente linea: 0 0 1 * * /home/geoip.sh
546
Se guardan los cambios. Si se quiere efectuar una prueba para ver si todo funciona como esperado: /home/geoip.sh que terminará con: iptables: Flushing firewall rules: [ OK ] iptables: Setting chains to policy ACCEPT: filter [ OK ] iptables: Unloading modules: [ OK ] iptables: Applying firewall rules: [ OK ] Stopping fail2ban: [ OK ] Starting fail2ban: [ OK ]
547
Capitulo XXII Monitorear Asterisk En este capitulo se ilustrará como monitorear Asterisk y el servidor Linux a través de dos distintos programas: • •
Monit Nagios y el protocolo SNMP
Se ilustrará también como monitorear la calidad de las llamadas desde la consola de Asterisk, guardando las estadísticas en una base de datos y a través del programa VoIPmonitor. Para terminar se mostrará como acceder a todas las estadísticas de las llamadas a través del programa CDR-STATS. 22.1 Monit Monit es un programa Open Source para la gestión y el monitoreo de procesos, programas, archivos, carpetas y particiones de un sistema Linux. Permite programar tareas de mantenimiento y de corrección de errores cuando se verifiquen problemas en el sistema. Se instala desde las fuentes: cd /usr/src wget http://mmonit.com/monit/dist/monit-5.12.2.tar.gz tar -xf monit-5.12.1.tar.gz cd monit-5.12.2 Se compila y se instala: ./configure --prefix=/usr --libdir=/usr/lib64 make make install Se termina la instalación con la copia y activación del script de inicio de monit: cd system/startup/ cp rc.monit /etc/init.d/monit chmod +x /etc/init.d/monit
chkconfig --add monit chkconfig monit on Ahora se modifica el archivo de configuración para monitorear los siguientes programas: • • • •
Sendmail MySQL Asterisk la troncal VozToVoice
El archivo de configuración de Monit se divide en tres bloques: • • •
Global Section; aquí se pone la configuración general del programa Services; donde se configuran los servicios Includes: permite incluir a la configuración de Monit otros archivo que contienen a su vez la configuración de otros procesos.
nano /etc/monitrc set daemon 60 # Indica cada cuantos segundos Monit controla los servicios (en este caso cada 60) with start delay 30 # Al iniciar el programa el primer ciclo de control se ejecutará después de 30 segundos set logfile /var/log/monit.log # Nombre del archivo donde se guardarán todos los registros de Monit set pidfile /var/run/monit.pid # Carpeta y nombre del del archivo del proceso de Monit cuando se inicia set idfile /var/.monit.id # Nombre de la carpeta y archivo donde se guardará el numero único del proceso de Monit set statefile /var/.monit.state # Carpeta y nombre del archivo donde Monit guardará el estado de cada ciclo de monitoreo set mailserver localhost # nombre del host del servidor de correo electrónico que Monit utilizará para enviar las alertas set eventqueue basedir /var/monit slots 100 # Si por alguna razón el servidor de correo electrónico no esté funcionando se puede indicar a Monit de # guardar todas las alerta en una determinada carpeta. Cuando el servidor volverá a funcionar, todas las # alertas serán enviadas siguiendo el orden cronológico en que se guardaron 550
set mail-format { From: [email protected] Subject: monit alerta -- $EVENT $SERVICE Message: $EVENT Servicio $SERVICE Fecha: $DATE Accion: $ACTION Host: $HOST Descripcion: $DESCRIPTION Tu devoto empleado, Monit } # Con el bloque de arriba, se define como tiene que ser enviado el correo electrónico de alerta # Personalizar el parámetro from set alert [email protected] # Con esta línea se define el correo electrónico que recibirá todas las alertas (personalizar) set httpd port 2812 allow admin:sesamo # Monit viene con un servidor Web embebido. En las dos lineas de arriba se activa en el puerto 2812 # (que hay que abrir en el cortafuegos) y se define nombre de usuario y contraseña para ingresar a la # pagina # Monitoreo Servidor Linux check system cursoasterisk.org if loadavg (1min) > 4 then alert if loadavg (5min) > 2 then alert if memory usage > 75% then alert if cpu usage (user) > 70% then alert if cpu usage (system) > 30% then alert if cpu usage (wait) > 20% then alert # Monitoreo Asterisk check process asterisk with pidfile /var/run/asterisk/asterisk.pid start program = "/etc/init.d/asterisk start" with timeout 60 seconds stop program = "/etc/init.d/asterisk stop" with timeout 60 seconds if failed host 127.0.0.1 port 5038 then restart if 5 restarts within 5 cycles then timeout # Monitoreo Troncal SIP check host VozToVoice with address sip.voztovoice.eu if failed port 5060 type udp protocol SIP and target sip.voztovoice.eu maxforward 10 then alert 551
# Monitoreo SendMail check process sendmail with pidfile /var/run/sendmail.pid group mail start program = "/etc/init.d/sendmail start" stop program = "/etc/init.d/sendmail stop" if failed port 25 protocol smtp then restart if 5 restarts within 5 cycles then timeout # Monitoreo MySQL check process mysql with pidfile /var/run/mysqld/mysqld.pid group database start program = "/etc/init.d/mysqld start" stop program = "/etc/init.d/mysqld stop" if failed port 3306 protocol mysql then restart if 5 restarts within 5 cycles then timeout Una explicación. Monit averiguará cada 60 segundos que los cuatro servicios estén corriendo. Si por alguna razón unos de los servicios se cae, Monit intentará iniciarlo nuevamente por 5 veces. Si no lo lograra, dejará de monitorear el servicio. Se guardan los cambios y se cambian los permisos del archivo de configuración: chmod 700 /etc/monitrc Se inicia Monit: /etc/init.d/monit start En el cortafuegos, hay que abrir el puerto 2812 TCP para tener acceso al servidor Web interno de Monit: nano /etc/sysconfig/iptables antes de este bloque: # DUNDi -A INPUT -p udp -m udp --dport 4520 -j ACCEPT se añade: # Monit -A INPUT -p tcp -m state --state NEW -m tcp --dport 2812 -j ACCEPT Se guardan los cambios y se reinicia iptables y fail2ban: service iptables restart service fail2ban restart 552
Después de unos minutos se puede acceder a la pagina de administración de Monit: http://IPservidor:2812
Nombre de usuario: admin Contraseña: sesamo Una vez entrados en la Web de Monit, el pagina principal aparecerán todos los procesos/programas monitoreados:
y en el caso del servidor Linux:
553
Cualquier problema se presente con el servidor y/o con los procesos/programas configurados, se recibirá una notificación al correo electrónico configurado. Se puede realizar una prueba parando Asterisk: service asterisk stop Después de 60 segundos (el intervalo en que Monit controla todos los procesos, en la pagina del servicio de Asterisk aparecerá:
554
Como Monit se da cuenta que Asterisk se ha caído, intenta reiniciarlo. De hecho ya se puede acceder nuevamente a la consola: asterisk -rvvvvvvvvvvvvvv y se recibirán tres correos electrónicos notificando los cambios. Uno de ellos:
22.2 SNMP Una definición del protocolo SNMP tomada de Wikipedia: “El Protocolo Simple de Administración de Red o SNMP es un protocolo de la capa de aplicación que facilita el intercambio de información de administración entre dispositivos de red. Es parte de la familia de protocolos TCP/IP. SNMP permite a los administradores supervisar el funcionamiento de la red, buscar y resolver sus problemas, y planear su crecimiento.” De hecho a través de este protocolo se monitorean servidores, router, switch y casi cualquier tipo de dispositivo conectado a la red (local o remota). Asterisk implementa el protocolo SNMP y, a través de ese protocolo, es posible monitorear muchos parámetros de la PBX. Para empezar se averigua si el modulo res_snmp está instalado y cargado en Asterisk: asterisk -rvvvvvvvvvvvvvvv CLI> module show like snmp
Significa que el modulo está instalado. Se sale de la consola de Asterisk:
555
CLI> quit Se configura el modulo: mv /etc/asterisk/res_snmp.conf /etc/asterisk/res_snmp.conf.old nano /etc/asterisk/res_snmp.conf Se añaden las siguientes lineas: [general] subagent = yes enabled = yes Se guardan los cambios y se descargan los OID de Asterisk en la carpeta de SNMP. Un OID (identificador de objeto) es una cadena alfanumérica que se utiliza para identificar de forma única un objeto que en el caso del protocolo SNMP representa un determinado parámetro del dispositivo que se quiere monitorear. Ejemplo: se puede conocer el numero de llamadas totales cursadas por la centralita desde su ultimo arranque. cd /usr/share/snmp/mibs wget http://www.voztovoice.org/tmp/asterisk-mib.txt wget http://www.voztovoice.org/tmp/digium-mib.txt Ahora se configura SNMP de modo que pueda interaccionar con Asterisk: cd /etc/snmp Se renombra el archivo de configuración predefinido: mv snmpd.conf snmpd.conf.old y se crea uno nuevo: nano snmpd.conf donde se ponen las siguientes líneas: master agentx agentXPerms 0660 0550 root root com2sec local localhost public com2sec remote XXX.XXX.XXX.XXX public group asterisk v1 local group asterisk v2c local 556
group NetWork v1 remote group NetWork v2c remote view all included .1 access asterisk "" any noauth exact all none none access NetWork "" any noauth exact all none none Una explicación. Primero se define el agente y los permisos de acceso. Luego se definen dos comunidades. Una tiene acceso local y otra remoto (útil si se quiere efectuar consultas desde otro servidor). Hay que sustituir XXX.XXX.XXX.XXX con la IP del servidor remoto. Luego se definen dos grupos y que tipo de consultas pueden realizar (en este caso SNMP versión 1 y versión 2c. Se define el tipo de objetos que pueden consultar (en este caso todos) y los permisos que cada grupo tiene. Se guardan los cambios y se reinicia Asterisk: /etc/init.d/asterisk restart se inicia snmp: /etc/init.d/snmpd start se vuelve el arranque automático: chkconfig snmpd on Para ver los resultados con la descripción de los OID en lugar de los números de los objetos: export MIBS=all Ahora ya se puede efecutar una consulta utilizando el OID raíz de Asterisk: snmpwalk -OT -c public -v 2c localhost .1.3.6.1.4.1.22736 De todas las lineas que aparecen, las que interesan son estas tres: ASTERISK-MIB::astChanTypeName.5 = STRING: SIP ASTERISK-MIB::astChanTypeName.7 = STRING: IAX2 ASTERISK-MIB::astChanTypeName.8 = STRING: DAHDI Se anotan los valores que aparecen en negrita y el tipo de canal asociado, es decir: SIP 5 IAX2 7 DAHDI 8 Se pasa a la instalación y configuración de Nagios. 557
22.3 Nagios Para la instalación de Nagios se utiliza el repositorio Epel. Para ver los paquetes disponibles: yum --enablerepo=epel search nagios Se instalan los siguientes paquetes (el programa, los plugins, una utilidad para guardar los registros de Nagios en una base de datos, unas librerías en Perl para utilizar el protocolo XMPP par las notificaciones, una aplicación para el envío de los correo electrónicos desde Nagios utilizando una linea de comando): yum --enablerepo=epel install nagios nagios-plugins-all perl-Net-Jabber \ perl-IO-Socket-SSL ndoutils mailx ndoutils-mysql -y CentOS se hará cargo de instalar también todas las dependencias necesarias. Se creará el grupo y usuario Nagios, unas carpetas donde se guardarán los registros y los archivo necesarios para que Nagios funcione, un archivo para la integración con el servidor Web (apache). Una vez terminada la instalación, se empieza con la configuración de Nagios. El archivo principal donde se definen los parámetros para el programa es nagios.cfg y se encuentra en la carpeta /etc/nagios. Para este tipo de instalación no hace falta realizar algún tipo de modifica es ese archivo. Los archivos de configuración de Nagios que hay que modificar son los siguientes y se encuentran en la carpeta /etc/nagios/objects: • • • •
commands.cfg localhost.cfg contact.cfg template.cfg
Se inicia con contact.cfg: nano /etc/nagios/objects/contacts.cfg En este archivo se cambian estas líneas: define contact{ contact_name nagiosadmin use generic-contact alias Nagios Admin email nagios@localhost } 558
para que queden: define contact{ contact_name nagiosadmin use generic-contact alias Nagios Administrador email [email protected] address1 fulano } [email protected] es la dirección de correo electrónico donde Nagios enviará las notificaciones (personalizar). Address1 es el usuario GoogleTalk donde Nagios enviará las notificaciones vía mensaje instantáneo. Nagiosadmin es el nombre del administrador predefinido en Nagios. Cada vez que aparece una línea que empieza con “use”, hace referencia a un template definido en el archivo templates.cfg. Se guardan los cambios y se abre el archivo templates.cfg. En este archivo el bloque del genericcontact es: nano /etc/nagios/objects/templates.cfg define contact{ name generic-contact service_notification_period 24x7 host_notification_period 24x7 service_notification_options w,u,c,r,f,s host_notification_options d,u,r,f,s service_notification_commands notify-service-by-email,notify-service-jabber host_notification_commands notify-host-by-email,notify-host-jabber register 0 } En este bloque se añaden las dos partes en negrita. Esto para enviar las notificaciones también vía GoogleTalk. Hay una explicación de estos parámetros en la documentación oficial de Nagios 3.0 En el servidor hay servicios que no son críticos y que se pueden monitorear cada 5 minutos (el tiempo predefinido en Nagios). Para Asterisk, a veces, estos cinco minutos pueden ser demasiados. Por eso al final del archivo se añade el siguiente bloque que define que para todos los servicios de Asterisk el control se efectuará cada 2 minutos (se puede personalizar): define service{ name asterisk use generic-service max_check_attempts 4 normal_check_interval 2 559
retry_check_interval 1 register 0 } Ahora se modifica el tercer archivo (commands.cfg) donde se definen los comandos que luego se utilizarán para la configuración del monitoreo del servidor local. Los plugins de Nagios se instalan en /usr/lib/nagios/plugins. Para monitorear Asterisk, se usará el plugin check_snmp y otro que se descargará. Para monitorear las troncales, se descargará un plugin del repositorio de Nagios y por ultimo, para enviar las notificaciones via GoogleTalk se descargará otro plugin. Se entra en la carpeta /usr/lib/nagios/plugins y se descargan los plugin que hacen falta: cd /usr/lib64/nagios/plugins wget http://www.voztovoice.org/campus/a2b/check_asterisk_peers wget http://www.voztovoice.org/campus/a2b/notify_via_jabber.pl wget http://www.voztovoice.org/campus/a2b/check_asterisk.pl Se cambian los permisos para que se pueda ejecutar: chmod +x check_asterisk_peers chmod +x notify_via_jabber.pl chmod +x check_asterisk.pl Notify_via_jabber.pl es el único que tiene que ser modificado. Se abre: nano notify_via_jabber.pl se modifican estas dos lineas: my $username = "usuarioGoogleTalk"; my $password = "password"; para que queden: my $username = "sutano"; my $password = "password"; sutano es el usuario googletalk y password su contraseña (no hace falta poner @gmail.com). Una paréntesis. El plugin funciona de la siguiente manera. En este archivo se configura el usuario de GoogleTalk que enviará las notificaciones. El usuario configurado en el contact.cfg serà él que las recibe siempre y cuando añadirá el usuario configurado en el plugin en su lista de amigos. Esto quiere decir que para que el sistema funcione se necesita tener dos cuentas de GoogleTalk. Para conocer la sintaxis de un plugin de Nagios el comando es:
560
cd /usr/lib/nagios/plugins ./check_snmp -h Para añadir los comandos en Nagios se modifica el archivo commands.cfg nano /etc/nagios/objects/commands.cfg Primero se configura el comando para enviar las notificaciones vía mensaje instantáneo. Esto se hace para los servidores (en este caso uno) y los servicios. Después del bloque notify-service-by-email se añade: # 'host-notify-by-jabber' command definition define command{ command_name notify-host-jabber command_line /usr/lib64/nagios/plugins/notify_via_jabber.pl $CONTACTADDRESS1$ "Host '$HOSTALIAS$' is $HOSTSTATE$ - Info: $HOSTOUTPUT$" } # 'service-notify-by-jabber' command definition define command { command_name notify-service-jabber command_line /usr/lib64/nagios/plugins/notify_via_jabber.pl $CONTACTADDRESS1$ "$NOTIFICATIONTYPE$ $HOSTNAME$ $SERVICEDESC$ $SERVICESTATE$ $SERVICEOUTPUT$ $LONGDATETIME$" } IMPORTANTE: todo lo que aparece en la linea command-line debe estar en la misma linea Se continua con el plugin check_snmp para monitorear Asterisk a través del protocolo SMNP. Se buscan estas lineas: # 'check_snmp' command definition define command{ command_name check_snmp command_line $USER1$/check_snmp -H $HOSTADDRESS$ $ARG1$ } y se modifican para que queden: define command{ command_name check_snmp command_line $USER1$/check_snmp -H $HOSTADDRESS$ -C public -o $ARG1$ -P 2c -l $ARG2$ -w $ARG3$ -c $ARG4$ } 561
IMPORTANTE: todo lo que aparece en la linea command-line debe estar en la misma linea Command name: nombre del comando Command line: los parámetros que se pasarán al comando: • La macro (variable) $USER1$ contiene el valor /usr/lib/nagios/plugins como especificado en el archivo /etc/nagios/resource.cfg • check_snmp – Nombre del plugin • -H $HOSTADDRESS$ – la opción –H define el servidor que se va a consultar y $HOSTADDRESS$ es una macro (variable) predefinida que contiene el nombre del servidor como se definirá luego en localhost.cfg • -C public – es la comunidad que se va a utilizar para la conexión al agente como definido en el archivo /etc/snmp/snmp.conf • -o – la OID que se consultará • -P 2c – versión de SNMP utilizada para la consulta • -l la etiqueta que luego se definirá • -w – está por Warning • -c – está por Critical • $ARG1$ $ARG2$ $ARG3$ ARG4$ son las macros (variables) cuyo valor será asignado desde la configuración de localhost.cfg Al verificarse el evento Warning y/o Critical, Nagios enviará una notificación por correo electrónico y vía mensaje instantáneo. El segundo plugin se define de la siguiente forma (añadir las lineas después del bloque anterior): define command{ command_name check_asterisk command_line $USER1$/check_asterisk.pl -h $HOSTADDRESS$ -m mgr -u nagios -p sesamo } nagios y sesamo indican respectivamente el usuario y la contraseña para conectarse al AMI de Asterisk. Para definirlos, luego hay que modificar el manager.conf de Asterisk: Como el servidor SSH está escuchando en el puerto 15000, se busca este bloque: # 'check_ssh' command definition define command{ command_name check_ssh command_line $USER1$/check_ssh $ARG1$ $HOSTADDRESS$ } y se modifica para que quede:
562
# 'check_ssh' command definition define command{ command_name check_ssh command_line $USER1$/check_ssh -p $ARG1$ $HOSTADDRESS$ } El ultimo plugin que se define en el archivo command.cfg, es el que permite monitorear las troncales: define command{ command_name check_voztovoice command_line sudo /usr/lib64/nagios/plugins/check_asterisk_peers -t sip -p $ARG1$ } Se guardan los cambios. Como se puede ver este plugin se activa con el programa sudo que permite ejecutar un comando con los permisos del usuario root. Esto porque el programa Nagios se inicia con usuario nagios y ese usuario no tiene los permisos para ejecutar el plugin. Para que pueda hacerlo hay que modificar el archivo sudousers que es donde se definen los usuarios que pueden ejecutar comandos con los permisos de root: visudo primero se modifica esta linea: Defaults
requiretty
para que quede: # Defaults
requiretty
luego se añade al final del archivo: nagios ALL=(ALL) NOPASSWD: /usr/lib64/nagios/plugins/check_asterisk_peers Se guardan los cambios. Como se había dicho el plugin check_asterisk.pl funciona conectándose a la AMI de Asterisk. Para que funcione hay que modificar el archivo manager.conf de Asterisk: nano /etc/asterisk/manager.conf Al final del archivo se añade: [nagios] secret = sesamo deny=0.0.0.0/0.0.0.0 563
permit=127.0.0.1/255.255.255.255 read=system,call,agent,user,dtmf,reporting,cdr,dialplan,agi,cc write=system,call,agent,user,config,command,reporting,otiginate,agi Se guardan los cambios y se actualiza la configuración de Asterisk: /etc/init.d/asterisk reload Para terminar la configuración de Nagios se modifica el archivo localhost.cfg donde se realizará la configuración del monitoreo del servidor Linux. Se mueve el predefinido: mv /etc/nagios/objects/localhost.cfg /etc/nagios/objects/localhost.cfg.old se crea uno nuevo: nano /etc/nagios/objects/localhost.cfg Se añaden las siguientes lineas: define host{ use linux-server host_name LibroAsterisk alias LibroAsterisk address 127.0.0.1 } define service{ use asterisk host_name LibroAsterisk service_description SIP check_command check_snmp!ASTERISK-MIB::astChanTypeChannels.5!"Canales SIP Activos"!8!16
} Si los canales SIP activos son más de 8 se recibirá un WARNING, si son mas de 16 un CRITICAL. Se continua copiando las lineas que siguen: define service{ use asterisk host_name LibroAsterisk service_description IAX2 check_command check_snmp!ASTERISK-MIB::astChanTypeChannels.7!"Canales IAX2 Activos"!4!8
} define service{ use asterisk host_name LibroAsterisk 564
service_description DAHDI check_command check_snmp!ASTERISK-MIB::astChanTypeChannels.8!"Canales DAHDI Activos"!4!8
} define service{ use asterisk host_name LibroAsterisk service_description Asterisk_check check_command check_asterisk } define service{ use asterisk host_name LibroAsterisk service_description Troncal_VozToVoice check_command check_voztovoice!voztovoice } Una pequeña explicación. En el primer bloque se define el nombre del servidor, un alias y la dirección IP (en este caso siendo Nagios y Asterisk instalados en el mismo servidor se indica 127.0.0.1 o localhost). En los tres bloques que siguen se controla a través del plugin check_snmp, los canales SIP, IAX2 y DAHDI activos. Se asignan a las cuatros macros (variables), que se han visto al momento de la configuración del comando ($ARG1$ $ARG2$ $ARG3$ ARG4$), los respectivos valores separados por el caracter ! Las OID se toman interrogando Asterisk con SNMP como hemos visto en el párrafo anterior. En el bloque que sigue se utiliza el plugin check_asterisk.pl y a través del AMI de Asterisk se controla que esté corriendo. El ultimo bloque se utilizan para monitorear la troncal SIP VozToVoice. En la segunda linea de cada bloque aparece el parámetro “use asterisk” que representa el template (la plantilla) configurada en templates.cfg que se utiliza para estos comandos. Si se quiere controlar también algunos servicios básicos del servidor (usuarios, procesos, carga, etc…), se añaden estas líneas: define service{ use local-service host_name LibroAsterisk service_description PING check_command check_ping!100.0,20%!500.0,60% } define service{ use local-service 565
host_name LibroAsterisk service_description Current Users check_command check_local_users!20!50 } define service{ use local-service host_name LibroAsterisk service_description Total Processes check_command check_local_procs!250!400!RSZDT } define service{ use local-service host_name LibroAsterisk service_description Current Load check_command check_local_load!5.0,4.0,3.0!10.0,6.0,4.0 } define service{ use local-service host_name LibroAsterisk service_description SSH check_command check_ssh!15000 } Antes de iniciar Nagios hay una forma para controlar que todos los archivos de configuración estén exentes de errores: nagios -v /etc/nagios/nagios.cfg Si la respuesta termina con: Total Warnings: 0 Total Errors: 0 Things look okay - No serious problems were detected during the pre-flight check Significa que la configuración está bien. En caso contrario Nagios indicará el archivo y la línea donde se encuentra el error. El acceso a la pagina Web de administración de Nagios está protegido y para poder acceder hay que configurar la contraseña del usuario predefinido, nagiosadmin, de la siguiente forma: htpasswd -bc /etc/nagios/passwd nagiosadmin sesamo Adding password for user nagiosadmin Este comando creará una archivo passwd que contendrá los datos de acceso para el usuario predefinido 566
nagiosadmin (en este caso la contraseña es sesamo) Se configuran Nagios para que arranque en automático: chkconfig nagios on Se inicia apache y luego se inicia Nagios: /etc/init.d/httpd start /etc/init.d/nagios start Antes de entrar a la pagina de administración de Nagios, hay que abrir el puerto 80 TCP (servidor WEB) en Iptables: nano /etc/sysconfig/iptables Antes de este bloque: # Monit -A INPUT -p tcp -m state --state NEW -m tcp --dport 2812 -j ACCEPT se añade: # HTTP -A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT Se guardan los cambios y se reinicia Iptables y fail2ban: service iptables restart service fail2ban restart Para entrar en la pagina de Nagios: http://IPservidor/nagios Aparecerá una ventana donde habrá que insertar las credenciales de acceso es decir: usuario: nagiosadmin contraseña: sesamo
567
Se presiona el botón Aceptar. Aparece la pagina inicial de Nagios:
En la derecha se selecciona el enlace Hosts para ver el servidor configurado:
Se selecciona Services para ver los servicios monitoreados:
568
Todos están bien. 22.3.1 NDOutils Para utilizar NDOutils para guardar todos los datos de Nagios en una base de datos MySQL, lo primero que hay que hacer es crear la base de datos: mysql -u root -psesamo mysql> create database nagios; se asigna al usuario nagios los permisos para la base de datos creada: mysql> GRANT ALL PRIVILEGES ON nagios.* TO 'nagios'@'localhost' IDENTIFIED BY 'sesamo'; mysql> flush privileges; mysql> quit Se crean las tablas en la base de datos nagios desde un archivo instalado con el paquete NDOutils: mysql -u root -psesamo nagios < /usr/share/doc/ndoutils-mysql-1.5.2/db/mysql.sql Ahora falta modificar dos archivos de configuración: nagios.cfg y ndo2db.cfg. Primero se modifica nagios.cfg nano /etc/nagios/nagios.cfg al final del archivo se añaden las siguientes lineas: event_broker_options=-1 broker_module=/usr/lib64/nagios/brokers/ndomod.so config_file=/etc/nagios/ndomod.cfg que permiten a Nagios conectarse a la librería de NDOutils y enviar todos los datos de configuración y los eventos: Se guardan los cambios y se continua con el ndo2db.cfg: nano /etc/nagios/ndo2db.cfg Después de estas dos lineas: ndo2db_user=nagios ndo2db_group=nagios 569
se añade: lock_file=/var/log/nagios/ndo2db.lock en db_user y db_password se pone: db_user=nagios db_pass=sesamo se guardan los cambios y se inicia NDOutils: /etc/init.d/ndo2db start Se configura para que arranque en automático: chkconfig ndo2db on y se reinicia Nagios: /etc/init.d/nagios restart se averigua que en el log de Nagios haya conexión con la librería NDOutils: nano /var/log/nagios/nagios.log Las lineas que interesan son:
Con instalado Webmin se puede controlar que las tablas se han ido llenando de nuevas entradas como, por ejemplo, la tabla nagios_commands:
570
Todo está funcionando como debería. Encuentran distintos tipos de consultas de las tablas en la carpeta /usr/share/doc/ndoutils-mysql-1.5.2/db/queries/. 22.3.2 PNP4NAGIOS Seguramente Nagios es un optimo programa para el monitoreo de servidores, switch y dispositivos, Pero le hace falta algo que la mayoría de los programas de monitoreo tienen: los gráficos. Pasa suplir esta falta existe el programa PNP4Nagios. En este párrafo se verá como instalarlo y complementarlo con Nagios. Requisitos previos: • • • •
Perl >= 5.x y los paquetes perl-Time-HiRes rrdtool-perl RRDtool >= 1.x, mejor 1.2 pero no obligatorio PHP >= 5.1.6 para el frontal web basado en Kohana Nagios >= 2.x o Icinga
Kohana necesita que el módulo de Apache “mod_rewrite” esté habilitado. Se instala el paquete perl-Time-HiRes: yum install perl-Time-HiRes rrdtool-perl perl-ExtUtils-MakeMaker -y RRDtool se instala desde las fuentes: cd /usr/src wget http://oss.oetiker.ch/rrdtool/pub/rrdtool-1.4.9.tar.gz tar -xf rrdtool-1.4.9.tar.gz cd rrdtool-1.4.9 ./configure --prefix=/usr --libdir=/usr/lib64 make make install Terminada la instalación de RRDTool ya se puede instalar PNP4Nagios: cd /usr/src wget http://downloads.sourceforge.net/project/pnp4nagios/PNP-0.6/pnp4nagios-0.6.25.tar.gz tar -xf pnp4nagios-0.6.25.tar.gz cd pnp4nagios-0.6.25 571
./configure Aparecerá:
PNP4Nagios detectará de forma automática RRDTool y estará listo para la instalación. Se continua con: make all make fullinstall Terminada la instalación los pasos a seguir son: • • • • • •
Modificar el templates.cfg de Nagios Modificar el commands.cfg de Nagios Modificar la configuración general de Nagios Modificar la configuración del servidor localhost y los servicios monitoreados Reiniciar Nagios Reiniciar el Servidor Web
Se inicia modificando el archivo templates.cfg: nano /etc/nagios/objects/templates.cfg al final del archivo se añade: define host { name host-pnp action_url /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=_HOST_ register 0 572
} define service { name srv-pnp action_url /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=$SERVICEDESC$ register 0 } Se guardan los cambios y se continua con el archivo commands.cfg nano /etc/nagios/objects/commands.cfg Después de este bloque de comentario: ################################################################################ # # SAMPLE PERFORMANCE DATA COMMANDS # # These are sample performance data commands that can be used to send performance # data output to two text files (one for hosts, another for services). If you # plan on simply writing performance data out to a file, consider using the # host_perfdata_file and service_perfdata_file options in the main config file. ################################################################################# se borran los dos bloques que siguen y se sustituyen con los siguientes: define command { command_name process-service-perfdata command_line /usr/bin/perl /usr/local/pnp4nagios/libexec/process_perfdata.pl } define command { command_name process-host-perfdata command_line /usr/bin/perl /usr/local/pnp4nagios/libexec/process_perfdata.pl -d HOSTPERFDATA
} Estos dos comandos son los que se encargan de recolectar los datos para luego crear los gráficos. Se guardan los cambios y se pasa al archivo nagios.cfg: nano /etc/nagios/nagios.cfg Se buscan estas lineas: process_performance_data=0 #host_perfdata_command=process-host-perfdata #service_perfdata_command=process-service-perfdata y se modifican para que queden: 573
process_performance_data=1 host_perfdata_command=process-host-perfdata service_perfdata_command=process-service-perfdata Al final del archivo se añade la siguiente linea: broker_module=/usr/local/pnp4nagios/lib/npcdmod.o config_file=/usr/local/pnp4nagios/etc/npcd.cfg Se guardan los cambios. El modulo npcdmod.o es el que se encarga de pasar los datos de Nagios a PNP4NAGIOS; para activar el servicio: chkconfig --add npcd chkconfig npcd on Se inicia: /etc/init.d/npcd start Para activar PNP4NAGIOS para cada host y servicio monitoreado, se abre el archivo localhost.cfg: nano /etc/nagios/objects/localhost.cfg se modifica el primer bloque: define host{ use linux-server host_name LibroAsterisk alias LibroAsterisk address 127.0.0.1 } para que quede: define host{ use linux-server,host-pnp host_name LibroAsterisk alias LibroAsterisk address 127.0.0.1 } Para los demás bloques al final de la linea use se añade una coma y srv-pnp. Ejemplo: define service{ use asterisk,srv-pnp 574
host_name LibroAsterisk service_description SIP check_command check_snmp!ASTERISK-MIB::astChanTypeChannels.6!"Canales SIP Activos"! 8!16 } Una vez modificado todo el archivo, se guardan los cambios y se reinicia Nagios: service nagios restart Antes de reiniciar el servidor web, se modifica el archivo de configuración de PNP4NAGIOS para el servidor web: nano /etc/httpd/conf.d/pnp4nagios.conf Se cambia esta linea: AuthUserFile /usr/local/nagios/etc/htpasswd.users para que quede: AuthUserFile /etc/nagios/passwd Se guardan los cambios y se reinicia el servidor web: service httpd restart Si se vuelve a entrar en la pagina de administración de Nagios:
A lado de cada servicio aparecerá un icono de un gráfico. Si se presiona el icono de la linea PING se abrirá otra pestaña en el navegador donde PNP4NAGIOS averiguará que la configuración esté sin errores. Si todo está bien, al final de la pagina aparecerá:
575
Como indicado se borra el archivo: rm /usr/local/pnp4nagios/share/install.php Se recarga la pagina:
Se verá el gráfico del servicio PING. Como el servicio se controla cada 5 minutos, habrá que esperar un poco para ver los datos en el gráfico. Si se quiere personalizar la configuración de PNP4Nagios hay que modificar el siguiente archivo: nano /usr/local/pnp4nagios/etc/config.php 22.4 Monitoreo calidad llamadas Como se ha mencionado al inicio de este capitulo, es posible monitorear la calidad de las llamadas de distintas formas. La primera es desde la consola de Asterisk: 22.4.1 Monitoreo de la calidad de las llamadas desde la consola de Asterisk Se entra en la consola de Asterisk: asterisk -rvvvvvvvvvvvvvvvvvv Si activan las estadísticas del protocolo RTCP (Real Time Control Protocol) definido en el RFC3550. CLI> rtcp set debug on RTCP Debugging Enabled 576
Para ver como funciona, desde la extensión 1000 se llama la extensión 1002. Se contesta la llamada. En la consola de Asterisk empezarán a aparecer todas una serie de bloques relacionados con el flujo media. En estos bloques es posible identificar si hay perdida de paquetes y el tiempo de latencia entre los dos dispositivos involucrados en la llamada. Otra forma de hacerlo es con el comando: CLI> sip show channelstats para verlo en acción, se vuelve a marcar desde la extensión 1000 la extensión 1001. Cuando las dos extensiones están hablando, se vuelve a ejecutar el comando: CLI> sip show channelstats
En las lineas aparecen todos los datos relacionados con las llamadas corrientes (en este caso una): • • • • • • • • • • •
Peer: la IP de las extensiones Call ID: el identificador único de llamada para cada extensión Duration: la duración de la llamada hasta el momento (en segundos) Recv: Pack: paquetes recibidos por Asterisk de las dos extensiones Lost: paquetes perdidos de las extensiones a Asterisk %: porcentaje de paquetes perdidos Jitter: Jitter entre las extensiones y Asterisk Send: Pack: paquete enviados por Asterisk Lost: paquetes perdidos de Asterisk a las extensiones %: porcentaje de paquetes perdidos Jitter: Jitter entre Asterisk y las extensiones
Si el porcentaje de los paquetes perdidos se mantiene por abajo del 1%, la calidad de la llamada es muy buena. Entre el 1 y el 5%, aceptable. 22.4.2 Monitoreo calidad de las llamadas con pre-dial handlers y hangup-handlers Con la versión 11 de Asterisk se ha introducido una funcionalidad que permite ejecutar una subrutina antes que la llamada empiece pero después que los dos canales, llamante y llamado, se han credo. Esta funcionalidad se llama pre-dial handlers. En la subrutina se puede indicar otra subrutina que se ejecutará cuando la llamada termine; esta subrutina, también introducida con la versión 11 de Asterisk, se llama hangup-handlers. Aprovechando estas dos funcionalidades es posible, con un mínimo de configuración, guardar en una tabla de una base de datos, todas las estadísticas de una llamada. Para empezar hay que crear los pre-dial handlers que se utilizarán solamente para las llamadas salientes. 577
La sintaxis para el canal del llamante es: B([[context^]exten^]priority[(arg1[^...][^argN])]) para el canal de llamado es: b([[context^]exten^]priority[(arg1[^...][^argN])]) Las dos subrutinas van configuradas en la linea del Dial. Se abre el archivo del dialplan: nano /etc/asterisk/extensions.conf y en en contexto internacio se modifica la linea del Dial: same => n,Dial(SIP/voztovoice/${EXTEN}) para que quede: same => n,Dial(SIP/voztovoice/${EXTEN},30,B(predial^caller_handler^1)b(predial^callee_handler^1))
Para el llamado (opción B) se ejecutará la subrutina en el contexto predial, extensión caller_handles y prioridad 1. Para el llamado (opción b) se ejecutará la subrutina en el contexto predial, extensión calle_handler, prioridad 1. Al final del archivo, se crean los dos respectivos bloques en el nuevo contexto predial: [predial] exten => caller_handler,1,NoOp(Caller_Handler) same => n,Set(CHANNEL(hangup_handler_push)=caller,s,1); same => n,Return exten => callee_handler,1,NoOp(Callee_Handler) same => n,Set(CHANNEL(hangup_handler_push)=callee,s,1); same => n,Return En el bloque del llamante se indica que cuando termine la llamada se ejecutará la subrutina presente en el contexto caller, extensión s, prioridad 1. Para el llamado la subrutina será presente en el contexto callee, extensión s, prioridad 1. El paso a seguir es crear las dos subrutinas. Para el llamante: [caller] exten => s,1,NoOp(${CHANNEL(rtpqos,audio,all)}) same => n,set(hangupcause=${HANGUPCAUSE}) same => n,set(accountcode=${CDR(accountcode)}) same => n,set(peerip=${CHANNEL(peerip)}) same => n,set(recvip=${CHANNEL(recvip)}) 578
same => n,set(useragent=${CHANNEL(useragent)}) same => n,set(codecr=${CHANNEL(audioreadformat)}) same => n,set(codecw=${CHANNEL(audiowriteformat)}) same => n,set(codecn=${CHANNEL(audionativeformat)}) same => n,set(tlp=${CHANNEL(rtpqos,audio,txcount)}) same => n,set(llp=${CHANNEL(rtpqos,audio,txploss)}) same => n,set(porlp=$[{CHANNEL(rtpqos,audio,txploss)} / ${CHANNEL(rtpqos,audio,txcount)} * 100])
same => n,set(trp=${CHANNEL(rtpqos,audio,rxcount)}) same => n,set(rlp=${CHANNEL(rtpqos,audio,rxploss)}) same => n,set(porrp=$[{CHANNEL(rtpqos,audio,rxploss)} / ${CHANNEL(rtpqos,audio,rxcount)} * 100])
same => n,set(ljitter=${CHANNEL(rtpqos,audio,local_maxjitter)}) same => n,set(rjitter=${CHANNEL(rtpqos,audio,remote_maxjitter)}) same => n,Set(ODBC_cdr4()=${STRFTIME(${EPOCH},,%y%m%d%H%M%S)},${hangupcause},$ {accountcode},${peerip},${recvip},${useragent},${codecr},${codecw},${codecn},${tlp},${llp},${porlp}, ${trp},${rlp},${porrp},${ljitter},${rjitter}) same => n,Return Para el llamado: [callee] exten => s,1,NoOp(${CHANNEL(rtpqos,audio,all)}) same => n,set(hangupcause=${HANGUPCAUSE}) same => n,set(accountcode=${CDR(accountcode)}) same => n,set(peerip=${CHANNEL(peerip)}) same => n,set(recvip=${CHANNEL(recvip)}) same => n,set(useragent=${CHANNEL(useragent)}) same => n,set(codecr=${CHANNEL(audioreadformat)}) same => n,set(codecw=${CHANNEL(audiowriteformat)}) same => n,set(codecn=${CHANNEL(audionativeformat)}) same => n,set(tlp=${CHANNEL(rtpqos,audio,txcount)}) same => n,set(llp=${CHANNEL(rtpqos,audio,txploss)}) same => n,set(porlp=$[{CHANNEL(rtpqos,audio,txploss)} / ${CHANNEL(rtpqos,audio,txcount)} * 100])
same => n,set(trp=${CHANNEL(rtpqos,audio,rxcount)}) same => n,set(rlp=${CHANNEL(rtpqos,audio,rxploss)}) same => n,set(porrp=$[{CHANNEL(rtpqos,audio,rxploss)} / ${CHANNEL(rtpqos,audio,rxcount)} * 100])
same => n,set(ljitter=${CHANNEL(rtpqos,audio,local_maxjitter)}) same => n,set(rjitter=${CHANNEL(rtpqos,audio,remote_maxjitter)}) same => n,Set(ODBC_cdr4()=${STRFTIME(${EPOCH},,%y%m%d%H%M%S)},${hangupcause},$ {accountcode},${peerip},${recvip},${useragent},${codecr},${codecw},${codecn},${tlp},${llp},${porlp}, ${trp},${rlp},${porrp},${ljitter},${rjitter}) same => n,Return Los datos que se guardarán son (para cada canal): • •
Hangupcause: el código relacionado con el colgado de la llamada accountcode: la cuenta utilizada para realizar la llamada
579
• • • • • • • • • • • • • •
peerip: la dirección IP de donde se ha originado la llamada recvip: la dirección IP recibida por Asterisk para la llamada useragent: el dispositivo utilizado para realizar la llamada codecr: el codec audio “leído” por Asterisk sobre el canal codecw: el codec audio “escrito” por Asterisk sobre el canal codecn: el codec nativo utilizado por Asterisk para el canal tlp: el total de paquetes audio trasmitidos desde el dispositivo hacia Asterisk llp: el total de paquetes audio perdidos desde el dispositivo hacia Asterisk porlp: el porcentaje de paquetes audio perdidos desde el dispositivo hacia Asterisk trp: el total de paquetes audio trasmitidos desde Asterisk hacia el dispositivo rlp: el total de paquetes audio perdidos desde Asterisk hacia el dispositivo porrp: el porcentaje de paquetes audio perdidos desde Asterisk hacia el dispositivo ljitter: el Jitter de la llamada desde el dispositivo hacia Asterisk rjitter: el Jitter de la llamada desde Asterisk hacia el dispositivo
Ahora todos los datos presentes en los dos hangup-handlers se guardan en una tabla de la base de datos asteriskcdr. Se entra en mysql: mysql -u root -psesamo se selecciona la base de datos asteriskcdr: mysql> use asteriskcdr y se crea la nueva tabla: CREATE TABLE `cdr4` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `calldate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `hangupcause` int(2) NOT NULL DEFAULT '0', `accountcode` varchar(20) DEFAULT NULL, `peerip` varchar(20) DEFAULT NULL, `recvip` varchar(20) DEFAULT NULL, `useragent` varchar(30) DEFAULT NULL, `codecr` varchar(10) DEFAULT NULL, `codecw` varchar(10) DEFAULT NULL, `codecn` varchar(10) DEFAULT NULL, `tlp` int(15) NOT NULL DEFAULT '0', `llp` int(15) NOT NULL DEFAULT '0', `porlp` decimal(6,3) unsigned zerofill NOT NULL DEFAULT '000.000', `trp` int(15) NOT NULL DEFAULT '0', `rlp` int(15) NOT NULL DEFAULT '0', `porrp` decimal(6,3) unsigned zerofill NOT NULL DEFAULT '000.000', `ljitter` decimal(7,6) unsigned zerofill NOT NULL DEFAULT '0.000000', 580
`rjitter` decimal(7,6) unsigned zerofill NOT NULL DEFAULT '0.000000', PRIMARY KEY (`id`) ); Para que los datos se guarden en la tabla se recurre nuevamente al archivo func_odbc. En este caso, como la conexión ODBC a la base de datos asteriskcdr se ha creado anteriormente, no hace falta modificar los archivos odbc.ini y res_odbc.ini. nano /etc/asterisk/func_odbc.conf al final del archivo se añade: [cdr4] dsn=cdr writesql=insert into cdr4 (calldate,hangupcause,accountcode,peerip,recvip,useragent,codecr,codecw,codecn,tlp,llp,porlp,trp,rl p,porrp,ljitter,rjitter) values ("${SQL_ESC(${VAL1})}","${SQL_ESC(${VAL2})}","${SQL_ESC(${VAL3})}","${SQL_ESC($ {VAL4})}","${SQL_ESC(${VAL5})}","${SQL_ESC(${VAL6})}","${SQL_ESC(${VAL7})}", "${SQL_ESC(${VAL8})}","${SQL_ESC(${VAL9})}","${SQL_ESC(${VAL10})}","${SQL_ESC($ {VAL11})}","${SQL_ESC(${VAL12})}","${SQL_ESC(${VAL13})}","${SQL_ESC(${VAL14})}", "${SQL_ESC(${VAL15})}","${SQL_ESC(${VAL16})}","${SQL_ESC(${VAL17})}") Todos los datos presentes en la linea writesql tienen que estar en el mismo renglón. Se guardan las modificaciones y se entra en la consola de Asterisk: asterisk -rvvvvvvvvvvvvvvvvvvvv se recarga el modulo func_odbc CLI> module reload func_odbc.so se recarga el dialplan: CLI> dialplan reload y se realiza una prueba llamando un numero fijo/celular. Una vez terminada la llamada se entra nuevamente en la consola de MySQL: mysql -u root -psesamo se selecciona la base de datos asteriskcdr: mysql> use asteriskcdr y se revisa que se ha guardado en la tabla cdr4: 581
mysql> select * from cdr4;
22.4.3 Monitoreo de la calidad de las llamadas con VoIPMonitor VoIPmonitor es un programa que permite guardar todos los datos relacionados con la calidad de las llamadas en una base de datos. De este programa existen dos versiones. Una Open Source sin la GUI (interfaz trafica) para ver la estadísticas desde un navegador Web, una comercial que incluye la GUI. El programa analiza y captura todos los paquetes SIP (señalización) y RTP (flujo media). De cada llamada, para ambos canales, guarda los siguientes datos: • • • • • • • • • • • • •
Fecha de la llamada Duración CallerID llamante CallerID llamado Quien de los dos canales ha colgado Codec Llamante Codec Llamado Paquetes recibidos, enviados, perdidos Jitter canal llamante Jitter canal llamado Jitter promedio de la llamada MOS (Mean Opinion Score) llamante MOS (Mean Opinion Score) llamado
Pre requisitos para la compilación e instalación: •
una versión de Libpcap >= 1.0 582
•
Librería MySQL++
Primero se averigua la versión de libpcap instalada: yum info libpcap
Como el numero de versión es 1, se puede continuar con MySQL++: cd /usr/src wget http://tangentsoft.net/mysql++/releases/mysql++-3.2.1.tar.gz tar -xf mysql++-3.2.1.tar.gz cd mysql++-3.2.1 ./configure --prefix=/usr --libdir=/usr/lib64 make make install Se instalan algunas dependencias: yum --enablerepo=epel install snappy* libssh-devel json-c-devel -y Instalados los pre requisitos se decarga VoIPMonitor ya compilado. cd /usr/src wget http://downloads.sourceforge.net/project/voipmonitor/11.1/voipmonitor-amd64-11.1-static.tar.gz
Se descomprime: tar -xf voipmonitor-amd64-11.1-static.tar.gz Se entra en la carpeta creada: cd voipmonitor-amd64-11.1-static Se ejecuta el script de instalación: ./install-script.sh
583
Se crea la carpeta donde se guardarán todos los datos de las llamadas (archivo pcap, archivo audio de la llamada si se utiliza el codec audio G711): mkdir /var/spool/voipmonitor Se crea la base de datos donde se guardarán los datos de las llamadas: mysql -u root -psesamo mysql> create database voipmonitor; mysql> quit Se modifica el archivo de configuración: nano /etc/voipmonitor.conf Se modifican las siguientes lineas: #id_sensor = 1 mysqlhost = 127.0.0.1 mysqlport = 3306 mysqlusername = root mysqlpassword = #interface = eth0,eth1 #sipport = 5061 #jitterbuffer_f1 = no #jitterbuffer_f2 = yes #jitterbuffer_adapt = no para que queden: id_sensor = 1 mysqlhost = 127.0.0.1 mysqlport = 3306 mysqlusername = root mysqlpassword = sesamo interface = eth0,eth0:1 sipport = 5061 jitterbuffer_f1 = yes jitterbuffer_f2 = yes jitterbuffer_adapt = yes Se guardan las modificaciones y se inicia el servicio: service voipmonitor start
584
e se efectúa una llamada desde la extensión 1000 a la extensión 1001. Terminada la llamada se mira las entradas en la base de datos voipmonitor, tabla cdr (serán dos).
22.5 CDR-STATS El programa CDR-STATS permite analizar todas las entradas presentes en la tabla CDR (Call Detail Records), que se ha creado en el párrafo 1.7 de este libro, y con los datos presentes crear reportes gráficos muy detallados. Implementa también un sistema de análisis de las llamadas que permite crear alarmas con relativas notificaciones en el caso el sistema detecte trafico anómalo hacia determinadas destinaciones. La instalación se basa en un script que se hace cargo de instalar todos los paquetes y dependencias necesarias para la instalación y configuración del programa. Para empezar, se descarga el archivo: cd /usr/src wget --no-check-certificate https://raw.github.com/Star2Billing/cdr-stats/master/install/installcdr-stats-asterisk.sh -O install-cdr-stats-asterisk.sh Se vuelve ejecutable: chmod +x install-cdr-stats-asterisk.sh y se inicia: ./install-cdr-stats-asterisk.sh
585
Se presiona la tecla Enter/Envío. Aparecerá: This script is only intended to run on Ubuntu LTS 10.04 / 12.04 or CentOS 6.X Como CentOS 6.6 no está incluido, primero de modifica: nano install-cdr-stats-asterisk.sh Cambiando estás dos lineas: wget --no-check-certificate https://raw.github.com/Star2Billing/cdr-stats/$BRANCH/install/bashcommon-functions.sh -O bash-common-functions.sh wget --no-check-certificate https://raw.github.com/Star2Billing/cdr-stats/$BRANCH/install/cdrstats-functions.sh -O cdr-stats-functions.sh Para que queden (comentadas): #wget --no-check-certificate https://raw.github.com/Star2Billing/cdr-stats/$BRANCH/install/bashcommon-functions.sh -O bash-common-functions.sh # wget --no-check-certificate https://raw.github.com/Star2Billing/cdr-stats/$BRANCH/install/cdrstats-functions.sh -O cdr-stats-functions.sh Luego se modifica: nano +31 bash-common-functions.sh en esa linea se cambia 6.2 con 6.6. Se guardan los cambios y se ejecuta nuevamente el script de instalación: ./install-cdr-stats-asterisk.sh
Se presiona la tecla Enter/Envío. Aparecerá:
586
Se escribe YES y se presiona la tecla Enter:
Se escribe 1 (Installa All) y se presiona la tecla Enter. Empezará la instalación del programa y de todas las dependencias:
Se presiona la tecla Enter:
Cuando el programa de instalación lo solicite, se ingresan todos los datos de configuración de la base de datos donde se ha creado la tabla CDR (asteriskcdr) y se continua presionando la tecla Enter:
Cuando el programa de instalación lo solicite, se escoge un nombre de usuario, un correo electrónico y una contraseña para acceder a la pagina de administración de CDR-STATS:
587
Terminada la instalación aparecerá la imagen de arriba indicando que el proceso ha tenido éxito. Se presiona la tecla Enter:
cuando se vuelve a este menú se digita 0 y la tecla Enter. Se volverá al prompt de la consola de Linux. Como hay que personalizar la configuración, se para el proceso de cdr-stats: /etc/init.d/cdr-stats-celeryd stop y se abre el archivo de configuración: nano /usr/share/cdr_stats/settings_local.py se modifica esta linea: TIME_ZONE = 'Etc/UTC' para que quede (para Colombia): TIME_ZONE = 'America/Bogota' se continua con este bloque: 588
DEFAULT_FROM_EMAIL = 'CDR-Stats ' EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' EMAIL_USE_TLS = True EMAIL_HOST = 'smtp.gmail.com' EMAIL_PORT = 587 EMAIL_HOST_USER = '[email protected]' EMAIL_HOST_PASSWORD = 'password' EMAIL_SUBJECT_PREFIX = '[CDR-Stats] ' Se personalizan los datos con su nombre de dominio, cuenta Gmail y contraseña de la cuenta. Se modifica: LOCAL_DIALCODE = 1 Con el prefijo de su país: LOCAL_DIALCODE = 57 En: PREFIX_TO_IGNORE = "+,0,00,000,0000,00000,011,55555,99999" Si es el caso se añaden los prefijos que se utiliza para sacar las llamadas con los distintos proveedores VoIP: PREFIX_TO_IGNORE = "+,0,00,000,0000,00000,00001,011,55555,99999" Se modifica la linea: LOCAL_SWITCH_IP = 'IPServidor' Para que quede: LOCAL_SWITCH_IP = 'localhost' Estas tres lineas: ASTERISK_MANAGER_HOST = 'localhost' ASTERISK_MANAGER_USER = 'cdrstats_user' ASTERISK_MANAGER_SECRET = 'cdrstats_secret' Permiten a CDR-STATS de conectaste a la AMI de Asterisk con nombre de usuario y contraseña que aparecen respectivamente en la segunda y tercera linea. Se guardan las modificaciones y se modifica el archivo manager.conf de Asterisk: nano /etc/asterisk/manager.conf 589
y al final se añade el siguiente bloques: [cdrstats_user] secret=cdrstats_secret deny=0.0.0.0/0.0.0.0 permit=127.0.0.1/255.255.255.255 read = system,call,log,verbose,agent,user,config,dtmf,reporting,cdr,dialplan write = system,call,agent,user,config,command,reporting,originate Se guardan los cambios y se recarga la configuración de Asterisk: service asterisk reload Ahora se puede iniciar nuevamente el programa: /etc/init.d/cdr-stats-celeryd start Antes de acceder a la pagina de administración de CDR-STATS hay que abrir los puertos 8008 y 9000 tcp en el Firewall: nano /etc/sysconfig/iptables después de esta linea: -A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT se añade: # CDR-STATS -A INPUT -p tcp -m state --state NEW -m tcp --dport 8008 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 9000 -j ACCEPT Se guardan los cambios y se reinicia iptables y fail2ban: service iptables restart service fail2ban restart ya se puede acceder a la pagina de administración con nombre de usuario y contraseña definidos a lo largo de la instalación: http://IPservidor:8008
590
Se presiona el botón Login y se entrará en la pagina de los reportes de CDR-STATS. Para asegurarse que el sistema esté funcionando sin problemas, en el menú Admin:
En la nueva pagina debe aparecer:
Las zonas evidenciadas son las que indican que el programa está funcionando bien. Para ver las estadísticas de las llamadas y/o efectuar búsquedas:
591
Para profundizar algunos temas de la configuración de CDR-STATS, se aconseja descargar el manual del programa.
592
Capitulo XXIII Conectar un Softphone (Blink) de forma segura: SIP TLS y SRTP En algunos contextos la privacidad de las comunicaciones es un factor importante para el desarrollo de las actividades de la empresa, más aun si los datos que se intercambian a lo largo de las conversaciones son datos sensibles tipo: números de tarjetas de crédito, datos de cuentas bancarias, secretos industriales, etc... Las conversaciones seguras eran importantes en las comunicaciones tradicionales y más aun lo son en la voz sobre IP. Con la versión de Asterisk 11.X se ha mejorado la implementación de dos protocolos: • •
SIP TLS para el cifrado de la señalización SIP SRTP para el cifrado del flujo media.
Aunque se puedan utilizar separadamente, no tendría mucho sentido, por las siguientes razones: • •
Si se utiliza solamente el protocolo SIP TLS, el flujo media seguirá viajando en claro y podría ser interceptado Las claves que intercambian el cliente y el servidor para instaurar el cifrado del flujo media, se envían a través de los paquetes SIP. Si no se utiliza el cifrado del protocolo SIP y alguien logra interceptar ese trafico, podrá tener acceso a las claves y de esta forma descifrar el flujo media.
El único Softphone con una versión gratuita que soporta los protocolos SIP TLS Y SRTP es Blink. De este producto existen versiones para Linux, MAC OS y Windows. Antes de instalarlo hay que configurar Asterisk para activar el protocolo SIP TLS y SRTP. 23.1 Creación de los certificados El primer paso es crear los certificados cliente, servidor y de la autoridad de certificación. Se crea la carpeta donde se guardarán las claves. mkdir /etc/asterisk/blink y se entra en la carpeta de las fuentes de Asterisk que contiene uno script para la generación de los certificados: cd /usr/src/asterisk-11.17.1/contrib/scripts/ Primero se crea el certificado de la autoridad de certificación y del servidor Asterisk: ./ast_tls_cert -C li204-236.members.linode.com -O "Libro VozToVoice" -d /etc/asterisk/blink • • •
con la opción -C se indica el nombre de dominio o la IP del servidor Asterisk con la opción -O se indica el nombre de la empresa o de la institución con la opción -d se indica la ruta donde se guardarán los certificados
No config file specified, creating '/etc/asterisk/keys/tmp.cfg' You can use this config file to create additional certs without re-entering the information for the fields in the certificate Creating /etc/asterisk/keys/ca.key Generating RSA private key, 4096 bit long modulus ............++ ..........................................................................++ e is 65537 (0x10001) Enter pass phrase for /etc/asterisk/keys/ca.key: Verifying - Enter pass phrase for /etc/asterisk/keys/ca.key: Creating /etc/asterisk/keys/ca.crt Enter pass phrase for /etc/asterisk/keys/ca.key: Creating /etc/asterisk/keys/asterisk.key Generating RSA private key, 1024 bit long modulus ....................................++++++ .........++++++ e is 65537 (0x10001) Creating signing request Creating /etc/asterisk/keys/asterisk.crt Signature ok subject=/CN=li374-112.members.linode.com/O=Campus VozToVoice Getting CA Private Key Enter pass phrase for /etc/asterisk/keys/ca.key: Combining key and crt into /etc/asterisk/keys/asterisk.pem Cuando el sistema lo solicita, se indica una contraseña que tiene que ser la misma a lo largo de todo el proceso. En este caso se utilizará la contraseña server. Con esta operación se crearán el certificado de la autoridad de certificación con relativa clave y el certificado del servidor Asterisk con relativa clave. El segundo paso es crear la clave del softphone utilizando la misa autoridad de certificación: ./ast_tls_cert -m client -c /etc/asterisk/blink/ca.crt -k /etc/asterisk/blink/ca.key -C blink1 -O "Libro VozToVoice" -d /etc/asterisk/blink -o blink1 • • • • • •
con la opción -m se indica el tipo de certificado. En este caso un certificado cliente con la opción -c se indica la ruta del certificado de la autoridad de certificación con la opción -k se indica la ruta de la clave del certificado de la autoridad de certificación con -C se indica el nombre de dominio o la IP de donde se conectará el softphone. Como en este caso el computador desde donde se conectará el softphone no tiene un nombre de dominio o una IP fija, se pone un nombre que identifique el softphone con la opción -O se indica el nombre de la empresa o de la institución con la opción -d se indica la ruta donde se guardarán los certificados
No config file specified, creating '/etc/asterisk/keys/tmp.cfg' You can use this config file to create additional certs without 595
re-entering the information for the fields in the certificate Creating /etc/asterisk/keys/blink1.key Generating RSA private key, 1024 bit long modulus .....................++++++ .....++++++ e is 65537 (0x10001) Creating signing request Creating /etc/asterisk/keys/blink1.crt Signature ok subject=/CN=blink1.li374-112.members.linode.com/O=Campus VozToVoice Getting CA Private Key Enter pass phrase for /etc/asterisk/keys/ca.key: Combining key and crt into /etc/asterisk/keys/blink1.pem Cuando el sistema lo solicite, se ingresa la misma contraseña utilizada en la fase anterior, es decir, server. Una vez creados los certificados se modifica la configuración del archivo sip.conf de Asterisk: nano /etc/asterisk/sip.conf al final de la parte general se añaden las siguientes lineas: tlsenable=yes tlsbindaddr=0.0.0.0 tlscertfile=/etc/asterisk/blink/asterisk.pem tlscafile=/etc/asterisk/blink/ca.crt tlscapath=/etc/asterisk/blink tlsdontverifyserver=yes • • • • • •
Linea 1: se activa el protocolo SIP TLS Linea 2: Asterisk se pondrá a la escucha en todas las direcciones IP presentes en el servidor Linea 3: ruta y nombre del certificado del servidor Asterisk Linea 4: ruta y nombre del certificado de la autoridad de certificación Linea 5: ruta donde se encuentran todos los certificados de las distintas autoridades de certificación Linea 6: como el softphone no utiliza un nombre de dominio propio, con este parámetro en yes, se indica que el servidor Asterisk no deberá verificar el certificado del cliente
Al final del archivo se crea una nueva extensión: [1005] type=friend accountcode=1005 language=es secret=pbx9095 596
qualify=yes mailbox=1005@default host=dynamic dtmfmode=rfc2833 context=externas directmedia=no callerid=Perengano <1005> callgroup=1 pickupgroup=1 disallow=all allow=ulaw allow=alaw allow=g729 allow=h263 cc_agent_policy=generic cc_monitor_policy=generic transport=tls encryption=yes Las ultimas dos lineas indican que para la extensión 1005, Asterisk aceptará solamente conexiones con el protocolo SIP TLS y el cifrado del flujo media. Se guardan los cambios y se recarga la configuración SIP: asterisk -rvvvvvvvvvvvvv CLI> sip reload Si todo sale bien, entre las varias lineas aparecerá: SSL certificate ok Como el protocolo SIP TLS utiliza el puerto 5061 TCP, hay que abrirlo en el cortafuegos (si ya no se ha hecho en el párrafo 18.5) nano /etc/sysconfig/iptables Después de esta linea: -A INPUT -p tcp -m state --state NEW -m tcp --dport 5060 -j ACCEPT se pone: -A INPUT -p tcp -m state --state NEW -m tcp --dport 5061 -j ACCEPT Se guardan los cambios y se reinicia iptables y fail2ban:
597
service iptables restart service fail2ban restart Para terminar esta primera parte, hay que trasferir los certificado en el computador donde se instalará el Softphone Blink. Los archivos que hay que descargar son: • •
ca.crt blink1.pem
Para esta operación, en Windows se puede utilizar el programa winscp. Bajo Linux el comando scp. 23.2 Configuración Softphone Blink Asterisk ya está configurado para el soporte SIP TLS y SRTP. Ahora se puede descargar el Softphone Blink según el sistema operativo utilizado. Una vez descargado se instala y se inicia la configuración entrando en el menú Blink → Accounts → Add Account:
• • •
Display name: un nombre que se le asigna a la cuenta SIP address: numero de extensión y dominio del servidor Asterisk Password: contraseña de la extensión 1005 598
Se presiona el botón ADD y se va al menú Blink → Account → Manage accounts. En la pestaña “Media”:
Se selecciona el protocolo SRTP como obligatorio “mandatory”. En la pestaña “Server settings”:
se configura como aparece en la imagen de arriba y se continua con la pestaña “Advanced”:
Se selecciona el certificado blink1.pem descargado del servidor Asterisk y se selecciona la casilla “Verify server”. Se pasa al icono Advanced:
599
Se selecciona el certificado de la autoridad de certificación descargado del servidor Asterisk: Se vuelve a la pantalla principal del softphone y se averigua en la consola de Asterisk que esté registrado: CLI> sip show peers Prueba llamadas Para probar la configuración, hay que modificar el dialplan: nano /etc/asterisk/extensions.conf Se modifica este bloque: exten => _100[0-2,4],1,Dial(SIP/${EXTEN},45,hHkKtTwWxX) same => n,Gosub(voicemail,s,1(${EXTEN})) same => n,Hangup para que quede: exten => _100[0-2,4-5],1,Noop(Protocolo SIPTLS = ${CHANNEL(secure_signaling)}) same => n,Noop(Protocolo SRTP = ${CHANNEL(secure_media)}) same => n,Dial(SIP/${EXTEN},45,hHkKtTwWxX) same => n,Gosub(voicemail,s,1(${EXTEN})) same => n,Hangup En la primera linea se lee el valor asociado a la variable de canal “secure_signaling” Si es ugual a 1 significa que la llamada ha sido iniciada por una extensión configurada con el protocolo SIP TLS. En la segunda linea se lee el valor asociado a la variable de canal “secure_media”. Si es igual a 1 significa que la llamada ha sido iniciada por una extensión configurada con el protocolo SRTP activado. Se guardan los cambios y se recarga el dialplan: asterisk -rvvvvvvvvvvvvvvvvv CLI> dialplan reload Ahora se hacen dos llamadas: 1. desde la extensión 1000 a la extensión 1005 2. desde la extensión 1005 a la extensión 1000 Los resultados: Executing [1005@externas:1] NoOp("SIP/1000-00000010", "Protocolo SIPTLS = ") in new stack -- Executing [1005@externas:2] NoOp("SIP/1000-00000010", "Protocolo SRTP = ") in new stack -- Executing [1005@externas:3] Dial("SIP/1000-00000010", "SIP/1005,45,hHkKtTwWxX") 600
Como la extensión 1000 (Softphone X-Lite) no soporta SIP TLS y SRTP, las dos variables de canal estarán vacías pero en el Softphone aparecerá:
El candado azul indica que entre Blink y Asterisk se está utilizando el cifrado de la señalización (SIP TLS). El canda naranjado indica que entre Blink y Asterisk el flujo media va cifrado. La llamada del Blink a la extensión 1000: -- Executing [1000@externas:1] NoOp("SIP/1005-00000014", "Protocolo SIPTLS = 1") in new stack -- Executing [1000@externas:2] NoOp("SIP/1005-00000014", "Protocolo SRTP = 1") in new stack -- Executing [1000@externas:3] Dial("SIP/1005-00000014", "SIP/1000,45,hHkKtTwWxX") Como la extensión 1005 (Softphone Blink) soporta SIP TLS y SRTP, las dos variables de canal tendrán el valor 1. Consideraciones finales Como se ha comentado en otro modulo, Asterisk siempre está en el medio de una llamada para la señalización SIP. Para el flujo media depende de la configuración del parámetro directmedia y si las extensiones se registran detrás de un NAT o no. Esto implica que es posible que se presenten estos escenarios:
SIP TSL - SRTP
SIP - RTP
SoftPhone Blink ---------------------> Asterisk -------------------------> SoftPhone X-Lite o: SIP - RTP
SIP TSL - SRTP SoftPhone X-Lite ---------------------> Asterisk -------------------------> SoftPhone Blink En el primer caso, aunque la segunda pata de la llamada no es segura, no implica que no se deban implementar los protocolo SIP TLS y SRTP cuando sea posible. Lo mismo vale para el segundo caso.
601
Capitulo XXIV Openfire y Asterisk 24.1 Instalación de Openfire Openfire es un servidor Jabber. Con Openfire instalado se tendrá un servidor de mensajería instantánea sin tener que acudir a servicios de terceros. Esto implica tener una red de mensajería instantánea privada, fácilmente manejable y segura gracias al uso del protocolo TLS. ¿Porque Openfire?. Entre tantos servidores con protocolo XMMP Openfire se destaca por la sencillez de la instalación, la administración desde una página Web, su multiplicidad de funciones y la posibilidad de ser integrado con Asterisk. Openfire es escrito en java y, para que funcione, hay que instalar la JDK (Java SE Development Kit) o instalar (la opción que se usará) la versión OpenSource del java development Kit yum install java-1.7.0-openjdk* -y Terminada la instalación se controla la versión instalada: java -version java version "1.7.0_79" OpenJDK Runtime Environment (rhel-2.5.5.1.el6_6-x86_64 u79-b14) OpenJDK 64-Bit Server VM (build 24.79-b02, mixed mode) Se descarga el servidor jabber Openfire: cd /opt wget http://www.igniterealtime.org/downloadServlet?filename=openfire/openfire_3_9_3.tar.gz mv downloadServlet\?filename\=openfire%2Fopenfire_3_9_3.tar.gz openfire_3_9_3.tar.gz se descomprime: tar -xf openfire_3_9_3.tar.gz Se copia el archivo de configuración en la carpeta /etc/sysconfig: cp openfire/bin/extra/redhat/openfire-sysconfig /etc/sysconfig/openfire Se modifica: nano /etc/sysconfig/openfire se modifican estas lineas: #OPENFIRE_HOME="" #OPENFIRE_USER="daemon"
#OPENFIRE_OPTS="-Xmx1024m" #JAVA_HOME=/usr/java/default para que queden: OPENFIRE_HOME="/opt/openfire" OPENFIRE_USER="root" OPENFIRE_OPTS="-Xmx512m" JAVA_HOME=/usr/lib/jvm/java-1.7.0-openjdk.x86_64 Se guardan los cambios y se inicia: /opt/openfire/bin/openfire start Se averigua que esté corriendo /opt/openfire/bin/openfire status Si aparece: The daemon is running. El servidor está funcionando. Ahora hay que configurarlo. Openfire para registrar los datos puede utilizar una base de datos interna o externa. En este caso se usará MySQL. Se crea la base de datos en MySQL mysqladmin create openfire -u root -psesamo Se entra en el cliente de mysql: mysql -u root -psesamo Se crea un usuario y se le otorgan todos los permisos para manejar la base de datos Openfire mysql> GRANT ALL PRIVILEGES ON openfire.* TO 'openfire'@'localhost' IDENTIFIED BY 'sesamo'; Query OK, 0 rows affected (0.01 sec) mysql> flush privileges; Query OK, 0 rows affected (0.00 sec) mysql> quit 604
Bye sesamo es la contraseña del usuario openfire Ahora se importan las tablas para la base de datos mysql openfire < /opt/openfire/resources/database/openfire_mysql.sql -u root -psesamo Para que Openfire sea accesible desde afuera de la red local hay que abrir unos puertos en el cortafuegos. nano /etc/sysconfig/iptables Después de este bloque: # Monit -A INPUT -p tcp -m state --state NEW -m tcp --dport 2812 -j ACCEPT Se añade: # Openfire -A INPUT -p tcp -m state --state NEW -m tcp --dport 5222:5223 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 5269 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 5275 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 7070 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 7443 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 9090 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 9091 -j ACCEPT Se guardan los cambios y se reinicia iptables y fail2ban: service iptables restart service fail2ban restart Una vez configurado el firewall se accede a la pagina de configuración de Openfire. En la barra de la direcciones del navegador se escribe: http://IPservidor:9090 en lugar de IPservidor se pone la dirección IP del servidor Linux o, si se tiene un dominio registrado, el nombre (Ej. www.ejemplo.com) aparecerá una pagina de configuración:
605
se elige el idioma Se configura el nombre del dominio o la dirección IP:
Se elige el tipo de base de datos que se utilizará:
606
Se configura el acceso a MySQL y la base de datos:
En seteos de perfil se elige la opción “por defecto”
607
Se configura el correo electrónico y la cuenta del administrador:
El servidor está listo para funcionar.
608
Antes de entrar en la página de administración de Openfire hay que parar y volver a arrancar el servidor: /opt/openfire/bin/openfire stop /opt/openfire/bin/openfire start
Ahora se puede configurar el servidor; crear usuarios, instalar plugins, crear conferencias y otras cuantas funciones. Para probar la conexión el cliente predefinido de Openfire es Spark (en este caso para Windows). Hay que descargarlo, instalarlo y abrirlo. Se pone come usuario admin, que es el que se ha creado a lo largo de la configuración de Openfire, se pone la contraseña del usuario admin y se presiona Login:
Después de unos segundos:
609
Se pueden configurar más usuarios y grupos desde la pagina de administración Si se quiere iniciar Openfire en automático: cp /opt/openfire/bin/extra/redhat/openfire /etc/init.d/openfired se vuelve ejecutable: chmod +x /etc/init.d/openfired y se añade a los servicios: chkconfig --add openfired chkconfig openfired on Para averiguar si Openfire se inicia en automático se hace un un reboot de la maquina Linux. reboot Se vuelve a entrar en el servidor y se averigua que Openfire esté corriendo: /etc/init.d/openfired status openfire is running
610
24.2 Instalar el Plugin SIPPhone en Openfire En este párrafo se verá come instalar el plugin SIPPhone para Openfire. Este plugin permite asociar a un usuario registrado en Openfire una cuenta SIP o extensión Asterisk. Luego se instala el mismo plugin en el cliente Spark y desde éste se podrán efectuar llamadas usando el dialplan configurado en Asterisk. Desde un navegador Web entramos en la pagina de administración.
En el menú Plugins se escoge Available Plugins en el menú de la izquierda. Dependiendo de los plugins que ya se instalaron, aparecerá una lista de los plugins disponibles entre los cuales:
Se presiona el botón a la derecha del plugin para instalarlo. Se presiona el botón Server en la barra del menú. En la segunda línea del menú habrá un nuevo menú: “Telefonía”. Se presiona para entrar en el menú de configuración del plugin.
Se escoge “Agregar nuevo mapeo” y se rellenan los campos:
611
• • • • • • • •
Nombre de usuario XMPP : el nombre del usuario openfire Nombre de usuario : el numero o nombre de la extensión Usuario de Autorización : el numero o nombre de la extensión Numero de teléfono a mostrar : el numero que aparecerá al llamado Clave: la contraseña asociada a la extensión Servidor: el nombre del dominio o IP del servidor Asterisk Outbound Proxy : si se utiliza un proxy para conectarse al servidor Asterisk hay que indicarlo aquí sino se pone la dirección IP o el nombre de dominio del servidor Asterisk Numero Correo de voz : como en el dialplan se ha definido que para acceder al buzón de voz se utiliza la extensión 97, se pone aquí el numero
Se presionas el botón “Crear” para guardar la configuración. Se repite la misma operación para todos los usuarios que se quiere asociar a una extensión de Asterisk. Una vez terminado hay que configurar el cliente Spark que es el único que funciona con este plugin. Se abre el cliente Spark y se abre una conexión con el nombre de usuario configurado arriba (en este caso admin). En el menú del cliente Spark se elige Spark → Plugins y en Plugins disponibles Phone client y se instala:
612
Cuando se termina de descargar el plugin, se cierra el cliente y se vuelve a iniciar. En el menú acciones se elige Phone Enabled. Aparecerá el cliente SIP en una nueva línea del menú de Spark y se podrá empezar a usarlo para hacer llamadas.
613
Ahora se puede realizar una primera prueba. Desde la extensión 1001 se marca la extensión 1000. Spark debería empezar a timbrar:
Si se quiere usar un único programa para chatear, hacer llamadas VoIP y, como se verá en el próximo párrafo, monitorear las extensiones, esta es una buena solución. La verdad es que el audio es pésimo y no es una buena opció para utilizarla en producción pero la idea es saber que es posible realizar este tipo de configuración. 24.3 El Plugin Asterisk-IM Asterisk-IM permite asociar a cada usuario Openfire una extensión SIP configurada en sip.conf. De este modo cuando esa extensión está hablando, en el cliente jabber Spark el estado del usuario Openfire asociado con la extensión cambiará de disponible a “on the phone”. Requisitos: • •
haber instalado openfire con una base de datos externa (Mysql) haber configurado el parámetro callevents=yes en la parte general del archivo sip.conf 614
•
haber configurado un usuario en el archivo manager.conf
Se modifica el archivo manager.conf: nano /etc/asterisk/manager.conf Al final del archivo se añade un nuevo usuario: [openfire] secret = sesamo deny=0.0.0.0/0.0.0.0 permit=127.0.0.1/255.255.255.255 read=system,call,agent,user,dtmf,reporting,cdr,dialplan,agi,cc,aoc write=system,call,agent,user,config,command,reporting,otiginate,agi,aoc Se actualiza la configuración de Asterisk: /etc/init.d/asterisk reload Se instala el plugin en Openfire. Desde un navegador Web se abre la pagina de administración de Openfire y se va al menú Plugins. Se presiona el menú “Available Plugins”
Para instalarlo se presiona el botón que aparece al fondo de la línea del plugin. Una vez instalado en el barra de los menú, habrá una nueva voz, Asterisk IM. Se escoge el menú Asterisk-IM y luego General Settings. Se configura siguiendo las pautas indicadas en la imagen que sigue:
615
Se presiona el botón SAVE. En la misma ventana se escoge el menú Add Server y se configura la conexión al Asterisk Manager
En la pagina que aparece se configura como en la imagen que sigue:
616
• • • • •
Server Name: un nombre que se quiere asignar al servidor Server Address: dirección IP o nombre de dominio del servidor Asterisk (en este caso como se encuentra en el mismo servidor Linux, se pone localhost Port: el puerto para conectarse a la AMI de Asterisk Username: el nombre de usuario definido en el archivo manager.conf Password: la contraseña configurada en el manager.conf
Se presiona el botón “Create Server”. La bolita verde a la izquierda indica che hay conexión con Asterisk.
Para averiguar que efectivamente el usuario Openfire esté conectado al Asterisk Manager se entra en la consola de Asterisk: asterisk -rvvvvvvvvvvvvvv se digita el comando: CLI> manager show connected Username openfire
IP Address Start Elapsed FileDes HttpCnt Read Write 127.0.0.1 1323817682 79 10 0 04079 04851
617
Se guardan los cambios y se entra en el menú Phone Mappings:
Se configuran todos los usuarios de Openfire que se quiere asociar con una extensión SIP presente en el servidor Asterisk. Para guardar los cambios, se presiona el botón “Add”. Desde el cliente Spark se abre una conexión con el usuario admin que se ha configurado en Phone Mappings. Desde el cliente Spark se marca el 97 para entrar en la buzón de voz, en el cliente Spark cambiará el estado del usuario admin:
24.4 Asterisk como cliente en Openfire La configuración de Asterisk como cliente jabber en Openfire es parecida a la del cliente Gmail (párrafo 5.1). Se empieza con la modifica del archivo xmpp.conf presente en la carpeta /etc/asterisk. nano /etc/asterisk/xmpp.conf Al final del archivo, se copian las siguientes lineas: [asterisk] ; etiqueta que define la conexión (importante para las funciones Jabberstatus y Jabbersend de Asterisk) 618
type=client ; Asterisk actuará como un cliente (las opciones son cliente, componente y server) serverhost=li204-236.members.linode.com ; el nombre de dominio o IP del servidor Openfire ;pubsub_node=pubsub.li40-214.members.linode.com ; Nombre del nodo para publicar los eventos para la configuración del monitoreo de extensiones ; remotas. Se deja comentado [email protected]/openfire ; Nombre del usuario Openfire del servidor asterisk secret=sesamo ; la contraseña priority=10 ; el nivel de prioridad que tiene en cliente en caso de conflictos (ej: dos conexiones simultaneas del ; mismo usuario) port=5222 ; el puerto TCP del servidor Openfire usado para conectarse usetls=yes ; Usar el protocolo TLS usesasl=yes ; Usar el protocolo SASL [email protected] ; la lista de amigos, uno por línea ;distribute_events=yes ; Se especifica si esta conexión se utilizará o no para la generación de eventos en la configuración del ; monitoreo de las extensiones remotas status=available ; En este parámetro se configura el estado de la cuenta como aparecerá a los demás contactos statusmessage=Asterisk server ; un mensaje personalizado del usuario timeout=100 ; sendtodialplan=yes ; se especifica si los mensajes enviados a este usuario se pasarán al dialplan 619
context=asterisk ; contexto del dialplan donde se enviarán los mensajes. Se guardan los cambios y antes de actualizar la configuración de Asterisk se configura este usuario en Openfire. Desde un navegador Web se entra en la pagina de administración de Openfire:
En la barra de menú se escoge “Users/Groups” y luego en el menú vertical en la izquierda “Create New User”
• • • • •
Username: el nombre de usuario Openfire Name: el nombre completo o un apodo Email: la dirección del correo electrónico del usuario (personalizar) Password: la contraseña creada en el jabber.conf (sesamo) Confirm Password: otra vez la contraseña
Se termina presionando el botón “Create User”. 620
Ya se puede recargar la configuración de Asterisk: /etc/init.d/asterisk reload Se averigua el resultado desde la consola de Asterisk asterisk -rvvvvvvvvvvvv CLI> xmpp show connections Jabber Users and their status: [campusvtv] [email protected] - Connected [asterisk] [email protected]/openfire
- Connected
Para ver la lista de amigos: CLI> xmpp show buddies Client: asterisk Buddy: [email protected] Resource: Spark 2.6.3 node: version: Google Talk capable: no Jingle capable: no En el menú “Sessions” de Openfire:
Se inicia el cliente Spark y se añade el usuario asterisk:
621
El resultado será:
24.5 Conectar dos servidores Openfire Si se conectan dos servidores Openfire entre ellos, los usuarios de uno podrán agregar en su lista de amigos usuarios del otro servidor. Para lograr este tipo de comportamiento hay que modificar la configuración en los dos servidores: Los dos servidores están instalados en dos computadores de la misma LAN: Openfire A dominio: li115-178.members.linode.com Openfire B dominio: li340-16.members.linode.com • •
Primero: si hay un cortafuegos por el medio, hay que abrir el puerto 5269 TCP en ambos Segundo: se entra en la pagina de administración del servidor A y se escoge el menú Server → 622
Server Settings → Server to Server Se configura la página como sigue:
Luego se pasa al menú Server > Server settings > Security settings y bajo el cuadro Server Connection Security se selecciona la casilla:
623
Se guardan los cambios y se sigue el mismo procedimiento en el servidor B indicando el dominio: li340-16.members.linode.com en la White List. Se guardan los cambios. La conexión se activa solamente cuando de un servidor se envía una solicitud a otro servidor. Para probarla en el servidor B se crea un nuevo usuario (menú Users/Groups → Create New User):
Ahora desde el cliente Spark conectado al servidor A, se añade a la lista de amigos el usuario servidorb:
624
Se entra en el menú Sessions > Server Session de ambos servidores donde debería aparecer: Servidor A:
Servidor B:
625
Si no aparece ninguna conexión se puede usar el programa Telnet para averiguar si el puerto 5269 TCP esté efectivamente abierto. Desde la consola de Linux del servidor A se escribe: yum install telnet telnet telnet> o -a li340-16.members.linode.com 5269 Trying 96.126.115.16... Connected to li340-16.members.linode.com. Escape character is '^]'. Connection closed by foreign host. Si aparece la expresión en negrita todo está bien. Para tres o más servidores Openfire, que queremos conectar entre ellos, se sigue el mismo procedimiento. 24.6 Openfire Connection Manager Si hay que manejar un numero considerable de usuarios (más de 1000 en linea a la vez), hay que recurrir al Connection Manager. Este programa se configura delante del servidor Openfire y gestiona las conexiones y las identificaciones de los usuarios. Se pueden instalar uno o más Connection Manager según el numero de usuarios. Cada Connection Manager es capaz de manejar cinco mil usuarios. El esquema de funcionamiento es el que aparece en la imagen que sigue:
En ese ejemplo hay tres Connection Managers instalados que reciben los registros de los usuarios y a su vez están conectados con el servidor Openfire. Los clientes tendrán que conectarse a ese servidor y luego serán enrutados por el Connection Manager al servidor Openfire. Se descarga el programa: 626
cd /opt wget http://www.voztovoice.org/tmp/connection_manager_3_6_3.tar.gz Se descomprime: tar -xf connection_manager_3_6_3.tar.gz Se entra en la carpeta de configuración y se modifica el archivo manager.xml cd /opt/connection_manager/conf nano manager.xml Las líneas que hay que modificar son: •
domain: el nombre de dominio del servidor Openfire (ej: miodominio.org)
•
hostname: la dirección IP del servidor Openfire
•
port: el puerto configurado en el servidor Openfire para aceptar las conexiones del Connection Manager (5262 predefinido)
•
password: la contraseña que se ha definido en el servidor Openfire para aceptar las conexiones del Connection Manager
•
name: un nombre que se quiere asignar a el Connection Manager (muy útil si se tiene planeado instalar más de uno).
•
interface: se pone el nombre de la interfaz de red donde el Connection Manager se pondrá a la escucha para las conexiones de los clientes
Se guardan los cambios. Para terminar se instala el “script” para iniciar Connection Manager en automático: cd /opt/connection_manager/bin/extra nano cmanagerd Se modifican las siguientes líneas: export CMANAGER_HOME=/opt/connection_manager export CMANAGER_USER=root 627
Se guardan los cambios y se termina: cp cmanagerd /etc/init.d/ chmod +x /etc/init.d/cmanagerd chkconfig --add cmanagerd chkconfig cmanagerd on Antes de arrancar el Connection Manager hay que modificar la configuración del servidor Openfire. Desde la pagina di administración del servidor Openfire bajo el menú “Server settings” se elige “Connection Manager”. En la pagina que aparece se activa el servicio, se escoge el puerto y se define una contraseña.
Se presiona el botón “Save Settings”. Como el Connection Manager utilizará los puertos 5222 y 5223 para aceptar las conexiones de los clientes y los mismos puertos están configurados en Openfire, hay que modificarlos. En Openfire se entra en el menú Server Manager → Server Information:
628
Se presiona el botón “Edit Properties”:
Se modifican los puertos como indicado en la imagen y se guardan las modificaciones presionando el botón “Save Properties”. Ahora se puede arrancar el Connection Manager. En el servidor Linux donde se instaló se escribe: /etc/init.d/cmanagerd start Se averigua que esté corriendo: /etc/init.d/cmanagerd status running pid is 5747 Connection Manager 3.6.3 [Feb 6, 2010 5:02:17 AM] y en la pagina de administración de Openfire se verifica que está conectado:
629
Desde un cliente XMPP se crea una conexión como si fuera para el servidor Openfire.
630
Capitulo XXV Asterisk y alta disponibilidad El servidor Asterisk ya está instalado y trabajando. Ahora se quiere tener una copia de la base de datos actualizada en tiempo real para hacer frente a cualquier tipo de evento que pueda afectar la integridad de los registros de las llamadas o de las configuraciones en Realtime. En este tipo de escenario hay disponible una funcionalidad de MySQL; la posibilidad de replicar los datos en un servidor MySQL instalado en otro computador. Hay dos formas de replicar los datos: • •
configurar una replicación master-slave (maestro-esclavo) configurar una replicación master-master (maestro-maestro)
Como no se pueden tener los dos tipos de configuraciones activas a la vez, antes de empezar, habrá que escoger el tipo que se quiere implementar. 25.1 Replicación MySQL Master-Slave En este párrafo se verá como crear una replicación MySQL Master-Slave. La replicación master-slave no es una copia de backup de la base de datos, de hecho si se borra una entrada en el MySQL maestro, automáticamente se borrará también en el esclavo. La idea es tener siempre una copia de backup y además crear la replicación maestro-esclavo. Se puede utilizar el esclavo para efectuar consultas desde otros programas y de esta manera no cargar demasiado el Maestro. Un ejemplo puede ser cuando se generan reportes mensuales de las llamadas. En vez de realizar las consultas en el maestro, se efectúan en el esclavo. Es buena practica usar una conexión dedicada para el intercambio de datos entre el maestro y el esclavo para evitar que hayan retrasos considerables en la actualización de la base de datos. ¿Como funciona la replicación MySQL Master-slave? • • •
El Maestro registra los cambios en un registro binario (Binary log) El esclavo copia los eventos en un registro propio (Relay log) El esclavo lee y repite los eventos presentes en el Relay log en la base de datos
Una imagen que explica el funcionamiento:
El escenario que se va a presentar es el siguiente: ServidorA: IP LAN: 192.168.128.144 Base de datos a replicar: asteriskcdr asterisk Master ServidorB: IP LAN: 192.168.128.145 Esclavo Base de datos replicadas: asteriskcdr asterisk Servidor A: Se crea una carpeta donde guardar los Binary log: mkdir /var/log/mysql Se cambian los permisos de modo que MySQL pueda escribir y leer en esa carpeta: chown mysql:mysql /var/log/mysql Se entra en el cliente mysql mysql -u root -psesamo y se crean los privilegios de replicación para un nuevo usuario que luego se configurará en el servidorB: 633
myslq> GRANT REPLICATION SLAVE ON *.* TO 'asterisk'@'192.168.128.145' IDENTIFIED BY 'sesamo'; La IP que se indica es la del ServidorB. Se actualizan los privilegios y se sale del cliente MySQL: mysql> flush privileges; mysql> quit Ahora se modifica el archivo de configuración de MySQL para configurar los parámetros necesarios para la replicación: nano /etc/my.cnf Bajo la etiqueta [mysqld] se añaden las siguientes líneas: server-id = 10 log_bin = /var/log/mysql/mysql-bin.log expire_logs_days = 10 max_binlog_size = 100M binlog_do_db = asteriskcdr binlog_do_db = asterisk sync_binlog=1 Una pequeña explicación de los parámetros: • • • • • •
server-id: identifica el servidor MySQL log_bin: nombre del archivo donde se guardará el Binary log expire_log_days: especifica que los archivos Binary log más viejos de 10 días se pueden borrar max_binlog_size: el tamaño máximo de un Binary log binlog_do_db: el nombre de las base de datos que se van a replicar (una por linea) sync_binlog: cada evento generado en el Master será escrito inmediatamente en el Binary log. Aumenta la carga del Master a cambio de una replicación más precisa. IMPORTANTE: en el caso de sistemas con muchas llamadas por segundo, es mejor deshabilitar esta opción
Se guardan los cambios y se reinicia MySQL /etc/init.d/mysqld restart Considerando que el servidor Asterisk tiene tiempo trabajando hay que crear una copia de las bases de datos para luego importarla en el servidor MySQL esclavo: mysql -u root -psesamo Se bloquea la lectura de todas las tablas de todas las bases de datos:
634
mysql> FLUSH TABLES WITH READ LOCK; Por ultimo se mira el estado del Master: mysql> SHOW MASTER STATUS; Aparecerá algo por el estilo:
Se anotan los datos que aparecen en la columna File (mysql-bin.000003) y en la columna Position (106). Sin cerrar esta ventana, se abre otra ventana terminal o otra conexión al servidor Linux y se crea una copia de la base de datos asteriskcdr y asterisk: cd /tmp mysqldump -u root -psesamo asteriskcdr > asteriskcdr.sql mysqldump -u root -psesamo asterisk > asterisk.sql se copian los archivos en el servidoB en la carpeta tmp: scp -P 15000 *.sql [email protected]:/tmp Se cierra esta ventana y se vuelve a la primera. Se desbloquean las tablas: mysql> UNLOCK TABLES; y se sale del cliente: mysql> quit Servidor B Si MySQL, no está instalado se instala: yum install mysql mysql-server mysql-devel Se inicia: /etc/init.d/mysqld start 635
Se crea una contraseña para el usuario root: mysqladmin –u root password sesamo Se modifica el archivo de configuración de MySQL nano /etc/my.cnf bajo la etiqueta [mysqld] se pone: server-id=20 master-connect-retry=60 replicate-do-db=asteriskcdr replicate-do-db=asterisk skip_slave_start read_only Los parámetros: • • • • •
server-id: numero que identifica el servidor MySQL del servidorB master-connect-retry: si el esclavo pierde la conexión con el maestro, cada 60 segundos intentará restablecerla replicate-do-db: la base de datos que se van a replicar (una por linea) skip_slave_start: evita que el esclavo se reinicie en el caso de un crash del servidor read_only: no permite a la mayoría de los usuarios del servidor MySQL esclavo cambiar las tablas
Se guardan los cambios y se reinicia MySQL: /etc/init.d/mysqld restart Se crean las base de datos: mysqladmin -u root -psesamo create asteriskcdr mysqladmin -u root -psesamo create asterisk se recuperan tablas y datos de la copia que está en la carpeta /tmp: cd /tmp mysql -u root -psesamo asteriskcdr < asteriskcdr.sql mysql -u root -psesamo asteriskcdr < asterisk.sql A este punto se crean los datos de acceso al servidor MySQL Master:
636
mysql -u root -psesamo mysql> CHANGE MASTER TO MASTER_HOST='192.168.128.144', MASTER_USER='asterisk', MASTER_PASSWORD='sesamo', MASTER_LOG_FILE='mysql-bin.000003', MASTER_LOG_POS=106; En MASTER_LOG_FILE Y MASTER_LOG_POS, se ponen los datos del servidor MySQL A que se había anotado. Antes de iniciar el esclavo, hay que abrir el puerto TCP 3306 en el servidorA. Se realiza indicando que la única IP que podrá conectarse será la del Servidor B: nano /etc/sysconfig/iptables Después de este bloque: # Monit -A INPUT -p tcp -m state --state NEW -m tcp --dport 2812 -j ACCEPT Se pone: # MySQL -A INPUT -p tcp -m state --state NEW -m tcp -s 192.168.128.145 --dport 3306 -j ACCEPT Se guardan los cambios y se reinicia iptables y Fail2ban: service iptables restart service fail2ban restart Se vuelve a la ventana del servidorB y se inicia el esclavo: mysql> START SLAVE; Se controla el estado de la conexión con el Master: mysql> SHOW SLAVE STATUS\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.128.144 Master_User: asterisk Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000003 Read_Master_Log_Pos: 106 Relay_Log_File: mysqld-relay-bin.000002 637
Relay_Log_Pos: 251 Relay_Master_Log_File: mysql-bin.000003 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: asteriskcdr,asterisk Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 106 Relay_Log_Space: 407 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0 Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: 1 row in set (0.00 sec) Asegurarse que estos dos parámetros: • •
Slave_IO_Running Slave_SQL_Running
estén en Yes. Se sale del cliente: mysql> quit Ahora se efectúa una llamada de prueba. Desde la extensión 1000 conectada al servidorA se llama el buzón de voz. Antes de hacerlo se activa en el servidorB la captura de paquetes con Ngrep para el puerto 3306 y la red local: ngrep -d eth0:1 -W byline port 3306 > /tmp/esclavo 638
Terminada la llamada, se cierra la captura de paquetes y se mira que contiene el archivo /tmp/esclavo El servidorA (192.168.128.144) ha enviado tres paquetes al servidorB (192.168.128.145) para actualizar las tablas CDR, CDR2, CDR3 y CDR4 de la base de datos asteriskcdr del servidor B. 25.2 Replicación MySQL Master-Master En el párrafo anterior se ha visto como usar la replicación MySQL Master-Slave para las bases de datos asteriskcdr y asterisk. En éste se verá como utilizar la replicación MySQL Master-Master para la mismas base de datos. ¿Qué diferencia hay entra una replicación Maestro-Esclavo y una Maestro-Maestro? En el primer caso se tiene una copia de todos los registros en otro servidor y se pueden efectuar estadísticas usando el Esclavo sin sobrecargar el Maestro. En el segundo caso la configuración se utiliza para la alta disponibilidad en Asterisk. Ejemplo: hay dos servidores Asterisk: A y B. Si A se cae B toma su lugar. Cuando A vuelve a funcionar, B vuelve a ser el servidor de respaldo. Como se verá en los próximos párrafos, para la alta disponibilidad en Asterisk, además de la replicación Master-Master, se necesitará configurar otros programas. Claramente para la alta disponibilidd en Asterisk, en el segundo servidor hay que instalar una copia exacta del servidor Asterisk con las mismas configuraciones. Escenario: ServidorA: IP 192.168.128.144 Base de datos a replicar: asteriskcdr asterisk MasterA SlaveA ServidorB: IP 192.168.128.145 Base de datos a replicar: asteriskcdr asterisk MasterB SlaveB Las bases de datos en el ServidorA ya existen y tienes unos cuantos datos registrados. El problema principal de la replicación Master-Master es el conflicto que se puede presentar en las entradas de la tabla. Ejemplo: el servidorA se cae y toma su lugar el servidorB. Se registran unos cuantos datos en la tabla cdr del servidorB. Mientras el servidorA vuelve a funcionar y antes que el servidorB pueda actualizar los datos de la tabla CDR en el servidorA, este empieza a grabar nuevas entradas en la misma tabla. En este escenario se pueden generar conflictos entre los datos de las dos tablas y errores de replicación porque los dos presentan entradas con el mismo ID en la clave primaria de la tabla (siendo progresivo). Para solucionar este tipo de problema se utilizarán estos dos parámetros: 639
• •
auto_increment_increment auto_increment_offset
ServidorA Se entra en el cliente MySQL y se consultan las fechas de las llamadas de la extensión 1000: mysql -u root -psesamo mysql> use asteriskcdr mysql> select acctid,calldate from cdr where dst=1000; +----+---------------------+ | id | calldate | +----+---------------------+ | 21 | 2011-12-14 13:21:42 | | 55 | 2011-12-15 09:01:57 | | 56 | 2011-12-15 09:03:10 | | 57 | 2011-12-15 09:03:28 | | 58 | 2011-12-15 09:03:56 | +----+---------------------+ 5 rows in set (0.00 sec) Se crea una carpeta donde guardar los Binary log de MySQL y se cambia usuario y grupo que tiene los permisos en la carpeta creada: mkdir /var/log/mysql chown mysql:mysql /var/log/mysql Se regresa al cliente MySQL y se crean los privilegios de replicación para un nuevo usuario: mysql -u root -psesamo mysql> GRANT REPLICATION SLAVE ON *.* TO 'masterb'@'192.168.128.145' IDENTIFIED BY 'sesamo'; mysql> flush privileges; mysql> quit Se modifica el archivo de configuración de MySQL: nano /etc/my.cnf
640
bajo la etiqueta [mysqld] se pone: server-id = 10 auto_increment_increment = 10 auto_increment_offset = 1 log_bin = /var/log/mysql/mysql-bin.log expire_logs_days = 10 max_binlog_size = 100M replicate-do-db =asteriskcdr replicate-do-db =asterisk sync_binlog =1 Los parámetros: • •
Con auto_increment_increment a 10 cada entrada en la tabla cdr tendrá un ID progresivo que irá de 10 en 10. Con auto_increment_offset a 1 cada entrada usará el entero 1
En el caso de tres entradas en la tabla el resultado será: ID 1 ID 11 ID 21 •
Con replicate-do-db se define que la replicación es para las bases de datos asteriskcdr y asterisk
Se reinicia mysql: /etc/init.d/mysqld restart Considerando que el servidor Asterisk tiene tiempo trabajando hay que crear una copia de las base de datos para luego importarla en el servidorB: mysql -u root -psesamo Se bloquea la lectura de todas las tablas de todas las bases de datos: mysql> FLUSH TABLES WITH READ LOCK; Por ultimo se mira el estado del Master: mysql> SHOW MASTER STATUS; Aparecerá algo por el estilo: +------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | 641
+------------------+----------+--------------+------------------+ | mysql-bin.000001 | 31292 | | | +------------------+----------+--------------+------------------+ 1 row in set (0.00 sec) Se anotan los datos que aparecen en la columna File (mysql-bin.000001) y en la columna Position (31292); sin cerrar esta ventana, se abre otra ventana terminal o otra conexión al servidor Linux y se crea una copia de las bases de datos: cd /tmp mysqldump -u root -psesamo asteriskcdr > asteriskcdr.sql mysqldump -u root -psesamo asterisk > asterisk.sql se copia el archivo en el servidorB en la carpeta tmp: scp -P 15000*.sql [email protected]:/tmp Se cierra esta ventana y se regresa a la primera. Se desbloquean las tablas: mysql> UNLOCK TABLES; y se sale del cliente: mysql> quit Para dar acceso a la base de datos al servidorB, hay que abrir el puerto TCP 3306 solamente para esa IP local en el servidorA: nano /etc/sysconfig/iptables En la sección filter se añade: # MySQL -A INPUT -p tcp -m state --state NEW -m tcp -s 192.168.128.145 --dport 3306 -j ACCEPT Se reinicia iptables y fail2ban: service iptables restart service fail2ban restart ServidorB Se crea la carpeta para guardar los Bynary log con los permisos para el usuario mysql: mkdir /var/log/mysql 642
chown mysql:mysql /var/log/mysql Se entra en el cliente mysql y se crea la base de datos asterisk: mysql -u root -psesamo mysql> create database asteriskcdr; mysql> create database asterisk; Se crean los usuarios que tendrán acceso a las dos base de datos: mysql> grant all privileges on asteriskcdr.* to 'asterisk'@'localhost' identified by 'sesamo'; mysql> grant all privileges on asterisk.* to 'asterisk'@'localhost' identified by 'sesamo'; mysql> flush privileges; mysql> quit Se importan las dos bases de datos: cd /tmp mysql -u root -psesamo asteriskcdr < asteriskcdr.sql mysql -u root -psesamo asterisk < asterisk.sql Se averigua que efectivamente las tabla y los datos presentes se han guardado: mysql -u root -psesamo mysql> use asteriskcdr mysql> select acctid,calldate from cdr where dst=1000; +----+---------------------+ | id | calldate | +----+---------------------+ | 21 | 2011-12-14 13:21:42 | | 55 | 2011-12-15 09:01:57 | | 56 | 2011-12-15 09:03:10 | | 57 | 2011-12-15 09:03:28 | | 58 | 2011-12-15 09:03:56 | +----+---------------------+ 5 rows in set (0.00 sec) Aparecerán las mismas entradas del servidorA. Se crea un nuevo usuarios con los permisos de replicación: 643
mysql> GRANT REPLICATION SLAVE ON *.* TO 'mastera'@'192.168.128.144' IDENTIFIED BY 'sesamo'; mysql> flush privileges; mysql> quit Ahora se modifica el archivo de configuración de MySQL: nano /etc/my.cnf bajo la etiqueta [mysqld] se pone: server-id = 20 auto_increment_increment = 10 auto_increment_offset = 2 log_bin = /var/log/mysql/mysql-bin.log expire_logs_days = 10 max_binlog_size = 100M replicate-do-db =asteriskcdr replicate-do-db =asterisk sync_binlog =1 El auto_increment_offset es igual a 2. En el caso de tres entradas el ID sería: ID 2 ID 12 ID 22 Como se puede ver, de esta forma no se presentarán conflictos en las entradas de la tabla CDR. Se reinicia Mysql: /etc/init.d/mysqld restart Y ahora como para el servidorA se mira el Binary log y se anotan los datos: mysql -u root -psesamo mysql> FLUSH TABLES WITH READ LOCK; mysql> SHOW MASTER STATUS; +------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+--------------+------------------+ | mysql-bin.000001 | 106 | | | +------------------+----------+--------------+------------------+ 644
1 row in set (0.00 sec) mysql> UNLOCK TABLES; mysql> quit Para dar acceso a la base de datos al servidorA, hay que abrir el puerto TCP 3306 solamente para esa IP local en el servidorB: nano /etc/sysconfig/iptables En la sección filter se añade: # MySQL -A INPUT -p tcp -m state --state NEW -m tcp -s 192.168.128.144 --dport 3306 -j ACCEPT Se reinicia el servicio y fail2ban: service iptables restart service fail2ban restart Ahora se conecta el servidorB al servidorA: mysql -u root -psesamo mysql> CHANGE MASTER TO MASTER_HOST='192.168.128.144', MASTER_USER='masterb', MASTER_PASSWORD='sesamo', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=31292; Query OK, 0 rows affected (0.00 sec) Se inicia el esclavo: mysql> START SLAVE; Query OK, 0 rows affected (0.00 sec) y se mira el resultado: mysql> SHOW SLAVE STATUS\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.128.144 Master_User: masterb Master_Port: 3306 Connect_Retry: 60 645
Master_Log_File: mysql-bin.000001 Read_Master_Log_Pos: 2418411 Relay_Log_File: mysqld-relay-bin.000002 Relay_Log_Pos: 1780183 Relay_Master_Log_File: mysql-bin.000001 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: asteriskcdr,asterisk Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 2418411 Relay_Log_Space: 1780339 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0 Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Se sigue el mismo procedimiento para el ServidorA: Se entra en MySQL: mysql -u root -psesamo mysql> CHANGE MASTER TO MASTER_HOST='192.168.128.145', MASTER_USER='mastera', MASTER_PASSWORD='sesamo', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=106; Query OK, 0 rows affected (0.10 sec)
646
mysql> START SLAVE; mysql> SHOW SLAVE STATUS\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.128.145 Master_User: mastera Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000002 Read_Master_Log_Pos: 359 Relay_Log_File: mysqld-relay-bin.000003 Relay_Log_Pos: 504 Relay_Master_Log_File: mysql-bin.000002 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: asteriskcdr,asterisk Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 359 Relay_Log_Space: 805 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0 Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: La prueba Se para el MySQL del servidorB y se efectúan dos llamadas desde la extensión 1000 del Asterisk A al buzón de voz. 647
El resultado en la base de datos: mysql -u root -psesamo mysql> use asteriskcdr mysql> select acctid,calldate from cdr where dst=97; +----+---------------------+ | id | calldate | +----+---------------------+ | 32 | 2011-12-14 18:06:06 | | 54 | 2011-12-15 08:51:20 | | 61 | 2011-12-15 09:33:23 | | 71 | 2011-12-15 09:33:48 | +----+---------------------+ 4 rows in set (0.00 sec) Mientras antes el ID era progresivo, las ultimas dos entradas tienen un salto de 10 y cada una termina con el numero 1. Terminada la operación, se para MySQL en el servidorA y se inicia MySQL en el servidorB efectuando dos llamadas al buzón de voz usando el Asterisk del servidorB. El resultado en la base de datos: mysql -u root -psesamo mysql> use asteriskcdr mysql> select acctid,calldate from cdr where dst=97; +----+---------------------+ | id | calldate | +----+---------------------+ | 32 | 2011-12-14 18:06:06 | | 54 | 2011-12-15 08:51:20 | | 61 | 2011-12-15 09:33:23 | | 71 | 2011-12-15 09:33:48 | | 72 | 2011-12-15 09:38:07 | | 82 | 2011-12-15 09:39:14 | +----+---------------------+ 6 rows in set (0.00 sec) El ID progresivo en el servidorB cambia con saltos de 10 y cada entrada termina con el numero 2. Ahora se inicia MySQL en el servidorA y se mira que pasa en los dos servidores: ServidorA 648
mysql -u root -psesamo mysql> use asteriskcdr mysql> select acctid,calldate from cdr where dst=97; +----+---------------------+ | id | calldate | +----+---------------------+ | 32 | 2011-12-14 18:06:06 | | 54 | 2011-12-15 08:51:20 | | 61 | 2011-12-15 09:33:23 | | 71 | 2011-12-15 09:33:48 | | 72 | 2011-12-15 09:38:07 | | 82 | 2011-12-15 09:39:14 | +----+---------------------+ 6 rows in set (0.00 sec) ServidorB mysql -u root -psesamo mysql> use asteriskcdr mysql> select acctid,calldate from cdr where dst=97; +----+---------------------+ | id | calldate | +----+---------------------+ | 32 | 2011-12-14 18:06:06 | | 54 | 2011-12-15 08:51:20 | | 61 | 2011-12-15 09:33:23 | | 71 | 2011-12-15 09:33:48 | | 72 | 2011-12-15 09:38:07 | | 82 | 2011-12-15 09:39:14 | +----+---------------------+ 6 rows in set (0.00 sec) Los datos se han replicado y no hubo ningún tipo de conflicto en la tabla cdr gracias al uso de: • •
auto_increment_increment auto_increment_offset
25.3 DRBD - Raid1 vía TCP DRBD es un programa que permite conectar particiones presentes en distintos servidores y tenerlas 649
sincronizadas. Funciona en el mismo modo de un sistema RAID1 con la sencilla diferencias que las copias de los datos se realizan a través de la red utilizando el protocolo TCP. Se verá como instalar DRBD en dos servidores VPS en Linode y de esta forma crear un sistema de alta disponibilidad para Asterisk. Lo mismo se puede realizar con dos servidores locales con las modificaciones oportunas. Al momento de configurar el servidor Linode, se han creado 4 particiones:
La ultimas dos es las que se utilizarán para DRDB. Claramente las mismas particiones tienen que ser creadas en el segundo servidor de respaldo. Una vez terminada esta operación, los dos servidores Linode estarán listos para la instalación y configuración de DRBD. Servidor A IP publico: 69.164.201.178 IP Lan: 192.168.128.144 Dominio: li115-178.members.linode.com Servidor B IP publico: 96.126.115.16 IP Lan: 192.168.128.145 Dominio: li340-16.members.linode.com Se inicia la configuración de los dos servidores para que cada uno sepa a que dirección IP encontrar el otro: Servidor A nano /etc/hosts Al final de archivo se añaden las siguientes líneas: 192.168.128.144 li115-178.members.linode.com 192.168.128.145 li340-16.members.linode.com Se guardan los cambios y se averigua que efectivamente se logra localizar el servidorB:
650
ping li340-16.members.linode.com PING li340-16.members.linode.com (192.168.128.145) 56(84) bytes of data. 64 bytes from li340-16.members.linode.com (192.168.128.145): icmp_seq=1 ttl=64 time=0.671 ms 64 bytes from li340-16.members.linode.com (192.168.128.145): icmp_seq=2 ttl=64 time=0.430 ms 64 bytes from li340-16.members.linode.com (192.168.128.145): icmp_seq=3 ttl=64 time=0.405 ms 64 bytes from li340-16.members.linode.com (192.168.128.145): icmp_seq=4 ttl=64 time=0.479 ms 64 bytes from li340-16.members.linode.com (192.168.128.145): icmp_seq=5 ttl=64 time=0.518 ms 64 bytes from li340-16.members.linode.com (192.168.128.145): icmp_seq=6 ttl=64 time=0.483 ms --- li340-16.members.linode.com ping statistics --6 packets transmitted, 6 received, 0% packet loss, time 4997ms rtt min/avg/max/mdev = 0.405/0.497/0.671/0.089 ms Se efectúa el mismo procedimiento en el servidor B Servidor B nano /etc/hosts Se añaden las siguientes líneas: 192.168.128.144 li115-178.members.linode.com 192.168.128.145 li340-16.members.linode.com ping li115-178.members.linode.com PING li115-178.members.linode.com (192.168.128.144) 56(84) bytes of data. 64 bytes from li115-178.members.linode.com (192.168.128.144): icmp_seq=1 ttl=64 time=0.587 ms 64 bytes from li115-178.members.linode.com (192.168.128.144): icmp_seq=2 ttl=64 time=0.422 ms 64 bytes from li115-178.members.linode.com (192.168.128.144): icmp_seq=3 ttl=64 time=0.542 ms 64 bytes from li115-178.members.linode.com (192.168.128.144): icmp_seq=4 ttl=64 time=0.420 ms 64 bytes from li115-178.members.linode.com (192.168.128.144): icmp_seq=5 ttl=64 time=0.386 ms 64 bytes from li115-178.members.linode.com (192.168.128.144): icmp_seq=6 ttl=64 time=0.525 ms --- li115-178.members.linode.com ping statistics --6 packets transmitted, 6 received, 0% packet loss, time 4996ms rtt min/avg/max/mdev = 0.386/0.480/0.587/0.076 ms Una vez terminada esta parte se prepara el sistema para la instalación de DRBD: Las operaciones que siguen hay que ejecutarlas en ambos servidores: yum install pcre-devel xmlrpc-c-devel lynx -y cd /usr/src
651
wget http://oss.linbit.com/drbd/8.3/drbd-8.3.15.tar.gz tar -xf drbd-8.3.15.tar.gz cd drbd-8.3.15 ./configure --prefix=/ --with-km Se compila utilizando la ultimas versión de las fuentes del Kernel instalado en el servidor, es decir: uname -r 2.6.32-504.12.2.el6.x86_64 make KDIR=/usr/src/kernels/2.6.32-504.12.2.el6.x86_64 make install Se mueve la configuración predefinida que viene con la instalación de DRBD mv /etc/drbd.conf /etc/drbd.conf.old se crea una nueva: nano /etc/drbd.conf Se copian las lineas que siguen en ambos servidores: global { usage-count yes; } common { protocol C; } resource data { net { allow-two-primaries; after-sb-0pri discard-zero-changes; after-sb-1pri discard-secondary; after-sb-2pri disconnect; } startup { become-primary-on both; } on li115-178.members.linode.com { device /dev/drbd1; disk /dev/xvdc; address 192.168.128.144:7789; meta-disk /dev/xvdd[0]; 652
} on li340-16.members.linode.com { device /dev/drbd1; disk /dev/xvdc; address 192.168.128.145:7789; meta-disk /dev/xvdd[0]; } } De esta forma se crean dos nodos primarios usando el protocolo C y se nombra este recurso creado “data”. El nodo 1 será li115-178.members.linode.com cuya IP local es 192.168.128.144 Se utilizarán las dos particiones creadas (xvdc y xvdd) una para las copia de los datos y la otra como meta disco para guardar los datos que DRBD crea al momento de conectarse y sincronizarse con el segundo nodo. El nodo 2 será li340-16.members.linode.com cuya IP local es 192.168.128.145. Para que los dos servidores DRBD pueda comunicarse hay que abrir los puerto de 7788 a 7799 TCP en ambos. ServidorA nano /etc/sysconfig/iptables Después de este bloque: # HTTP -A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT se añade: # DRBD -A INPUT -p tcp -m state --state NEW -m tcp -s 192.168.128.145 --dport 7788:7799 -j ACCEPT indicando la IP del servidorB. Se guardan los cambios y se reinicia IPtables y Fail2Ban: service iptables restart service fail2ban restart ServidorB nano /etc/sysconfig/iptables Después de este bloque: # HTTP 653
-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT se añade: # DRBD -A INPUT -p tcp -m state --state NEW -m tcp -s 192.168.128.144 --dport 7788:7799 -j ACCEPT indicando la IP del servidorA. Se guardan los cambios y se reinicia IPtables y Fail2Ban: service iptables restart service fail2ban restart Ahora se crean los meta-datos en la partición xvdd de ambos servidores: drbdadm create-md data Normalmente sale este error: Found ext3 filesystem This would corrupt existing data. If you want me to do this, you need to zero out the first part of the device (destroy the content). You should be very sure that you mean it. Operation refused. Command 'drbdmeta 1 v08 /dev/xvdd 0 create-md' terminated with exit code 40 Se soluciona destruyendo todos los datos presentes en la partición: dd if=/dev/zero of=/dev/xvdd bs=1M count=128 128+0 records in 128+0 records out 134217728 bytes (134 MB) copied, 1,2176 seconds, 110 MB/s Se ejecuta otra vez el comando: drbdadm create-md data Writing meta data... initializing activity log NOT initializing bitmap New drbd meta data block successfully created. success Se configurara el programa para que el servicio arranque en automático: chkconfig --add drbd 654
chkconfig drbd on Para crear una primera sincronización entre los datos de las dos particiones de los dos servidores se carga el modulo DRBD en el Kernel: modprobe drbd se averigua que efectivamente esté cargado: lsmod | grep drbd drbd 251364 0 Ahora se crea la conexión entre los dos servidores: drbdadm attach data drbdadm syncer data drbdadm connect data Se efectúa una primera sincronización de los datos: Servidor A drbdadm -- --overwrite-data-of-peer primary data Esta operación puede durar bastante tiempo dependiendo del tamaño de los discos. Se puede controlar en cualquier momento a que punto ha llegado con el comando: cat /proc/drbd version: 8.3.7 (api:88/proto:86-91) GIT-hash: ea9e28dbff98e331a62bcbcc63a6135808fe2917 build by [email protected], 2011-12-15 11:24:58 1: cs:SyncSource ro:Primary/Secondary ds:UpToDate/Inconsistent C r---ns:3672 nr:0 dw:0 dr:3672 al:0 bm:0 lo:6 pe:0 ua:6 ap:0 ep:1 wo:b oos:815528 [>....................] sync'ed: 1.0% (815528/819200)K finish: 0:42:28 speed: 252 (244) K/sec Cuando el proceso termine, aparecerá: cat /proc/dbd version: 8.3.7 (api:88/proto:86-91) 655
GIT-hash: ea9e28dbff98e331a62bcbcc63a6135808fe2917 178.members.linode.com, 2011-12-15 11:24:58
build
by
root@li115-
1: cs:Connected ro:Primary/Secondary ds:UpToDate/UpToDate C r---ns:819200 nr:0 dw:0 dr:819200 al:0 bm:50 lo:0 pe:0 ua:0 ap:0 ep:1 wo:b oos:0 Se reinician ambos servidores: reboot Servidor A Se crea una nueva carpeta donde se copiarán los datos que se quieren sincronizar: mkdir /home/data Se monta la partición de los datos: mount /dev/drbd1 /home/data se crean unos cuantos archivos de prueba: touch /home/data/file1 touch /home/data/file2 touch /home/data/file3 ls /home/data file1 file2 file3 lost+found Se desmonta la partición: umount /home/data y se averigua el resultado en el servidor B Servidor B mkdir /home/data mount /dev/drbd1 /home/data ls /home/data file1 file2 file3 lost+found 656
umount /home/data En el caso que se quiera tener sincronizados los archivos de configuración de Asterisk, se copian directamente la carpeta de esta forma: Servidor A mount /dev/drbd1 /home/data mkdir /home/data/etc cd /etc mv asterisk /home/data/etc/asterisk Para terminar se crea un enlace simbólico a la nueva carpeta: ln -s /home/data/etc/asterisk asterisk Lo mismo con DAHDI: mv dahdi /home/data/etc/dahdi ln -s /home/data/etc/dahdi dahdi umount /home/data Servidor B mount /dev/drbd1 /home/data cd /etc rm -fr asterisk rm -fr dahdi ln -s /home/data/etc/asterisk asterisk ln -s /home/data/etc/dahdi dahdi umount /home/data Ya está configurado y funcionando DRBD. No hace falta dejar la partición montada en ninguno de los dos servidores porque, como se verá en el próximo párrafo, Heartbeat se encargará de hacerlo según el 657
servidor que esté activo en ese momento. 25.4 Heartbeat Se termina el capitulo dedicado a Asterisk y alta disponibilidad con la instalación y configuración de Heartbeat. Heartbeat se necesita para que los dos servidores conozcan el estado del otro. Cuando el master se cae, el slave toma el control cargando la partición de DRBD donde hemos guardado los datos de configuración de Asterisk, poniendo activo el IP compartido y iniciando dahdi y asterisk. Cuando se utiliza Asterisk alta disponibilidad con este tipo de configuración, habrá un IP publico compartido que es él que se utilizará para registrar las extensiones. En el caso de una red publica y de Linode sería algo parecido: IP Servidor Asterisk Master IP Asterisk Publico IP servidor Asterisk Slave Se utilizará la misma configuración que se presentó en el párrafo 25.3. Para resumir: Servidor A IP publico: 69.164.201.178 IP Lan: 192.168.128.144 Servidor B IP publico: 96.126.115.16 IP Lan: 192.168.128.145 Primero se compra en Linode un segundo IP publico para el servidor A (costo: un dólar al mes) que será el IP “virtual” que compartirán los dos servidores. Una vez comprado, en la pagina de administración de Linode del servidor B se configura el failover. Esto permite que al caerse el servidor A, el servidor B tomará la gestión de ese IP. En el menú “Remote Access” del Servidor B:
Se escoge el enlace “IP Failover”. En la nueva pagina:
Se selecciona la nueva IP adquirida y se presiona el botón “Save Changes”. Ahora hay que instalar Heartbeat en ambos servidores. Este programa es presente en los repositorios epel: yum --enablerepo=epel install heartbeat* -y 658
Ahora hay que crear tres archivos de configuración: • ha.cf • authkeys • haresources Se empieza con el que se encarga de controlar el estado de los servidores. Servidor A: nano /etc/ha.d/ha.cf se pegan las siguientes líneas: debugfile /var/log/ha-debug logfile /var/log/ha-log logfacility local0 keepalive 2 deadtime 120 initdead 120 ucast eth0 192.168.128.145 udpport 694 auto_failback on node li115-178.members.linode.com node li340-16.members.linode.com Servidor B: nano /etc/ha.d/ha.cf debugfile /var/log/ha-debug logfile /var/log/ha-log logfacility local0 keepalive 2 deadtime 120 initdead 120 ucast eth0 192.168.128.144 udpport 694 auto_failback on node li115-178.members.linode.com node li340-16.members.linode.com Ahora en ambos servidores se crea el archivo que utilizará Heartbeat para el intercambios de llaves de autentificación y el archivo donde se indicará la IP virtual compartida y los servicios que heartbeat deberá gestionar. Estos archivos tienen que ser iguales en ambos servidores:
659
nano /etc/ha.d/authkeys auth 3 3 md5 sesamo Se usa como método de cifrado MD5 y después se pone la contraseña que se quiere utilizar (en este caso sesamo). Ahora hay que cambiar los permisos de este archivo para que sea accesible (en lectura y escritura) solamente para el usuario root: chmod 600 /etc/ha.d/authkeys Para terminar el archivo de los recursos: nano /etc/ha.d/haresources Se pone: li115-178.members.linode.com IPaddr2::173.255.196.191 drbddisk::data Filesystem::/dev/drbd1::/home/data::ext3 Delay::5 dahdi asterisk IMPORTANTE: tiene que estar todo en la misma línea Se define como servidor Master li115-178.members.linode.com y se indica como IP virtual la que se acaba de comprar. drbddisk es el script que se encarga de montar la partición donde se han guardado los archivos de configuración de Asterisk, en este caso /dev/drbd1. Por ultimo se indican los servicios que Heartbeat tiene que iniciar, en este caso dahdi y asterisk. Los servicios se inician después de DRBD con un retraso de 5 segundos. Estos servicios tienen que ser indicados en la carpeta etc/ha.d/resource.d. Para hacerlo se crea un enlace simbólico: cd /etc/ha.d/resource.d ln -s /etc/init.d/asterisk asterisk ln -s /etc/init.d/dahdi dahdi Por ultimo se modifica el archivo drbddisk para que apunte correctamente al archivo de configuración creado anteriormente: nano /etc/ha.d/resource.d/drbddisk Se cambia esta linea:
660
DEFAULTFILE="/etc/default/drbd" para que quede: DEFAULTFILE="/etc/drbd.conf" indicando donde efectivamente se encuentra el archivo de configuración de drbd. Para terminar la configuración los últimos cambios en ambos servidores: chkconfig asterisk off chkconfig dahdi off Esto porque es Heartbeat que se encarga de iniciar los dos programas. chkconfig --add heartbeat chkconfig heartbeat on Se abre el puerto UDP 694 que permite a los servicios Hertbeat instalados en los dos servidores de comunicarse entre ellos: Servidor A nano /etc/sysconfig/iptables después de este bloque: # HTTP -A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT se añade: # Heartbeat -A INPUT -p udp -m udp -s 192.168.128.145 --dport 694 -j ACCEPT Se reinicia iptables y fail2ban: service iptables restart service fail2ban restart Servidor B nano /etc/sysconfig/iptables después de este bloque: # HTTP 661
-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT se añade: # Heartbeat -A INPUT -p udp -m udp -s 192.168.128.144 --dport 694 -j ACCEPT Se reinicia iptables y fail2ban: service iptables restart service fail2ban restart Con esta ultima operación se ha terminado la configuración de Heartbeat. Solo falta reiniciar los dos servidores y mirar si todo funciona: reboot Si se realiza una captura de paquetes en el Servidor A, puerto 694: ngrep -d eth0:1 -W byline port 694 Se verán una serie de paquetes de este tipo: U 192.168.128.145:54002 -> 192.168.128.144:694 >>> t=status st=active dt=1d4c0 protocol=1 src=li340-16.members.linode.com (1)srcuuid=9ku7IyMqS7uMVmJpcNsTCg== seq=274 hg=4eea4a62 ts=4eea4ec9 ld=0.07 0.06 0.07 1/189 8883 ttl=3 auth=3 3fe72eec1f8c4df616b8067ce368f847 <<< Donde Heartbeat comunica al Servidor B su estado. Si en algún momento el servidor A se cae, automáticamente el servidor B tomará su lugar. Todas las extensiones tendrán que conectarse a la nueva IP compartida, es decir: 173.255.196.191.
662
CAPITULO XXVI Asterisk GUI Asterisk GUI es una interfaz gráfica desarrollada para la gestión y la configuración de Asterisk desde un navegador Web. Simplifica el manejo de Asterisk siempre y cuando se tenga un conocimiento básico del funcionamiento de la PBX. Al iniciar la GUI, ésta añade macros y extensiones al plan de marcado pero no lee totalmente la configuración ya presentes en la carpeta /etc/asterisk; para evitar de perder el trabajo que se ha hecho hasta el momento, es buena practica efectuar una copia de todos los archivo de configuración de Asterisk presentes en la carpeta /etc/asterisk: IMPORTANTE: Digium ya no da más soporte para esta GUI. Esto significa que no hay actualizaciones disponibles desde el 29 de noviembre 2012. A pesar de eso a mi sigue pareciendo una buena solución para determinados escenarios. mkdir /tmp/asterisk cp -rf /etc/asterisk/* /tmp/asterisk/ Para descargar la ultima versión disponible hay que instalar el programa SUBVERSION. yum install subversion -y cd /usr/src Se descargan los archivos de la GUI svn co http://svn.asterisk.org/svn/asterisk-gui/branches/2.0 Se entra en la carpeta: cd 2.0/ Se compila y instala: ./configure make make install Para terminar con la instalación hay que modificar dos archivos de configuración de Asterisk. Primero el manager.conf (si ya se ha configurado como indicado en el párrafo 19.1, se añade solamente al final del archivo el nuevo usuario): nano /etc/asterisk/manager.conf Se averigua que todos los parámetros que siguen tengan el valor indicado:
[general] enabled=yes webenabled=yes port=5038 bindaddr=0.0.0.0 ;tlsenable=no ;tlsbindport=5039 ;tlsbindaddr=0.0.0.0 ;tlscertfile=/tmp/asterisk.pem ;tlsprivatekey=/tmp/private.pem allowmultiplelogin=yes displayconnects=yes timestampevents=yes ;channelvars = var1,var2,var3 debug=no authtimeout=60 authlimit=20 httptimeout=60 Se crea un usuario que sera él que se usará para entrar en la pagina de administración de la GUI de Asterisk [asterisk] secret=sesamo writetimeout=100 read=system,call,agent,user,dtmf,reporting,cdr,dialplan,agi,cc,aoc write=system,call,agent,user,config,command,reporting,otiginate,agi,aoc Se guardan los cambios y se sigue con el archivo http.conf nano /etc/asterisk/http.conf se modifica el contenido para que quede: [general] enabled = yes enablestatic = yes bindaddr=0.0.0.0 bindport=8088 Se guardan los cambios y se reinicia Asterisk /etc/init.d/asterisk restart Ahora hay que abrir el puerto 8088 TCP en el cortafuegos nano /etc/sysconfig/iptables 665
Después de este bloque: # HTTP -A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT Se añaden las siguientes linea: # Asterisk GUI -A INPUT -p tcp -m state --state NEW -m tcp --dport 8088 -j ACCEPT Se guardan los cambios y se reinicia el cortafuegos y fail2ban: service iptables restart service fail2ban restart Ahora se averigua que todo esté bien configurado make checkconfig * Checking for http.conf: OK * Checking for manager.conf: OK * Checking if HTTP is enabled: OK * Checking if HTTP static support is enabled: OK * Checking if manager is enabled: OK * Checking if manager over HTTP is enabled: OK --- Everything looks good --* GUI should be available at http://li115-178.members.linode.com:8088/asterisk/static/config/index.html
A pesar que aparezca la linea en negrita como dirección para acceder a la GUI, la dirección exacta es: http://li204-236.members.linode.com:8088/static/config/index.html Desde un navegador Web se visita la pagina de administración de la GUI de Asterisk.
Username: asterisk Password: sesamo 666
Se presiona el botón “Login” Después de unos segundos aparecerá:
Se vuelve a la ventana terminal del servidor y se para y reinicia Asterisk: service asterisk stop service asterisk start Se vuelve a la pagina de administración de Asterisk y se presiona el Botón Aceptar. Se vuelve a poner Username y password presionando el botón “Login”. El Asterisk GUI leerá algunas configuraciones (colas de espera, conferencias) desde los archivos presentes en la carpeta /etc/asterisk. Las extensiones configuradas en el sip.conf no aparecerán porque Asterisk GUI las lee y guarda en el archivo users.conf Aquí van algunas imágenes de la interfaz gráfica:
667
El orden para configurar la GUI es: • • • •
Crear las troncales en el menú Trunks Crear los contextos para las llamadas salientes en el menú Outgoing Calling Rules Crear el dialplan en el menú Dial Plans Crear las extensiones en el menú Users
Una vez que que se ha probado la GUI de Asterisk y se quiere volver a la configuración anterior, se copian los dos archivos modificados y se recarga la configuración guardada: cd /etc/asterisk cp manager.conf /tmp/asterisk cp http.conf /tmp/asterisk rm -fr *.conf cp /tmp/asterisk/* /etc/asterisk /etc/init.d/asterisk restart La diferencia entre esta GUI y otras es que no utiliza muchos recursos del sistema para funcionar porque no necesita un servidor Web externo (Apache). Para pequeñas instalaciones con configuraciones básicas, es la más indicada.
668
CAPITULO XXVII FreePBX Personalmente no soy partidario de las instalaciones de Asterisk con Interfaz gráfica. Como entiendo que a muchos puede interesar el tema, en este capitulo se verá como instalar la GUI FreePBX. Como la GUI se basa en PHP, si no se ha ya instalado, se instala ahora junto al servidor Apache y el modulo mod_ssl: yum install php-* httpd mod_ssl -y se instala tabién php-pear-DB desde los repositorios epel: yum --enablerepo=epel install php-pear-DB -y Se añade el usuario Asterisk con home directory /var/lib/asterisk: useradd -c "Asterisk PBX" -d /var/lib/asterisk asterisk useradd: aviso: el directorio personal ya existe. No se copia ningún fichero del directorio skel en él. Se cambian los permisos en todas las carpetas creadas por la instalación de Asterisk asignándolos al usuario asterisk que se acaba de crear: chown -R asterisk /var/run/asterisk chown -R asterisk /var/log/asterisk chown -R asterisk /var/lib/asterisk/moh chown -R asterisk /var/lib/php/session chown -R asterisk /var/spool/asterisk chown -R asterisk /etc/asterisk Como para la música en espera Asterisk + FreePBX utilizan archivos en formato wav, si se quiere utilizar archivos mp3 hay que instalar mpg123 (si ya no se ha hecho en el párrafo 10.1) que se encargará de convertir los archivos mp3 en wav: cd /usr/src wget http://downloads.sourceforge.net/project/mpg123/mpg123/1.13.4/mpg123-1.13.4.tar.bz2 tar -xf mpg123-1.13.4.tar.bz2 cd mpg123-1.13.4 ./configure –prefix=/usr --libdir=/usr/lib64 make make install Se cambia el usuario y grupo predefinido del servidor WEB de apache a asterisk: sed -i "s/User apache/User asterisk/" /etc/httpd/conf/httpd.conf
sed -i "s/Group apache/Group asterisk/" /etc/httpd/conf/httpd.conf Para prevenir problemas de acceso se modifica el parámetro AllowOverride de All a None: sed -i "s/AllowOverride All/AllowOverride None/" /etc/httpd/conf/httpd.conf Se entra en el cliente MySQL y se crean dos bases de datos y los respectivos permisos (si no existen): mysql -u root -psesamo Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 5 Server version: 5.0.77 Source distribution Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> create database asterisk; Query OK, 1 row affected (0.02 sec) mysql> create database asteriskcdrdb; Query OK, 1 row affected (0.00 sec) mysql> GRANT ALL PRIVILEGES ON asteriskcdrdb.* TO asteriskuser@localhost IDENTIFIED BY 'sesamo'; Query OK, 0 rows affected (0.00 sec) mysql> GRANT ALL PRIVILEGES ON asterisk.* TO asteriskuser@localhost IDENTIFIED BY 'sesamo'; Query OK, 0 rows affected (0.00 sec) mysql> flush privileges; Query OK, 0 rows affected (0.00 sec) mysql> quit Bye Se descarga la ultima versión estable de FreePBX: cd /usr/src wget http://mirror.freepbx.org/freepbx-12.0.43.tgz Se descomprime el paquete y se entra en la carpeta creada: tar -xf freepbx-12.0.43.tgz cd freepbx Se crean las tablas para las bases de datos asterisk y asteriskcdrdb: 671
mysql -u root -psesamo asterisk < SQL/newinstall.sql mysql -u root -psesamo asteriskcdrdb < SQL/cdr_mysql_table.sql Se reinicia Asterisk: /etc/init.d/asterisk restart Se reinicia el servidor Apache y se configura para que arranque en automático: service httpd restart chkconfig httpd on Se lanza el script de instalación de FreePBX: ./install_amp
Se insertan los datos como aparecen en la imagen y al terminar se para FreePBX: /usr/bin/amportal stop Se entra en el archivo de configuración de FreePBX y se modifican estas tres líneas (password para el administrador de la pagina de los buzones de voz personales, tipo de autentificación para acceder a la pagina de administración del FreePBX y la dirección IP publica del servidor Linux, respectivamente): 672
nano /etc/amportal.conf ARI_ADMIN_PASSWORD=ari_password AMPWEBADDRESS= para que queden: ARI_ADMIN_PASSWORD=sesamo AMPWEBADDRESS=IPservidor (poner la IP publica del servidor Linux) Se guardan los cambios y se inicia nuevamente FreePBX: /usr/bin/amportal start En el archivo rc.local se copia esta línea para que el arranque sea automático: nano /etc/rc.local /usr/bin/amportal start Se guardan los cambios y se entra a la pagina web para administrar FreePBX utilizando la siguiente dirección: http://IPservidor
673
Se rellena el formulario que aparece y se presiona el botón “Set up my Account”:
Se selecciona el enlace “FreePBX Adminsitration”:
Se pone admin y contraseña admin. Una vez adentro de la interfaz, se selecciona el menú Admin → Module Admin. Se averigua si hay actualizaciones y se instalan:
674
De la misma forma se pueden instalar los módulos que se necesiten. Se selecciona el menú Reports → FreePBX System Status y se controla que no hayan avisos, errores de configuración:
Una vez que se hayan corregido todos los avisos/errores:
Ya se puede empezar con la configuración de Asterisk a través de la GUI FreePBX.
675
Apéndice A Instalar CentOS 6.4 en una maquina virtual con VirtualBox En esta guía se ilustrará como instalar el sistema operativo CentOS 6.4 32bit en un maquina virtual creada con el sistema de virtualización VirtualBOX. Esta maquina se puede utilizar como laboratorio para trabajar con el libro. Para iniciar se descarga Virtualbox desde esta pagina: https://www.virtualbox.org/wiki/Downloads Luego se instala y se continua con la descarga de la ISO de CentOS: http://centos.arcticnetwork.ca/6.4/isos/i386/CentOS-6.4-i386-netinstall.iso Una vez terminada la descarga se crea la maquina virtual: Se abre VitualBox y se presiona el icono “Nueva”. En la ventana que aparecerá, se selecciona el botón “Siguiente” y se siguen los pasos mostrados en las imágenes:
Nombre: CentOSLocal Sistema Operativo: Linux Versión: Red Hat
En la memoria RAM para el sistema huésped, hay que poner por lo menos 512 Mb. Si el sistema lo permite, seleccionar 1GB (1024 Mb)
678
679
680
Se selecciona el icono marcado con el circulo y en la ventana que aparece se escoge la iso de CentOS que se acaba de bajar. Debe quedar:
681
Se pasa a la configuración de red:
Se habilita un Adaptador y se escogen las opciones como aparecen en la pagina. En Nombre hay que poner la tarjeta de red instalada en el computador. Para terminar se presiona el botón “Aceptar”.
ya se puede iniciar la maquina.
682
Se continua presionando la tecla Enter (Envío):
No se realiza el test del CD:
683
Se escoge el idioma.
El tipo de teclado.
684
El tipo de instalación (vía URL):
Se activa la tarjeta de red para las direcciones IPv4 y IPv6 la URL: http://mirror.centos.org/centos/6.4/os/i386
685
Inicia la descarga del sistema base:
Una vez terminada:
686
Terminada la primera fase se iniciará la configuración del sistema:
Se indica que los dispositivo utilizando (discos) son comunes:
687
Se borran todos los datos presentes en el disco duro:
Se pone un nombre de dominio:
688
Se selecciona el huso horario:
Se configura la contraseña para el usuario root:
Se utiliza todo el espacio disponible en el disco duro para la instalación:
689
Se escriben los cambios en el disco duro:
Se escoge como tipo de instalación “Minimal”:
690
Inicia la instalación del sistema operativo.
Cuando termine se presiona el botón reiniciar. El sistema se reiniciará y como el Cd todavía está presente, volverá a presentar la pagina de instalación del sistema operativo. Se cierra la ventana a través del menú Maquina → Cerrar:
691
Se vuelve a la configuración de la maquina virtual. Se entra en el menú Almacenamiento:
Se selecciona el icono evidenciado y en el menú que aparece se escoge la opción “Eliminar disco de la unidad virtual”, para que quede:
692
Ahora se puede iniciar nuevamente la maquina virtual. Al primer arranque se entra con nombre de usuario root y la contraseña que se ha configurado a lo largo de la instalación. Normalmente cuando CentOS se instala en local, el cortafuegos viene configurado por defecto y arranca con una configuración básica. Si se quiere, se puede mover la configuración predefinida: mv /etc/sysconfig/iptables /etc/sysconfig/iptables.old y reiniciar iptables: service iptables restart Otra opción es desactivar el cortafuegos y utilizar el router para definir los puertos que se querrá dejar abiertos. Otra operación que hay que ejecutar es desactivar Selinux: Primero se instala el editor NANO: yum install nano luego se abre el archivo de configuración de Selinux: nano /etc/selinux/config Modificar las distintas opciones de forma que el archivo quede de la siguiente manera: # This file controls the state of SELinux on the system. # SELINUX= can take one of these three values: # enforcing - SELinux security policy is enforced. # permissive - SELinux prints warnings instead of enforcing. # disabled - No SELinux policy is loaded. SELINUX=disabled # SELINUXTYPE= can take one of these two values: # targeted - Targeted processes are protected, # mls - Multi Level Security protection. SELINUXTYPE=targeted Se guardan los cambios y se actualiza el sistema: yum update -y Si se quiere configurar el servidor con una IP estática se instala la relativa utilidad: yum install system-config-network-tui y se ejecuta: 693
system-config-network En la ventana que aparece se escoge “device configuration”:
Se selecciona la tarjeta de red instalada en el servidor:
Se configura la IP estática:
Static IP: dirección IP que se quiere asignar al servidor (tiene que estar dentro del rango configurado en el router) Netmask: normalmente el valor es 255.255.255.0 Default Gateway IP: dirección IP del router 694
Primary DNS Server: dirección IP del router Secondary DNS Server: se puede dejar en blanco Se presiona el botón Ok y se vuelve a la pagina anterior donde se escoge el botón Save y en la pagina principal se escoge DNS configuration:
En la pagina que sigue se escoge un nombre de dominio y se configura nuevamente el DNS primario:
Se presiona el botón OK y en la pagina que sigue el botón Save&Quit. De esta forma se sale de la aplicación. Para terminar, se activa una DMZ en el router para la IP del servidor Linux. Un ejemplo:
Se vuelve a la maquina virtual y se actualiza el sistema:
695
yum -y update Se reinicia el servidor reboot Una vez que se acceda nuevamente al sistema se retoma el libro a partir del párrafo 1.2.
696
Apéndice B Licencia GNU FDL GNU Free Documentation License Version 1.3, 3 November 2008 Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. 0. PREAMBLE The purpose of this License is to make a manual, textbook, or other functional and useful document "free" in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others. This License is a kind of "copyleft", which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software. We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference. 1. APPLICABILITY AND DEFINITIONS This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The "Document", below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as "you". You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law. A "Modified Version" of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language. A "Secondary Section" is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document's overall
subject (or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them. The "Invariant Sections" are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none. The "Cover Texts" are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words. A "Transparent" copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount of text. A copy that is not "Transparent" is called "Opaque". Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, and standard-conforming simple HTML, PostScript or PDF designed for human modification. Examples of transparent image formats include PNG, XCF and JPG. Opaque formats include proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML, PostScript or PDF produced by some word processors for output purposes only. The "Title Page" means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, "Title Page" means the text near the most prominent appearance of the work's title, preceding the beginning of the body of the text. The "publisher" means any person or entity that distributes copies of the Document to the public. A section "Entitled XYZ" means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following
699
text that translates XYZ in another language. (Here XYZ stands for a specific section name mentioned below, such as "Acknowledgements", "Dedications", "Endorsements", or "History".) To "Preserve the Title" of such a section when you modify the Document means that it remains a section "Entitled XYZ" according to this definition. The Document may include Warranty Disclaimers next to the notice which states that this License applies to the Document. These Warranty Disclaimers are considered to be included by reference in this License, but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is void and has no effect on the meaning of this License. 2. VERBATIM COPYING You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3. You may also lend copies, under the same conditions stated above, and you may publicly display copies. 3. COPYING IN QUANTITY If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the Document's license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects. If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages. If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a computer-network location from which the general network-using public has access to download using public-standard network protocols a complete Transparent copy of the Document, free of added material. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure
700
that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public. It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document. 4. MODIFICATIONS You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version: A. Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission. B. List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has fewer than five), unless they release you from this requirement. C. State on the Title page the name of the publisher of the Modified Version, as the publisher. D. Preserve all the copyright notices of the Document. E. Add an appropriate copyright notice for your modifications adjacent to the other copyright notices. F. Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below. G. Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document's license notice. H. Include an unaltered copy of this License. I. Preserve the section Entitled "History", Preserve its Title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section Entitled "History" in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence. J. Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions it was based on. These may be placed in the "History" section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission. K. For any section Entitled "Acknowledgements" or "Dedications", Preserve the Title of the section, and preserve in the section all
701
L. M. N. O.
the substance and tone of each of the contributor acknowledgements and/or dedications given therein. Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles. Delete any section Entitled "Endorsements". Such a section may not be included in the Modified Version. Do not retitle any existing section to be Entitled "Endorsements" or to conflict in title with any Invariant Section. Preserve any Warranty Disclaimers.
If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version's license notice. These titles must be distinct from any other section titles. You may add a section Entitled "Endorsements", provided it contains nothing but endorsements of your Modified Version by various parties--for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard. You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one. The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version. 5. COMBINING DOCUMENTS You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice, and that you preserve all their Warranty Disclaimers. The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work.
702
In the combination, you must combine any sections Entitled "History" in the various original documents, forming one section Entitled "History"; likewise combine any sections Entitled "Acknowledgements", and any sections Entitled "Dedications". You must delete all sections Entitled "Endorsements". 6. COLLECTIONS OF DOCUMENTS You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects. You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document. 7. AGGREGATION WITH INDEPENDENT WORKS A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, is called an "aggregate" if the copyright resulting from the compilation is not used to limit the legal rights of the compilation's users beyond what the individual works permit. When the Document is included in an aggregate, this License does not apply to the other works in the aggregate which are not themselves derivative works of the Document. If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one half of the entire aggregate, the Document's Cover Texts may be placed on covers that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate. 8. TRANSLATION Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License, and all the license notices in the Document, and any Warranty Disclaimers, provided that you also include the original English version of this License and the original versions of those notices and disclaimers. In case of a disagreement between the translation and the original version of this License or a notice or disclaimer, the original version will prevail.
703
If a section in the Document is Entitled "Acknowledgements", "Dedications", or "History", the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual title. 9. TERMINATION You may not copy, modify, sublicense, or distribute the Document except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, or distribute it is void, and will automatically terminate your rights under this License. However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, receipt of a copy of some or all of the same material does not give you any rights to use it. 10. FUTURE REVISIONS OF THIS LICENSE The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See http://www.gnu.org/copyleft/. Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License "or any later version" applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation. If the Document specifies that a proxy can decide which future versions of this License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Document. 11. RELICENSING
704
"Massive Multiauthor Collaboration Site" (or "MMC Site") means any World Wide Web server that publishes copyrightable works and also provides prominent facilities for anybody to edit those works. A public wiki that anybody can edit is an example of such a server. A "Massive Multiauthor Collaboration" (or "MMC") contained in the site means any set of copyrightable works thus published on the MMC site. "CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0 license published by Creative Commons Corporation, a not-for-profit corporation with a principal place of business in San Francisco, California, as well as future copyleft versions of that license published by that same organization. "Incorporate" means to publish or republish a Document, in whole or in part, as part of another Document. An MMC is "eligible for relicensing" if it is licensed under this License, and if all works that were first published under this License somewhere other than this MMC, and subsequently incorporated in whole or in part into the MMC, (1) had no cover texts or invariant sections, and (2) were thus incorporated prior to November 1, 2008. The operator of an MMC Site may republish an MMC contained in the site under CC-BY-SA on the same site at any time before August 1, 2009, provided the MMC is eligible for relicensing. ADDENDUM: How to use this License for your documents To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page: Copyright (c) YEAR YOUR NAME. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License". If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, replace the "with...Texts." line with this: with the Invariant Sections being LIST THEIR TITLES, with the Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. If you have Invariant Sections without Cover Texts, or some other combination of the three, merge those two alternatives to suit the situation. If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software license, such as the GNU General Public License,
to permit their use in free software. 705