Post on 05-Dec-2014
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
CLI> indica que estamos trabajando en la consola de Asterisk
mysql> indica que estamos trabajando en el cliente MySQL
Si encuentran alguna incorrección o errata pueden escribir al autor:
libro@voztovoice.org
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 H de este libro.
Copyright (C) 2012-2016 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 Linode 11.2 GRUB, Kernel-XEN y clave RSA 71.3 Utilidades, librerías, dependencias 161.4 Libpri 191.5 DAHDI 191.6 App_fax, GoogleTalk, LibiCAL y SRTP 211.7 Instalación de Asterisk 27
Capitulo II - Configuración inicial de Asterisk ......................................................................... 36
2.1 Instalar y configurar un cortafuego 362.2 Carpetas y archivos 392.3 asterisk.conf 412.4 modules.conf 432.5 Música en espera y MP3 452.6 Preparación del dialplan – extensions.conf 48
Capitulo III – Protocolo SIP y archivo sip.conf.......................................................................... 54
3.1 sip.conf 563.2 Directmedia 693.3 Contraseñas seguras 703.4 Ngrep 713.5 SoftPhone X-Lite y REGISTER 723.6 Softphone 3CX 773.7 Llamadas entre extensiones 793.8 SIP INVITE y CANCEL 80
Capitulo IV – Protocolo IAX2 – iax.conf ................................................................................. 84
4.1 iax.conf 844.2 Softphone Zoiper 89
Capitulo V - GoogleTalk – gtalk.conf jabber.conf................................................................... 95
5.1 jabber.conf y gtalk.conf 955.2 Google Voice 101
iii
5.3 Aplicación JabberSend 1025.4 La función JABBER_RECEIVE 104
Capitulo VI - Asterisk y la red PSTN........................................................................................ 107
6.1 Tarjeta Digium TDM410 108 6.1.1 OSLEC 112
6.2 Tarjeta Digium TE120P 1166.2.1 MFG/R2 – Openr2 117
6.4 Wanpipe 1226.5 Linksys SPA3102 – Gateway FXO/FXS 124
Capitulo VII - Dialplan – Configuración avanzada.................................................................. 134
7.1 Las Variables 134 7.2 Pattern Matching 1377.3 La aplicación Echo 1387.4 El contexto Subscribe 1397.5 Las Macro 1437.6 Autenticar las Llamadas Salientes con la aplicación Authenticate 1467.7 Limitar llamadas salientes: funciones GROUP y GROUP_COUNT 149
Capitulo VIII - IVR …................................................................................................................. 156
8.1 Grabación de las locuciones 1568.2 Configuración numero geográfico 1578.3 Creación del IVR 158
Capitulo IX - Funcionalidades avanzadas de Asterisk – features.conf ................................... 164
9.1 features.conf 1649.2 Callgroup y Pickupgroup 1729.3 Aplicación Dial y features.conf 174
Capitulo X - Asterisk y los calendarios ….................................................................................. 180
10.1 calendar.conf 18110.2 CALENDAR_BUSY 19010.3 CALENDAR_EVENT 19210.4 CALENDAR_QUERY y CALENDAR_QUERY_RESULT 19410.5 CALENDAR_WRITE 19710.6 Enviar las notificaciones de los calendarios a números fijos/celulares 201
iv
Capitulo XI - CCSS (Call Completion Supplementary System) – Rellamada …................... 206
11.1 Configuración del CCSS 20611.2 CCSS 1ª Prueba 20811.3 CCSS 2ª Prueba 20911.4 CCSS 3ª Prueba 210
Capitulo XII – Asterisk Realtime............................................................................................... 213
12.1 Realtime estático 21312.2 Realtime dinámico 220
12.2.1 Extensiones SIP en Realtime 22012.2.2 Extensiones IAX en Realtime 22812.2.3 Dialplan en Realtime dinámico 233
Capitulo XIII – IVR avanzados – func_odbc.conf ........... ....................................................... 237
13.1 Empleados 23713.2 Encuesta 242
Capitulo XIV - Buzón de voz – voicemail.conf........................................................................ 246
14.1 voicemail.conf 24614.2 Mensajes de voz en una base de datos 25814.3 Buzones de voz en una base de datos 261
Capitulo XV - Las conferencias audio ................................................................................... 265
15.1 meetme.conf 26515.2 Aplicación ConfBridge 26915.3 Meetme en Realtime Dinámico 27115.4 Aplicación Page 274
Capitulo XVI - Distribución automática de llamadas – Colas de espera …........................... 278
16.1 Los agentes 27816.2 Las colas de espera – queue.conf 28116.3 Agentes dinámicos 29116.4 Estadísticas de las colas 29416.5 Colas, agentes y estadísticas en Realtime dinámico 297
v
Capitulo XVII - Asterisk y los FAX …........................................................................................ 309
17.1 IAXmodem 30917.2 Hylafax 31317.3 Protocolo T38 328
17.3.1 Aplicación ReceiveFax 33217.3.2 Applicación SendFax 334
Capitulo XVIII - Conexiones entre servidores Asterisk …....................................................... 339
18.1 Conectar dos servidores Asterisk con el protocolo SIP 33918.2 Conectar dos servidores Asterisk con el protocolo IAX2 34318.3 El protocolo DUNDi 34518.4 Conectar dos servidores Asterisk con OpenVPN 35618.5 Conectar dos Servidores Asterisk con TLS y SRTP 374
Capitulo XIX – AMI y AGI …............................................................................................ 382
19.1 AMI (Asterisk Manager Interface) 38219.2 AGI (Asterisk Gateway Interface) 39119.3 Las variantes AGI 397
19.3.1 EAGI 39719.3.2 FastAGI 39819.3.3 Async AGI 400
Capitulo XX - Los registros en Asterisk …................................................................................. 405
20.1 CDR (Call Detail Record) 40520.1.1 cdr.conf 40720.1.2 cdr_manager.conf 40920.1.3 CDR adaptive 411
20.2 CEL (Channel Event Logging) 41620.3 Logger.conf 423
20.3.1 Debug 426
Capitulo XXI - Seguridad en Asterisk …................................................................................... 429
21.1 Reglas de oro 42921.2 Fail2ban 429
Capitulo XXII - Monitorear Asterisk ….....................................................................................434
vi
22.1 Monit 43422.2 SNMP 43922.3 Nagios 442
22.3.1 NDOutils 45322.4 Monitoreo calidad llamadas 455
22.4.1 Monitoreo calidad llamadas desde la consola de Asterisk 45522.4.2 Monitoreo calidad llamadas con VoIPMonitor 456
Capitulo XXIII - Conectar un Softphone (Blink) de forma segura: SIP TLS y SRTP …...... 462
23.1 Creación de los certificados 46223.2 Configuración Softphone Blink 466
Capitulo XXIV - Openfire y Asterisk …..................................................................................... 471
24.1 Instalación de Openfire 47124.2 Instalar el Plugin SIPPhone en Openfire 47924.3 El Plugin Asterisk-IM 48324.4 Asterisk como cliente en Openfire 48724.5 Conectar dos servidores Openfire 49024.6 Openfire Connection Manager 494
Capitulo XXV - Asterisk y alta disponibilidad ......................................................................... 499
25.1 Replicación MySQL Master-Slave 49925.2 Replicación MySQL Master-Master 50525.3 DRBD - Raid1 vía TCP 51525.4 Heartbeat 522
Capitulo XXVI - Asterisk GUI …............................................................................................. 529
Capitulo XXVII – FreePBX …................................................................................................... 535
Apéndice A – Instalar CentOS 5.8 en una maquina virtual con VirtualBox 542
Apéndice B – Archivos de configuración 564
Apéndice C – Licencia GNU FDL 582
vii
Introducción
Después de unos cuantos meses de trabajo, toma vida la primera versión del libro dedicado a la versión 1.8.X de Asterisk PBX. Como siempre pasa con los manuales, muchos dirán que no se abordaron algunos temas importantes, otros que la parte descriptiva es muy sucinta. La verdad, todos tienen razón. Iba a añadir una cuantos párrafos más pero pensé que podía dejarlo para “mañana”. Lo que si les puedo decir es que en la próxima versión estarán presentes estos termas:
• Aplicación Chan_spy• Aplicación GotoIfTime (para enrutar las llamadas entrantes según la fecha y la hora)• El funcionamiento de la negociación de los codec audio a lo largo de una llamada
Siempre he sido una persona muy parca con las palabras y la escritura. No me gusta alargarme demasiado cuando escribo y no me gusta que las palabras sobren. Puede ser que en algunas partes del libro me he pasado un poco aplicando esta regla, pero para eso están las primera versiones de un manual. De ellas se aprende para mejorarlas.
La que me gusta de este manual es que parte desde la instalación del sistema operativo (Linux CentOS 5.8) y acompaña quien lo lee hacia la instalación y configuración de Asterisk hasta armar una centralita completamente lista para las funciones básicas e intermedias. Todo esto probando cada nueva configuración como si se estuviera trabajando en un laboratorio de prueba.
Quiero darles las gracias a los viejos y nuevos participantes a mis cursos a distancia que son los que me animaron y me animan a escribir y mejorar este libro. Es gracias a ellos que he ido aprendiendo cada día más y que me inspiran con sus preguntas a la hora de escribir.
viii
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
Una vez adquirido el servidor Linode, desde la pagina de administración, se selecciona el enlace que aparece en la imagen que sigue:
Se escoge el centro de datos donde se quiere tener el servidor virtual remoto (en este caso Dallas):
En la nueva ventana que aparecerá se configurarán algunos parámetros (distribución Linux, Memoria disco, swap y contraseña del usuario root. Se deja una parte del espacio del disco duro para crear dos particiones que se utilizarán para la configuración de alta disponibilidad.
Terminada la configuración se presiona el botón “Rebuild”. Empezará el proceso de instalación y configuración del sistema operativo. En la sección “Disk Images”, se crean dos nuevas particiones seleccionando el enlace “Create a new disk image”:
2
La primera:
La segunda:
Para añadir las dos particiones al perfil del VPS se selecciona el enlace que aparece en la siguiente imagen:
3
y en la sección “Block device Assignment”, se añaden las dos particiones como mostrado en la imagen:
Se va al final de la pagina y se presiona el botón “Save Changes”.Ya se puede iniciar el servidor presionando el botón “Boot”.
Como se puede ver en la imagen, el Kernel que se instala es la versión “Latest 3.0 (3.0.18-linode43). De esta versión no hay las fuentes disponibles y eso imposibilita la instalación de DAHDI. Por eso en el próximo párrafo se verá como instalar en el servidor la ultima versión disponible del Kernel-XEN.
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):
4
Para conocer la dirección IP del servidor Linode, se entra en la siguiente pagina, donde aparecen todos los datos de configuración de la red:
Se descarga el programa PuTTy para Windows desde esta pagina:
http://the.earth.li/~sgtatham/putty/latest/x86/putty.exe
Una vez descargado se ejecuta. Aparecerá la siguiente ventana:
5
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
en lugar de IPlinode se pone la dirección IP publica del servidor remoto.
El resultado será:
La primera cosa que hay que hacer es actualizar el sistema:
yum -y update
y luego reiniciarlo:
reboot
Se esperan un par de minutos y se vuelve a entrar con el cliente PuTTy.
6
1.2 GRUB, Kernel-XEN y clave RSA
En este párrafo se verá como instalar el sistema de arranque GRUB con la ultima versión disponible del Kernel-XEN y como volver más seguro el acceso al servidor remoto a través de la creación y configuración de SSH utilizando una clave RSA. Primero se descarga y se ejecuta el script que sigue que se ocupará de la configuración de GRUB y de la instalación de Selinux:
cd /usr/src
wget http://www.voztovoice.org/tmp/selinux-grub
Como la versión del Kernel-XEN puede cambiar, antes de ejecutar el script, se averigua cual es la ultima versión disponible del kernel-xen
yum info kernel-xen
y se compara con la que aparece en estas lineas del archivo selinux-grub:
title CentOS (2.6.18-274.12.1.el5xen)kernel /boot/vmlinuz-2.6.18-274.12.1.el5xen root=/dev/xvdainitrd /boot/initrd-2.6.18-274.12.1.el5xen.img
Si las versiones son diferentes se modifican las lineas indicando la versión corriente. Si son iguales, se cierra el archivo y se vuelve ejecutable:
chmod +x selinux-grub
y se inicia:
./selinux-grub
Se puede averiguar que efectivamente se ha instalado el sistema de arranque GRUB con este comando:
7
ls /boot/grub/
Como el script instala dos servicios relacionados con el protocolo iSCSI que no se necesitan, se desabilitan:
chkconfig iscsi off
chkconfig iscsid off
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:
En Botton Settings – Kernel escogemos “pv-grub-x86_32
8
Casi al final de la pagina se modifican los dos parámetros indicados cambiado la opción de Yes a No. 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-XEN 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:
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 (se crea una clave de 2048 Byte) 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 se hace moviendo el ratón en el cuadro que aparece bajo la linea “Key”:
Hay que seguir moviendolo hasta que la barra que aparece no llegue al final de la linea. Terminada la
10
operación se tendrá disponible la clave RSA (publica y privada):
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 operativo 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 hundiendo las teclas CTRL-X. Se asigna al archivo recién creado los permisos de lectura y escritura solamente al usuario root:
chmod 600 /root/.ssh/authorized_keys
Terminada esta operación se modifican 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 hace 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 hundir la tecla CTRL junto a la tecla W):
#Port 22#RSAAuthentication yesPasswordAuthentication yes
y se modifican para que queden:
Port 15000RSAAuthentication yesPasswordAuthentication no
De esta forma se cambia el puerto predefinido para acceder al servidor remoto (de 22 a 15000), se activa el acceso con claves RSA y se desactiva la autentificación con nombre de usuario y contraseña. Se guardan los cambios y se reinicia el servidor SSH:
/etc/init.d/sshd restart
Se abre otra instancia del cliente SSH:
13
Se pone la IP del servidor Linode, come puerto el 15000 y se asigna un nuevo nombre a esta nueva conexión.
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 hundiendo 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:
14
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 terminar la configuración del VPS, se modifica la hora predefinida del servidor y, si se quieres, el idioma del sistema operativo:
rm /etc/localtimerm: remove regular file `/etc/localtime'? Y
En el caso de Colombia, se crea un enlace simbólico a la hora de Bogotá:
ln -s /usr/share/zoneinfo/America/Bogota /etc/localtime
se averigua que la hora sea exacta con el comando:
date
Para que la hora se actualice de manera automática se instala el servidor NTP (Network Time Protocol):
yum install ntp
Se configura para que se inicie automáticamente al arrancar el servidor Linux:
chkconfig ntpd on
y se inicia:
service ntpd startStarting ntpd:
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:
15
LANG="es_CO.iso88591"
Para activar el nuevo idioma basta salir y volver a entrar al servidor con PuTTy.
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 casi todos 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
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
se instalan todas las librerías y dependencias que se necesitan para compilar las fuentes:
yum install gcc ncurses-devel make gcc-c++ libtermcap-devel zlib-devel libtool bison bison-devel
yum install openssl-devel bzip2-devel wget newt-devel subversion flex gtk2-devel
a seguir para crear y gestionar las bases de datos, MySQL:
yum install mysql mysql-server mysql-devel
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
Se instala FESTIVAL, que es un sistema de text to speech (disponible en español):
yum install festival festival-devel
Una vez terminada esta parte se empieza a instalar una serie de programas desde las fuentes; 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
16
tar -xf speex-1.2rc1.tar.gz
cd speex-1.2rc1
./configure --prefix=/usrmakemake install
Se continua con LAME que es utiliza para codificar 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=/usrmakemake 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=/usrmakemake install
WAVPACK es un compresor audio de alto rendimiento sin perdida de calidad:
cd /usr/src
wget http://www.wavpack.com/wavpack-4.60.1.tar.bz2
tar -xf wavpack-4.60.1.tar.bz2
cd wavpack-4.60.1
17
./configure --prefix=/usrmakemake 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.0/sox-14.4.0.tar.gz
tar -xf sox-14.4.0.tar.gz
cd sox-14.4.0
./configure -prefix=/usr
Al finalizar el configure aparecerá esta tabla donde se encontrarán todos los formatos audio que se podrán manipular con SOX:
Se termina con la compilación e instalación:
makemake install
18
1.4 LIBPRI
En el caso que se quiera instalar tarjetas digitales en el servidor Asterisk (E1, T1, ISDN), antes de instalar DAHDI, hay que instalar la librería libpri
cd /usr/src
wget http://downloads.asterisk.org/pub/telephony/libpri/libpri-1.4.12.tar.gz
se descomprime:
tar -xf libpri-1.4.12.tar.gz
se entra en la carpeta:
cd libpri-1.4.12
se compila y se instala:
makemake install
1.5 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). Se instala el paquete de desarrollo del Kernel-Xen:
yum install kernel-xen-devel
IMPORTANTE: La única diferencia con un sistema CentOS local o un servidor dedicado es que se instala el paquete estándar del Kernel: yum install kernel-devel
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
tar -xf dahdi-linux-current.tar.gz
cd dahdi-linux-2.6.0
19
makemake 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.6.0
./configure
make menuselect
en la ventana que aparece se seleccionan todos los módulos disponibles como indicado en la imagen que sigue:
Se guarda la configuración presionando la tecla tabulador hasta posicionarse sobre “Save & Exit”. Se termina con la compilación e instalación:
makemake installmake config
Ya se puede iniciar DAHDI:
/etc/init.d/dahdi startLoading DAHDI hardware modules: wct4xxp: [ OK ] wcte12xp: [ OK ]
20
wct1xxp: [ OK ] wcte11xp: [ OK ] wctdm24xxp: [ OK ] wcfxo: [ OK ] wctdm: [ OK ] wcb4xxp: [ OK ] wctc4xxp: [ OK ] xpp_usb: [ OK ]
No hardware timing source found in /proc/dahdi, loading dahdi_dummyRunning dahdi_cfg: [ OK ]
1.6 App_fax, GoogleTalk, 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
se continua con SpanDSP:
cd /usr/src
wget http://www.soft-switch.org/downloads/spandsp/spandsp-0.0.6pre20.tgz
tar -xf spandsp-0.0.6pre20.tgz
cd spandsp-0.0.6
./configure --prefix=/usrmakemake 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
se continua con IKSEMEL:
cd /usr/src
21
wget http://iksemel.googlecode.com/files/iksemel-1.4.tar.gz
tar -xf iksemel-1.4.tar.gz
cd iksemel-1.4
./configure --prefix=/usrmake
antes de la instalación se ejecuta un test para averiguar que la compilación haya tenido éxito:
make checkPASS: tst-ikstackPASS: tst-iksPASS: tst-saxPASS: tst-domPASS: tst-shaPASS: tst-md5PASS: tst-filterPASS: tst-jid==================All 8 tests passed==================
Ya que todo está bien, se puede instalar:
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
Se configura para que arranque 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”
22
En este caso el sub-dominio asignado es li371-235.members.linode.com. Ese nombre se pone en la configuración de red del servidor de la siguiente forma:
nano /etc/sysconfig/network
al final del archivo se añade la siguiente linea:
HOSTNAME=li371-235.members.linode.com
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
buscar esta linea:
DAEMON_OPTIONS(`Port=smtp,Addr=127.0.0.1, Name=MTA')dnl
y modificarla 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
23
se reinicia el servidor de correo:
/etc/init.d/sendmail restart
para hacer la prueba de conexión al servidor de correo electrónico desde remoto, se abre una ventana terminal en Windows 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
SNMP es el Protocolo Simple de Administración de Red y sirve para controlar y monitorear el desempeño del servidor Linux. En Asterisk permite monitorear, entre otras cosas, los canales y las llamadas. Se utilizará junto a NAGIOS para controlar 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
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://download.berlios.de/radiusclient-ng/radiusclient-ng-0.5.6.tar.gz
tar -xf radiusclient-ng-0.5.6.tar.gz
cd radiusclient-ng-0.5.6
./configure --prefix=/usrmakemake install
24
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
luego el programa:
cd /usr/src
wget http://www.lua.org/ftp/lua-5.2.0.tar.gz
tar -xf lua-5.2.0.tar.gz
cd lua-5.2.0
Se modifica el archivo Makefile para que el programa se instale por defecto en la carpeta /usr:
nano Makefile
se modifica esta linea:
INSTALL_TOP= /usr/local
para que quede:
INSTALL_TOP= /usr
Se guardan los cambios, se compila e instala:
make linux make install
Para terminar se compilan los paquetes que permiten utilizar las nuevas funcionalidades de Asterisk 1.8.X. Primero LIBICAL que permite la implementación del protocolo iCalendar (RFC5546) en Asterisk a través del modulo res_calendar:
cd /usr/src
wget http://downloads.sourceforge.net/project/freeassociation/libical/libical-0.48/libical-0.48.tar.gz
tar -xf libical-0.48.tar.gz
cd libical-0.48
./configure --prefix=/usr
25
makemake install
Luego NEON que es una librería que permite la implementación del protocolo WebDAV en Asterisk:
cd /usr/src
wget http://webdav.org/neon/neon-0.29.6.tar.gz
tar -xf neon-0.29.6.tar.gz
cd neon-0.29.6
./configure --prefix=/usrmakemake install
Por ultimo la librería LIBSRTP que permite implementar en Asterisk el cifrado del flujo media a través del protocolo SRTP (RFC3711):
cd /usr/src
wget http://downloads.sourceforge.net/project/srtp/srtp/1.4.4/srtp-1.4.4.tgz
tar -xf srtp-1.4.4.tgz
cd srtp
./configure --prefix=/usr CFLAGS=-fPIC make
Antes de lanzar el make runtest, para que tenga éxito, hay que modificar una linea en el archivo que ejecuta el test:
nano test/rtpw_test.sh
cambiar esta linea:
RTPW=rtpw
para que quede:
RTPW=./rtpw
Se continua con el test:
make runtest
26
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 1.8.X disponible:
cd /usr/src
wget http://downloads.asterisk.org/pub/telephony/asterisk/asterisk-1.8.11.0.tar.gz
tar -xf asterisk-1.8.11.0.tar.gz
cd asterisk-1.8.11.0
./configuremake menuselect
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 en las versiones futuras de Asterisk serán eliminados. Se entra en el menú “Add-ons” y se activan los paquetes que siguen:
En Asterisk 1.8.X está presente un nuevo 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:
27
En “Resource modules” se controla que los módulos relacionados con las funciones calendario y cifrado del flujo media estén activados:
Se seleccionan todos los módulos en el menú “Utilities” y “AGI Samples”:
En “Core Sound Packages” se seleccionan todos los paquetes disponibles:
28
En “Music On Hold File Packages” se hace lo mismo:
Como se hace lo mismo en “Extra Sound Packages”:
29
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 1make: *** [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
30
se configura el script de arranque de Asterisk:
make config
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): sesamoOK, 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...
31
All done! If you've completed all of the above steps, your MySQLinstallation should now be secure.
Thanks for using MySQL!
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 ( 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));
32
Con 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';
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=localhostdbname=asteriskcdrtable=cdrpassword=sesamouser=asteriskport=3306sock=/var/lib/mysql/mysql.sock
Los datos:
33
1. [global] – etiqueta inicial del bloque2. hostname - nombre de dominio o IP del servidor MySQL3. dbname - nombre de la base de datos4. table - nombre de la tabla5. password - contraseña del usuario que tiene los permisos para acceder a la base de datos6. user - nombre del usuario que tiene los permisos para acceder a la base de datos7. port – puerto donde MySQL recibirá las conexiones (predefinido 3306)8. sock – archivo que se crea cuando se inicia MySQL y que se necesita indicar para una correcta
conexión
Se guardan los cambios y se inicia Asterisk:
/etc/init.d/asterisk start
se averigua que esté corriendo:
/etc/init.d/asterisk statusasterisk (pid 2403) is running...
se entra en la consola:
asterisk -rvvvvvvvvvvvvvvvv
se controla que la conexión a la base de datos esté activa:
CLI> cdr mysql statusConnected to asteriskcdr@localhost, port 3306 using table cdr for 59 seconds. Wrote 0 records since last restart.
Se sale de la consola:
CLI> quitExecuting last minute cleanups
34
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 una DMZ en el router y luego gestionar los puertos directamente con Iptables en el
servidor Linux
Para instalar iptables:
yum install iptables
Iptables se encarga de gestionar todos los paquetes que entren y salgan del servidor Linux. Para eso se utilizan 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 se aplicarán a la tabla filter:
Se acepta todo el trafico en entrada direccionado a la interfaz lookpack
iptables -A INPUT -i lo -j ACCEPT
Se rechaza (REJECT) todo el trafico entrante direccionado 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 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
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 REJECTiptables -A FORWARD -j REJECT
Se averigua el estado de las reglas definidas con el comando:
iptables -L
Aparecerá:
37
Chain INPUT (policy ACCEPT)target prot opt source destinationACCEPT all -- anywhere anywhereREJECT all -- anywhere 127.0.0.0/8 reject-with icmp-port-unreachableACCEPT all -- anywhere anywhere state RELATED,ESTABLISHEDACCEPT tcp -- anywhere anywhere state NEW tcp dpt:hydapACCEPT udp -- anywhere anywhere udp dpt:iaxACCEPT udp -- anywhere anywhere udp dpt:sipACCEPT tcp -- anywhere anywhere state NEW tcp dpt:sipACCEPT udp -- anywhere anywhere udp dpts:ndmp:dnpACCEPT icmp -- anywhere anywhere icmp echo-requestREJECT all -- anywhere anywhere reject-with icmp-port-unreachable
Chain FORWARD (policy ACCEPT)target prot opt source destinationREJECT all -- anywhere anywhere reject-with icmp-port-unreachable
Chain OUTPUT (policy ACCEPT)target prot opt source destinationACCEPT all -- anywhere anywhere
Para guardar los cambios:
service iptables saveSaving firewall rules to /etc/sysconfig/iptables: [ OK ]
Se inicia el servicio:
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/video)
Se renombra el archivo predefinido:
mv /etc/asterisk/rtp.conf /etc/asterisk/rtp.conf.old
Se crea uno nuevo:
nano /etc/asterisk/rtp.conf
38
Se copian las siguientes lineas:
[general]rtpstart=10000rtpend=20000rtpchecksums=nodtmftimeout=3000rtcpinterval=5000strictrtp=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 del trafico 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 los reportes del protocolo RTCP (protocolo che se utiliza para controlar el
trafico RTP• strictrtp – Lo paquetes que no proceden del mismo flujo RTP utilizado en la conexión serán
eliminados
Se guardan los cambios efectuados y se recarga la configuración de Asterisk:
/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/lib/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/
39
donde se guardan los script AGI.
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/
Claves publicas y privadas que Asterisk necesita para autenticarse con otros servidores o servicios (Ej: DUNDi).
sounds/
Contiene todas las locuciones que se pueden utilizar en el plan de marcado (dialplan).
moh/
La música en espera que viene con la instalación de Asterisk (no mp3).
licences/
Las licencias de uso que se han adquirido (Ej: para el codec audio g729).
/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/
Si se graba una llamada, esta es la carpeta donde se guardarán los archivos audio.
outgoing/
Donde hay que mover los archivo de llamadas (call files). Véase el archivo callfiles.txt en la carpeta
40
doc de las fuentes de Asterisk para una explicación del funcionamiento de estos archivos.
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
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). 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• 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/asteriskastmoddir => /usr/lib/asterisk/modulesastvarlibdir => /var/lib/asteriskastdbdir => /var/lib/asteriskastkeydir => /var/lib/asteriskastdatadir => /var/lib/asteriskastagidir => /var/lib/asterisk/agi-binastspooldir => /var/spool/asteriskastrundir => /var/run/asterisk
41
astlogdir => /var/log/asterisk
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;nocolor = yes;dontwarn = yes;dumpcore = yes;languageprefix = yes;internal_timing = yes;systemname = my_system_name;autosystemname = yes;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;sendfullybooted = yes;runuser = asterisk;rungroup = asterisk;lightbackground = yes;documentation_language = en_US;hideconnect = yes
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
42
• si se quiere que al alcanzar un consumo del 0,9 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 el sistema 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.
;[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.6res_agi=1.6app_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.4res_agi=1.4app_set=1.4
2.4 modules.conf
Cuando se compila Asterisk, todos los módulos se guardan en la carpeta /usr/lib/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
43
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 cargarlos antes de todos los demás.
Es muy probable que a lo largo de la configuración de Asterisk, no se necesitará 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.
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 hace 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 Countchan_local.so Local Proxy Channel (Note: used internal 0chan_iax2.so Inter Asterisk eXchange (Ver 2) 0chan_sip.so Session Initiation Protocol (SIP) 0chan_dahdi.so DAHDI Telephony Driver w/PRI 0chan_oss.so OSS Console Channel Driver 0app_chanspy.so Listen to the audio of an active channel 0chan_bridge.so Bridge Interaction Channel 0app_dumpchan.so Dump Info About The Calling Channel 0chan_mgcp.so Media Gateway Control Protocol (MGCP) 0chan_gtalk.so Gtalk Channel Driver 0chan_unistim.so UNISTIM Protocol (USTM) 0
44
chan_agent.so Agent Proxy Channel 0func_channel.so Channel information dialplan functions 0chan_jingle.so Jingle Channel Driver 0app_channelredirect.so Redirects a given channel to a dialplan 0app_chanisavail.so Check channel availability 0chan_phone.so Linux Telephony API Support 017 modules loaded
El canal chan_skinny no aparece porque se ha configurado para que no se cargue. Si en un determinado 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
[Dec 9 11:09:18] NOTICE[3054]: chan_skinny.c:7144 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)) == 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.
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
Ahora 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:
sox --i fresas.mp3
45
Terminada la descarga del fichero MP3, el paso que sigue es configurar el archivo musiconhold.conf.
Se modifica de la siguiente manera:
nano /etc/asterisk/musiconhold.conf
Se añaden las siguientes líneas al final del archivo:
[mp3]mode=filesdirectory=/var/lib/asterisk/mohmp3random=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
46
localhosDirectory: /var/lib/asterisk/moh
Class: mp3Mode: filesDirectory: /var/lib/asterisk/mohmp3
CLI> quit
Usando archivos MP3 para la música de 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 sampling 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 pasamos el archivo de estéreo a mono (un canal).• -r 22050 frecuencia de sampling de 44100 H/z a 22050 Hz.• archivo1.mp3 - el resultado del sampling.
Usando la opción -V aparecerá en la pantalla todo el proceso:
47
Se borra el archivo original:
rm fresas.mp3rm: 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 musica en espera [mp3]
asterisk -rvvvvvvvvvvvvvvv
CLI> moh show filesClass: 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_dayClass: mp3 File: /var/lib/asterisk/mohmp3/fresas1
2.6 Preparación del dialplan – extensions.conf
El archivo de configuración de Asterisk extensions.conf es donde se define el dialplan de la centralita. Todas las llamadas entrantes y salientes se procesan en este archivo. Para que Asterisk sepa come enrutarlas 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 una serie de números o letras que definen un bloque del dialplan dentro del cual se ejecutan aplicaciones o funciones de la PBX.
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
48
En la columna descripción, en negrita, el valor asociado al parámetro. Al final del modulo, la configuración completa del archivo.
Parámetro Descripción[general] etiqueta que da inicio a la parte generalstatic 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, la llamada será terminada
extenpatternmatchnew yes=mejora la velocidad de elaboración del dialplan para contextos con un numero elevado de extensiones.
clearglobalvars no=si se recarga el dialplan, las variables globales mantendrán su valor definidoyes=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
JUST se asocia a la variable JUST el valor SIP/justvoipmarko se asocia a la variable marko el valor
IAX2/marko
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
49
exten => 123,1,Answer
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,Answerexten => 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,Answersame => n,Playback(hello-world)same => n,Hangup
Ahora se configura otra extensión que permite escuchar la música de espera MP3 creada en el párrafo 2.5:
exten => 200,1,Answersame => n,MusicOnHold(mp3,60)same => n,Hangup
Marcando la extensión 200, Asterisk contestará la llamada (Answer) ejecutará la aplicación
50
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, la llamada terminará (Hangup).
En el dialplan se pueden definir contextos que incluyen otros contextos. De esta forma si un determinado contexto incluye a 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=yeswriteprotect=yseautofallthrough=yseextenpatternmatchnew=yseclearglobalvars=no
[globals]1000=SIP/1000JUST=SIP/justvoipmarko=IAX2/marko
[internas]exten => 123,1,Answersame => n,Playback(hello-world)same => n,Hangup
exten => 200,1,Answersame => n,MusicOnHold(mp3,60)same => n,Hangup
[externas]include => internas
51
[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 dialplan externas:
CLI> dialplan show externas[ Context 'externas' created by 'pbx_config' ] Include => 'internas' [pbx_config]-= 0 extensions (0 priorities) in 1 context. =-
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 variabledialplan 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 dialplan show chanvar Show channel variables dialplan show globals Show global dialplan variables
52
dialplan show Show dialplan
53
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/video) 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 define el 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• INVITE• BYE• ACK• CANCEL• OPTIONS
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 desde 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 enrutar las 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, 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 estén en el mismo Datacenter. Para volver la configuración del sip.conf lo más real posible, se activará esta IP local. 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:
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:1BOOTPROTO=noneONBOOT=yesIPADDR=192.168.181.15NETMASK=255.255.128.0
En IPADDR hay que poner 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
56
veremos 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 1.8 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ónallowguest No = no se permiten llamadas entrantes (INVITE) de usuarios
no autenticados (aumenta la seguridad de Asterisk)Yes = se permiten llamadas entrantes (INVITE de usuarios no autenticados
context default = el contexto donde llegarán las llamadas no autenticadas si allowguest=yes
allowtransfer En casi todos los teléfonos SIP, a lo largo de una llamada, es posible hundir un botón para transferirla a otra extensión. Este parámetro define si Asterisk aceptará este tipo de solicitudes. Posibles opciones: No y Yes
realm si al servidor es asociado un dominio registrado, se puede definir este parámetro para que la autentificación se haga utilizando ese nombre de dominio (digest authentication RFC2617). Se deja comentado
*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 es posible configurar cuatro escenarios distintos:
1. 192.168.1.0 – Asterisk aceptará conexiones solamente si enviadas a la dirección IPv4 indicada
2. 2600:3c00::f03c:91ff:fedf:a455 - Asterisk aceptará conexiones solamente si enviadas a la dirección IPv6 indicada
3. 0.0.0.0 – Asterisk aceptará conexiones en todas las direcciones IPv4 presentes en el servidor Linux
57
Parámetro Descripción
4. :: - Asterisk aceptará conexiones 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
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 registrarse utilizando el protocolo TCP. Si no lo hace antes del tiempo indicado, sera desconectado. Valor: 30
tcpauthlimit Numero máximo de conexiones no autenticadas permitidas utilizando el protocolo TCP. Valor:100
srvlookup Permite hacer búsquedas de registros DNS SRV basadas en los nombres de dominio para llamadas SIP salientes del tipo: SIP/usuario@dominio. Asterisk hace esta búsqueda limitándose al primer valor encontrado. Valor: Yes
maxexpiry Tiempo máximo, en segundos, permitido para REGISTER y SUBSCRIBE entrantes. Valor 3600
minexpiry Tiempo mínimo, en segundos, permitido para REGISTER y SUBSCRIBE entrantes. Valor: 60
defaultexpiry Cuando un cliente se registra a Asterisk, envía el tiempo de duración de su registro. En el caso que no lo haga, Asterisk considerará que el registro durará el tiempo indicado en este parámetro expresado en segundos. Valor: 120
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 “suscribe” a este tipo de servicio en el servidor Asterisk. Este parámetro indica cada cuantos segundos las suscripción tendrá que ser renovada. Valor 3600
maxforwards Cada vez que un “mensaje” Sip se envía puede atravesar distintos servidores antes de llegar al destinatario. Con este parámetro se limita el numero de veces que se puede reenviar. Se utiliza también para evitar que se creen bucles. Valor. 70
58
Parámetro Descripción
qualifyfreq Cada cuantos segundos enviar un paquete OPTIONS a la extensión registrada en Asterisk. Esto permite saber si la extensión misma es alcanzable. El método OPTIONS del protocolo SIP se utiliza también para conocer los métodos disponible en un determinado cliente. Valor 60
*preferred_codec_only Asterisk contesta a un INVITE entrante con un solo codec audio en lugar de enviar toda la lista de codecs configurados. 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 videoallow Se indican los codec audio y video utilizables. Pueden ser
indicados uno por linea o en la misma linea separados por una coma:allow=alawallow=ulawoallow=alaw,ulawulaw: se utiliza en Estados Unidos, Canadá y Australiaalaw = 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 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 . Valor es (Español)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 los datos de una sesión es enviando un SIP UPDATE. Con este parámetro se activa o desactiva. Valor: yes
prematuremedia En Asterisk es posible enviar audio aunque la llamada no ha sido contestada. Un ejemplo es cuando llamamos un numero celular (en Colombia) y si nadie contesta escuchamos la voz que dice "Sistema correo de voz. Tendrá cobro a partir de este momento". Si colgamos, no pagamos nada porque la llamada realmente no
59
Parámetro Descripción
ha sido contestada. Esta funcionalidad se llama "Early Media". Durante el Early Media, los tonos DTMF no funcionan y no se pueden utilizar. Este comportamiento se obtiene poniendo como valor no
useragent Asterisk se presentará con este nombre al momento de comunicarse con otros servidores o proveedores SIP. Valor: VozToVoice v. 1.0 Personalizar
sdpsession asterisksdpowner asterisk dtmfmode protocolo para el envío de los DTMF (Dual-Tone Multi-
Frequency). Serían los tonos que se generan cuando se hunden 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
videosupport no=no se activa el soporte para video llamadasyes=se activa el soporte para video llamadas
maxcallbitrate Banda máxima utilizable para video 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 pueda 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 contestará siempre con un 401 Unauthorized no permitiendo dar pistas a los que están intentando acceder al sistema
use_q850_reason Yes Permite el envío de los códigos Q850 en el Header Reason que normalmente se utiliza para conocer el motivo 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
allowsubscribe yes=permite suscribirse al estado de una extensiónsubscribecontext subscribe=Este parámetro define el contexto que se utilizará
60
Parámetro Descripción
para permitir a las extensiones acceder al estado de otras.notifyringing yes=Notifica si la extensión está timbrandonotifyhold yes= Notifica si la extensión está en esperacallcounter 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 hacer.
*t38pt_udptl Permite el uso del protocolo T38 (fax sobre IP). Desde la versión 1.8.X, 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” 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 = dehabilitado• 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
61
Parámetro Descripción
force_rport = impone siempre el uso del parámetro rportyes = impone siempre el uso del parámetro rport y envía el flujo audio/video por el mismo puerto utilizado por el dispositivo remoto.comedia = usa el parámetro rport solamente si requerido por el dispositivo remoto
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
;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:sesamo@sip.provider1.comPara 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:sesamo@sip.provider1.com:5061En 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 queremos que las llamadas entre a una extensión definida, tenemos 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ña@sip.provider1.com/1234registertimeout 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 hará para registrarse. Si ponemos 0, los intentos serán infinitos. Valor 10
62
Parámetro Descripción
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:password@mysipprovider.com/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ónaccountcode Código que aparecerá en el registro de llamadas
para esta extensión. Valor 1000language es=esta extensión utilizará las locuciones en
españoltype 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 predefinido: 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
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 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 rfc2833context El contexto a que tendrá acceso la extensión.
63
Valor externas como se ha creado en el dialplandirectmedia Si las extensiones, como es el caso de una VPS
Linode, están detrás de un NAT, el valor es nocallerid el nombre y el numero que identifica la extensión
cuando llama. valor Fulano <1000> Personalizarcallgrouppickupgroup
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 alawallow g722=se habilita el codec audio g722allow g729=se habilita el codec audio g729allow h263=se habilita el codec video H263
Se configura una segunda extensión:
[1001]type=friendaccountcode=1001language=essecret=pbx9091qualify=yesmailbox=1001@defaulthost=dynamicdtmfmode=rfc2833context=externasdirectmedia=nocallerid=zutano <1001>callgroup=1pickupgroup=1disallow=allallow=alawallow=g722allow=g729allow=h263
Cuando se deben configurar muchas extensiones, se pueden crear templates (plantillas) donde se definen todos los parámetros compartidos por todas las extensiones. Luego por cada una de ellas, se configuran solamente los parámetros que la diferencian de las demás. Para crear un template la primera linea debe tener esta sintaxis:
64
[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=friendlanguage=esqualify=yeshost=dynamicdtmfmode=rfc2833context=localesdirectmedia=nocallgroup=1pickupgroup=1disallow=allallow=alawallow=g722allow=g729allow=h263
Ahora para configurar una nueva extensión se puede utilizar ese template de la siguiente forma:
[1002](int-locales)accountcode=1002secret=pbx9092mailbox=1002@defaultcallerid=Mengano <1002>
Terminada la configuración de las extensiones, se pasa a la troncal SIP utilizando el proveedor JustVoIP:
Parámetro Descripción[justvoip] nombre que se le asigna a la troncaltype la troncal es de tipo peerhost sip.justvoip.com=dominio del proveedor SIPfromdomain sip.justvoip.com=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
65
From de la cabecera SIP. Muchos proveedores lo exigen para autenticar las llamadas.
defaultuser el mismo valor del parametro fromusersecret la contraseña.qualify yesdtmfmode rfc2833context from-justvoip=el contexto donde llegarán las
llamadas si se utiliza el proveedor también para las llamadas entrantes
directmedia nolanguage esnat no=no hay NAT entre el servidor Asterisk y el
proveedor SIPdisallow allallow alawallow 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:
[general]allowguest=nocontext=defaultallowtransfer=yes;realm=mydomain.tldudpbindaddr=0.0.0.0:5060tcpenable=yestcpbindaddr=0.0.0.0:5060tcpauthtimeout=30tcpauthlimit=100srvlookup=yesmaxexpiry=3600minexpiry=60defaultexpiry=120mwiexpiry=3600maxforwards=70
66
qualifyfreq=60preferred_codec_only=nodisallow=allallow=ulawallow=alawmohinterpret=defaultmohsuggest=defaultparkinglot=defaultlanguage=essendrpid=yerpid_update=yesprematuremedia=nouseragent=VozToVoice v. 1.0sdpsession=asterisksdpowner=asteriskdtmfmode=rfc2833videosupport=yesmaxcallbitrate=384callevents=yesauthfailureevents=yesalwaysauthreject=yesuse_q850_reason=yesrtptimeout=60rtpholdtimeout=300rtpkeepalive=0allowsubscribe=yessubscribecontext=subscribenotifyringing=yesnotifyhold=yescallcounter=yest38pt_udptl=yes,fec,maxdatagram=400 faxdetect=yeslocalnet=externaddr=;externhost=prueba.dyndns.org;externrefresh=180nat=force_rportdirectmedia=no;media_address=0.0.0.0rtcachefriends=nortupdate=yes
;register => fulano:sesamo@sip.provider1.com;register => fulano:sesamo@sip.provider1.com:5061;register => fulano:contraseña@sip.provider1.com/1234registertimeout=20registerattempts=10
67
;mwi => 1234:password@mysipprovider.com/1234
[1000]accountcode=1000language=estype=friendsecret=pbx9090qualify=yesmailbox=1000@defaulthost=dynamicdtmfmode=rfc2833context=externasdirectmedia=nocallerid=callerid=Fulano <1000>callgroup=1pickupgroup=1disallow=allallow=alawallow=g722allow=g729allow=h263
[1001]type=friendaccountcode=1001language=essecret=pbx9091qualify=yesmailbox=1001@defaulthost=dynamicdtmfmode=rfc2833context=externasdirectmedia=nocallerid=zutano <1001>callgroup=1pickupgroup=1disallow=allallow=alawallow=g722allow=g729allow=h263
[int-locales](!)type=friendlanguage=esqualify=yeshost=dynamic
68
dtmfmode=rfc2833context=localesdirectmedia=nocallgroup=1pickupgroup=1disallow=allallow=alawallow=g722allow=g729allow=h263
[1002](int-locales)accountcode=1002secret=pbx9092mailbox=1002@defaultcallerid=Mengano <1002>
[justvoip] type=peerhost=sip.justvoip.comfromdomain=sip.justvoip.comfromuser=defaultuser=secret=qualify=yesdtmfmode=rfc2833context=from-justvoipdirectmedia=nolanguage=esnat=nodisallow=allallow=alawallow=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 Justvoip se ponen los datos de usuario y contraseña creados 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:
69
CLI> sip show peersName/username Host Dyn Nat ACL Port Status1000 (Unspecified) D N 5060 UNKNOWN1001 (Unspecified) D N 5060 UNKNOWN1002 (Unspecified) D N 5060 UNKNOWNjustvoip/pbx2020 77.72.169.129 5060 OK (160 ms)4 sip peers [Monitored: 1 online, 3 offline Unmonitored: 0 online, 0 offline]
Para ver los users configurados:
CLI> sip show usersUsername Secret Accountcode Def.Context ACL NAT1000 pbx9090 1000 phones No Always1001 pbx9091 1001 phones No Always1002 pbx9092 1002 phones No Always
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 configurationsip set debug {on|off|ip|peer} Enable/Disable SIP debugging sip set history {on|off} Enable/Disable SIP historysip 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 sched 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
70
dispositivos o pasa por Asterisk que se encarga de enrutarlo de una extensión a otra. Para poder entender un poco mejor este comportamiento, se puede ver el gráfico que sigue:
SIP SIP RPT RPT
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
La señalización SIP sigue pasando por Asterisk, mientras que el flujo media va directo de una extensión a otra. Este escenario funciona solamente si las extensiones no están detrás de un NAT. 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. Si en el sip.conf el parámetro dtmfmode=inband, como los tonos viajan en el flujo audio y Asterisk no recibe ese flujo, no se podrán utilizar funcionalidades avanzadas configuradas en Asterisk que utilizan los tonos para ser activadas.
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
71
RPT
extensiones. Para evitar esto y volver más seguro el sistema, es posible cifrarlas con el algoritmo MD5.Tomamos como ejemplo la primera extensión cuya contraseña es pbx9090. Para cifrarla la sintaxis es:
echo -n "<extensión>:<realm>:<secret>" | 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:
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 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
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=/usrmakemake install
72
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 configura la cuenta 1000 creada en Asterisk:
Account name: una descripción de la cuentaUserID: el numero de la extensiónDomain: la dirección IP o el nombre de dominio del servidor Asterisk (la IP del VPS Linode)
73
Password: la contraseña de la extensión 1000 (pbx9090)Display name: el numero de la extensiónAuthorization 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.
74
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. Si la conexión es contra un servidor local, hay que seleccionar la casilla “None (use local IP address).
75
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 para mantener la conexión abierta, y rport. 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:
nano /tmp/register
76
Encontraremos esta secuencia:
X-Lite ------------------Register---------------> AsteriskX-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
X-Lite ------------------Register---------------> AsteriskX-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---------------- AsteriskX-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:asterisk@96.126.121.135.Voice-Message: 0/0 (0/0).
En la consola de Asterisk aparecerá la extensión conectada:
asterisk -rvvvvvvvvvvvvvvvvv
CLI> sip show peersName/username Host Dyn Nat ACL Port Status1000/1000 190.255.234.54 D N 10527 OK (135 ms)
77
Otra forma de ver los mensajes SIP es activar el sip debug en Asterisk. Se puede hacer de forma general:
CLI> sip set debug onSIP Debugging re-enabled
o solamente para una extensión/troncal especifica:
CLI> sip set debug peer 1000SIP Debugging Enabled for IP: 190.255.234.54:10527
CLI> sip set debug peer justvoipSIP Debugging Enabled for IP: 77.72.169.129:5060
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:
78
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 peersName/username Host Dyn Nat ACL Port Status1000/1000 190.255.234.54 D N 10527 OK (134 ms)
79
1001/1001 190.255.234.54 D N 10870 OK (220 ms)
3.7 Llamadas entre extensiones
Si desde la extensión 1000 se llama la extensión 1001, en la consola de Asterisk aparecerá:
NOTICE[29214]: chan_sip.c:20785 handle_request_invite: Call from '1000' 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 Pattern-matching. 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 esta parte del 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 Justvoip 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/justvoip/${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]
80
include => internasinclude => 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 [1000@externas:1] Dial("SIP/1000-00000001", "SIP/1000,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 hará la traza de una llamada con ngrep. En la ventana terminal del servidor se escribe:
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 CTRL-C
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-------------
81
<------------200 OK---------------------------------ACK--------------->
<---------------200 OK---------------------------------ACK------------------>
<----------------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 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-----------------------------BYE-------------------><--------------200 OK-----------------<-------487 Request Terminated---------------------ACK----------------->
--------------CANCEL----------->
82
Sesion Media
<-------------200 OK--------------<----- 487 Request Terminated-------------------ACK---------------->
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 '1002' to extension '005714013434' rejected because extension not found in context 'locales'.
De esta forma podemos controlar las extensiones que tienen acceso a las llamadas salientes.
83
CAPITULO IV
Protocolo IAX2 – iax.conf
El protocolo IAX (ahora IAX2) ha sido desarrollado por Mark Spencer, quien empezó a escribir el 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 utilizar un único “trunk” para distintos flujos media, 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 IAX2bindport El puerto UDP usado por este protocolo. Este parámetro va
configurado antes del bindaddr. Valor 4569bindaddr 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 IP presentes en el servidor Linux. Valor: 0.0.0.0
nochecksums no=no se realiza la suma de verificación de los paquetes UDPdelayreject yes=mejora la seguridad contra “brute force password attacks”
retrasando el envío de los rechazos de autentificaciónamaflags Automated Message Accounting. Con este parámetro se configura un
Parámetro Descripcióncampo del CDR (call data records) univoco para todas las llamadas. Este campo se puede personalizar en cada extensión. Valor: documentation
srvlookup yes=Permite hacer búsquedas de registros DNS SRV basadas en los nombres de dominio para llamadas SIP salientes del tipo: IAX2/usuario@dominio.
language es=el idioma predefinido para las locucionesmohinterpret clase de música de espera predefinida – defaultmohsuggest Clase de música de espera cuando un canal de tipo peer se pone en
espera – defaultbandwidth 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 y videoallow Se indican los codec audio y video utilizables. Pueden ser indicados
uno por linea o en la misma linea separados por una coma:allow=alawallow=ulawoallow=alaw,ulaw
minregexpire 60=tiempo mínimo de espiración del registro de las troncales IAX2maxregexpire 60=tiempo máximo de espiración del registro de las troncales IAX2encryption yes=se habilita el cifrado de la señalización y del flujo mediaforceencryption no=no se fuerza el uso del cifradotrunkmaxsize 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 el 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 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.
86
Parámetro DescripciónPuede ser:
• caller• host• disabel
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
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 soportaregister => El segundo bloque empieza con las lineas de register. Algunos
ejemplos:• register => marko:secretpass@tormenta.linux-support.net
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
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óntype friend Puede ser peer y userhost Si la extensión se conecta remotamente con un IP
dinámico se pone dynamic. En caso contrario se pone la dirección IP
87
Parametro Descripciónsecret La contraseña para la extensión. Valor
predefinido: pbx9094context El contexto a que tendrá acceso la extensión.
Valor externasmailbox 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 markorequirecalltoken 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=4569bindaddr=0.0.0.0nochecksums=nodelayreject=yesamaflags=documentationsrvlookup=yeslanguage=esmohinterpret=defaultmohsuggest=defautlbandwidth=highdisallow=allallow=alawallow=alawminregexpire=60maxregexpire=60encryption=yesforceencryption=no
88
trunkmaxsize=128000trunkmtu=1240autokill=yescodecpriority=hostrtcachefriends=nortupdate=yesparkinglot=defaultcalltokenoptional=0.0.0.0/0.0.0.0requirecalltoken=auto
;register => marko:secretpass@tormenta.linux-support.net;register => joe@remotehost:5656 ;register => marko:[key]@tormenta.linux-support.net
[marko]type=friendhost=dynamicsecret=pbx9094context=externasmailbox=1234@defaultqualify=yescallerid=markorequirecalltoken=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
* Name : marko Secret : <Set> 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
89
Addr->IP : (Unspecified) Port 0 Defaddr->IP : 0.0.0.0 Port 4569 Username : Codecs : 0x8 (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 New IAX account"
90
se pone el nombre de la cuenta (marko) y se hunde el botón OK:
Se ponen los datos come definidos en el archivo di configuración iax.conf y se hunde el botón Register. Luego el botón OK que aparece al fondo de la ventana. Se entra nuevamente en el Menú "Settings -> Preferences":
Se escoge el usuario marko:
En alto a la derecha, aparecerá la voz "Registered". También en la consola de Asterisk el usuario aparecerá registrado:
CLI> IAX2 show peersName/Username Host Mask Port Status
91
marko 190.254.129.133 (D) 255.255.255.255 26599 (E) OK (127 ms)1 iax2 peers [1 online, 0 offline, 0 unmonitored]
CLI> quit
Ya que en Zoiper se pueden configurar también extensiones SIP, se configura la extensión 1002:
Se presiona el botón o ok y en la nueva ventana se ponen los datos de conexión:
Se presiona el botón register y el botón ok que aparece al fondo de la pagina. Se averigua que la extensión esté conectada:
asterisk -rvvvvvvvvvvvvvvv
CLI> sip show peersName/username Host Dyn Nat ACL Port Status1000/1000 190.254.129.133 D N 27174 OK (125 ms)1001/1001 190.254.129.133 D N 27256 OK (250 ms)1002/1002 190.254.129.133 D N 5060 OK (137 ms)justvoip/pbx2020 77.72.169.129 5060 OK (161 ms)4 sip peers [Monitored: 4 online, 0 offline Unmonitored: 0 online, 0 offline]
CLI> quit
92
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
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-00000007", "IAX2/marko,30") in new stack
El resultado en Zoiper:
De esta forma se ha hecho la prueba de una llamada entre dos teléfonos con distintos protocolos.
93
CAPITULO V
GoogleTalk – gtalk.conf jabber.conf
Como se ha visto a lo largo de la instalación de Asterisk, la centralita soporta el protocolo XMMP que permite conectarla a servidores que utilizan ese protocolo. En Asterisk el modulo relacionado es el res_jabber.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_jabberModule Description Use Countres_jabber.so AJI - Asterisk Jabber Interface 01 modules loaded
luego se quita y se vuelve a cargar para controlar eventuales errores:
CLI> module unload res_jabber.so == 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 > JABBER: Disconnecting
CLI> module load res_jabber.so == Parsing '/etc/asterisk/jabber.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' Loaded res_jabber.so => (AJI - Asterisk Jabber 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_jabber.so, hay que configurar el modulo chan_gtalk que es el que permite llamadas de este tipo:
• Asterisk → GoogleTalk• GoogleTalk → Asterisk• Asterisk → GoogleVoice
Esto significa que se podrán recibir llamadas de usuarios GoogleTalk en Asterisk y luego, a través de la configuración del dialplan, enrutarlas 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.
5.1 jabber.conf y gtalk.conf
Se empieza con el archivo de configuración jabber.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 generaldebug no=no se activa el debug en la consola de Asterisk
yes=se activa el debug en la consola de Asteriskautoprune 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 su lista de amigos, Asterisk automáticamente lo añadirá a la lista de amigosno=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 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.
96
;auth_policy=accept=yes La especificación XEP-048 se basa en un sistema de suscripciones que los usuarios activan para recibir actualizaciones. Con este parámetro en yes las suscripciones de los usuarios se aceptan en automático. Se deja comentado
[campus.voztovoice] A partir de esta etiqueta, la configuración del usuario GoogleTalk. Suponiendo que el usuario creado es campus.voztovoice@gmail.com, en la etiqueta se pone el nombre de usuario. Personalizar con el nombre del usuario google creado.
type puede ser client o componentserverhost 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 campus.voztovoice@gmail.com. Personalizar
secret la contraseña asociada al usuario creado en Google. Personalizarport 5222 Es el puerto que utiliza GoogleTalk para aceptar
conexionesusetls yes=se activa el protocolo TLS. De esta forma todos los
paquetes intercambiados entre cliente y servidor serán cifradosusesasl 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 pone una linea con este parámetro para cada amigo. Para este ejemplo se pone voztovoicenet@gmail.com en esta linea.
;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
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)
Terminada la configuración del archivo jabber.conf, se continua con el archivo gtalk.conf. En la columna descripción, en negrita, aparecen los valores que hay que configurar.
97
Parámetro Desc[general] inicia la parte general del archivocontext contexto del dialplan donde entrarán las llamadas
de los usuarios GoogleTalk. Valor: google-inbindaddr dirección ip para la escucha de peticiones
GoogleTalk. Se configura para que escuche en todas las direcciones presentes en el servidor. Valor: 0.0.0.0
externip A partir de la versión 1.8 de Asterisk se ha añadido este parámetro, que permite definir la IP publica del servidor. Se pone la IP de Linode
allowguest no=no se permiten llamadas de usuarios GoogleTalk que no estén en la lista de amigosyes=se permiten
[guest] a partir de esta etiqueta empieza la configuración para los usuarios huéspedes (que no están en la lista de amigos).
disallow all=se desactivan todos los codec audioallow alaw=se activa el codec audio alawcontext google-in=nombre del contexto del dialplan donde
llegarán las llamadas de usuarios huéspedesconnection se pone la etiqueta definida en el jabber.conf para
el usuario GoogleTalk configurado en Asterisk. en este ejemplo es campus.voztovoice. Personalizar
[voztovoicenet] a partir de esta linea, se definen todos los amigos que se quiere tener en la lista. Para un ejemplo real el usuario es voztovoicenet.
username nombre del usuario: voztovoicenet@gmail.comdisallow all=se desactivan todos los codec audioallow alaw=se activa el codec audio alawconnection se pone la etiqueta definida en el jabber.conf para
el usuario GoogleTalk configurado en Asterisk. en este ejemplo es campus.voztovoice. Personalizar
context el contexto del dialplan donde llegarán las llamadas del usuario google-in
Una vez definidos todos los parámetros de jabber.conf y gtalk.conf, se crean los respectivos archivos. Primero se renombran los predefinidos:
mv /etc/asterisk/jabber.conf /etc/asterisk/jabber.conf.old
98
mv /etc/asterisk/gtalk.conf /etc/asterisk/gtalk.conf.old
Luego se crea el archivo jabber.conf:
nano /etc/asterisk/jabber.conf
se pegan las siguientes lineas:
[general]debug=yesautoprune=noautoregister=yes;collection_nodes=yes;pubsub_autocreate=yes;pubsub_autocreate=yes
[campus.voztovoice]type=clientserverhost=talk.google.com;pubsub_node=pubsub.dominio.comusername=campus.voztovoice@gmail.comsecret=passwordport=5222usetls=yesusesasl=yesbuddy=voztovoicenet@gmail.com;distribute_events=yesstatusmessage=Asterisk Servertimeout=100
IMPORTANTE: antes de guardar la configuración, hay que personalizar los parámetros username, secret y la etiqueta [campus.voztovoice], con los datos de su cuenta Google.
Se pasa al archivo gtalk.conf
nano /etc/asterisk/gtalk.conf
[general]context=google-inbindaddr=0.0.0.0externip=IPasteriskallowguest=yes
99
[guest]disallow=allallow=alawcontext=google-inconnection=campus.voztovoice
[voztovoicenet]username=voztovoicenet@gmail.comdisallow=allallow=alawconnection=campus.voztovoicecontext=google-in
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 jabber.conf (en este ejemplo campus.voztovoice) y el parámetro externip.
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_jabber.so
CLI> module unload chan_gtalk.so
CLI> module load res_jabber.so
CLI> module load chan_gtalk.so
Después de algunos segundos, el usuario debería estar conectado:
CLI> jabber show connectionsJabber Users and their status: User: campus.voztovoice@gmail.com - Connected---- Number of users: 1
Para ver la lista de amigos conectados (voztovoicenet@gmail.com)
CLI> jabber show buddiesJabber buddy listsClient: campus.voztovoice@gmail.com Buddy: voztovoicenet@gmail.com Resource: talk5D9E1034 node: http://www.asterisk.org/xmpp/client/caps version: asterisk-xmpp
100
Jingle capable: yes Status: 1 Priority: 10
Para una lista de comandos disponibles en los dos módulos
CLI> help jabber jabber create collection Creates a PubSub node collection. jabber create leaf Creates a PubSub leaf node jabber delete node Deletes a PubSub node jabber list nodes Lists PubSub nodes jabber purge nodes Purges PubSub nodes jabber reload Reload Jabber configuration jabber set debug {on|off} Enable/Disable Jabber debug jabber show buddies Show buddy lists of our clients jabber show connections Show state of clients and components jabber test Shows roster, but is generally used for mog's debugging.
CLI> help gtalk gtalk show channels Show GoogleTalk channels
Por ultimo si se entra en GoogleTalk con otro nombre de usuario y se añade a la lista de amigos el usuario configurado en Asterisk (en este ejemplo campus.voztovoice@gmail.com), el resultado será:
El icono del teléfono que aparece, indica que se puede tener una conversación audio con ese usuario.
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)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:
101
exten => _[a-z].,1,Dial(gtalk/campus.voztovoice/${EXTEN},30)same => n,Hangup
Una explicación de las dos lineas: Se dice a Asterisk de llamar a través del canal gtalk, usando la conexión campus.voztovoice que es la etiqueta que inicia el bloque de configuración del usuario campus.voztovoice@gmail.com. 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.
Para que esto funcione, hay que añadir un bloque nuevo en el archivo gtalk.conf para cada nuevo usuario siguiendo las mismas pautas utilizadas para configurar el usuario voztovoicenet@gmail.com. En el caso que se quiera llamar un usuario no configurado en gtalk.conf, hay que añadirlo de esta forma en el dialplan (contexto internas):
exten => 10000,1,Dial(gtalk/campus.voztovoice/fulano@gmail.com,30)same => n,Hangup
suponiendo que fulano@gmail.com es el usuario que se quiera llamar. 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 hacer una primera prueba llamando el usuario voztovoicenet@gmail.com desde el X-LIte
Se marca de esta manera:
Se presiona el botón “Call”. El resultado:
Para llamar al usuario fulano@gmail.com se marcará la extensión 10000 desde X-Lite. Como nota utilizando el cliente GoogleTalk en un celular Android, es posible efectuar llamadas al usuario configurado en Asterisk pero no es posible (hasta el momento) recibirlas.
5.2 Google Voice
Google Voice es el servicio de Google que permite efectuar llamadas a cualquier parte del mundo. Esta
102
funcionalidad es disponible en la pagina personal de la cuenta Google:
Desde la versión 1.8.X de Asterisk, es posible efectuar llamadas utilizando una cuenta Google Voice. 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(gtalk/campus.voztovoice/+${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.
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(gtalk/campus.voztovoice/+${EXTEN}@voice.google.com)same => n,Hangup
5.3 Aplicación JabberSend
Una aplicación que se activa con el modulo res_jabber.conf es “JabberSend” que permite enviar mensajes instantáneos a usuarios GoogleTalk.
La sintaxis de la aplicación es:
103
JabberSend(Jabber,JID,Message)
Un ejemplo. Cada vez que una extensión llame la extensión de la música en espera, queremos enviar un 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,Answersame => n,MusicOnHold(mp3,60)same => n,Hangup
para que quede:
exten => 200,1,Answersame => n,Jabbersend(campus.voztovoice,voztovoicenet@gmail.com,Estamos escuchando MP3)same => n,MusicOnHold(mp3,60)same => n,Hangup
Cambiar “campus.voztovoice” con la etiqueta que define el usuario configurado en el archivo jabber.conf; cambiar el usuario voztovoicenet@gmail.com 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 en la versión 1.8 de Asterisk. Esta función permite interactuar con un usuario Google Talk a través del envío y recepción de mensajes de textos. Para el envío de mensajes de texto se utiliza la aplicación SendText que permite, cuando un canal ya está conectado, enviar texto a ese canal.
104
La sintaxis de la función es:
asterisk -rvvvvvvvvvvvvvv
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 jabber.conf (en este caso campus.voztovoice)
• 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(campus.voztovoice,${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.
Se guardan los cambios y se recarga el dialplan:
asterisk -rx "dialplan reload"
105
Ahora desde un usuario GoogleTalk, se llama el usuario configurado en Asterisk. En la ventana de chat 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.
106
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 la RTB, 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 adquirente. Un ejemplo de dispositivo FXO/FXS es la tarjeta Digium TDM410 que permite 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) o 30 (E1) canales de voz. En la T1 los canales 0 y 24 son 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 usan. T1 son la lineas disponibles en Estados Unidos, E1 en Europa y gran parte de latino américa, J1 en Japón.
En este capitulo se verá como instalar las siguientes tarjetas:
• Digium TDM410 con 4 puertos FXO• Digium TE120 (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 TDM410
La tarjeta Digium TDM410 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. Apagar el computador2. Desconectar el cable de alimentación3. Abrir el chasis del Computador4. Insertar la tarjeta en una ranura PCI disponible5. Volver a poner el chasis del computador6. Conectar el cable de alimentación al computador7. Conectar las lineas telefónicas a los puertos FXO de la tarjeta a través de un normal cable
telefónico8. 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:
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
109
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 (timbrando, 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)• Alemania (de)• Suiza (ch)• Dinamarca (dk)• Republica Checa (cz)• China (ch)• Argentina (ar)• Malasia (my)• Tailandia (th)• Bulgaria (bg)• Venezuela (ve)• Filipinas (ph)
110
• 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.6.0
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" }, { 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 el mismo renglón.
111
Se guardan los cambios y se vuelve a compilar dahdi-tools:
make distclean./configuremake manuselectmakemake installmake 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 = codefaultzone = co
Se define el tipo de señalización (fxsks para FXO y fxoks para FXS); en este caso se configuran 4 modulos 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:
echocanceller = mg2,1-4
El archivo final será:
loadzone = codefaultzone = cofxsks=1-4echocanceller = mg2,1-4
Se guardan los cambios.
Para mejorar la cancelación de eco se instala OSLEC
112
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.6.0/drivers/staging
cp -fR /usr/src/linux-2.6.28/drivers/staging/echo /usr/src/dahdi-linux-2.6.0/drivers/staging
sed -i "s|#obj-m += dahdi_echocan_oslec.o|obj-m += dahdi_echocan_oslec.o|" /usr/src/dahdi-linux-2.6.0/drivers/dahdi/Kbuild
sed -i "s|#obj-m += ../staging/echo/|obj-m += ../staging/echo/|" /usr/src/dahdi-linux-2.6.0/drivers/dahdi/Kbuild
echo 'obj-m += echo.o' > /usr/src/dahdi-linux-2.6.0/drivers/staging/echo/Kbuild
113
Ahora se recompilan DAHDI-linux y DAHDI-tools:
cd /usr/src/dahdi-linux-2.6.0
make distcleanmakemake install
DAHDI-Tools:
cd /usr/src/dahdi-tools-2.6.0
make distclean./configuremake menuselectmakemake installmake 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:
nano /etc/asterisk/chan_dahdi.conf
Se añaden las siguientes lineas:
[trunkgroups]
[channels]language=es
114
context=from-pstnoverlapdial=yessignalling=fxs_kstoneduration=100usecallerid=yescidsignalling=v23cidstart=polarityhidecallerid=nocallwaiting=yescallwaitingcallerid=yesthreewaycalling=yestransfer=yescanpark=yescancallforward=yescallreturn=yesechocancel=yesrelaxdtmf=yesrxgain=2.0txgain=3.0callerid = asreceivedamaflags=documentationaccountcode=pstnbusydetect=yesbusycount=6mohinterpret=defaultmohsuggest=default
group=1channel => 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
Reiniciamos 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.4.1DAHDI Version: 2.5.0.1 Echo Canceller(s): OSLEC Configuration
115
======================
El en servidor Linode, se recibirán solamente 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 canal 1:
CLI> dahdi show channel 1
Se sale de la consola:
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:
116
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
CLI> dialplan reload
se sale de la consola:
CLI> quit
6.2 Tarjeta Digium TE120P
La tarjeta TE120P 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:
Los pasos a seguir son:
1. Apagar el computador
117
2. Desconectar el cable de alimentación3. Abrir el chasis del Computador4. Insertar la tarjeta en una ranura PCI disponible5. Volver a poner el chasis del computador6. Conectar el cable de alimentación al computador7. Conectar el cable RJ45 de la linea E1 a la tarjeta8. Encender el computador
Se paran los servicios Asterisk y DAHDI:
service asterisk stop
service dahdi stop
6.2.1 MFG/R2 - Openr2
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.1.tar.gz
se descomprime:
tar -xf openr2-1.3.1.tar.gz
se entra en la carpeta:
cd openr2-1.3.1
y se compila:
./configure --prefix=/usrmakemake install
Luego hay que volver a compilar Asterisk:
cd /usr/src/asterisk-1.8.11.0
make distclean./configuremake
118
make install
Si aparece este WARNING (advertencia):
WARNING WARNING WARNING
Your Asterisk modules directory, located at /usr/lib/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_mysql.so app_saycountpl.so cdr_mysql.so format_mp3.so res_config_mysql.so
WARNING WARNING WARNING
no hay problema ya que esos módulos se han anteriormente compilado 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 openr2libopenr2.so.3 => /usr/lib/libopenr2.so.3 (0x004bf000)
Para ver las distintas versiones de la señalización MFG/R2 soportadas por la librería:
r2test -lVariant Code CountryAR ArgentinaBR BrazilCN ChinaCZ Czech RepublicCO ColombiaEC EcuadorID IndonesiaITU International Telecommunication UnionMX MexicoPH PhilippinesVE Venezuela
119
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 => <Number>,<Timing>,<Line Build Out>,<Framing>,<Coding>[,Yellow]
Number: el puerto donde está conectado el cable de la linea E1. En este caso 1Timing: determina la fuente de sincronización para la tarjeta. Posibles valores:
0 = la fuente la genera la misma tarjeta1 = la fuente es remota
Line Build Out: 0 predefinidoFraming: 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,0,0,cas,hdb3,crc4
o
span => 1,0,0,css,hdb3
Luego se configuran los canales:
bchan = 1-15,17-31dchan = 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
se termina con:
loadzone = codefaultzone = co
Por ultimo se configura el chan_dahdi.conf
120
los dos valores más importantes son:
switchtypesignaling
que también facilita el proveedor. Lo más común es:
switchtype=euroisdnsignaling=pri_cpe
Un ejemplo de archivo de configuración es:
[trunkgroups]
[channels]usecallerid=yeshidecallerid=nocallwaiting=yesusecallingpres=yescallwaitingcallerid=yesthreewaycalling=yestransfer=yescanpark=yescancallforward=yescallreturn=yesechocancel=yesechocancelwhenbridged=yesrelaxdtmf=yesrxgain=2.0txgain=3.0immediate=nocontext=from-pstngroup=1switchtype=euroisdnsignaling=pri_cpechannel => 1-15,17-31
Para la señalización MFC/R2 sería:
system.conf
span=1,1,0,cas,hdb3cas=1-15:1101dchan=16cas=17-31:1101loadzone = co
121
defaultzone = co
chan_dahdi.conf
[trunkgroups]
[channels]usecallerid=yeshidecallerid=nocallwaiting=yesusecallingpres=yescallwaitingcallerid=yesthreewaycalling=yestransfer=yescanpark=yescancallforward=yescallreturn=yesechocancel=yesechocancelwhenbridged=yesrelaxdtmf=yesrxgain=2.0txgain=3.0immediate=nocontext=from-pstngroup=1signalling = mfcr2mfcr2_variant = comfcr2_get_ani_first = nomfcr2_max_ani = 10mfcr2_max_dnis = 4mfcr2_category = national_subscribermfcr2_mfback_timeout = -1mfcr2_metering_pulse_timeout = -1mfcr2_logdir = logmfcr2_logging = allchannel => 1-15,17-31
Terminada la configuración se reinician los servicios:
service dahdi startservice asterisk start
y se averigua en la consola si todos los canales están configurados:
CLI> dahdi show channels
122
6.3 Wanpipe
Se termina esta parte del capitulo con la instalación del driver Wanpipe necesario para tarjetas SANGOMA. Primero se instala la tarjeta:
Los pasos a seguir son:
1. Apagar el computador2. Desconectar el cable de alimentación3. Abrir el chasis del Computador4. Insertar la tarjeta en una ranura PCI disponible5. Volver a poner el chasis del computador6. Conectar el cable de alimentación al computador7. Conectar el cable RJ45 de la linea E1 a la tarjeta8. Encender el computador
se para Asterisk y DAHDI:
service asterisk stopservice dahdi stop
Se descarga el driver:
cd /usr/src
wget ftp://ftp.sangoma.com/linux/current_wanpipe/wanpipe-3.5.23.tgz
se descomprime:
tar -xf wanpipe-3.5.23.tgz
se entra en la carpeta:
cd wanpipe-3.5.23
y se instala:
./Setup dahdi
se escribe y y se continua con envío:
123
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.
Al terminar este párrafo, y para volver a la configuración anterior, se vuelven a poner los archivos predefinidos:
mv /etc/dahdi/system.conf.old /etc/dahdi/system.conf
mv /etc/asterisk/chan_dahdi.conf.old /etc/asterisk/chan_dahdi.conf
y se reinician los dos servicios:
service dahdi start
124
service asterisk start
6.4 Linksys SPA3102 – Gateway FXO/FXS
El SPA3102 es un Gateway que soporta una linea FXO, una linea FXS y 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 la pagina de administración desde remoto, así que lo primero que hay que hacer es activarla.
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 toma de red del computador. Para finalizar, en Internet se conecta un cable de red que luego se conecta al Router. 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:
125
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 hace en la pestaña Voice y luego System:
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á:
126
Para aceptar la advertencia se presiona el botón “Continue”:
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”:
127
Se pone el usuario admin y la clave que se acaba de crear. Se presiona el botón “OK”:
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:
128
Line Enable = yesNAT 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:
Proxy = dirección IP o nombre de dominio del servidor Asterisk remotoRegister = yesDisplay 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 AsteriskUse Auth ID =yesAuth ID = lo mismo que User ID
129
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:
VoIP-To-PSTN Gateway Enable =yesVoIP Caller Auth Method = none (ninguna autentificación)One Stage Dialing = yesLine 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 =yesPSTN 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)
130
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 = 30Detect VoIP Long Silence = yes Lo mismo para lado VoIPVoIP Long Silence Duration = 30Detect Disconnect Tone = YesDisconnect 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=friendsecret=passwordqualify=yesnat=yeshost=dynamicdirectmedia=no
131
context=from-spa3102dtmfmode=rfc2833language=escallerid=LineaTel <NumTel>allowtransfer=yesallowsubscribe=yessubscribecontext=subscribecallcounter=yesdisallow=allallow=alawallow=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):
El dialplan:
nano /etc/asterisk/extensions.conf
para las llamadas salientes al final del contexto internas se pone:
exten => _8.,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:
132
[from-spa3102]exten => s,1,NoOpsame => 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 y se espera que empiece a timbrar la extensión 1000.
133
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.6, se ha explicado la división del dialplan en contextos, extensiones y prioridades. En esta parte se ilustrarán:
• las variables• los pattern matching• la aplicación ECHO• el contexto subscribe• las Macro• la aplicación Authenticate• Limitar llamadas salientes• Enrutamiento llamadas entrantes según fecha hora
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ñadirle 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 visto 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 visto ${EXTEN}. Es una buena practica, cuando se crean variables, 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 las llamadas para luego utilizarlos. 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,Answersame => n,Playback(hello-world)same => n,Hangup
para que quede:
exten => 123,1,Answersame => n,Dumpchansame => n,Playback(hello-world)same => n,Hangup
Se guardan las modificaciones y se recarga el dialplan:
asterisk -rvvvvvvvvvvvvvvv
CLI> dialplan reload
136
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-00000001:===========================================================Info:Name= SIP/1000-00000001Type= SIPUniqueID= 1318352043.1CallerIDNum= 1000CallerIDName= callerid=FulanoDNIDDigits= 123RDNIS= (N/A)Parkinglot=Language= esState= Up (6)Rings= 0NativeFormat= 0x8 (alaw)WriteFormat= 0x8 (alaw)ReadFormat= 0x8 (alaw)RawWriteFormat= 0x8 (alaw)RawReadFormat= 0x8 (alaw)1stFileDescriptor= 29Framesin= 1Framesout= 0TimetoHangup= 0ElapsedTime= 0h0m0sContext= externasExtension= 123Priority= 2CallGroup= 1PickupGroup= 1Application= DumpChanData= (Empty)Blocking_in= (Not Blocking)
Variables:SIPCALLID=YzBkYjQ1MjYyOWYxMzllYjU5Y2RhNmM3MDM3MjFkYTU.SIPDOMAIN=96.126.121.135SIPURI=sip:1000@190.253.173.215:15480
CLI> quit
Para una lista completa de las variables predefinidas se puede consultar la Wiki de Asterisk. Una variable muy peculiar es la variable ${EXTEN}, que contiene el numero marcado. Esta variable tiene la siguiente sintaxis ${EXTEN:x:y) donde x es la posición inicial e y el numero de dígitos que se
137
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 la 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
Desde la extensión 1000 se marca el numero 50. En la consola de Asterisk:
Executing [50@externas:1] Set("SIP/1000-0000000b", "PBX=en_US.UTF-8") in new stackExecuting [50@externas:2] NoOp("SIP/1000-0000000b", "Idioma Servidor en_US.UTF-8") in new stackExecuting [50@externas:3] Hangup("SIP/1000-0000000b", "") in new stack
No todas las variables de ambiente se pueden leer desde Asterisk.
7.2 Pattern Matching
138
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 llamada, 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 puede ser un numero de 0 a 9• Z puede ser un numero de 1 a 9• N puede ser un numero de 2 a 9• [1-4,6-8] 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 Justvoip, la primera linea sería:
exten => _00573XXXXXXXXX,1,Dial(SIP/justvoip/${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/justvoip/${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, siempre hay que anteponer 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})
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 configurarla se modifica el dialplan:
nano /etc/asterisk/extensions.conf
y en el contexto internas se añade el siguiente bloque:
exten => 150,1,Answer
139
same => n,Playback(demo-echotest)same => n,Echosame => 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 hace 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=yesallowsubscribe=yessubscribecontext=subscribenotifyringing=yesnotifyhold=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/1000exten => 1001,hint,SIP/1001exten => 1002,hint,SIP/1002exten => 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.
Otra forma de escribir el bloque es:
[subscribe]exten => _100[0-2],hint,SIP/100[0-2]exten => marko,hint,IAX2/marko
es decir utilizando los Pattern Marching. En este caso se utilizará la primera forma. Se guardan los
140
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 State:Idle Watchers 0 1001@subscribe : SIP/1001 State:Unavailable Watchers 0 1002@subscribe : SIP/1002 State:Unavailable Watchers 0 marko@subscribe : IAX2/marko 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).
Ahora se abre el Xlite configurado como extensión 1000 y se presiona el icono evidenciado:
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:
CLI> quit
y se inicia la captura de los paquetes SIP:
ngrep 1000 -W byline port 5060 > /tmp/subscribe
Se vuelve al Xlite y se presiona el botón OK. Se vuelve a la ventana terminal y se termina la captura de
141
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---------------- AsteriskX-Lite <-----------------NOTIFY---------------- AsteriskX-Lite -------------------200 OK----------------> Asterisk
Y en el NOTIFY final, estará anexa esta parte:
<?xml version="1.0" encoding="ISO-8859-1"?><presence xmlns="urn:ietf:params:xml:ns:pidf"xmlns:pp="urn:ietf:params:xml:ns:pidf:person"xmlns:es="urn:ietf:params:xml:ns:pidf:rpid:status:rpid-status"xmlns:ep="urn:ietf:params:xml:ns:pidf:rpid:rpid-person"entity="sip:1000@96.126.121.135"><pp:person><status><ep:activities><ep:away/></ep:activities></status></pp:person><note>Not online</note><tuple id="1001"><contact priority="1">sip:1001@96.126.121.135</contact><status><basic>closed</basic></status></tuple></presence>
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--------------> XliteAsterisk <--------200 OK-------------- Xlite
La parte final del paquete de Notify enviado por Asterisk a la extensión 1000 será:
<?xml version="1.0" encoding="ISO-8859-1"?><presence xmlns="urn:ietf:params:xml:ns:pidf"xmlns:pp="urn:ietf:params:xml:ns:pidf:person"xmlns:es="urn:ietf:params:xml:ns:pidf:rpid:status:rpid-status"
142
xmlns:ep="urn:ietf:params:xml:ns:pidf:rpid:rpid-person"entity="sip:1000@96.126.121.135"><pp:person><status></status></pp:person><note>Ready</note><tuple id="1001"><contact priority="1">sip:1001@96.126.121.135</contact><status><basic>open</basic></status></tuple></presence>
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 State:Idle Watchers 0 1001@subscribe : SIP/1001 State:Idle Watchers 1 1002@subscribe : SIP/1002 State:Unavailable Watchers 0 marko@subscribe : IAX2/marko 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 Xlite se subscribe el estado de ambas. El resultado será:
Desde la extensión 1001 se marca el numero 150 (test de echo). En el Xlite aparecerá:
143
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.5 Las Macro
Si en el dialplan algunas acciones se repiten a menudo, Asterisk brinda la posibilidad de crear una Macro que permite simplificar este tipo de operaciones. La sintaxis de la aplicación Macro:
asterisk -rvvvvvvvvvvvv
CLI> core show application Macro -= Info about application 'Macro' =-
[Synopsis]Macro Implementation.
[Description]Executes a macro using the context macro-<name>, jumping to the 's' extensionof that context and executing each step, then returning when the steps end.The calling extension, context, and priority are stored in ${MACRO_EXTEN}, ${MACRO_CONTEXT} and ${MACRO_PRIORITY} respectively. Arguments become${ARG1}, ${ARG2}, etc in the macro context.If you Goto out of the Macro context, the Macro will terminate and controlwill be returned at the location of the Goto.
144
If ${MACRO_OFFSET} is set at termination, Macro will attempt to continueat priority MACRO_OFFSET + N + 1 if such a step exists, and N + 1 otherwise.WARNING!!!: Because of the way Macro is implemented (it executes thepriorities contained within it via sub-engine), and a fixed per-thread memorystack allowance, macros are limited to 7 levels of nesting (macro callingmacro calling macro, etc.); It may be possible that stack-intensiveapplications in deeply nested macros could cause asterisk to crash earlierthan this limit. It is advised that if you need to deeply nest macro calls,that you use the Gosub application (now allows arguments like a Macro) withexplict Return() calls instead.WARNING!!!: Use of the application 'WaitExten' within a macro will notfunction as expected. Please use the 'Read' application in order to read DTMFfrom a channel currently executing a macro.
[Syntax]Macro(name[,arg1[,arg2[,...]]])
[Arguments]name The name of the macro
El comando seria:
Macro(nombre_de_la_macro, argumento1,argumento2,argumentoN)
ArgumentoN es un valor o una variable que se pasa a la macro al momento de llamarla desde el plan de llamadas.
La aplicación macro crea las siguientes variables de canal:
• ${MACRO_EXTEN} contendrá el numero marcado• ${MACRO_CONTEXT} contendrá el contexto de donde se ha llamado la Macro• ${MACRO_PRIORITY} contendrá la prioridad de la línea de donde se ha llamado la Macro• ${ARG1}, ${ARG2}, ${ARGN) son las variables que contienen los argumentos que se han
enviado a la Macro.
Para empezar a utilizar la aplicación Macro se creará una muy sencilla que antes de marcar 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 llamadas:
CLI> quit
nano /etc/asterisk/extensions.conf
Al final del archivo se añaden estas líneas:
145
[macro-disponible]exten => s,1,Set(estado=${DEVICE_STATE(SIP/${MACRO_EXTEN})})exten => s,n,Gotoif($["${estado}" = "NOT_INUSE"]?5)exten => s,n,Busyexten => s,n,Hangupexten => s,n,MacroExit
Una explicación de las aplicaciones y funciones nuevas que aparecen en las lineas de la Macro:
La función DEVICE_STATE: controla si una extensión está disponible y retorna un valor que 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 MacroExit: sale de la macro y vuelve al mismo contexto, extensión, prioridad + 1 de donde se llamó.
Para insertar la Macro 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,Macro(disponible)same => n,Dial(SIP/${EXTEN},45)same => n,Hangup
Se guardan los cambios y se actualiza el plan de llamadas:
146
asterisk -rvvvvvvvvvvvvvvv
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] Macro("SIP/1000-00000011", "disponible") in new stackExecuting [s@macro-disponible:1] Set("SIP/1000-00000011", "estado=NOT_INUSE") in new stackExecuting [s@macro-disponible:2] GotoIf("SIP/1000-00000011", "1?5") in new stackGoto (macro-disponible,s,5)Executing [s@macro-disponible:5] MacroExit("SIP/1000-00000011", "") in new stackExecuting [1001@externas:2] Dial("SIP/1000-00000011", "SIP/1001,45") in new stack
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] Macro("SIP/1000-00000013", "disponible") in new stackExecuting [s@macro-disponible:1] Set("SIP/1000-00000013", "estado=UNAVAILABLE") in new stackExecuting [s@macro-disponible:2] GotoIf("SIP/1000-00000013", "0?5") in new stackExecuting [s@macro-disponible:3] Busy("SIP/1000-00000013", "") in new stack
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 Justvoip. 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á:
[Feb 2 10:29:18] NOTICE[31745]: chan_sip.c:22147 handle_request_invite: Call from '1002' (186.112.195.81:10000) to extension '00573126814740' rejected because extension not found in context 'locales'.
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 hará utilizando la aplicación Authenticate.
Para conocer la sintaxis de la aplicación:
asterisk -rvvvvvvvvvvvvvv
147
CLI> core show application authenticate
[Syntax]Authenticate(password[,options[,maxdigits[,prompt]]])
[Arguments]password Password the user should knowoptions a: Set the channels' account code to the password that is entered d: Interpret the given path as database key, not a literal file 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 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 /tmp/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”
148
nano /etc/asterisk/extensions.conf
después del contexto internas se añade el siguiente bloque:
[auten]exten => _00.,1,NoOPsame => n,Authenticate(/tmp/pin.txt,am,4)same => n,Dial(SIP/justvoip/${EXTEN})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 haya utilizado para efectuar la llamada
• La opción m define que el archivo de texto contendrá las contraseñas cifradas con 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 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 => internasinclude => 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:
149
mysql -u root -psesamo
Se selecciona la base de datos asteriskcdr (donde se ha creado la tabal CDR):
mysql> use asteriskcdr
y se hace una consulta en la tabal 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 +------+--------------+-------------------+---------+-------------+| 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, 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 Justvoip.
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
150
configurada en Asterisk, el comando es:
asterisk -rvvvvvvvvvvvvvvvvv
CLI> sip show inuse* Peer name In use Limit1000 0/0/0 21474836471001 0/0/0 21474836471002 0/0/0 2147483647justvoip 0/0/0 2147483647
Bajo la columna In use, los significados de las tres columnas (de la izquierda a la derecha) son:
• Canales in uso• Canales timbrando• 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/justvoip/${EXTEN},30)same => n,Hangup
Para que queden:
exten => _00X.,1,NoOpsame => n,Set(GROUP(voip)=justvoip)same => n,Set(GROUP(salida)=${CALLERID(num)})same => n,Set(trunksal=${GROUP_COUNT(justvoip@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 Justvoip)same => n,Gotoif($[${extsal} > 2 | ${trunksal} > 2]?busy)same => n,Dial(SIP/justvoip/${EXTEN})same => n,Hangupsame => n(busy),Playback(all-outgoing-lines-unavailable)same => n,Hangup
Una explicación del dialplan creado:
• En la segunda linea se se asigna al grupo voip la troncal justvoip• En la tercera linea se asigna al grupo salida la variable ${CALLERID(num)} que contiene el
151
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.
Ahora para hacer 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 == Extension Changed 1001[subscribe] new state InUse for Notify User 1000 -- Executing [005714013434@externas:1] NoOp("SIP/1001-00000020", "") in new stack -- Executing [005714013434@externas:2] Set("SIP/1001-00000020", "GROUP(voip)=justvoip") in new stack -- Executing [005714013434@externas:3] Set("SIP/1001-00000020", "GROUP(salida)=1001") in new stack -- Executing [005714013434@externas:4] Set("SIP/1001-00000020", "trunksal=1") in new stack -- Executing [005714013434@externas:5] Set("SIP/1001-00000020", "extsal=1") in new stack -- Executing [005714013434@externas:6] NoOp("SIP/1001-00000020", "Hay 1 llamadas desde la extension 1001 y 1 con el proveedor Justvoip") in new stack -- Executing [005714013434@externas:7] GotoIf("SIP/1001-00000020", "0?busy") in new stack -- Executing [005714013434@externas:8] Dial("SIP/1001-00000020", "SIP/justvoip/005714013434") in new stack Segunda Llamada == Using UDPTL CoS mark 5 == Using SIP RTP CoS mark 5 -- Called SIP/justvoip/005714013434 -- SIP/justvoip-00000021 is making progress passing it to SIP/1001-00000020 == Using UDPTL CoS mark 5 == Using SIP RTP CoS mark 5 -- Executing [005714013434@externas:1] NoOp("SIP/1000-00000022", "") in new stack -- Executing [005714013434@externas:2] Set("SIP/1000-00000022", "GROUP(voip)=justvoip") in new stack -- Executing [005714013434@externas:3] Set("SIP/1000-00000022", "GROUP(salida)=1000") in new stack -- Executing [005714013434@externas:4] Set("SIP/1000-00000022", "trunksal=2") in new stack -- Executing [005714013434@externas:5] Set("SIP/1000-00000022", "extsal=1") in new stack
152
-- Executing [005714013434@externas:6] NoOp("SIP/1000-00000022", "Hay 1 llamadas desde la extension 1000 y 2 con el proveedor Justvoip") in new stack -- Executing [005714013434@externas:7] GotoIf("SIP/1000-00000022", "0?busy") in new stack -- Executing [005714013434@externas:8] Dial("SIP/1000-00000022", "SIP/justvoip/005714013434") in new stack
Tercera Llamada == Using UDPTL CoS mark 5 == Using SIP RTP CoS mark 5 -- Called SIP/justvoip/005714013434 -- SIP/justvoip-00000023 is making progress passing it to SIP/1000-00000022 -- SIP/justvoip-00000021 answered SIP/1001-00000020 == Using UDPTL CoS mark 5 == Using SIP RTP CoS mark 5 -- Executing [005714013434@externas:1] NoOp("SIP/1000-00000024", "") in new stack -- Executing [005714013434@externas:2] Set("SIP/1000-00000024", "GROUP(voip)=justvoip") in new stack -- Executing [005714013434@externas:3] Set("SIP/1000-00000024", "GROUP(salida)=1000") in new stack -- Executing [005714013434@externas:4] Set("SIP/1000-00000024", "trunksal=3") in new stack -- Executing [005714013434@externas:5] Set("SIP/1000-00000024", "extsal=2") in new stack -- Executing [005714013434@externas:6] NoOp("SIP/1000-00000024", "Hay 2 llamadas desde la extension 1000 y 3 con el proveedor Justvoip") in new stack -- Executing [005714013434@externas:7] GotoIf("SIP/1000-00000024", "1?busy") in new stack -- Goto (externas,005714013434,10) -- Executing [005714013434@externas:10] Playback("SIP/1000-00000024", "all-outgoing-lines-unavailable") in new stack -- <SIP/1000-00000024> Playing 'all-outgoing-lines-unavailable.ulaw' (language 'es')[Feb 6 11:52:16] NOTICE[3578]: channel.c:4148 __ast_read: Dropping incompatible voice frame on SIP/1000-00000024 of format alaw since our native format has changed to 0x4 (ulaw) -- SIP/justvoip-00000023 answered SIP/1000-00000022 -- Started music on hold, class 'default', on SIP/justvoip-00000023 -- Executing [005714013434@externas:11] Hangup("SIP/1000-00000024", "") 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 Limit1000 1/0/0 21474836471001 1/0/0 21474836471002 0/0/0 2147483647justvoip 2/0/0 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.
153
154
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 interactuar 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. Algunos ejemplos: el menú que se escucha cuando se llama un centro de atención al cliente; los bancos que permiten hacer 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 hacer consulta a base de datos, devolver los resultados y, en general, interactuar de forma activa con el usuario.
• la contestadora automática permite navegar entre menús vocales permitiendo elegir entre distintos menús 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 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 configurado en el teléfono IP o softphone de quien 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
157
De esta forma se convierte la locución al formato audio ulaw
CLI> file convert custom/prompt01.wav custom/prompt01.alaw
para el formato alaw.
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 ella envía 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 hace desde el panel de control que cada cliente tiene a disposición. Para una idea de como funciona y de como se configuran los números geográficos, puede visitar la pagina de la empresa VozToVoice.
El el caso que se adquiera un numero geográfico, al momento de configurarlo, 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 hacer 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" <sip:6620016037@46.19.209.76>;tag=as4dbd19b8
Asterisk no puede autenticar el INVITE en entrada
Para solucionar el problema hay que añadir en el sip.conf de Asterisk todas las direcciones IP de donde puede llegar una llamada. Estas direcciones están configuradas en un archivo que se descargará:
cd /etc/asterisk
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:
158
#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 no Asterisk no encuentra el contexto from-voztooice. Más adelante se creará ese contexto
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)exten => i,2,Goto(IVR,s,2)exten => i,3,Hangupexten => 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)
159
exten => s,5,WaitExten()exten => 1,1,Playback(demo-echotest)exten => 1,2,Echo()exten => 2,1,MusicOnHoldexten => 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,hangupexten => 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 => 2,1,MusicOnHoldexten => 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,hangupexten => 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:
• 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 de segundos máximo (7) entre el primer dígito y los
siguientes• Set(TIMEOUT(response)=10) – numero 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
160
• 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 dialplanLa 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 digita 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,Noopsame => n,Dial(SIP/1000&SIP/1001&SIP/1002,30)same => n,Hangup
Lo que se 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:
[from-didvoztovoice]exten => s,1,Answersame => n,Goto(IVR,s,2)same => n,Hangup
from-didvoztovoice es el contexto donde llegarán las llamadas al 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,Answersame => 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
161
#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
162
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 y asistida• Captura de las llamadas (Pickup)• Grabación de las llamadas
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 archivoparkext => 700 = numero de extensión donde transferir una llamada para
parquearlaparkpos => 701-709 = numero de extensiones reservadas para parquear las
llamadasparkinghints no = las prioridades Hint para monitorear el estado de las
extensiones dedicadas al parqueo hay que configurarlas manualmente en el dialplan. Con yes se crean de forma automática
parkingtime => Numero de segundos que quedará parqueada una llamadas. 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 parkedcallstimeout, extensión s, prioridad 1. En ese caso hay que crear el contexto en el dialplan
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 cuando es una llamada parqueada. Puede ser:
• callee (llamado)• caller (llamante)
Parámetro Descripción
• both (ambos)• no (no permitido)
parkedcallreparking Activa o desactiva la secuencia de tonos para parquear la llamada cuando es 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 es 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 es una llamada parqueada. Puede ser:
• callee (llamado)• caller (llamante)• both (ambos)• no (no permitido)
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 está timbrando. Depende 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
165
Parámetro Descripción(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
funcionalidadesblindxfer => # = tecla para activar la transferencia ciegadisconnect => *0 = secuencia de dígitos para terminar una llamadaautomon => *1 = secuencia de dígitos para iniciar la grabación de la llamada (en
dos archivos audio, uno para cada canal)atxfer => *2 = secuencia de dígitos para activar la transferencia asistidaparkcall => *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: <FeatureName> => <DTMF_sequence>,<ActivateOn>[/<ActivatedBy>],<Application>[,<AppArguments>[,MOH_Class]]
166
Parámetro Descripción
• FeatureName: El nombre de la funcionalidad;• DTMF_sequence: la secuencia de dígitos para activar la
funcionalidad;• ActivateOn: aquí se define para quien activar la
funcionalidad. Los valores son self y peer. Con self la funcionalidad se activa para quien la activa, 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.
test1 => *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
Antes de crear el archivo una pequeña explicación de la diferencia entre transferencia ciega y transferencia asistida:
• blinxfer: A lo largo de una conversación se quiere transferir la llamada a otra extensión. Hay que presionar la tecla # y luego el numero de la extensión. La llamada será transferida y el el canal de quien la transfirió será colgado
• atxfer: A lo largo de una conversación se quiere transferir la llamada a otra extensión. Se presiona la secuencia *2 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 se colgará la llamada será efectivamente transferida.
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 => 700parkpos => 701-709
167
parkinghints=noparkingtime => 45comebacktoorigin=yescourtesytone=beepparkedplay=bohtparkedcalltransfers=callerparkedcallreparking=callerparkedcallhangup=callerparkedcallrecording=callerparkedmusicclass=defaulttransferdigittimeout => 5xfersound=beepxferfailsound=beeperrpickupexten=*8pickupsound=beeppickupfailsound=beeperrfeaturedigittimeout=2000atxfernoanswertimeout=15atxferdropcall=noatxferloopdelay=10atxfercallbackretries=2
;[parkinglot_empresa2];context => empresa2;parkpos => 801-810;findslot => next
[featuremap]blindxfer => #disconnect => *0automon => *1atxfer => *2parkcall => *7automixmon => *3
[applicationmap]test1 => *9,peer,Playback,tt-monkeys,default
Se guardan los cambios. Para volver disponibles estas funcionalidades hay que modificar el plan de llamadas. Se va a recoger la configuración del archivo así como se dejó en el modulo anterior. En negrita aparecen las modificaciones:
nano /etc/asterisk/extensions.conf
[general]static=yeswriteprotect=yse
168
autofallthrough=yseextenpatternmatchnew=yseclearglobalvars=no
[globals]1000=SIP/1000JUST=SIP/justvoipmarko=IAX2/markoDYNAMIC_FEATURES=test1#blindxfer#automon#disconnect#atxfer#parkcall#automixmon
[from-didvoztovoice]exten => s,1,Answersame => n,Goto(IVR,s,2)same => n,Hangup
[internas]exten => 50,1,Set(PBX=${ENV(LANG)})same => n,Noop(Idioma Servidor ${PBX})same => n,Hangup
exten => 75,1,Answersame => n,Wait(1)same => n,Goto(IVR,s,2)
exten => 100,1,Noopsame => n,Dial(SIP/1000&SIP/1001&SIP/1002,30)same => n,Hangup
exten => 123,1,Answersame => n,Dumpchansame => n,Playback(hello-world)same => n,Hangup
exten => 150,1,Answersame => n,Playback(demo-echotest)same => n,Echosame => n,Playback(demo-echodone)same => n,Hangup
exten => 200,1,Answersame => n,Jabbersend(campus.voztovoice,voztovoicenet@gmail.com,Estamos escuchando MP3)same => n,MusicOnHold(mp3,60)same => n,Hangup
exten => _100[0-2],1,Macro(disponible)same => n,Dial(SIP/${EXTEN},45)same => n,Hangup
169
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 => _[a-z].,1,Dial(gtalk/campus.voztovoice/${EXTEN},30)same => n,Hangup
exten => 10000,1,Dial(gtalk/campus.voztovoice/fulano@gmail.com,30)same => n,Hangup
exten => _8.,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,NoOPsame => n,Authenticate(/tmp/pin.txt,am,4)same => n,Dial(SIP/justvoip/${EXTEN})same => n,Hangup
[subscribe]exten => 1000,hint,SIP/1000exten => 1001,hint,SIP/1001exten => 1002,hint,SIP/1002exten => marko,hint,IAX2/markoexten => 701,hint,park:701@parkedcallsexten => 702,hint,park:702@parkedcallsexten => 703,hint,park:703@parkedcallsexten => 704,hint,park:704@parkedcallsexten => 705,hint,park:705@parkedcallsexten => 706,hint,park:706@parkedcallsexten => 707,hint,park:707@parkedcallsexten => 708,hint,park:708@parkedcallsexten => 709,hint,park:709@parkedcalls
[google-in]
170
exten => s,1,NoOp( Call from Gtalk )same => n,SendText(Hola,Como te llamas?)same => n,Set(nombre=${JABBER_RECEIVE(campus.voztovoice,${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,NoOpsame => n,Dial(SIP/1000)same => n,Hangup
[from-pstn]exten => s,1,Dial(SIP/1000,45)exten => s,n,Hangup
[internacio]exten => _00X.,1,NoOpsame => n,Set(GROUP(voip)=justvoip)same => n,Set(GROUP(salida)=${CALLERID(num)})same => n,Set(trunksal=${GROUP_COUNT(justvoip@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 Justvoip)same => n,Gotoif($[${extsal} > 2 | ${trunksal} > 2]?busy)same => n,Dial(SIP/justvoip/${EXTEN})same => n,Hangupsame => n(busy),Playback(all-outgoing-lines-unavailable)same => n,Hangup
exten => _1XXXXXXXXXX,1,Dial(gtalk/campus.voztovoice/+${EXTEN}@voice.google.com)same => n,Hangup
exten => _NNXX.,1,Dial(gtalk/campus.voztovoice/+${EXTEN}@voice.google.com)same => n,Hangup
[externas]include => internasinclude => internacioinclude => parkedcalls
[locales]include => internasinclude => auten
171
include => parkedcalls
[macro-disponible]exten => s,1,Set(estado=${DEVICE_STATE(SIP/${MACRO_EXTEN})})exten => s,n,Gotoif($["${estado}" = "NOT_INUSE"]?5)exten => s,n,Busyexten => s,n,Hangupexten => s,n,MacroExit
#include IVR
Para que las funcionalidades configuradas en features.conf sean activas hay que definir la variable DYNAMIC_FEAUTURES y añadirle todas las funcionalidades que se han configurado. 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 (en los teléfonos IP software y hardware que soportan esta funcionalidad).
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].
Hay tres aplicaciones relacionadas con el parqueo de llamadas que se pueden utilizar en el dialplan:
• Park• ParkAndAnnounce• ParkedCall
Se guardan los cambios y se reinicia Asterisk:
/etc/init.d/asterisk restart
Desde la consola de Asterisk podemos ver las funcionalidades activadas.
asterisk -rvvvvvvvvvvvv
CLI> features show
Builtin Feature Default Current--------------- ------- -------Pickup *8 *8Blind Transfer # #Attended Transfer *2One Touch Monitor *1Disconnect Call * *0Park Call *7
172
One Touch MixMonitor *3
Dynamic Feature Default Current--------------- ------- -------test1 no def *9
Feature Groups:---------------(none)
Call parking (Parking lot: default)------------Parking extension : 700Parking context : parkedcallsParked call extensions: 701-709
9.2 Callgroup y Pickupgroup
En todas las extensiones SIP configuradas se han definido los siguientes parámetros:
callgroup=1pickupgroup=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
173
El escenario es que cada trabajador 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:
[1000]callgroup=1pickupgroup=1
[1001]callgroup=1pickupgroup=1
[1002]callgroup=1pickupgroup=1
[2000]callgroup=2pickupgroup=2
[2001]callgroup=2pickupgroup=2
[2002]callgroup=2pickupgroup=2
[3000]callgroup=3pickupgroup=3
[3001]callgroup=3pickupgroup=3
[3000]callgroup=3pickupgroup=3
[4000]callgroup=4pickupgroup=1,2,3
La extensión 4000, con el parámetro pickupgroup configurado con 1,2,3 podrá capturar las llamadas de
174
las extensiones que perteneces a uno de los grupos configurados, es decir:
• grupo 1 – 1000,1001,1002• grupo 2 – 2000,2001.2002• grupo 3 – 3000,3001,3002
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 nos permite efectuar una llamada• Technology: el protocolo o la tecnología usada para efectuar la llamada (ej: SIP, IAX2)• resource: el recurso utilizado para hacer 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
funcionalida)
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á 30 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/justvoip/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 Justvoip). Esperará una respuesta por 45 segundos y si nadie contesta terminará la llamada. Como tecnología se ha indicado SIP porque justvoip usa solo este tipo de protocolo. En el caso de proveedores que utilicen el protocolo IAX2 sería:
exten => 00573001000000,1,Dial(IAX2/justvoip/00573001000000,45)same => n,,Hangup
Para configurar las funcionalidades definidas en el archivo features.conf se tendrá que utilizar unas
175
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
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)
176
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. (en negrita los cambios):
nano /etc/asterisk/extensions.conf
exten => _100[0-2],1,Macro(disponible)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:
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á:
177
La extensión 1002 esta parqueada en la extensión 701. 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 hacer es grabar la llamada utilizando la secuencia de dígitos *3 para tener un solo archivo audio de toda la conversación.
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á:
-- <SIP/1001-00000009> Playing 'beep.ulaw' (language 'es') -- User hit '*3' to record call. filename: auto-1318460210-1001-1002 == Begin MixMonitor Recording SIP/1002-0000000a -- <SIP/1001-00000009> 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 233964 Oct 12 17:57 auto-1318460210-1001-1002.wav
178
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.
179
Capitulo X
Asterisk y los calendarios
Asterisk puede ser integrado con distintos formatos de calendarios. Esta nueva funcionalidad ha sido incluida desde la versión 1.8.X. 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 interactuar con estos formatos de Calendario. Los módulos que se encargan de esta integración son:
asterisk -rvvvvvvvvvvvvv
CLI> module show like res_calendarModule Description Use Countres_calendar.so Asterisk Calendar integration 1res_calendar_caldav.so Asterisk CalDAV Calendar Integration 0res_calendar_ews.so Asterisk MS Exchange Web Service Calenda 0res_calendar_icalendar.so Asterisk iCalendar .ics file integration 0res_calendar_exchange.so Asterisk MS Exchange Calendar Integratio 0
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
[campusvoztovoice] 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 caldavurl La URL para conectarse al calendario. En el caso de GoogleCalendar la
sintaxis es:https://www.google.com/calendar/dav/username@gmail.com/events/Personalizar username@gmail con su cuenta de Google
user Nombre usuario gmail. En este ejemplo: campus.voztovoice@gmail.com Personalizar
secret la contraseña del usuario Googlerefresh Cada cuantos minutos consultar el Calendario de Google para actualizar
los datos en Asterisk. Valor: 10timeframe 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• ejecutar una aplicación y definir sus parámetros.
context nombre del contexto: calendario
182
Parámetro Descripción
extension numero de extensión: calappappdata
aplicación a ejecutar cuando la extensión conteste: Playbackopciones 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
[campusvoztovoice]type=caldavurl=https://www.google.com/calendar/dav/username@gmail.com/events/user=campus.voztovoice@gmail.comsecret=passwordrefresh=10timeframe=180autoreminder=10channel=SIP/1000context=calendarioextension=calwaittime=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:
183
Se entra en la consola de Asterisk:
asterisk -rvvvvvvvvvvvvvvvvvvvv
Se recarga el modulo calendario:
CLI> module reload res_calendar.so
Si aparece esta advertencia:
[Feb 7 16:20:09] WARNING[27477]: res_calendar_caldav.c:157 caldav_request: Unknown response to CalDAV calendar campusvoztovoice, request REPORT to /calendar/dav/campus.voztovoice@gmail.com/events/: Could not read status line: connection was closed by server
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:
https://www.google.com/calendar/dav/campus.voztovoice@gmail.com/events/
Aparecerá:
184
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 parametro 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.29.6
y se lanza nuevamente un configure:
./configure
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:
185
make distclean
./configure --prefix=/usr --with-ssl=openssl
Ahora si se compiló con el soporte SSL. Se termina la compilación e instalación:
makemake 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-1.8.11.0
se borra la compilación anterior:
make distclean
se vuelve a compilar:
./configure
Se necesita volver a entrar en la interfaz gráfica para seleccionar los módulos Add-ons ya que por defecto no están seleccionados:
make menuselect
186
Se guardan los cambios y se vuelve a compilar:
makemake install
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
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 Type Status-------- ---- ------campusvoztovoice caldav free
Con este comando:
CLI> calendar show calendar campusvoztovoice
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 campusvoztovoice con el nombre de su calendario.
187
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 ultimo modulo del curso, en este caso se implementará esta solución. Para que el AGI funcione, los requisitos son:
• Paquete Perl• Paquete perl-libwww• sox
188
• mpg123• el servidor donde está instalado Asterisk debe tener acceso a Internet
Como sox ya está instalado, se instalan los paquetes de perl:
yum install perl perl-libwww-perl
se descarga, compila e instala mpg123:
cd /usr/srcwget http://downloads.sourceforge.net/project/mpg123/mpg123/1.13.4/mpg123-1.13.4.tar.bz2tar -xf mpg123-1.13.4.tar.bz2cd mpg123-1.13.4./configure --prefix=/usrmakemake install
Ya se puede descargar el archivo que contiene el AGI:
cd /usr/src
wget http://www.voztovoice.org/campus/pbx18/asterisk-googletts-0.5.tar.gz
Se descomprime:
tar -xf asterisk-googletts-0.5.tar.gz
Se entra en la carpeta creada:
cd asterisk-googletts-0.5
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)
189
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á siempre con este CALLERID:
Cuando el evento iniciará en el calendario aparecerá el estado ocupado:
asterisk -rvvvvvvvvvvvvvv
CLI> calendar show calendarsCalendar Type Status-------- ---- ------campusvoztovoice caldav 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
190
es:
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 beaccessed 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 tabuladorCALENDAR_BUSY CALENDAR_EVENT CALENDAR_QUERY CALENDAR_QUERY_RESULT CALENDAR_WRITE
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
191
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.
Se abre el dialplan
nano /etc/asterisk/extensions.conf
se modifica este bloque:
exten => _100[0-2],1,Macro(disponible)same => n,Dial(SIP/${EXTEN},45,hHkKtTwWxX)same => n,Hangup
para que quede:
exten => _100[0-2],1,Macro(disponible)same => n,Macro(calendario)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 macro:
[macro-calendario]exten => s,1,Noop(${MACRO_EXTEN})same => n,GotoIf($[${MACRO_EXTEN} = 1000]?calendario)same => n,MacroExitsame => n(calendario),Set(estado=${CALENDAR_BUSY(campusvoztovoice)})same => n,Noop(Estado = ${estado})same => n,Gotoif($[${estado} = 1]?ocupado)same => n,MacroExitsame => n(ocupado),Agi(googletts.agi,"la extensión se encuentra ocupada, llame mas tarde. Gracias",es)same => n,Hangup
Esta nueva macro 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 campusvoztovoice) 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 Macro y se vuelve al contexto, extensión, prioridad +1 de donde la Macro se ha llamado.
Se guardan los cambios y se recarga el dialplan:
asterisk -rvvvvvvvvvvvvvvvvvvvvv
192
CLI> dialplan reload
se averigua el estado del calendario:
CLI> calendar show calendarsCalendar Type Status-------- ---- ------campusvoztovoice caldav 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] Macro("SIP/1001-0000000f", "disponible") in new stack -- Executing [s@macro-disponible:1] Set("SIP/1001-0000000f", "estado=NOT_INUSE") in new stack -- Executing [s@macro-disponible:2] GotoIf("SIP/1001-0000000f", "1?5") in new stack -- Goto (macro-disponible,s,5) -- Executing [s@macro-disponible:5] MacroExit("SIP/1001-0000000f", "") in new stack -- Executing [1000@externas:2] Macro("SIP/1001-0000000f", "calendario") in new stack -- Executing [s@macro-calendario:1] NoOp("SIP/1001-0000000f", "1000") in new stack -- Executing [s@macro-calendario:2] GotoIf("SIP/1001-0000000f", "1?calendario") in new stack -- Goto (macro-calendario,s,4) -- Executing [s@macro-calendario:4] Set("SIP/1001-0000000f", "estado=1") in new stack -- Executing [s@macro-calendario:5] NoOp("SIP/1001-0000000f", "Estado = 1") in new stack -- Executing [s@macro-calendario:6] GotoIf("SIP/1001-0000000f", "1?ocupado") in new stack -- Goto (macro-calendario,s,8) -- Executing [s@macro-calendario:8] AGI("SIP/1001-0000000f", "googletts.agi,"la extension se encuentra ocupada, llame mas tarde. Gracias",es") in new stack -- Launched AGI Script /var/lib/asterisk/agi-bin/googletts.agi -- Playing '/tmp/80eb1469553d3ab98b95661fbf6a2f1c' (escape_digits=) (sample_offset 0) -- <SIP/1001-0000000f>AGI Script googletts.agi completed, returning 0 -- Executing [s@macro-calendario:9] Hangup("SIP/1001-0000000f", "") in new stack
10.3 CALENDAR_EVENT
Como ya se ha visto más arriba, esta función permite extraer todas las informaciones relacionadas con un evento. 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
193
• categories – Categoría del evento• priority – Prioridad asignada al 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
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:
194
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,Hangupsame => n(conf),Agi(googletts.agi,"${CALENDAR_EVENT(description)}",es)same => n,Confbridge(${CALENDAR_EVENT(location)},cM(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 ConfBridge 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 hacer 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:
195
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 univocamente 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:
196
Perfecto! Ahora se crea el dialplan para hacer 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(campusvoztovoice,${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,Endwhilesame => 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 puede hacer 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 campusvoztovoice indicando la ora de inicio y la hora final de la consulta, es decir los eventos
197
que tendrán lugar en lo próximos 180 minutos• 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 usa para crear un ciclo y este ciclo se ejecutará hasta que la
variable ${numeve} sea mayor a 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 Justvoip 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:
198
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 anota el 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=caldavurl=https://www.google.com/calendar/dav/gkcb6avik25hne6tg10d20sf1k@group.calendar.google.com/events/user=campus.voztovoice@gmail.comsecret=passwordrefresh=10timeframe=180autoreminder=10channel=SIP/1000context=calendarioextension=calwaittime=45
199
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 calendarsCalendar Type Status-------- ---- ------campusvoztovoice caldav freellamadas caldav 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,NoOpsame => n,Set(GROUP(voip)=justvoip)same => n,Set(GROUP(salida)=${CALLERID(num)})same => n,Set(trunksal=${GROUP_COUNT(justvoip@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 Justvoip)same => n,Gotoif($[${extsal} > 2 | ${trunksal} > 2]?busy)same => n,Dial(SIP/justvoip/${EXTEN})same => n,Hangup
200
same => n(busy),Playback(all-outgoing-lines-unavailable)same => n,Hangup
Para que quede:
[internacio]exten => _00X.,1,NoOpsame => 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)=justvoip)same => n,Set(GROUP(salida)=${CALLERID(num)})same => n,Set(trunksal=${GROUP_COUNT(justvoip@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 Justvoip)same => n,Gotoif($[${extsal} > 2 | ${trunksal} > 2]?busy)same => n,Dial(SIP/justvoip/${EXTEN})same => n,Hangupsame => 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
por Google Calendar
El resultado en Google Calendar será:
201
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 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.
202
Primero se modifica la configuración del calendario:
nano /etc/asterisk/calendar.conf
Se modifica esta linea:
channel=SIP/1000
para que quede:
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 6000, 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/justvoip/0057XXXXXXXXXX)same => n,hangupsame => 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:
203
Si no se contesta dentro de 15 segundos, la llamada se enviará al numero fijo/celular configurado:
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.
204
Capitulo XI
CCSS (Call Completion Supplementary System) – Rellamada
El CCSS es una nueva funcionalidad de Asterisk 1.8.X 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 Internet Draft “draft-ietf-bliss-call-completion-04”. Un Internet Draft es una propuesta de estandarización presentada a la IETF (Internet Engineering Task Force) para que sea analizada y, si el caso, aprobada y transformada en un RFC (Request for Comment), es decir, un estándar de hecho.
En este caso los desarrolladores de Asterisk han optado por implementar un sistema que todavía no es un estándar de hecho. Esto explica porque muchas veces no hay interoperabilidad entre dispositivos SIP de distintos productores aunque, supuestamente, todos utilizan el protocolo SIP.
Actualmente la única PBX que utiliza este Draft 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 Draft 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 se utiliza el agente genérico para solicitar la rellamada, habrá que utilizar la aplicación CallCompletion. Si se utiliza el agente nativo, el mismo productor del dispositivo que implementa el Draft, 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 hace 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 la aplicación CallCompletionCancel en el dialplan.
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 se pone, después de la etiqueta general, el parámetro cc_max_requests:
[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 de 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óncc_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 Draft sino el sub-sistema basado en el
207
DEVICE_STATE• native: cuando se utiliza el Draft para el
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 monitorep del llamado utilizando el sub-sistema basado en el DEVICE_STATE
• native: cuando se utiliza el Draft para el sistema de rellamada (el teléfono del llamado lo soporta)
• always: cuando no se sabe si el teléfono soporta el Draft. 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 hacer 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=genericcc_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
208
nano /etc/asterisk/extensions.conf
en el contexto internas se añaden las siguientes lineas:
exten => *30,1,CallCompletionRequestsame => n,Agi(googletts.agi,"Rellamada activada",es)same => n,Hangup
exten => *31,1,CallCompletionCancelsame => 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 la extensión 1000
CLI> cc report status
Ahora para solicitarla desde la extensión 1000 se marca *30.
CLI> cc report status
209
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 efectúe, el sistema esperará que la extensión 1001 haga 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 de 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:
210
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 se 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:
211
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 Draft se basa en un sistema de SUBSCRIBE, NOTIFY y PUBLISH donde el cuerpo del paquete SIP contiene la información en ese formato (XML).
212
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 hagan 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 hace 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.sopreload => 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. Se crea una nueva base de datos2. Se crea la tabla para el Realtime estático3. Se configurar el conector ODBC4. Se configura el archivo de configuración de Asterisk res_odbc.conf5. 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;
Se otorgan los permisos de acceso a la base de datos creada al usuario asterisk, desde local:
215
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.
mysql> INSERT INTO ast_config (cat_metric,var_metric,filename,category,var_name,var_val) VALUES ('0','0','musiconhold.conf','default','mode','files');
216
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 aleatoriamente. 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 aleatoriamente.
Se sale del cliente MySQL:
mysql> quit
Creada la base de datos y la tabla, se configura el conector ODBC. Esto se hace en dos archivos de configuración:
• odbcinst.ini• odbc.ini
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
217
rm /etc/odbcinst.ini
se crea uno nuevo:
nano /etc/odbcinst.ini
y para ODBC → MySQL se ponen las siguientes lineas:
[MySQL]Description = ODBC para MySQLDriver = /usr/lib/libmyodbc3.soSetup = /usr/lib/libodbcmyS.soFileUsage = 1
Para una versión 64 bit de CentOS sería:
[MySQL]Description = ODBC para MySQLDriver = /usr/lib64/libmyodbc3.soSetup = /usr/lib64/libodbcmyS.soFileUsage = 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 AsteriskDriver = MySQLDatabase = asteriskServer = localhostUser = asteriskPassword = sesamoPort = 3306Option = 3
Se guardan los cambios. Para probar la conexión entre ODBC y la base de datos asterisk se usa el comando:
isql asterisk asterisk sesamo
• asterisk – etiqueta que da inicio al bloque configurado en odbc.ini• asterisk – nombre del usuario que tiene acceso a la base de datos creada
218
• 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 => yesdsn => asteriskusername => asteriskpassword => sesamopre-connect => yessanitysql => select 1idlecheck => 3600connect_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
después de esta linea:
;extensions.conf => sqlite,asterisk,ast_config
219
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:
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 allODBC DSN Settings-----------------
Name: asterisk DSN: asterisk Last connection attempt: 1969-12-31 19:00:00 Pooled: No
220
odbc.ini res_odbc.conf
extconfig.conf
Connected: Yes
se mira la configuración de la música de espera:
CLI> moh show classesClass: default Mode: files Directory: /var/lib/asterisk/mohClass: 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 hace 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 los 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• regserver• useragent• lastms
221
Para crear una tabla más completa, se puede tomar como referencia el resultado de este comando:
CLI> sip show peer 1000
* Name : 1000 Secret : <Set> MD5Secret : <Not set> Remote Secret: <Not set> Context : externas Subscr.Cont. : subscribe Language : es Accountcode : 1000 AMA flags : Unknown Transfer mode: open CallingPres : Presentation Allowed, Not Screened Callgroup : 1 Pickupgroup : 1 Mailbox : 1000@default VM Extension : asterisk LastMsgsSent : 32767/65535 Call limit : 2147483647 Dynamic : Yes Callerid : "callerid=Fulano" <1000> MaxCallBR : 384 kbps Expire : 2917 Insecure : no Nat : Always ACL : No T.38 support : Yes T.38 EC mode : FEC T.38 MaxDtgrm: 400 DirectMedia : No PromiscRedir : No User=Phone : No Video Support: Yes Text Support : No Ign SDP ver : No Trust RPID : No Send RPID : Yes Subscriptions: Yes Overlap dial : Yes Forward Loop : Yes DTMFmode : rfc2833 Timer T1 : 500 Timer B : 32000 ToHost : Addr->IP : 190.253.175.156 Port 22840
222
Defaddr->IP : 0.0.0.0 Port 5060 Prim.Transp. : UDP Allowed.Trsp : UDP Def. Username: 1000 SIP Options : replaces replace Codecs : 0x8010c (ulaw|alaw|g729|h263) Codec Order : (alaw:20,ulaw:20,g729:20) Auto-Framing : No 100 on REG : Yes Status : OK (129 ms) Useragent : Reg. Contact : sip:1000@190.253.175.156:22840;rinstance=3201f90c0a78b7d0 Qualify Freq : 60000 ms Sess-Timers : Accept Sess-Refresh : uas Sess-Expires : 1800 secs Min-Sess : 90 secs Parkinglot :
Todos los parámetros que aparecen en la lista, se pueden configurar en la tabla.
CLI> quit
Para empezar se crea la tabla en la base de datos asterisk:
mysql -u root -psesamo
mysql> use asterisk
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,`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,
223
`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,`nat` varchar(3) NOT NULL,`useragent` varchar(40) default NULL,`Directmedia` varchar(3) default 'no',`Deny` varchar(31) default '',`Permit` varchar(31) default NULL,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> quitBye
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
224
Se modifican esta linea:
;sippeers => odbc,asterisk
para que queden:
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 conexiones seguras):
yum install perl-Net-SSLeay
Se descarga el paquete:
cd /usr/src
wget http://downloads.sourceforge.net/project/webadmin/webmin/1.580/webmin-1.580-1.noarch.rpm
y se instala
rpm -ivh webmin-1.580-1.noarch.rpmwarning: webmin-1.570-1.noarch.rpm: Header V3 DSA signature: NOKEY, key ID 11f63c51Preparing... ########################################### [100%]Operating system is CentOS Linux 1:webmin ########################################### [100%]Webmin install complete.
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
225
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”:
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:
226
227
228
Al terminar se presiona el botón "Save". Si desde la consola de Asterisk se escribe el comando:
asterisk -rvvvvvvvvvvvv
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
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
Se recarga la configuració 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.
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
229
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, `allow` varchar(40) NULL, `codecpriority` varchar(40) NULL, `qualify` varchar(10) NULL, `qualifysmoothing` varchar(10) NULL, `qualifyfreqok` varchar(10) NULL, `qualifyfreqnotok` varchar(10) NULL,
230
`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,iaxexteniaxpeers => odbc,asterisk,iaxexten
se guarda la configuración y se crea una extensión IAX en Realtime desde Webmin entrando en la tabla iaxexten:
231
232
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 la extensiones creadas en Realtime:
233
CLI> quit
nano /etc/asterisk/extensions.conf
Se modifica este bloque:
exten => _100[0-2],1,Macro(disponible)same => n,Macro(calendario)same => n,Dial(SIP/${EXTEN},45,hHkKtTwWxX)same => n,Hangup
para que quede:
exten => _100[0-2,4],1,Macro(disponible)same => n,Macro(calendario)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/1004exten => 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` (
234
`id` int(11) NOT NULL auto_increment,`context` varchar(20) NOT NULL default '',`exten` varchar(20) NOT NULL default '',`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 una extensión muy sencilla en la tabla:
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
235
Se guardan los cambios y se pasa al dialplan
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 => internasinclude => internacioinclude => parkedcallsinclude => test
[locales]include => internasinclude => auteninclude => parkedcallsinclude => 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.
236
Capitulo XIII
IVR avanzados – func_odbc.conf
La función func_odbc permite hacer 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 dos 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
13.1 Empleados
La tabla de los empleados contendrá solamente dos campos:
1. numero de matricula2. 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;
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=asteriskreadsql=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 odbc.ini
para la base de datos asterisk• readsql=SELECT nombre FROM empleados WHERE matricula='${SQL_ESC(${ARG1})}' –
la sentencia SQL para hacer consultas en la base de datos asterisk (en este caso la tabla empleados)
Para interactuar 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 configurarlo. Primero se averigua si le 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
Festival viene con el inglés como idioma predefinido. Para configurarlo para el español se siguen estos
239
pasos:
cd /usr/share/festival/voices
wget http://www.voztovoice.org/tmp/festival-spanish.zip
unzip festival-spanish.zip
Ahora se modifica el archivo de configuración de festival
nano /usr/share/festival/festival.scm
se añaden estas líneas antes de la ultima linea del archivo
;(language__spanish)(set! voice_default 'voice_el_diphone)(define (tts_textasterisk string mode)"(tts_textasterisk STRING MODE)Apply tts to STRING. This function is specifically designed foruse 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 la líneas que hay que añadir:
[general]host=localhostport=1314festivalcommand=(tts_textasterisk "%s" 'file)(quit)\n
Se guardan las modificaciones. Se actualiza la configuración de Asterisk:
/etc/init.d/asterisk reload
Para arrancar el servidor Festival en automático:
nano /etc/rc.local
240
al final del archivo se añade esta linea:
/usr/bin/festival_server > /dev/null &
Se inicia el servidor festival;
/usr/bin/festival_server > /dev/null &
Se controla que esté corriendo:
ps aux | grep festivalroot 24071 0.0 0.2 4600 1096 pts/1 S 13:36 0:00 /bin/sh /usr/bin/festival_serverroot 24077 0.4 3.6 23464 19324 pts/1 S 13:36 0:00 festival --server ./festival_server.scmroot 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 hacer 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 hacer consultas a la tabla empleados:
nano /etc/asterisk/extensions.conf
en el contexto internas se pone:
exten => 660,1,Answersame => n,Wait(2)same => n,Festival(Por favor ingrese los 4 digitos de la matricula del empleado.)same => n,Read(EMPNUM,beep,4)
241
same => n,Set(EMPNAME=${ODBC_Empleados(${EMPNUM})})same => n,GotoIf($[${EXISTS(${EMPNAME})}]?nombre)same => n,Festival(Ningun empleado encontrado. Hasta luego.)same => n,Hangupsame => 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 hace 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 hacen 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. -- <SIP/1000-00000010> 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)
242
-- 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 -- 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 pregrabar 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=asteriskwritesql=insert into encuesta (Fecha,resp1,resp2,resp3,resp4) values ("${SQL_ESC(${VAL1})}","$
243
{SQL_ESC(${VAL2})}","${SQL_ESC(${VAL3})}","${SQL_ESC(${VAL4})}","${SQL_ESC(${VAL5})}")
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,Answersame => 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
244
mysql> select * from encuesta;
Los resultados aparecen ordenados por ID y fecha.
245
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 por lo 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 generalformat Los formatos audio en que se grabará cada mensaje de voz.
Valor wav49|gsm|wavserveremail Correo electrónico del remitente en la notificaciones de la
presencia de un nuevo mensaje de voz. Valor buzondevoz@dominio.com. Un ejemplo para Linode: buzondevoz@li370-135.members.linode.com 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 5
maxgreet Duración máxima, en segundos, del mensaje de bienvenida que cada propietario de un buzón de voz puede grabar para presentarse. Valor 180
skipms Cuando se escuchan los mensaje de voz, se puede usar el teclado numérico del teléfono para adelantar o devolver el mensaje. Se expresa en mili segundos. Valor 3000
Parámetro Descripciónmaxsilence 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 4 Tienes que ser un valor menor 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 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. 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
fromstring Nombre del remitente del los correos electrónicos. Valor Buzón de Voz
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
248
Parámetro Descripciónusando el conector ODBC. En este parámetro se define el nombre de la base de datos. Valor asterisk (se deja comentado)
;odbctable 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 buzon de voz ${VM_MAILBOX}
emailbody Contenido del correo electrónico. Tiene que estar todo en la misma linea. Valor: Estimando ${VM_NAME}:\n\n\t le estamos enviando este correo para avisarle que ha recibido un nuevo mensajede 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
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: 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
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 vozsaydurationm define la duración mínima del mensaje de voz para que sea
249
Parámetro Descripciónanunciado (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 enviar el mensaje de voz a otra extensión (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, CLI, 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 de más de un mensaje de voz presente en el buzón de voz, permite pasar al mensaje siguiente sin presionar las teclas 7 o 9 (borrar/guardar el mensaje respectivamente)
forcename yes = obliga cada usuario con un buzón de voz configurado, grabar su nombre la primera vez que acceda. Un usuario se considera nuevo si la contraseña del buzón de voz coincide con el numero de extensió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á usando es temporal hasta que no grabe uno personalizado.
passwordlocation A partir de la versión 1.8.X de Asterisk 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
250
Parámetro Descripción
– spooldir – la contraseñas se guardarán en un archivo de texto (secret.conf) que hay que crear 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 6 desde el ultimo mensaje escuchado volver al primero, presionando 4 del primero mensaje ir al ultimo.
minpassword define una longitud mínima para la contraseña del buzón de voz (en numero de cifras). Valor 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
estos parámetros permiten personalizar las locuciones. Se dejan comentadas
listen-control-forward-key # = tecla para el avance rápido del mensajelisten-control-reverse * = tecla para rebobinar el mensajelisten-control-pause-key 0 = tecla numérica para poner en pausa/reanudar el mensajelisten-control-restart-key 2 = tecla numérica para volver a escuchar el mensaje desde el
iniciolisten-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[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' IMpcentral America/Chicago|'vm-received' Q 'digits/at' IMpeuropean Europe/Copenhagen|'vm-received' a d b 'digits/at' HMcolombia America/Bogota|'vm-received' aebY 'digits/at' HM
251
Parámetro Descripciónmexico 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,fulano@gmail.com,,tz=colombia1001 => 1001,fulano de pascual,fulano@gmail.com,,tz=colombia1002 => 1002,zutano pelado,zutano@gmail.com,,tz=european1234 => 1234,marko,fulano@gmail.com,,tz=mexico1235 => 1235,marko2,fulano@gmail.com,,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 meno la 1004. Como la contraseña es igual al numero de extensión, la primera vez que el usuario entre en 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
se copian las siguientes lineas:
[general]format=wav49|gsm|wavserveremail=buzondevoz@li370-135.members.linode.comattach=yesmaxmsg=100maxsecs=500minsecs=5maxgreet=180skipms=3000maxsilence=4
252
silencethreshold=128maxlogins=3moveheard=yesforward_urgent_auto=no;externnotify=/usr/bin/myapp;externpass=/usr/bin/myapp;externpassnotify=/usr/bin/myappdirectoryintro=dir-introcharset=ISO-8859-1pbxskip=yesfromstring=Buzon de Vozusedirectory=yes;odbcstorage=asterisk;odbctable=mensajes
emailsubject=Nuevo mensaje de voz ${VM_MSGNUM} en el buzon de voz ${VM_MAILBOX}emailbody=Estimando ${VM_NAME}:\n\n\t le estamos enviando este correo para avisarle que ha recibido un nuevo mensajede 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:%Smailcmd=/usr/sbin/sendmail -ttz=centrallocale=es_CO.iso88591attach=yesattachfmt=wavsaycid=yescidinternalcontexts=internassayduration=yessaydurationm=2dialout=externassendvoicemail=yes;callback=fromvm:exitcontext=fromvmreview=yes;operador=yesenvelope=yesdelete=novolgain=0.0nextaftercmd=yesforcename=yesforcegreeting=nohidefromdir=no
253
tempgreetwarn=yespasswordlocation=voicemail.confmessagewrap=yesminpassword=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_soundlisten-control-forward-key=#listen-control-reverse=*listen-control-pause-key=0listen-control-restart-key=2listen-control-stop-key=13456789backupdeleted=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); q "" (for today), "yesterday", weekday, or ABdY; (*note: not standard strftime value); R 24 hour time, including minuteeastern=America/New_York|'vm-received' Q 'digits/at' IMpcentral=America/Chicago|'vm-received' Q 'digits/at' IMpeuropean=Europe/Copenhagen|'vm-received' a d b 'digits/at' HMcolombia=America/Bogota|'vm-received' aebY 'digits/at' HMmexico=America/Bogota|'vm-received' aebY 'digits/at' HM
[default]; personalizar nombres, apellidos, correos electrónicos y zona horaria1000 => 1000,fulano de tal,fulano@gmail.com,,tz=colombia
254
1001 => 1001,fulano de pascual,fulano@gmail.com,,tz=colombia1002 => 1002,zutano pelado,zutano@gmail.com,,tz=european1234 => 1234,marko,fulano@gmail.com,,tz=mexico1235 => 1235,marko2,fulano@gmail.com,,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 usersContext Mbox User Zone NewMsgdefault general New User 0default 1000 fulano de tal colombia 0default 1001 fulano de pascual colombia 0default 1002 zutano de tal european 0default 1234 marko mexico 0default 1235 marko2 central 0
Para ver la zonas horarias configuradas:
CLI> voicemail show zonesZone Timezone Message Formatmexico America/Bogota 'vm-received' aebY 'digits/at' HMcolombia America/Bogota 'vm-received' aebY 'digits/at' HMeuropean Europe/Copenhagen 'vm-received' a d b 'digits/at' HMcentral America/Chicago 'vm-received' Q 'digits/at' IMpeastern America/New_York 'vm-received' Q 'digits/at' IMp
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 Macro.
Se abre el archivo del dialplan:
nano /etc/asterisk/extensions.conf
255
Primero se añade la parte para llamar el buzón de voz en el contexto internas:
exten => 97,1,Answersame => 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,VoicemailMainsame => 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,Macro(disponible)same => n,Macro(calendario)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:
exten => _100[0-2,4],1,Dial(SIP/${EXTEN},45,hHkKtTwWxX)same => n,Macro(voicemail)same => n,Hangup
exten => 1234,1,Dial(IAX2/marko,30)same => n,Macro(voicemail)same => n,Hangup
exten => 1235,1,Dial(IAX2/marko2,30)same => n,Macro(voicemail)
256
same => n,Hangup
Luego al final del archivo se crea la macro:
[macro-voicemail]exten => s,1,Goto(s-${DIALSTATUS},1)exten => s-BUSY,1,Voicemail(${MACRO_EXTEN}@default,b)same => n,Hangupexten => s-CANCEL,1,Hangupexten => s-CONGESTION,1,Congestionsame => n,Hangupexten => _s-.,1,Voicemail(${MACRO_EXTEN}@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 macro, por ejemplo, si el valor es BUSY, la llamada se transferirá al buzón de voz anunciando al llamante que la extensión está hablando.
Se guardan los cambios y se recarga el dialplan:
asterisk -rvvvvvvvvvvvvvvv
CLI> dialplan reload
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. Hacer 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 (extension 1000), aparecerá:
257
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 usersContext Mbox User Zone NewMsgdefault general New User central 0default 1000 fulano de tal colombia 1default 1001 fulano de pascual colombia 0default 1002 zutano pelado european 0default 1234 marko mexico 0default 1235 marko2 central 07 voicemail users configured.
y con el correo electrónico recibido:
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:
258
ls - /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=1000context=macro-voicemailmacrocontext=localesexten=s-BUSYpriority=1callerchan=SIP/1002-00000032callerid="Mengano" <1002>origdate=Thu Oct 20 01:37:07 AM UTC 2011origtime=1319074627category=flag=duration=10
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-1.8.11.0
make distclean
./configure
make menuselect
Cuando se recompila Asterisk, como ya se ha visto anteriormente, hay que volver a seleccionar los
259
modulos Add-ons:
Luego en el menú “Voicemail Build Options” seleccionar “ODBC_STORAGE”:
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
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 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
260
para que queden:
odbcstorage=asteriskodbctable=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
CLI> module load app_voicemail.soLoaded app_voicemail.so == Parsing '/etc/asterisk/voicemail.conf': == Found == Parsing '/etc/asterisk/users.conf': == Found == Registered application 'VoiceMail' == Registered application 'VoiceMailMain' == Registered application 'MailboxExists' == Registered application 'VMAuthenticate' == Registered application 'VMSayName' == Registered custom function 'MAILBOX_EXISTS' == 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 | macro-voicemail | "zutano" <1001> |+--------------------------------------------------+--------+-----------------+-----------------+1 row in set (0.00 sec)
Perfecto!!
261
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
Como para la tabla de los mensajes de voz, se utilizará la tabla presente en las fuentes de Asterisk:
cd /usr/src/asterisk-1.8.11.0/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 restart
Ahora se configura el buzón de voz de la extensión 1004 (la configurada en SIP realtime) en la tabla a través de webmin:
262
En la tabla aparecen todas las opciones que se pueden configurar para un buzón de voz. Se termina
263
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.
264
Capitulo XV
Las conferencias audio
Cuarta parte - Las conferencias audio – meetme.conf
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 a DAHDI para generar la sincronización de los canales audios presentes en la conferencia creando una canal pseudo-DAHDI para cada conferencia. Sin DAHDI instalado, meetme no funciona. Confbridge ha sido añadida a Asteirks a partir de la versión 1.6.1.X y no necesita DAHDI para funcionar, pero implementa menos funciones y no es posible configurarla en Realtime dinámico. La configuración de meetme se hace a partir de un archivo dedicado mientras las conferencias creadas con Confbridge no necesitan configuración previa.
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ónaudiobuffers 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 usan 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 eésta no ha empezado. 300 es el número de
Parámetro Descripciónsegundos. 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=32schedule=nologmembercount=yesfuzzystart=300earlyalert=3600endalert=120
267
[rooms]conf => 3500conf => 3501,1234conf => 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.
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:
• s - Con esta opción se activa el menú del cuarto de conferencias para usuarios y
268
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 está 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 usa 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 que será digitado por la primera persona que entre en la conferencia. Si en lugar de la opción D se pone la opción d no se necesitará definir 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 Macro. En el contexto conferencias se pone:
exten => 3520,1,Set(confmax=10)same => n,Macro(meetme)same => n,Hangup
y al final del archivo se añade la Macro:
[macro-meetme]exten => s,1,MeetMeCount(${MACRO_EXTEN},count)same => n,Gotoif($[${count} > ${confmax}]?llena)same => n,MeetMe(${MACRO_EXTEN},D)same => n,Hangupsame => 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 macro meetme. Con la primera línea de la macro 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) 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:
269
[externas]include => internasinclude => internacioinclude => parkedcallsinclude => testinclude => conferencias
[locales]include => internasinclude => auteninclude => parkedcallsinclude => testinclude => 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 3500User #: 01 1000 callerid=Fulano Channel: SIP/1000-00000003 (unmonitored) 00:02:45User #: 02 1001 zutano Channel: SIP/1001-00000007 (unmonitored) 00:00:532 users in that conference.
Para sacar un usuario de la conferencia:
CLI> meetme kick 3500 1 == Setting global variable 'MEETMEADMINSTATUS' to 'OK' -- <SIP/1000-00000003> Playing 'conf-kicked.alaw' (language 'es') -- Executing [3500@externas:2] Hangup("SIP/1000-00000003", "") in new stack
Quedará:
CLI> meetme list 3500User #: 02 1002 Mengano Channel: SIP/1002-00000005 (unmonitored) 00:04:091 user in that conference.
Para probar la Macro desde la extensión 1000 se marca 3520.
15.2 Aplicación ConfBridge
270
Para conocer la sintaxis de la aplicación ConfBridge:
CLI> core show application ConfBridge
-= Info about application 'ConfBridge' =-
[Synopsis]Conference bridge application.
[Description]Enters the user into a specified conference bridge. The user can exit theconference by hangup only.The join sound can be set using the 'CONFBRIDGE_JOIN_SOUND' variable andthe leave sound can be set using the 'CONFBRIDGE_LEAVE_SOUND' variable. Thesecan be unique to the caller.NOTE: This application will not automatically answer the channel.
[Syntax]ConfBridge([confno][,options])
[Arguments]confno The conference numberoptions a: Set admin mode.
A: Set marked mode.
c: Announce user(s) count on joining a conference.
m: Set initially muted.
M[(class)]: Enable music on hold when the conference has a single caller. Optionally, specify a musiconhold class to use. If one is not provided, it will use the channel's currently set music class, or 'default'.
1: Do not play message when first person enters
s: Present menu (user or admin) when '*' is received (send to menu).
w: Wait until the marked user enters the conference.
q: Quiet mode (don't play enter/leave sounds).
271
[See Also]Not available
Como esta aplicación no contesta automáticamente el canal, para configurarla en el dialplan hay que iniciar el bloque con un Answer:
CLI> quit
nano /etc/asterisk/extensions.conf
En el contexto conferencias se añade:
exten => 3530,1,Answersame => n,ConfBridge(3530,Mcs)same => n,Hangup
Se guardan los cambios y se actualiza el dialplan:
asterisk -rvvvvvvvvvvvvvvv
CLI> dialplan reload
Ahora desde la extensión 1000 se marca el numero 3530. A diferencia de meetme, con ConfBridge no se puede, desde la consola de Asterisk, controlar los participantes presentes, ni hacer otros tipos de operaciones.
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, `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',
272
`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:
tar -xf confprompts.tar
y moverlas en la carpeta de la locuciones en ingles:
mv *.wav /var/lib/asterisk/sounds/en
273
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 duren una hora.
Se guardan los datos presionando el botón Save. La segunda:
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
274
• 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. 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• q – modo silencioso, el llamante no escuchará un beep• r – se grabará la conferencia en un archivo audio
275
• 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 telefonos. 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 hacer 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:
exten => 503,1,SIPAddHeader (P-Auto-answer: normal)same => n,Page(SIP/1001,i)same => hangup
276
El gerente marca 503 y hace 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.
277
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 las 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.
¿Cómo se configura en Asterisk la gestión de las colas? A través de dos archivos:
• agents.conf• queues.conf
En el primero se configuran, definiendo algunas variables y parámetros, los agentes que atenderán las colas. En el queues.conf se configuran las colas (pueden ser una o más), los agentes miembros de cada cola y que tipo de estrategia se utilizará para enrutar las llamadas en la cola.
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
archivomultiplelogin Define si está permitido a una extensión
conectarse como agente múltiple. Valor no[agents] A partir de esta etiqueta inicia la configuración de
los agentesmaxlogintries Numero de intentos permitidos a un agente para
autenticarse. Valor 3autologoff 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ónconecta 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
;goodbye=vm-goodbye locución que el agente escuchará al terminar una llamada. Si se deja comentado será la predefinida (vm-goodbye)
updatecdr Actualizar o no el CDR con el nombre del agente. Valor no
;group obsoleto. No usarrecordagentcalls grabar o no las llamadas de los agentes. Valor norecordformat Formato audio de las llamadas grabadas. Valor
wav;urlprefix el prefijo del nombre del los archivos grabados.
Puede ser una URL. Ejemplo http://www.voztovoice.org/calls. Se deja comentado
;savecallsin 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,nameValor: 2000,1234,Fulano
280
Parámetro Descripciónagent 2001,1235,Zutanoagent 2002,1236 Mengano
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]multiplelogin=no
[agents]maxlogintries=3autologoff=15autologoffunavail=yesackcall=noacceptdtmf=#endcall=yesenddtmf=*wrapuptime=5000musiconhold=default;goodbye=vm-goodbyeupdatecdr=yes;grouprecordagentcalls=norecordformat=wav;urlprefix=http://dominio.org/calls;savecallsin=/home/callscustom_beep=beep
agent => 2000,1234,Fulanoagent => 2001,1235,Zutanoagent => 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
281
Para ver la lista de los agentes configurados:
CLI> agent show2000 (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]
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 show2000 (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]
Este sistema de conectar los agentes a las colas se ha vuelto un poco obsoleto para perqueños CallCenter y se está optando más para aplicaciones que permiten añadir a las colas de espera agentes dinámicos. Es poco productivo tener una 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
282
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 archivopersistentmembers yes = se guardan los datos de los miembros de la cola
activos en la base de datos interna de Asterisk. Si se 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 hace 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
[ventas] con esta etiqueta se define la primera cola de esperamusiclass 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
agentes que pertenecen a más de una cola sepan, antes de atender una llamada, de que cola proviene el cliente. Se deja comentado
283
Parámetro Descripciónstrategy En este parámetro se define la lógica con que se
enrutarán las llamadas de una cola a los agentes:• Leastrecent: Asigna la siguiente llamada al
agente que más tiempo lleva sin atender una llamada.
• Fewestcalls: Asigna la siguiente llamada al agente que menos llamadas ha atendido.
• 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.
• 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
timeout En la cola se pueden configurar dos distintos tipos de 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
284
Parámetro Descripciónagente 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 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 = lo agentes que no atenderán una llamada serán puestos en pausa
maxlen Numero máximo de personas que pueden estar esperando en la cola. Valor 50 Si se pone 0 no se fijará 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
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
285
Parámetro Descripciónnueva 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
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• 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 5announce-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-periodic-announce;periodic-announce=anuncio1,anuncio2 en este parámetro se definen los anuncios periódicos
personalizados separados por una coma. Se deja
286
Parámetro Descripcióncomentado
;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:
• 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,unknownleavewhenempty 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
287
Parámetro Descripción;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
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/2000member => Agent/2001member => 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ónSe 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=yesautofill=yesmonitor-type=mixmonitorupdatecdr=no
288
shared_lastcall=yes
[ventas]musicclass=default;announce=queue-ventasstrategy=ringallservicelevel=120context=ventas-exittimeout=15retry=4timeoutpriority=appweight=0wrapuptime=15autofill=yesautopause=yesmaxlen=50setinterfacevar=yessetqueueentryvar=yessetqueuevar=yes;membermacro=macroannounce-frequency=90min-announce-frequency=15;periodic-announce-frequency=60;random-periodic-announce=noannounce-holdtime=onceannounce-position=moreannounce-position-limit=5announce-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|wav49monitor-type=mixmonitorjoinempty=paused,unavailable,invalid,unknownleavewhenempty=paused,unavailable,invalid,unknown;eventwhencalled = yes;eventmemberstatus = yesreportholdtime=yesringinuse=nomemberdelay=5
289
timeoutrestart=yes;defaultrule=myrulemember => Agent/2000member => Agent/2001member => Agent/2002
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 ventasventas 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 queuequeue add member Add a channel to a specified queuequeue 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 show Show status of a specified queue queue {pause|unpause} member Pause or unpause a queue member queue show rules Show the rules defined in queuerules.conf
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,Answersame => n,Queue(ventas,R)same => n,Hangup
Con la opción R, introducida con la versión 1.8.X de Asterisk, cuando la llamada es enviada a un
290
agente, dejará de enviar la musca de espera al cliente y en su lugar el cliente escuchará el tono de timbrado.
Se guardan los cambios y se recarga el dialplan:
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á.
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 ventasventas 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 ventasventas 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 ventasventas 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
291
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,Answersame => 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 stackExecuting [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 llamadas, contexto internas, se añaden estos dos bloques:
292
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 llamadas 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 llamadas:
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:
CLI> database show/Queue/PersistentMembers/ventas : SIP/1000;0;0;SIP/1000;SIP/1000
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
293
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 ventasventas 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 ventasventas 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 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
294
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|
• AGENTDUMP: el agente ha rechazado la llamada mientra el cliente estaba escuchando el anuncio de la cola
• 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
295
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 URLsi aplica y el CALLERID del cliente.
Ejemplo: 1323690653|1323690653.4|ventas|NONE|ENTERQUEUE||1001
• 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.
296
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 milisegundos) 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.
• 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 entes 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.
297
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,`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,`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,
298
`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`));
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 (
299
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_tablequeue_members => odbc,asterisk,queue_member_tablequeue_log => odbc,asterisk,queue_log
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. El resultado 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:
300
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:
301
302
303
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 comprascompras 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
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:
304
Se vuelve nuevamente a la consola de Asterisk:
CLI> queue show comprascompras has 0 calls (max 50) in 'ringall' strategy (0s holdtime, 0s talktime), W:1, C:0, A:0, SL:0.0% within 120s Members: Fulamo (Agent/2000) (realtime) (Unavailable) has taken no calls yet Sutano (Agent/2001) (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 showcompras has 0 calls (max 50) in 'ringall' strategy (0s holdtime, 0s talktime), W:1, C:0, A:0, SL:0.0% within 120s Members: Fulamo (Agent/2000) (realtime) (Not in use) has taken no calls yet Sutano (Agent/2001) (realtime) (Unavailable) has taken no calls yet No Callers
ventas has 0 calls (max 50) in 'ringall' strategy (14s holdtime, 10s talktime), W:0, C:4, A:1, SL:100.0% within 120s Members: Agent/2002 (Unavailable) has taken no calls yet
305
Agent/2000 (Not in use) has taken no calls yet Agent/2001 (Unavailable) has taken no calls yet SIP/1000 (dynamic) (In use) has taken 4 calls (last was 9443 secs ago) No Callers
El agente estará conectado a las dos colas creadas (en negrita).
306
Capitulo XVII
Asterisk y los FAX
Hasta la versión 1.6.2.X, Asterisk soportaba la recepción y trasmisión de FAX a través del modulo app_fax. A partir de la versión 1.8.X hay dos nuevos módulos:
• res_fax• res_fax_spandsp
La idea detrás de este cambio es mejorar el soporte del protocolo T38 en Asterisk. 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/ttyIAX1owner uucp:uucpmode 660port 4570refresh 60server 127.0.0.1peername iaxmodem1secret pbx5050cidname VozToVoicecidnumber XXXXXXXXXXcodec 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
309
device /dev/ttyIAX2owner uucp:uucpmode 660port 4571refresh 60server 127.0.0.1peername iaxmodem2secret pbx5051cidname VozToVoicecidnumber XXXXXXXXXXcodec 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=friendcontext=faxdisallow=allallow=alawusername=iaxmodem1secret=pbx5050qualify=yesnotransfer=yeshost=dynamicrequirecalltoken=auto
[iaxmodem2]type=friendcontext=faxdisallow=allallow=alawusername=iaxmodem2secret=pbx5051qualify=yesnotransfer=yeshost=dynamicrequirecalltoken=auto
Se guardan los cambios y se actualiza la configuración de IAX2 en Asterisk
310
asterisk -rvvvvvvvvvvvvvvvvvvv
CLI> iax2 reload
Se abre otra ventana terminal o se crea otra sesión de PuTTy y se hace 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 linkIgnoring 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
mv iaxmodem.init.fedora /etc/init.d/iaxmodem
se vuelve ejecutable:
chmod +x /etc/init.d/iaxmodem
311
e se configura para el inicio automático:
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 peersName/Username Host Mask Port Statusmarko (Unspecified) (D) 255.255.255.255 0 (E) UNKNOWNmarko2/marko2 190.253.162.206 (D) 255.255.255.255 13269 (E) OK (102 ms)iaxmodem1/iaxmo 127.0.0.1 (D) 255.255.255.255 4570 (E) OK (1 ms)iaxmodem2/iaxmo 127.0.0.1 (D) 255.255.255.255 4571 (E) OK (3 ms)4 iax2 peers [3 online, 1 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 el envía el FAX
Hay que empezar instalando algunas (dependencias) requeridas por Hylafax:
yum install ghostscript ghostscript-devel sharutils ghostscript-fonts
En la pagina de Hylafax están presentes los paquetes para las distintas distribuciones de Linux:
Se descargan los paquetes para CentOS 5 (cliente y servidor):
cd /usr/src
wget ftp://ftp.hylafax.org/binary/linux/redhat/6.0.5/hylafax-server-6.0.5-1rhel5.i386.rpm
wget ftp://ftp.hylafax.org/binary/linux/redhat/6.0.5/hylafax-client-6.0.5-1rhel5.i386.rpm
Se instalan:
rpm -ivh hylafax*.rpm
312
El paso a seguir es la configuración de de Hylafax. Esto se hace a través de la utilidad faxsetup:
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: yes [2] Init script starts hfaxd yes [3] Start paging protocol: noAre these ok [yes]? yes
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]? 57Area code []? 5Long distance dialing prefix [1]? 0International dialing prefix [011]? 00Dial 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: 57AreaCode: 5LongDistancePrefix: 0InternationalPrefix: 00
313
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 startStarting 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 areconfigured 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]? yesSerial port that modem is connected to []? ttyIAX1
Ok, time to setup a configuration file for the modem. The manualpage config(5F) may be useful during this process. Also be awarethat 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]? +5753850962Local identification string (for TSI/CIG) ["NothingSetup"]? CursoAsteriskLong distance dialing prefix [1]? 0International dialing prefix [011]? 00Dial 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]? 2Modem 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) [""]?
314
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: 57AreaCode: 5FAXNumber: +5753850962LongDistancePrefix: 0InternationalPrefix: 00DialStringRules: etc/dialrulesSessionTracing: 11RingsBeforeAnswer: 2SpeakerVolume: offGettyArgs: "-h %l dx_%s"LocalIdentifier: CursoAsteriskTagLineFont: etc/lutRS18.pcfTagLineFormat: "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 typeof 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 themodem is turned off, this may hang (just go and cable up the modemor 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 interactswith the modem and the fax protocol features that are used when sendingor receiving faxes. One class isn't inherently better than another;however, one probably will suit a user's needs better than others.
315
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 thanwhen using most modems' Class 2 or Class 2.0 implementations. Generallyany problems encountered in Class 1/1.0 can be resolved by modificationsto HylaFAX, but usually any problems encountered in Class 2/2.0/2.1 willrequire 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 willhave to fill in the appropriate parameters by hand. You will need themanual for how to program your modem to do this task. In case you areuncertain of the meaning of a configuration parameter you shouldconsult the config(5F) manual page for an explanation.
Note that modem commands must be specified exactly as they are to besent to the modem. Note also that quote marks (") will not be displayedand will automatically be deleted. You can use this facility to supplynull parameters as "".
Finally, beware that the set of parameters is long. If you prefer touse your favorite editor instead of this script you should fill thingsin 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]?
316
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.0Class1PPMWaitCmd: AT+FTS=7Class1TCFWaitCmd: AT+FTS=7Class1EOPWaitCmd: AT+FTS=9Class1FrameOverhead: 4Class1RecvAbortOK: 200Class1RecvIdentTimer: 40000Class1SwitchingCmd: AT+FRS=7Class1TCFMaxNonZero: 10Class1TCFMinRun: 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]? yesSerial port that modem is connected to []? ttyIAX2
Ok, time to setup a configuration file for the modem. The manualpage config(5F) may be useful during this process. Also be awarethat 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
317
Local identification string (for TSI/CIG) ["NothingSetup"]? CursoAsteriskLong distance dialing prefix [1]? 0International dialing prefix [011]? 00Dial 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]? 2Modem 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: 57AreaCode: 5FAXNumber: +5753850962LongDistancePrefix: 0InternationalPrefix: 00DialStringRules: etc/dialrulesSessionTracing: 11RingsBeforeAnswer: 2SpeakerVolume: offGettyArgs: "-h %l dx_%s"LocalIdentifier: CursoAsteriskTagLineFont: etc/lutRS18.pcfTagLineFormat: "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
318
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 themodem is turned off, this may hang (just go and cable up the modemor 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 interactswith the modem and the fax protocol features that are used when sendingor 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 thanwhen using most modems' Class 2 or Class 2.0 implementations. Generallyany problems encountered in Class 1/1.0 can be resolved by modificationsto HylaFAX, but usually any problems encountered in Class 2/2.0/2.1 willrequire 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 willhave to fill in the appropriate parameters by hand. You will need themanual for how to program your modem to do this task. In case you areuncertain of the meaning of a configuration parameter you shouldconsult the config(5F) manual page for an explanation.
319
Note that modem commands must be specified exactly as they are to besent to the modem. Note also that quote marks (") will not be displayedand will automatically be deleted. You can use this facility to supplynull parameters as "".
Finally, beware that the set of parameters is long. If you prefer touse your favorite editor instead of this script you should fill thingsin 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.0Class1PPMWaitCmd: AT+FTS=7Class1TCFWaitCmd: AT+FTS=7Class1EOPWaitCmd: AT+FTS=9Class1FrameOverhead: 4Class1RecvAbortOK: 200Class1RecvIdentTimer: 40000Class1SwitchingCmd: AT+FRS=7Class1TCFMaxNonZero: 10Class1TCFMinRun: 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.
320
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 schedulerabout new modems and/or their status. This means that you must use thefaxmodem program to inform the new faxq process about the modems youwant to have scheduled by HylaFAX. Beware that if you have modems thatrequire non-default capabilities specified to faxmodem then you shouldread faxmodem(8C) manual page and do this work yourself (since thisscript is not intelligent enough to automatically figure out the modemcapabilities 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 el archivo inittab de forma que la utilidad se inicie al arrancar el servidor Linux:
nano /etc/inittab
después de esta linea:
#6:2345:respawn:/sbin/mingetty tty6
se pone:
fax1:2345:respawn:/usr/sbin/faxgetty ttyIAX1fax2:2345:respawn:/usr/sbin/faxgetty ttyIAX2
Se guardan los cambios y se recarga la configuración de inittab:
init q
Se averigua que faxgetty este corriendo para los dos FAX:
ps aux | grep ttyIAX
321
Se reinicia Hylafax
/etc/init.d/hylafax restartShutting 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 usa este comando:
faxstat
El resultado es:
HylaFAX scheduler on li370-135.members.linode.com: RunningModem ttyIAX2 (+5753850962): Running and idleModem 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: "<delay:7>"
Lo mismo se hace con el módem ttyIAX2:
nano /var/spool/hylafax/etc/config.ttyIAX2
al final del archivo se añade esta linea:
Class1SwitchingCmd: "<delay:7>"
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
322
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):
SENDTO=fulano@gmail.com
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
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:
323
nano /etc/asterisk/extensions.conf
[fax]exten => _X.,1,Dial(SIP/justvoip/${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,Answersame => 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 <faxnumber> <file.txt>
Se crea el archivo de texto que se enviará:
nano /tmp/pruebafax.txt
y se pone:
Libro Asterisk 1.8.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 recibirá. 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 hace esta prueba.
sendfax -h ttyIAX1@localhost -n -d numerolocal /tmp/pruebafax.txt
324
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.psDefault options: -f Courier -1 -p 11bp -o 0Se ha producido un error al convertir el documento; el comando fue "/usr/sbin/textfmt -B -f Courier-Bold -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 /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: RunningModem ttyIAX2 (+5753850962): Running and idleModem ttyIAX1 (+5753850962): Initializing serverJID Pri S Owner Number Pages Dials TTS Status1 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:
325
CLI> quit
y se controla que ha pasado:
faxstat -sHylaFAX scheduler on li374-112.members.linode.com: RunningModem ttyIAX2 (+5753850962): Running and idleModem ttyIAX1 (+5753850962): Running and idle
En este caso el fax se ha enviado con éxito ya que los dos FAX configurados están disponibles. ¿Cómo puedo comprobarlo? Abriendo el correo del usuario root (desde terminal o webmin):
y comprobando que el fax enviado ha llegado al correo electrónico definido a lo largo de la configuración de Hylafax:
326
Abriendo el PDF:
Si se quiere usar 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 el caso que se utilice un cliente remoto en el cortafuegos hay que abrir el puerto 4559 TCP (usado por Hylafax) y los puertos desde el 30000 hasta el 65000 TCP para los datos.
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 hace cuando se quiere enviar un FAX. Todo lo
327
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:
El FAX está conectado a la línea telefónica y también a un Gateway con soporte T.38. Este 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:
328
Los datos del FAX T.30 vienen analizados y manipulados para luego ser transformados 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 permitido es UDPTL que funciona de la siguiente forma:
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 destinación).
Asterisk 1.8.X soporta el protocolo T.38 solamente como pasarela, es decir que no está “en el medio” a
329
lo largo del envío del fax. A un lado y al otro de la trasmisión deberán estar dos Gateway T.38 que se hagan cargo de la tarea de enviar/recibir el fax. 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 contenidas en el modulo app_fax
CLI> core show application ReceiveFax -= Info about application 'ReceiveFAX' =-
[Synopsis]Receive a FAX and save as a TIFF/F file.
[Description]This application is provided by res_fax, which is a FAX technology agnosticmodule that utilizes FAX technology resource modules to complete a FAXtransmission.Session arguments can be set by the FAXOPT function and to check resultsof the ReceiveFax() application.
[Syntax]ReceiveFAX(filename[,options])
[Arguments]options d: Enable FAX debugging.
f: Allow audio fallback FAX transfer 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 agnosticmodule that utilizes FAX technology resource modules to complete a FAXtransmission.Session arguments can be set by the FAXOPT function and to check resultsof the SendFax() application.
330
[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.
s: Send progress Manager events (overrides statusevents setting in res_fax.conf).
z: Initiate a T.38 reinvite on the channel if the remote end does not.
Algunos ATA comercializados soportan el protocolo T.38. En Voip-info aparece una lista (aunque no muy actualizada).
Para el soporte T.38 en Asterisk hay que modificar este archivo:
mv /etc/asterisk/udptl.conf /etc/asterisk/udptl.con.old
nano /etc/asterisk/udptl.conf
Se pone:
[general]udptlstart=4000udptlend=4099udptlchecksums=yesudptlfecentries = 3udptlfecspan = 3use_even_ports = no
Se guardan los cambios y se vuelve a arrancar Asterisk:
/etc/init.d/asterisk restart
17.3.1 Aplicación ReceiveFax
Para el test que se va a ejecutar hay que modificar el dialplan:
nano /etc/asterisk/extensions.conf
331
se modifica este bloque:
exten => 1234,1,Dial(IAX2/iaxmodem2)same => n,hangup
Para que quede:
exten => 1234,1,Answersame => n,Receivefax(/tmp/${UNIQUEID}.tif,df)same => n,Hangupexten => h,1,Noop(FAXSTATUS ${FAXSTATUS}, FAXERROR ${FAXERROR})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
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
entran en la consola de Asterisk y 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
332
[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
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 Ttiff (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
333
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)
El resultado del archivo sin los comentarios será:
cd /tmp
nano enviofax
Channel: Local/1234@faxCallerid: "FAX"WaitTime: 30Maxretries:3RetryTime: 300Account: 1000Application: SendFaxData: /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
334
[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 Justvoip como se puede ver con esta prueba:
nano enviofax
Channel: SIP/justvoip/003907331870494Callerid: "FAX"WaitTime: 30Maxretries:3RetryTime: 300Account: 1000Application: SendFaxData: /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/justvoip-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*;
335
;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.
336
Capitulo XVIII
Conexiones entre servidores Asterisk
Este capitulo es dedicado a la 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 sobre 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, y se quiere conectarlos 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=friendremotesecret=pass2context=internasqualify=yeshost=dynamiclanguage=esdisallow=allallow=gsmallow=ulawallow=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 ya no se utiliza el parámetro secret sino el parámetro remotesecret (esto desde la versión 1.6.1.X de Asterisk)
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=friendremotesecret=pass1context=internashost=dynamiclanguage=esqualify=yesdisallow=allallow=gsmallow=ulawallow=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 registry69.164.196.73:5060 N serverA 105 Registered Wed, 26 Oct 2011 10:17:54
339
CLI> sip show peersserverB/serverA 69.164.196.73 D N 5060 OK (1 ms)
para el servidor B:
CLI> sip show registry96.126.121.135:5060 N serverB 105 Registered Wed, 26 Oct 2011 10:18:42
CLI> sip show peersserverA/serverB 96.126.121.135 D 5060 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 digitar 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 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
340
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:
[2011-01-25 22:42:24] WARNING[14692]: chan_sip.c:12849 check_auth: username mismatch, have <1000>, digest has <serverA>[2011-01-25 22:42:24] NOTICE[14692]: chan_sip.c:20212 handle_request_invite: Failed to authenticate device "Fulano" <sip:1000@178.79.144.247>;tag=as2e5f74a9
La llamada no funciona.
¿Porqué pasa eso?
Porque el servidor B piensa que la llamada esté llegando desde la extensión 1000 local y no logra distinguir entre extensión 1000 local y extensión 1000 remota. Para solucionar el problema, hay que modificar el plan de llamadas en ambos servidores.
Servidor A
nano /etc/asterisk/extensions.conf
modificar este bloque
exten => _*1XXX,1,NoOp()same => n,Dial(SIP/serverB/${EXTEN:1},30)same => n,Hangup()
para que quede:
exten => _*1XXX,1, Set(CALLERID(num)=serverA)same => n,Dial(SIP/serverB/${EXTEN:1},30)same => n,Hangup()
Servidor B
nano /etc/asterisk/extensions.conf
modificar estas lineas:
exten => _*1XXX,1,NoOp()same => n,Dial(SIP/serverA/${EXTEN:1},30)same => n,Hangup()
341
para que queden:
exten => _*1XXX,1, Set(CALLERID(num)=serverB)same => n,Dial(SIP/serverA/${EXTEN:1},30)same => n,Hangup()
Se actualiza el dialplan en ambos servidores y se intenta llamar nuevamente desde el servidor A el numero *1000. En la consola de Asterisk del servidor A aparecerá:
Executing [*1000@externas:1] Set("SIP/1000-00000004", "CALLERID(num)=serverA") in new stack -- Executing [*1000@externas:2] Dial("SIP/1000-00000004", "SIP/serverB/1000,30") in new stack == Using SIP RTP CoS mark 5 == Using SIP VRTP CoS mark 6 == Using UDPTL CoS mark 5 -- Called serverB/1000 -- SIP/serverB-00000005 is ringing
La llamada funciona. Este tipo de configuración se necesita solamente si las extensiones de los dos servidores Asterisk tienen los mismos números asignados. En el caso de servidores Asterisk con números de extensiones distintos, no hace falta modificar el CALLERID antes de marcar.
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 con dirección 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.112nome trunk: serveraExtensiones: 1000-1001-1002
Servidor B:IP: 66.228.49.216nome trunk: serverbExtensiones: 1000-1001-1002
Servidor A
Si abre el archivo iax.conf
nano /etc/asterisk/iax.conf
342
al final del archivo se añaden las siguientes lineas:
[serverb]type=friendhost=66.228.49.216trunk=yescontext=internasqualify=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=friendhost=96.126.125.112trunk=yescontext=internasqualify=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 peersserverb 66.228.49.216 (S) 255.255.255.255 4569 (T) (E) OK (1 ms)
Servidor B:
CLI> iax2 show peersservera 96.126.125.112 (S) 255.255.255.255 4569 (T) (E) OK (1 ms)
CLI> quit
En el dialplan se crea un nuevo bloque que permita llamar de un servidor a otro:
343
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-00000000", "IAX2/servera/1000") in new stack -- Called IAX2/servera/1000 -- Call accepted by 96.126.125.112 (format alaw) -- Format for call is alaw -- IAX2/servera-17542 answered SIP/1000-00000000
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. 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.
344
A lo largo de la configuración se puede decidir si compartir contextos ya configurados en el Dialplan o crear contextos nuevos definiendo las extensiones que se volverán disponibles a los demás servidores.. Aunque la configuración y puesta en marcha pueda parecer algo complicado, con un poco 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 pone:
# 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.142usuario: server1Extensiones: 1000-1001-1002MAC Tarjeta de red: F2:3C:91:DF:5B:3E
Servidor B:IP: 192.168.182.236usuario: server2Extensiones: 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 mismo archivo se define el tipo de protocolo que los dos servidores usarán para efectuar y recibir llamadas(puede ser IAX2, SIP o H323).
345
Terminada la configuración de dundi.conf, se modifica el dialplan para definir cuales son las rutas o contextos que se quiere 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 Descripción[general] inicia la configuración general del archivodepartment=EmpresaAorganization=EmpresaAlocality=Santa Martastateprov=Magdalenacountry=Colombiaemail=admin@servidorA.comphone=+57XXXXXXXXXX
En estos parámetros se indican los datos de la empresa.
bindaddr Dirección IP que se quiere utilizar con el protocolo DUNDi. Con 0.0.0.0 todas las direcciones IP 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. 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á por el tiempo definido en este parámetro (en segundos) en la base de datos interna de Asterisk del servidor que envió la solicitud. 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 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:
346
Parámetro Descripcióndundi_context => local_context,weight,tech,dest[,options]]
• 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 por las cuales no hay una conexión directa o de alta calidad se pone un numero más alto. Al momento de hacer 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 hace 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 residencia4. commercial – el numero es de una empresa5. mobile – el numero es un celular6. nopartial – no se harán búsquedas por números
incompletos
servera => 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• ${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)
347
Parámetro Descripción
• ${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 = symmetrichost = 192.168.182.236inkey = server2outkey = server1include = allpermit = serveraqualify = 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 solicitudes2. outbound: solo efectúa solicitudes pero no las recibe3. symmetric: recibe y efectúa solicitudes
• host: direccion 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]department=EmpresaAorganization=EmpresaAlocality=Santa Martastateprov=Magdalena
348
country=Colombiaemail=admin@servidorA.comphone=+57XXXXXXXXXXbindaddr=0.0.0.0port=4520entityid=F2:3C:91:DF:5B:3Ecachetime=3600ttl=32autokill=yessecretpath=dundistorehistory=yes
[mappings]servera => servera-local,0,IAX2,server1:${SECRET}@192.168.129.142/${NUMBER}
[F2:3C:91:96:EC:A3]model = symmetrichost = 192.168.182.236inkey = server2outkey = server1include = allpermit = serveraqualify = 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 usará 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 pairin PEM format for use by Asterisk. You will be asked toenter a passcode for your key multiple times. Pleaseenter the same code each time. The resulting files willneed to be moved to /var/lib/asterisk/keys if you wantto use them, and any private keys (.key files) willneed to be initialized at runtime either by runningAsterisk with the '-i' option, or with the 'init keys'command once Asterisk is running.
349
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 keyKey creation successful.Public key: server1.pubPrivate 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 root@192.168.182.236:/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=userdbsecret=dundi/secretcontext=servera-localqualify=yesdisallow=allallow=ulawallow=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
[servera-local]exten => 20,1,Answer()exten => 20,n,Playback(hello-world)
350
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 => internasinclude => internacioinclude => parkedcallsinclude => testinclude => conferenciasinclude => dundi-remoto
[locales]include => internas
include => auteninclude => parkedcallsinclude => testinclude => conferenciasinclude => 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á:
[general]department=EmpresaBorganization=EmpresaBlocality=Santa Martastateprov=Magdalenacountry=Colombiaemail=admin@servidorB.com
351
phone=+57XXXXXXXXbindaddr=0.0.0.0port=4520entityid=F2:3C:91:96:EC:A3cachetime=3600ttl=32autokill=yessecretpath=dundistorehistory=yes
[mappings]serverb => serverb-local,0,IAX2,server2:${SECRET}@192.168.182.236/${NUMBER}
[F2:3C:91:DF:5B:3E]model = symmetrichost = 192.168.129.142inkey = server1outkey = server2include = allpermit = serverbqualify = 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 pairin PEM format for use by Asterisk. You will be asked toenter a passcode for your key multiple times. Pleaseenter the same code each time. The resulting files willneed to be moved to /var/lib/asterisk/keys if you wantto use them, and any private keys (.key files) willneed to be initialized at runtime either by runningAsterisk 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 'server2':Generating RSA private key, 1024 bit long modulus............++++++
352
..........................++++++e is 65537 (0x10001)writing RSA keyKey creation successful.Public key: server2.pubPrivate key: server2.key
Se copia la clave publica en el Servidor Asterisk A
scp server2.pub root@192.168.129.142:/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=userqualify=yesdbsecret=dundi/secretcontext=serverb-localdisallow=allallow=ulawallow=alaw
Para terminar se modifica el plan de llamadas:
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 => internasinclude => internacioinclude => parkedcallsinclude => testinclude => conferenciasinclude => dundi-remoto
[locales]
353
include => internasinclude => auteninclude => parkedcallsinclude => testinclude => conferenciasinclude => 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 dundidundi flush [stats] Flush DUNDi cachedundi lookup Lookup a number in DUNDidundi precache Precache a number in DUNDidundi query Query a DUNDi EIDdundi set debug {on|off} Enable/Disable DUNDi debuggingdundi show entityid Display Global Entity IDdundi show mappings Show DUNDi mappingsdundi show peers [registered|i Show defined DUNDi peersdundi show peer Show info on a specific DUNDi peerdundi show precache Show DUNDi precachedundi show requests Show DUNDi requestsdundi show trans Show active DUNDi transactionsdundi store history {on|off} Enable/Disable DUNDi historic records
Se controla que haya conexión entre los dos servidores:
CLI> dundi show peersEID Host Port Model AvgTime Statusf2: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.
354
Ahora se puede hacer la primera consulta para controlar que efectivamente las rutas se están compartiendo:
CLI> dundi lookup 40@serverb 1. 0 IAX2/server2:kGYzcabppQ577UVIWc6eGQ==@192.168.182.236/40 (EXISTS|CANMATCH) from f2:3c:91:96:ec:a3, expires in 3600 sDUNDi 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@serverbDUNDi lookup returned no results.DUNDi lookup completed in 3 ms
Se hace otra solicitud de prueba desde el Servidor Asterisk B
CLI> dundi lookup 20@servera 1. 0 IAX2/server1:7+9kTsdabHhfGCokZ+x2Cg==@192.168.142.248/20 (EXISTS|CANMATCH) from f2:3c:91:df:5b:3e, expires in 3600 sDUNDi 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
Desde la versión 1.8.X es posible cifrar la señalización SIP y el flujo media. A pesar de la nueva implementación, 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:
355
cd /usr/src
Se descarga:
wget http://www.oberhumer.com/opensource/lzo/download/lzo-2.06.tar.gz
Se descomprime y se instala:
tar -xf lzo-2.06.tar.gzcd lzo-2.06./configure --prefix=/usrmakemake install
Ahora se puede instalar la ultima versión disponible de OpenVPN:
cd /usr/src
se descarga:
wget http://swupdate.openvpn.org/community/releases/openvpn-2.2.2.tar.gz
se descomprime:
tar -xf openvpn-2.2.2.tar.gz
se entra en la carpeta creada:
cd openvpn-2.2.2
se compila:
./configuremakemake install
Se prepara el servidor Linux para crear las distintas claves (CA, servidor, cliente):
cd easy-rsa/2.0
Se crea la carpeta donde se guardarán las distintas claves:
mkdir /usr/local/sbin/keys
nano vars
356
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 parametros 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="admin@voztovoice.org"export KEY_EMAIL=admin@voztovoice.org
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
Ahora se puede empezar a generar las claves empezando con la CA (Certificate Authority):
./build-ca
Generating a 1024 bit RSA private key..++++++......++++++writing new private key to 'ca.key'-----You are about to be asked to enter information that will be incorporatedinto 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 blankFor 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) [Magdalena]:Locality Name (eg, city) [SantaMarta]:Organization Name (eg, company) [VozToVoice]:Organizational Unit Name (eg, section) [changeme]:PBXACommon Name (eg, your name or your server's hostname) [changeme]:li44-242.members.linode.comName [changeme]:voztovoiceEmail Address [admin@voztovoice.org]:
En “Common Name” se pone el nombre de dominio de Linode o del servidor Linux que se está
357
utilizando. Se continua con la clave del servidor:
./build-key-server server
Generating a 1024 bit RSA private key..............++++++..............++++++writing new private key to 'server.key'-----You are about to be asked to enter information that will be incorporatedinto 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 blankFor 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) [Magdalena]:Locality Name (eg, city) [SantaMarta]:Organization Name (eg, company) [VozToVoice]:Organizational Unit Name (eg, section) [changeme]:PBXACommon Name (eg, your name or your server's hostname) [server]:li44-242.members.linode.comName [changeme]:voztovoiceEmail Address [admin@voztovoice.org]:
Please enter the following 'extra' attributesto be sent with your certificate requestA challenge password []:An optional company name []:Using configuration from /root/openvpn-2.2.1/easy-rsa/2.0/openssl-0.9.8.cnfCheck that the request matches the signatureSignature okThe Subject's Distinguished Name is as followscountryName :PRINTABLE:'CO'stateOrProvinceName :PRINTABLE:'Magdalena'localityName :PRINTABLE:'SantaMarta'organizationName :PRINTABLE:'VozToVoice'organizationalUnitName:PRINTABLE:'PBXA'commonName :PRINTABLE:'li44-242.members.linode.com'name :PRINTABLE:'voztovoice'emailAddress :IA5STRING:'admin@voztovoice.org'Certificate is to be certified until Dec 10 14:16:09 2021 GMT (3650 days)Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]yWrite out database with 1 new entries
358
Data Base Updated
Para terminar se crea una clave para el cliente (el servidor Asterisk B):
./build-key clienteb
Generating a 1024 bit RSA private key.......++++++................................................++++++writing new private key to 'clienteb.key'-----You are about to be asked to enter information that will be incorporatedinto 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 blankFor 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) [Magdalena]:Locality Name (eg, city) [SantaMarta]:Organization Name (eg, company) [VozToVoice]:Organizational Unit Name (eg, section) [changeme]:PBXACommon Name (eg, your name or your server's hostname) [clienteb]:li44-242.members.linode.comName [changeme]:voztovoiceEmail Address [admin@voztovoice.org]:
Please enter the following 'extra' attributesto be sent with your certificate requestA challenge password []:An optional company name []:Using configuration from /root/openvpn-2.2.1/easy-rsa/2.0/openssl-0.9.8.cnfCheck that the request matches the signatureSignature okThe Subject's Distinguished Name is as followscountryName :PRINTABLE:'CO'stateOrProvinceName :PRINTABLE:'Magdalena'localityName :PRINTABLE:'SantaMarta'organizationName :PRINTABLE:'VozToVoice'organizationalUnitName:PRINTABLE:'PBXA'commonName :PRINTABLE:'li44-242.members.linode.com'name :PRINTABLE:'voztovoice'emailAddress :IA5STRING:'admin@voztovoice.org'Certificate is to be certified until Dec 10 14:19:20 2021 GMT (3650 days)Sign the certificate? [y/n]:y
359
1 out of 1 certificate requests certified, commit? [y/n]yWrite out database with 1 new entriesData Base Updated
Si se tiene planeado utilizar la conexión para conectar telefonos IP y/o Softphone, se crean otras claves cliente. Se termina con la generación del parámetro Diffie Hellman
./build-dhGenerating DH parameters, 1024 bit long safe prime, generator 2This 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:
service iptables restart
Lo siguiente es instalar el script de arranque presente en las fuentes de OpenVPN:
cd /usr/src/openvpn-2.2.2/sample-scripts/
cp openvpn.init /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:
360
cd /etc/openvpn
nano server.conf
Se copian las siguientes lineas:
port 1194proto udpdev tunca /usr/local/sbin/keys/ca.crtcert /usr/local/sbin/keys/server.crtkey /usr/local/sbin/keys/server.keydh /usr/local/sbin/keys/dh1024.pemserver 10.8.0.0 255.255.255.0ifconfig-pool-persist ipp.txtkeepalive 10 120comp-lzomax-clients 30persist-keypersist-tunlog openvpn.loglog-append openvpn.logverb 3management localhost 7505
Para más informaciones sobre estos parámetros:
http://openvpn.net/index.php/open-source/documentation/howto.html#examples
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
361
Se sigue el mismo procedimiento para el servidor B:
cd /usr/src
Se descarga:
wget http://www.oberhumer.com/opensource/lzo/download/lzo-2.06.tar.gz
Se descomprime y se instala:
tar -xf lzo-2.06.tar.gzcd lzo-2.06./configure –prefix=/usrmakemake install
Ahora se puede instalar la ultima versión disponible de OpenVPN:
cd /usr/src
se descarga:
wget http://swupdate.openvpn.org/community/releases/openvpn-2.2.2.tar.gz
se descomprime:
tar -xf openvpn-2.2.2.tar.gz
se entra en la carpeta creada:
cd openvpn-2.2.2
se compila:
./configuremakemake install
Se prepara el servidor Linux para crear las distintas claves (CA, servidor, cliente):
cd easy-rsa/2.0
Se crea la carpeta donde se guardarán las distintas claves:
mkdir /usr/local/sbin/keys
nano vars
362
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="admin@voztovoice.com"export KEY_EMAIL=admin@voztovoice.com
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
Ahora se puede empezar a generar las claves empezando con la CA (Certificate Authority):
./build-ca
Generating a 1024 bit RSA private key.++++++....++++++writing new private key to 'ca.key'-----You are about to be asked to enter information that will be incorporatedinto 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 blankFor 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) [Magdalena]:Locality Name (eg, city) [SantaMarta]:Organization Name (eg, company) [VozToVoice]:Organizational Unit Name (eg, section) [changeme]:PBXBCommon Name (eg, your name or your server's hostname) [changeme]:li212-33.members.linode.comName [changeme]:voztovoiceEmail Address [admin@voztovoice.org]:
363
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 1024 bit RSA private key.++++++..++++++writing new private key to 'server.key'-----You are about to be asked to enter information that will be incorporatedinto 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 blankFor 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) [Magdalena]:Locality Name (eg, city) [SantaMarta]:Organization Name (eg, company) [VozToVoice]:Organizational Unit Name (eg, section) [changeme]:PBXBCommon Name (eg, your name or your server's hostname) [server]:li212-33.members.linode.comName [changeme]:voztovoiceEmail Address [admin@voztovoice.org]:
Please enter the following 'extra' attributesto be sent with your certificate requestA challenge password []:An optional company name []:Using configuration from /usr/src/openvpn-2.2.1/easy-rsa/2.0/openssl-0.9.8.cnfCheck that the request matches the signatureSignature okThe Subject's Distinguished Name is as followscountryName :PRINTABLE:'CO'stateOrProvinceName :PRINTABLE:'Magdalena'localityName :PRINTABLE:'SantaMarta'organizationName :PRINTABLE:'VozToVoice'organizationalUnitName:PRINTABLE:'PBXB'commonName :PRINTABLE:'li212-33.members.linode.com 'name :PRINTABLE:'voztovoice'emailAddress :IA5STRING:'admin@voztovoice.org'Certificate is to be certified until Dec 10 15:13:18 2021 GMT (3650 days)Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
364
Write out database with 1 new entriesData Base Updated
Para terminar se crea una clave para el cliente (el servidor Asterisk B):
./build-key clientea
Generating a 1024 bit RSA private key..........++++++....++++++writing new private key to 'clientea.key'-----You are about to be asked to enter information that will be incorporatedinto 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 blankFor 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) [Magdalena]:Locality Name (eg, city) [SantaMarta]:Organization Name (eg, company) [VozToVoice]:Organizational Unit Name (eg, section) [changeme]:PBXBCommon Name (eg, your name or your server's hostname) [clientea]:li212-33.members.linode.comName [changeme]:voztovoiceEmail Address [admin@voztovoice.org]:
Please enter the following 'extra' attributesto be sent with your certificate requestA challenge password []:An optional company name []:Using configuration from /usr/src/openvpn-2.2.1/easy-rsa/2.0/openssl-0.9.8.cnfCheck that the request matches the signatureSignature okThe Subject's Distinguished Name is as followscountryName :PRINTABLE:'CO'stateOrProvinceName :PRINTABLE:'Magdalena'localityName :PRINTABLE:'SantaMarta'organizationName :PRINTABLE:'VozToVoice'organizationalUnitName:PRINTABLE:'PBXB'commonName :PRINTABLE:'li212-33.members.linode.com 'name :PRINTABLE:'voztovoice'emailAddress :IA5STRING:'admin@voztovoice.org'Certificate is to be certified until Dec 10 15:15:37 2021 GMT (3650 days)Sign the certificate? [y/n]:y
365
1 out of 1 certificate requests certified, commit? [y/n]yWrite out database with 1 new entriesData Base Updated
Se termina con la generación del parámetro Diffie Hellman
./build-dhGenerating DH parameters, 1024 bit long safe prime, generator 2This 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
# 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.2.2/sample-scripts/
cp openvpn.init /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 1194proto udp
366
dev tunca /usr/local/sbin/keys/ca.crtcert /usr/local/sbin/keys/server.crtkey /usr/local/sbin/keys/server.keydh /usr/local/sbin/keys/dh1024.pemserver 10.10.0.0 255.255.255.0ifconfig-pool-persist ipp.txtkeepalive 10 120comp-lzomax-clients 30persist-keypersist-tunlog openvpn.loglog-append openvpn.logverb 3management 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:
367
• 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:
clientdev tunproto udpremote 66.228.49.216 1194resolv-retry infinitenobindpersist-keypersist-tunca /etc/openvpn/ca.crtcert /etc/openvpn/clientea.crtkey /etc/openvpn/clientea.keycomp-lzoverb 3ns-cert-type serverroute-method exeroute-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:
368
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.0localnet=10.10.0.0/255.255.255.0
Se recarga la configuración SIP:
asterisk -rx "sip reload"
Se sigue el mismo procedimiento para el servidor B:
cd /etc/openvpn
nano client.conf
se copian las siguientes lineas:
clientdev tunproto udpremote 96.126.125.112 1194resolv-retry infinitenobindpersist-keypersist-tunca /etc/openvpn/ca.crtcert /etc/openvpn/clienteb.crtkey /etc/openvpn/clienteb.keycomp-lzoverb 3ns-cert-type server
369
route-method exeroute-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:
nano /etc/asterisk/sip.conf
Después del primer parámetro localnet se añade:
localnet=10.8.0.0/255.255.255.0localnet=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]
370
type=peercontext=vpnhost=10.8.0.6disallow=allallow=g729allow=alawlanguage=esqualify=yesdtmfmode = 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=peercontext=vpnhost=10.8.0.1disallow=allallow=g729allow=alawlanguage=esqualify=yesdtmfmode = 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 serverbvpnName/username Host Dyn Nat ACL Port Status Realtimeserverbvpn 10.8.0.6 N 5060 OK (2 ms)1 sip peers [Monitored: 1 online, 0 offline Unmonitored: 0 online, 0 offline]
Servidor B:
371
CLI> sip show peers like serveravpnName/username Host Dyn Nat ACL Port Status Realtimeserveravpn 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. Como para la prueba con la conexión entre servidores Asterisk con el protocolo SIP, hay que “engañar” Asterisk para que acepte la llamada ya que las extensiones configuradas en los dos servidores son las mismas. En el caso de servidores con números de extensiones distintas, no hace falta añadir la linea donde se modifica el CALLERID
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,Answersame => n,Playback(demo-congrats)same => n,Hangup
y en el contexto internas se pone:
exten => 70,1,Set(CALLERID(num)=openvpna)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,Answersame => n,Playback(demo-congrats)same => n,Hangup
y en el contexto internas se pone:
exten => 70,1,Set(CALLERID(num)=openvpnb)same => n,Dial(SIP/serveravpn/${EXTEN})same => n,hangup
372
Se guardan los cambios en ambos servidores y se recarga el dialplan
asterisk -rx "dialplan reload"
Para terminar, se hace 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] NoOp("SIP/1000-00000045", "") in new stackExecuting [70@externas:2] Set("SIP/1000-00000045", "CALLERID(num)=openvpna") in new stack -- Executing [70@externas:3] NoOp("SIP/1000-00000045", "openvpna") in new stack -- Executing [70@externas:4] Dial("SIP/1000-00000045", "SIP/serverbvpn/70") in new stack == Using SIP RTP CoS mark 5 == Using SIP VRTP CoS mark 6 == Using UDPTL CoS mark 5 -- Called serverbvpn/70 -- SIP/serverbvpn-00000046 answered SIP/1000-00000045
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 T26 para arriba).
18.5 Conectar dos Servidores Asterisk con TLS y SRTP
En esta parte 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 hace con una utilidad presente en las fuentes de Asterisk. Desde el servidor A:
mkdir /etc/asterisk/keys
Primero se crea el certificado CA y el certificado para el servidorA:
cd /usr/src/asterisk-1.8.11.0/contrib/scripts
./ast_tls_cert -d certs -C li374-112.members.linode.com -o serverA
No config file specified, creating 'certs/tmp.cfg'You can use this config file to create additional certs withoutre-entering the information for the fields in the certificateCreating certs/ca.keyGenerating RSA private key, 4096 bit long modulus..........++.....................................++e is 65537 (0x10001)
373
Enter pass phrase for certs/ca.key:Verifying - Enter pass phrase for certs/ca.key:Creating certs/ca.crtEnter pass phrase for certs/ca.key:Creating certs/serverA.keyGenerating RSA private key, 1024 bit long modulus...............++++++....++++++e is 65537 (0x10001)Creating signing requestCreating certs/serverA.crtSignature oksubject=/CN=li374-112.members.linode.com/O=AsteriskGetting CA Private KeyEnter 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 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 withoutre-entering the information for the fields in the certificateCreating certs/ca.keyGenerating 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 certs/ca.crtEnter pass phrase for certs/ca.key:Creating certs/serverB.keyGenerating RSA private key, 1024 bit long modulus....................++++++..................................++++++e is 65537 (0x10001)Creating signing requestCreating certs/serverB.crtSignature oksubject=/CN=li291-216.members.linode.com/O=AsteriskGetting CA Private Key
374
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/keys/cp serverA.pem /etc/asterisk/keys/
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=yestlsbindaddr=96.126.125.112tlscertfile=/etc/asterisk/keys/serverA.pemtlscafile=/etc/asterisk/keys/ca.crttlscapath=/etc/asterisk/keystlsdontverifyserver=yes
en tlsbindaddr se pone la dirección IP del servidorA
al final del archivo se configura la troncal para el servidorB
[serverbtls]type=peercontext=from-tlshost=66.228.49.216disallow=allallow=alawlanguage=esqualify=yestransport=tlsencryption=yes
Los parámetros importantes:
• context: nombre del contexto donde entrarán las llamadas del servidoB
375
• 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,Answersame => n,Noop(TLS = ${CHANNEL(secure_signaling)}, SRTP = ${CHANNEL(secure_media)})same => n,Playback(tt-monkeys)same => n,Hangup
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:
376
mkdir /etc/asterisk/keys
Se vuelve al servidor A y se copian las dos claves:
scp ca.crt root@66.228.49.216:/etc/asterisk/keysscp serverB.pem root@66.228.49.216:/etc/asterisk/keys
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=yestlsbindaddr=66.228.49.216tlscertfile=/etc/asterisk/keys/serverB.pemtlscafile=/etc/asterisk/keys/ca.crttlscapath=/etc/asterisk/keystlsdontverifyserver=yes
en tlsbindaddr se pone la dirección IP del servidorB. Al final del archivo se configura la troncal para el servidorA:
[serveratls]type=peercontext=from-tlshost=96.126.125.112disallow=allallow=alawlanguage=esqualify=yestransport=tlsencryption=yes
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
377
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,Answersame => 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
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 peersserverbtls 66.228.49.216 N 5061 OK (1 ms)
Se hace la misma operación en el servidorB:
CLI> sip show peersserveratls 96.126.125.112 N 5061 OK (2 ms)
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
378
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 -- <SIP/serveratls-00000015> 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.
379
Capitulo XIX
AMI y AGI
19.1 AMI (Asterisk Manager Interface)
AMI (Asterisk Manager Interface) es una interfaz de monitoreo y gestión que interactúa 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
archivoenabled yes – Se activa el acceso a la AMIwebenabled yes = se activa el acceso a la AMI vía HTTPport 5038 – el puerto predefinido para la conexión a la AMI de
Asterisk vía TCPbindaddr 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
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 para 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ónconsola 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 AMI2. 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
382
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 Writeall El usuario puede leer todos los eventos de
la AMIEl 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 relacionados con las colas de espera y los agentes
Permite al usuario enviar acciones para gestionar y monitorear el estado de las 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 relacionados con el registro de las llamadas según la configuración del archivo cdr_manager.conf
Solo lectura
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
383
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 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 corrienteMá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=yeswebenabled=yesport=5038bindaddr=0.0.0.0;tlsenable=no;tlsbindport=5039;tlsbindaddr=0.0.0.0 ;tlscertfile=/tmp/asterisk.pem ;tlsprivatekey=/tmp/private.pemallowmultiplelogin=yesdisplayconnects=yestimestampevents=yes;channelvars = var1,var2,var3debug=noauthtimeout=60authlimit=20httptimeout=60
[admin]secret=sesamodeny=0.0.0.0/0.0.0.0permit=127.0.0.1/255.255.255.255;eventfilter=Event: Newchannel
384
;eventfilter=!Channel: DAHDI*writetimeout=100read=system,call,agent,user,dtmf,reporting,cdr,dialplan,agi,cc,aocwrite=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 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 hacer la primera prueba. Para conocer la sintaxis:
CLI> manager show command Login
385
[Syntax]Action: Login[ActionID:] <value>Username: <value>[Secret:] <value>
[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
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: adminSecret: sesamoEvents: Off
Después de cada linea, para pasar a la siguiente se presiona la tecla envío. Después de la ultima linea la
386
tecla envío se presiona dos veces. El resultado será:
Response: SuccessMessage: Authentication accepted
Para salir de la AMI:
Action: Logoff
Response: GoodbyeMessage: 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 5038Trying 127.0.0.1...Connected to localhost.Escape character is '^]'.Asterisk Call Manager/1.1
Action: LoginUsername: adminSecret: sesamoEvents: On
Response: SuccessMessage: Authentication accepted
Event: FullyBootedPrivilege: system,allStatus: 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: SIPshowpeerPeer: 1000
387
Response: SuccessChanneltype: SIPObjectName: 1000ChanObjectType: peerSecretExist: YRemoteSecretExist: NMD5SecretExist: NContext: externasLanguage: esAccountcode: 1000AMAflags: UnknownCID-CallingPres: Presentation Allowed, Not ScreenedCallgroup: 1Pickupgroup: 1MOHSuggest: defaultVoiceMailbox: 1000@defaultTransferMode: openLastMsgsSent: -1Maxforwards: 0Call-limit: 2Busy-level: 0MaxCallBR: 384 kbpsDynamic: YCallerid: "callerid=Fulano" <1000>RegExpire: -1 secondsSIP-AuthInsecure: noSIP-Forcerport: YACL: NSIP-CanReinvite: NSIP-DirectMedia: NSIP-PromiscRedir: NSIP-UserPhone: NSIP-VideoSupport: YSIP-TextSupport: NSIP-T.38Support: YSIP-T.38EC: FECSIP-T.38MaxDtgrm: 400SIP-Sess-Timers: AcceptSIP-Sess-Refresh: uasSIP-Sess-Expires: 1800SIP-Sess-Min: 90SIP-RTP-Engine: asteriskSIP-Encryption: NSIP-DTMFmode: rfc2833ToHost:Address-IP: (null)Address-Port: 0
388
Default-addr-IP: (null)Default-addr-port: 0Default-Username: 1000Codecs: 0x8010c (ulaw|alaw|g729|h263)CodecOrder: alaw,ulaw,g729Status: UNKNOWNSIP-Useragent: X-Lite 4 release 4.1 stamp 63214Reg-Contact: sip:1000@190.67.234.11:13642;rinstance=c25bb0cf558f37bbQualifyFreq: 60000 msParkinglot: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 5038Trying 127.0.0.1...Connected to localhost.Escape character is '^]'.Asterisk Call Manager/1.1
Action: LoginUsername: adminSecret: sesamoEvents: On
Response: SuccessMessage: Authentication accepted
Event: FullyBootedPrivilege: system,allStatus: 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
Response: GoodbyeMessage: Thanks for all the fish.
389
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 interactuar 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.
19.2 AGI (Asterisk Gateway Interface)
El Asterisk Gateway Interface (AGI) permite desarrollar aplicaciones externas que pueden interactuar 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
¿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:
390
• 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:
cd phpagi-2.20
y se copian las dos librerías para AGI en la carpeta de agi-bin de Asterisk:
cp phpagi.php /var/lib/asterisk/agi-bincp phpagi-asmanager.php /var/lib/asterisk/agi-bin
391
se vuelven los archivos ejecutables:
chmod 755 /var/lib/asterisk/agi-bin/phpagi.phpchmod 755 /var/lib/asterisk/agi-bin
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=falseerror_handler=trueadmin=fulano@gmail.comhostname=li374-112.members.linode.comtempdir=/var/spool/asterisk/tmp/
[asmanager]server=localhostport=5038username=adminsecret=sesamo
[fastagi]setuid=truebasedir=/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 script AGI.
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 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
392
#!/usr/bin/php -q<?php require('phpagi.php'); error_reporting(E_ALL); $agi = new AGI(); $agi-> 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 -- Launched AGI Script /var/lib/asterisk/agi-bin/pruebaudio.php -- Playing 'demo-congrats' (escape_digits=) (sample_offset 0) -- <SIP/1000-00000050>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
393
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<SIP/1000-00000051>AGI Tx >> agi_request: pruebaudio.php<SIP/1000-00000051>AGI Tx >> agi_channel: SIP/1000-00000051<SIP/1000-00000051>AGI Tx >> agi_language: es<SIP/1000-00000051>AGI Tx >> agi_type: SIP<SIP/1000-00000051>AGI Tx >> agi_uniqueid: 1331227067.81<SIP/1000-00000051>AGI Tx >> agi_version: 1.8.8.2<SIP/1000-00000051>AGI Tx >> agi_callerid: 1000<SIP/1000-00000051>AGI Tx >> agi_calleridname: callerid=Fulano<SIP/1000-00000051>AGI Tx >> agi_callingpres: 0<SIP/1000-00000051>AGI Tx >> agi_callingani2: 0<SIP/1000-00000051>AGI Tx >> agi_callington: 0<SIP/1000-00000051>AGI Tx >> agi_callingtns: 0<SIP/1000-00000051>AGI Tx >> agi_dnid: 250<SIP/1000-00000051>AGI Tx >> agi_rdnis: unknown<SIP/1000-00000051>AGI Tx >> agi_context: externas<SIP/1000-00000051>AGI Tx >> agi_extension: 250<SIP/1000-00000051>AGI Tx >> agi_priority: 1<SIP/1000-00000051>AGI Tx >> agi_enhanced: 0.0<SIP/1000-00000051>AGI Tx >> agi_accountcode: 1000<SIP/1000-00000051>AGI Tx >> agi_threadid: -1229980784<SIP/1000-00000051>AGI Tx >><SIP/1000-00000051>AGI Rx << ANSWER<SIP/1000-00000051>AGI Tx >> 200 result=0<SIP/1000-00000051>AGI Rx << STREAM FILE demo-congrats "" 0 -- Playing 'demo-congrats' (escape_digits=) (sample_offset 0)<SIP/1000-00000051>AGI Tx >> 200 result=0 endpos=313776<SIP/1000-00000051>AGI Rx << HANGUP<SIP/1000-00000051>AGI Tx >> 200 result=1 -- <SIP/1000-00000051>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
nano /var/lib/asterisk/agi-bin/callerid.php
#!/usr/bin/php -q<?php require('phpagi.php'); error_reporting(E_ALL); $agi = new AGI(); $agi-> answer();
394
$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/
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:
395
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 opción 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 desde la versión 1.6.X es “deprecated” y va sustituida con la normal aplicación AGI
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
396
-= Info about application 'EAGI' =-
[Synopsis]Executes an EAGI compliant application.
[Description]Using 'EAGI' provides enhanced AGI, with incoming audio available out of bandon file descriptor 3.Executes an Asterisk Gateway Interface compliant program on a channel. AGIallows Asterisk to launch external programs written in any language to controla telephony channel, play audio, read DTMF digits, etc. by communicating withthe AGI protocol on *stdin* and *stdout*. As of '1.6.0', this channel willnot stop dialplan execution on hangup inside of this application. Dialplanexecution will continue normally, even upon hangup until the AGI applicationsignals 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 SIGHUPon hangup from the channel except when using DeadAGI. A fast AGI server willcorrespondingly receive a HANGUP inline with the command dialog. Both of thesessignals 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()
19.3.2 FastAGI
FastAGI trabaja sobre una conexión TCP que se realiza con un servidor FastAGI. El control sobre el canal se hace vía TCP y no requiere iniciar un nuevo proceso por cada llamada. La sintaxis es:
AGI(agi://IPservidorFastAGI:puerto)
El puerto predefinido es el 4573
397
En las fuentes de Asterisk es presente un servidor FastAGI para hacer 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,Noopsame => 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-1.8.11.0/agi/fastagi-test
y se inicia:
/usr/src/asterisk-1.8.11.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 -- <SIP/1000-00000011>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'
Consola del servidor FastAgi:
AGI Environment Dump from 59836 -- -- accountcode = 1000 -- callerid = 1000 -- calleridname = callerid=Fulano -- callingani2 = 0 -- callingpres = 0 -- callingtns = 0 -- callington = 0
398
-- 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.21. 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)
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:
399
exten => 253,1,Noopsame => 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 5038Trying 127.0.0.1...Connected to localhost.Escape character is '^]'.Asterisk Call Manager/1.1
Se autentica el usuario admin:
Action:loginUsername:adminSecret:sesamoEvents:off
Response: SuccessMessage: Authentication accepted
Se ejecuta la primera acción agi para contestar el canal (el numero de canal aparece en la consola de Asterisk):
Action:AgiChannel:SIP/1000-00000017Command:Answer
Response: SuccessMessage: Added AGI command to queue
Se envía la música de espera al canal:
Action:AgiChannel:SIP/1000-00000017Command:Exec startmusiconhold
Response: SuccessMessage: Added AGI command to queue
400
Se para la música de espera en el canal:
Action:AgiChannel:SIP/1000-00000017Command:Exec stopmusiconhold
Response: SuccessMessage: Added AGI command to queue
Se termina la llamada:
Action:AgiChannel:SIP/1000-00000017Command:hangup
Response: SuccessMessage: 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<SIP/1000-00000017>AGI Tx >> agi_request: async<SIP/1000-00000017>AGI Tx >> agi_channel: SIP/1000-00000017<SIP/1000-00000017>AGI Tx >> agi_language: es<SIP/1000-00000017>AGI Tx >> agi_type: SIP<SIP/1000-00000017>AGI Tx >> agi_uniqueid: 1331246894.27<SIP/1000-00000017>AGI Tx >> agi_version: 1.8.8.2<SIP/1000-00000017>AGI Tx >> agi_callerid: 1000<SIP/1000-00000017>AGI Tx >> agi_calleridname: callerid=Fulano<SIP/1000-00000017>AGI Tx >> agi_callingpres: 0<SIP/1000-00000017>AGI Tx >> agi_callingani2: 0<SIP/1000-00000017>AGI Tx >> agi_callington: 0<SIP/1000-00000017>AGI Tx >> agi_callingtns: 0<SIP/1000-00000017>AGI Tx >> agi_dnid: 254<SIP/1000-00000017>AGI Tx >> agi_rdnis: unknown<SIP/1000-00000017>AGI Tx >> agi_context: externas<SIP/1000-00000017>AGI Tx >> agi_extension: 254<SIP/1000-00000017>AGI Tx >> agi_priority: 2<SIP/1000-00000017>AGI Tx >> agi_enhanced: 0.0<SIP/1000-00000017>AGI Tx >> agi_accountcode: 1000<SIP/1000-00000017>AGI Tx >> agi_threadid: -1225098352<SIP/1000-00000017>AGI Tx >><SIP/1000-00000017>AGI Tx >> 200 result=0
-- AGI Script Executing Application: (startmusiconhold) Options: ()
401
-- Started music on hold, class 'default', on SIP/1000-00000017<SIP/1000-00000017>AGI Tx >> 200 result=0 -- AGI Script Executing Application: (stopmusiconhold) Options: () -- Stopped music on hold on SIP/1000-00000017<SIP/1000-00000017>AGI Tx >> 200 result=0<SIP/1000-00000017>AGI Tx >> 200 result=1 == Spawn extension (externas, 254, 2) exited non-zero on 'SIP/1000-00000017'
402
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:
• id: numero progresivo que identifica cada entrada de la tabla• 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 la extensión 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: aplicación utilizada• lastdata: opciones de la aplicación utilizadas• duration: duración total de la llamada• billsec: duración de la llamada después de 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 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)})
Con esta linea 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.
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
total 192drwxr-xr-x 2 root root 4096 Mar 22 11:42 cdr-csvdrwxr-xr-x 2 root root 4096 Mar 20 10:11 cdr-custom
405
drwxr-xr-x 2 root root 4096 Mar 20 10:11 cel-custom-rw-r--r-- 1 root root 24576 Mar 23 15:21 master.db-rw-r--r-- 1 root root 149285 Mar 23 15:27 messages-rw-r--r-- 1 root root 2022 Mar 22 17:35 queue_log
La carpeta cdr-csv contiene el archivo Master.csv, que contiene la lista de todas las llamadas efectuadas, y un archivo por 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 Descripción[general] Etiqueta que indica el inicio de la parte general de la configuraciónenable 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
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 hace un 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 10Esto porque a pesar 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
406
Parámetro DescripciónEsto 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 uniqueIDloguserfield yes = en el archivo csv se guarda el campo userfieldaccountlogs 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
se crea uno nuevo:
nano /etc/asterisk/cdr.conf
y se copial las lineas que siguen:
[general]enable=yesunanswered=no
407
endbeforehexten=noinitiatedseconds=yesbatch=no;size=100;time=300;scheduleronly=no;safeshutdown=yes
[csv]usegmtime=nologuniqueid=yesloguserfield=yesaccountlogs=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
* Registered Backends ------------------- mysql csv cdr_sqlite3_custom cdr-custom Adaptive ODBC
20.1.2 cdr_manager.conf
Como se ha visto en el parrafo 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:
408
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
* Registered Backends ------------------- cdr_manager mysql csv cdr_sqlite3_custom cdr-custom Adaptive ODBC
Se puede hacer una prueba entrando en la AMI de asterisk:
telnet localhost 5038
autenticándose:
Action:LoginUsername:adminSecret: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á:
409
Event: CdrPrivilege: cdr,allTimestamp: 1332542079.937863AccountCode: 1000Source: 1000Destination: 1001DestinationContext: externasCallerID: "callerid=Fulano" <1000>Channel: SIP/1000-00000008DestinationChannel: SIP/1001-00000009LastApplication: DialLastData: SIP/1001,45,hHkKtTwWxXStartTime: 2012-03-23 17:34:26AnswerTime: 2012-03-23 17:34:29EndTime: 2012-03-23 17:34:39Duration: 13BillableSeconds: 11Disposition: ANSWEREDAMAFlags: DOCUMENTATIONUniqueID: 1332542066.10UserField:
20.1.3 CDR adaptive
Como el modulo cdr-mysql en la ultima versión de la rama 1.8 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 ( 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 '',
410
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:
[asteriskcdr]Description = MySQL AsteriskCDRDriver = MySQLDatabase = asteriskcdrServer = localhostUser = asteriskPassword = sesamoPort = 3306Option = 3
Se pasa al archivo res_odbc:
nano /etc/asterisk/res_odbc.conf
y al final del archivo, se copian las siguientes lineas:
[asteriskcdr]enabled => yesdsn => asteriskcdrusername => asteriskpassword => sesamopre-connect => yessanitysql => select 1idlecheck => 3600connect_timeout => 10
411
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=asteriskcdrtable=cdr2alias 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 se 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 hace 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.conf Reloading module 'res_odbc.so' (ODBC resource) == Parsing '/etc/asterisk/res_odbc.conf': == Found[Mar 27 15:40:32] NOTICE[11036]: res_odbc.c:1481 odbc_obj_connect: Connecting asterisk[Mar 27 15:40:32] NOTICE[11036]: res_odbc.c:1511 odbc_obj_connect: res_odbc: Connected to asterisk [asterisk][Mar 27 15:40:32] NOTICE[11036]: res_odbc.c:902 load_odbc_config: Registered ODBC class 'asterisk' dsn->[asterisk][Mar 27 15:40:32] NOTICE[11036]: res_odbc.c:1481 odbc_obj_connect: Connecting asteriskcdr[Mar 27 15:40:32] NOTICE[11036]: res_odbc.c:1511 odbc_obj_connect: res_odbc: Connected to asteriskcdr [asteriskcdr][Mar 27 15:40:32] NOTICE[11036]: res_odbc.c:902 load_odbc_config: Registered ODBC class 'asteriskcdr' dsn->[asteriskcdr]
412
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,amaflags,accountcode,uniqueid,linkedid) VALUES ({ ts '2012-03-27 15:49:17' },'"callerid=Fulano" <1000>','1000','1001','externas','SIP/1000-0000000f','SIP/1001-00000010','Dial','SIP/1001,45,hHkKtTwWxX',12,10,'ANSWERED',3,'1000','1332881357.17','1332881357.17')]
Que indica que los datos de la llamada se han guardado en la tabla CDR2. En la tabla:
La misma entrada estará en la tabla CDR. Otra cosa que se puede hacer con el modulo CDR Adaptive
413
es filtrar los datos que se van a guardar en la tabla. En el ejemplo que sigue se guardarán 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:
nano /etc/asterisk/cdr_adaptive_odbc.conf
Al final del archivo se añade el siguiente bloque:
[cdr3]connection=asteriskcdrtable=cdr3alias start => calldatefilter src => 1000
414
• 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,amaflags,accountcode,uniqueid,linkedid) VALUES ({ ts '2012-03-27 16:01:52' },'"callerid=Fulano" <1000>','1000','1001','externas','SIP/1000-00000015','SIP/1001-00000016','Dial','SIP/1001,45,hHkKtTwWxX',11,8,'ANSWERED',3,'1000','1332882112.23','1332882112.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:
• inicio de la llamada• duración de la conversación• finalizació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
415
• 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 en 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 archivoenable yes = se activa el registro de los eventos del modulo CELapps 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
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
416
Parámetro Descripción
• 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: Alldateformat 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 Asteriskenabled 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
se crea uno nuevo:
nano /etc/asterisk/cel.conf
y se añaden las siguientes lineas:
[general]enable=yesapps=dial,park,queue,meetmeevents=alldateformat=%F %T
[manager]
417
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 , 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:
418
• 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 AsteriskCELDriver = MySQLDatabase = asteriskcelServer = localhostUser = asteriskPassword = sesamoPort = 3306Option = 3
Se guarda los cambios y se prueba la nueva conexión:
isql asteriskcel asterisk sesamo+---------------------------------------+| Connected! || || sql-statement || help [tablename] || quit || |+---------------------------------------+SQL> quit
Se pasa al archivo res_odbc.conf:
nano /etc/asterisk/res_odbc.conf
se añade el siguiente bloque:
[asteriskcel]enabled => yesdsn => asteriskcelusername => asteriskpassword => sesamopre-connect => yes
419
sanitysql => select 1idlecheck => 3600connect_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=asteriskceltable=cel
• CEL1:nombre que se le 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:
CLI> odbc show
ODBC DSN Settings-----------------
Name: asterisk DSN: asterisk Last connection attempt: 1969-12-31 19:00:00 Pooled: No Connected: Yes
Name: asteriskcdr
420
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;
421
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 archivodateformat formato de la fecha. Predefinido ISO 8601 - %F %Tappendhostname si se quiere añadir o no al nombre del archivo el nombre del dominio
del servidor. Valor noqueue_log define si se quiere guardar o no las estadísticas de las colas de espera
en un archivo. Valor yesqueue_log_name El nombre del archivo donde guardar las estadísticas de la colas de
espera. Valor queue_logqueue_log_to_file yes = las estadísticas de las colas se siguen guardando en el archivo
queue_log aunque estén configuradas en Realtime.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)
debug => debug – se crea un archivo donde se guardará solamente el debug de
422
Parámetro Descripciónla 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.
Para crear el nuevo archivo, se renombra el predefinido:
mv /etc/asterisk/logger.conf /etc/asterisk/logger.conf.old
y se crea uno nuevo:
nano /etc/asterisk/logger.conf
Se copian las siguientes lineas:
[general]dateformat=%F %Tappendhostname=noqueue_log=yesqueue_log_name=queue_logqueue_log_to_file=yesrotatestrategy=rotate
[logfiles]debug => debugverbose => verbosefax => faxconsole => notice,warning,error,debug,dtmf,faxmessages => notice,warning,dtmferror => error
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
423
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/debug/var/log/verbose {missingokrotate 7dailypostrotate/usr/sbin/asterisk -rx 'logger reload' > /dev/null 2> /dev/nullendscript}
/var/log/asterisk/queue_log {missingokrotate 5size=1000kpostrotate/usr/sbin/asterisk -rx 'logger reload'> /dev/null 2> /dev/nullendscript}
El primer bloque define la rotación para los archivos messages, error, debug y verbose 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
424
se escribe:
CLI> logger reload
Para ver la configuración del archivo:
CLI> logger show channels
Channel Type Status Configuration------- ---- ------ -------------/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/debug File Enabled - DEBUG/var/log/asterisk/verbose File Enabled - VERBOSE
CLI> quit
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 tipo de problema que está afectando el funcionamiento de la PBX. Esto se hace 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.
425
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 si se ha generado 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:
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 justvoip
Como se ha visto en el párrafo 3.4 , se puede utilizar también la utilidad ngrep.
426
Capitulo XXI
Seguridad en Asterisk
21.1 Reglas de oro
Hay una 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 extensiones3. 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 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 ACCEPTCon 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 http://downloads.sourceforge.net/project/fail2ban/fail2ban-stable/fail2ban-0.8.4/fail2ban-0.8.4.tar.bz2
se descomprime:
tar -xf fail2ban-0.8.4.tar.bz2
se entra en la carpeta:
cd fail2ban-0.8.4
y se instala:
python setup.py install
Se activa el script para arrancarlo como servicio:
cp /usr/src/fail2ban-0.8.4/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
y se añaden estas líneas:
# Fail2Ban configuration file#[INCLUDES]# Read common prefixes. If any customizations available -- read them from# common.local#before = common.conf
[Definition]#_daemon = asterisk
# Option: failregex# Notes.: regex to match the password failures messages in the logfile. The# host must be matched by a group named "host". The tag "<HOST>" can# be used for standard IP/hostname matching and is only an alias for# (?:::f{4,6}:)?(?P<host>\S+)# Values: TEXT#failregex = NOTICE.* .*: Registration from '.*' failed for '<HOST>(:[0-9]{1,5})?' - Wrong password NOTICE.* .*: Registration from '.*' failed for '<HOST>(:[0-9]{1,5})?' - No matching peer found NOTICE.* .*: Registration from '.*' failed for '<HOST>(:[0-9]{1,5})?' - Username/auth name mismatch NOTICE.* .*: Registration from '.*' failed for '<HOST>(:[0-9]{1,5})?' - Device does not match ACL NOTICE.* .*: Registration from '.*' failed for '<HOST>(:[0-9]{1,5})?' - Peer is not supposed to register NOTICE.* .*: <HOST> failed to authenticate as '.*'$ NOTICE.* .*: No registration for peer '.*' \(from <HOST>\) NOTICE.* .*: Host <HOST> failed MD5 authentication for '.*' (.*) NOTICE.* .*: Failed to authenticate user .*@<HOST>.* NOTICE.* .*: Sending fake auth rejection for device .*@<HOST>.*
429
# Option: ignoreregex# Notes.: regex to ignore. If this regex matches, the line is ignored.# Values: TEXT#ignoreregex =
Con estas líneas se configura fail2ban para que controle eventuales accesos indeseados que aparecen en el archivo de registro de Asterisk.
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 = truefilter = asteriskaction = iptables-allports[name=ASTERISK, protocol=all]sendmail-whois[name=ASTERISK, dest=root@localhost, sender=fail2ban@pbx.dyndns.org]logpath = /var/log/asterisk/messagesmaxretry = 5bantime = 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 fail2ban@pbx.dyndns.org 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.
Para que funcione hay que averiguar que en el archivo de configuración de Asterisk
nano /etc/asterisk/logger.conf
en la siguiente linea esté presente el valor notice (configuración predefinida):
messages => notice,warning,dtmf
Se inicia fail2ban:
/etc/init.d/fail2ban start
Starting fail2ban: [ OK ]
430
Se averigua que no haya errores en el log de fail2ban:
tail -f /var/log/fail2ban.log
Si se quiere hacer 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:
Si por error se bloquea la IP de un computador, la única forma de quitar el bloqueo es parar y reiniciar Iptables o reiniciar el servidor Linux.
431
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 directamente desde la consola de Asterisk y a través del programa VoIPmonitor.
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 instalará desde las fuentes:
cd /usr/src
wget http://mmonit.com/monit/dist/monit-5.3.2.tar.gz
tar -xf monit-5.3.2.tar.gz
cd monit-5.3.2
Se compila y se instala:
./configure --prefix=/usr
make
make install
Se termina la instalación con la copia y activación del script de inicio de monit:
cd contrib
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 Justvoip
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 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 idfile /var/.monit.id# Nombre de la carpeta y archivo donde se guardará el numero del proceso de Monit
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 podemos decirle a Monit de # guardar todas las alerta en una determinada carpeta. Cuando el servidor volverá a funcionar, todas las# alertas serán enviada siguiendo el orden cronológico en que se guardaron
set mail-format {From: monit@libroasterisk.orgSubject: monit alerta -- $EVENT $SERVICEMessage: $EVENT Servicio $SERVICE
Fecha: $DATEAccion: $ACTION
434
Host: $HOSTDescripcion: $DESCRIPTION
Tu devoto empleado,Monit}# Con el bloque de arriba, se define como tiene que ser enviado el correo electrónico de alerta
set alert admin@voztovoice.com# Con esta línea se define el correo electrónico que recibirá todas las alertas (personalizar)
set httpd port 2812allow admin:sesamo# Monit viene con un servidor Web. 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
# Servidor Linuxcheck system cursoasterisk.orgif loadavg (1min) > 4 then alertif loadavg (5min) > 2 then alertif memory usage > 75% then alertif cpu usage (user) > 70% then alertif cpu usage (system) > 30% then alertif cpu usage (wait) > 20% then alert
# Asteriskcheck process asterisk with pidfile /var/run/asterisk/asterisk.pidstart program = "/etc/init.d/asterisk start" with timeout 60 secondsstop program = "/etc/init.d/asterisk stop" with timeout 60 secondsif failed host 127.0.0.1 port 5038 then restartif 5 restarts within 5 cycles then timeout
# Troncal SIPcheck host Justvoip with address sip.justvoip.comif failed port 5060 type udp protocol SIPand target usuario@sip.justvoip.com maxforward 10then alert
# SendMailcheck process sendmail with pidfile /var/run/sendmail.pidgroup mailstart program = "/etc/init.d/sendmail start"stop program = "/etc/init.d/sendmail stop"if failed port 25 protocol smtp then restartif 5 restarts within 5 cycles then timeout
435
# MySQLcheck process mysql with pidfile /var/run/mysqld/mysqld.pidgroup databasestart program = "/etc/init.d/mysqld start"stop program = "/etc/init.d/mysqld stop"if failed port 3306 protocol mysql then restartif 5 restarts within 5 cycles then timeout
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
service iptables restart
Después de unos minutos se puede acceder a la pagina de administración de Monit:
http://ipservidor:2812
436
Nombre de usuario: adminContraseñ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:
437
Cualquier problema se presente con el servidor y/o con los procesos/programas configurados, se recibirá una notificación al correo electrónico configurado.
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 aparado 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:
438
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 = yesenabled = 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.txtwget http://www.voztovoice.org/tmp/digium-mib.txt
Ahora se configura SNMP de modo que pueda interactuar 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 agentxagentXPerms 0660 0550 root root
com2sec local localhost publiccom2sec remote XXX.XXX.XXX.XXX public
group asterisk v1 localgroup asterisk v2c local
439
group NetWork v1 remotegroup NetWork v2c remote
view all included .1
access asterisk "" any noauth exact all none noneaccess 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 hacer 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 hacer (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 hacer una consulta utilizando el OID raiz 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.6 = STRING: IAX2ASTERISK-MIB::astChanTypeName.4 = STRING: SIPASTERISK-MIB::astChanTypeName.7 = STRING: DAHDI
Se anotan los valores que aparecen en negrita y el tipo de canal asociado, es decir:
SIP 4IAX2 6DAHDI 7
Se pasa a la instalación y configuración de Nagios.
440
22.3 Nagios
Para la instalación de Nagios desde los paquetes precompilados, hay que instalar el repositorio rpmforge:
cd /usr/src
wget http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.2-2.el5.rf.i386.rpm
rpm -ivh rpmforge-release-0.5.2-2.el5.rf.i386.rpm
Ahora se controlan los paquetes disponibles para Nagios:
yum search nagios
check_logfiles.i386 : Logfile check plugin for nagiosicinga.i386 : Open Source host, service and network monitoring programnagios.i386 : Open Source host, service and network monitoring programnagios-devel.i386 : Header files, libraries and development documentation for nagiosnagios-nrpe.i386 : Nagios Remote Plug-ins Execution daemonnagios-nsca.i386 : Nagios Service Check Acceptornagios-nsca-client.i386 : nagios send_nscanagios-plugins.i386 : Host/service/network monitoring program plugins for Nagiosnagios-plugins-nrpe.i386 : Nagios plug-in for NRPEnagios-plugins-setuid.i386 : Host/service/network monitoring program plugins for Nagios requiring setuidndoutils.i386 : Nagios plugin to store Nagios data in a relational databasensc.i386 : Console monitor for Nagiosnsc.noarch : Console monitor for Nagiosperl-Nagios-Object.noarch : Nagios::Object - Nagios object configuration parsingperl-Nagios-Plugin.noarch : Family of perl modules to streamline writing Nagiosrss4nagios.i386 : Authenticated RSS alerts for 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, una aplicación para el envío de los correo electrónicos desde Nagios utilizando una linea de comando.
yum install nagios nagios-plugins perl-Net-Jabber perl-IO-Socket-SSL ndoutils mailx httpd
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
441
la carpeta /etc/nagios.
Para este tipo de instalación no hace falta hacer 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 nagiosadminuse generic-contactalias Nagios Adminemail nagios@localhost}
para que queden:
define contact{contact_name nagiosadminuse generic-contactalias Nagios Administradoremail fulano@gmail.comaddress1 fulano}
fulano@gmai.com 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 generic-contact es:
nano /etc/nagios/objects/templates.cfg
define contact{
442
name generic-contact service_notification_period 24x7host_notification_period 24x7service_notification_options w,u,c,r,f,shost_notification_options d,u,r,f,sservice_notification_commands notify-service-by-email,notify-service-jabberhost_notification_commands notify-host-by-email,notify-host-jabbercan_submit_commands 1register 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 hará cada 2 minutos (se puede personalizar):
define service{name asteriskuse generic-service max_check_attempts 4 normal_check_interval 2retry_check_interval 1register 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 viene en la carpeta /usr/lib/nagios/plugins/contrib, check_asterisk.pl. 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/lib/nagios/plugins
wget http://www.voztovoice.org/campus/a2b/check_asterisk_peerswget http://www.voztovoice.org/campus/a2b/notify_via_jabber.pl
Se cambian los permisos para que se pueda ejecutar:
chmod +x check_asterisk_peers
443
chmod +x notify_via_jabber.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:
cd /usr/lib/nagios/plugins
./check_snmp -h
Para añadir los comandos en Nagios, se modificará 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 definitiondefine command{ command_name notify-host-jabber command_line /usr/lib/nagios/plugins/notify_via_jabber.pl $CONTACTADDRESS1$"Host '$HOSTALIAS$' is $HOSTSTATE$ - Info: $HOSTOUTPUT$" }
# 'service-notify-by-jabber' command definitiondefine command { command_name notify-service-jabber
444
command_line /usr/lib/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 definitiondefine command{command_name check_snmpcommand_line $USER1$/check_snmp -H $HOSTADDRESS$ $ARG1$}
y se modifican para que queden:
define command{command_name check_snmpcommand_line $USER1$/check_snmp -H $HOSTADDRESS$ -C public -o $ARG1$ -P 2c -l $ARG2$ -w $ARG3$ -c $ARG4$}
IMPORTANTE: todo lo que aparece en la linea command-line debe estar en la misma linea
Command name: nombre del comandoCommand line: los parámetros que pasaremos 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
445
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_asteriskcommand_line $USER1$/contrib/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 definitiondefine command{ command_name check_ssh command_line $USER1$/check_ssh $ARG1$ $HOSTADDRESS$ }
y se modifica para que quede:
# 'check_ssh' command definitiondefine 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_justvoipcommand_line sudo /usr/lib/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. Para modificar este archivo con el editor nano hay que seguir este procedimiento:
cd /root
nano .bash_profile
446
al final del archivo se añade la siguiente linea:
export EDITOR=/usr/bin/nano
Se guardan los cambios y se recarga el perfile de la shell bash:
source .bash_profile
Ahora se puede modificar el archivo sudousers con nano con el comando:
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/lib/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 modifica el archivo manager.conf de Asterisk:
nano /etc/asterisk/manager.conf
Al final del archivo se añade:
[nagios]secret = sesamodeny=0.0.0.0/0.0.0.0permit=127.0.0.1/255.255.255.255read=system,call,agent,user,dtmf,reporting,cdr,dialplan,agi,ccwrite=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. Se mueve el predefinido:
447
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-serverhost_name CursoAsteriskalias CursoAsteriskaddress 127.0.0.1}
define service{use asteriskhost_name CursoAsteriskservice_description SIPcheck_command check_snmp!ASTERISK-MIB::astChanTypeChannels.4!"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 CursoAsteriskservice_description IAX2check_command check_snmp!ASTERISK-MIB::astChanTypeChannels.6!"Canales IAX2 Activos"!4!8}
define service{use asterisk host_name CursoAsteriskservice_description DAHDIcheck_command check_snmp!ASTERISK-MIB::astChanTypeChannels.7!"Canales DAHDI Activos"!4!8}
define service{use asteriskhost_name CursoAsteriskservice_description Asterisk_checkcheck_command check_asterisk}
448
define service{use asteriskhost_name CursoAsteriskservice_description Troncal_Justvoipcheck_command check_justvoip!justvoip}
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 Justvoip. 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-servicehost_name CursoAsteriskservice_description PINGcheck_command check_ping!100.0,20%!500.0,60%}
define service{use local-servicehost_name CursoAsteriskservice_description Current Userscheck_command check_local_users!20!50}
define service{use local-servicehost_name CursoAsteriskservice_description Total Processescheck_command check_local_procs!250!400!RSZDT}
449
define service{use local-servicehost_name CursoAsteriskservice_description Current Loadcheck_command check_local_load!5.0,4.0,3.0!10.0,6.0,4.0}
define service{use local-servicehost_name CursoAsteriskservice_description SSHcheck_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: 0Total Errors: 0Things 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/htpasswd.users nagiosadmin sesamoAdding password for user nagiosadmin
Este comando creará una archivo htpasswd.users que contendrá los datos de acceso para el usuario predefinido nagiosadmin (en este caso la contraseña es sesamo)
Se configuran Nagios para que arranque en automático:
chkconfig nagios on
Se reinicia apache y luego se inicia Nagios:
/etc/init.d/httpd start/etc/init.d/nagios start
450
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:
service iptables 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
Se presiona el botón Aceptar. Aparece la pagina inicial de Nagios:
451
En la derecha se selecciona el enlace Hosts para ver el servidor configurado:
Se selecciona Services para ver los servicios monitoreados:
Todos están bien.
22.3.1 NDOutils
NDOutils permite 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;
452
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/ndoutils/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=-1broker_module=/usr/libexec/ndomod-3x.o 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=nagiosndo2db_group=nagios
se añade:
lock_file=/var/nagios/ndo2db.lock
en db_user y db_password se pone:
db_user=nagiosdb_pass=sesamo
se guardan los cambios y se inicia NDOutils:
/etc/init.d/ndoutils start
453
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:
tail -f /var/log/nagios/nagios.log
Las lineas que interesan son:
En Webmin se puede controlar que las tablas se ha ido llenando de nuevas entradas como, por ejemplo, la tabla nagios_commands:
Todo está funcionando como debería. Hay disponibles distintos tipos de consultas de las tablas en la carpeta /usr/share/ndoutils/queries/
22.4 Monitoreo calidad llamadas
Como se ha dicho 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 calidad llamadas desde la consola de Asterisk
Se entra en la consola de Asterisk:
454
asterisk -rvvvvvvvvvvvvvvvvvv
Si activan las estadísticas del protocolo RTCP (Real Time Control Protocol) definido en el RFC 3550.
CLI> rtcp set stats onRTCP Stats Enabled
Para ver como funciona, desde la extensión 1000 se llama la extensión 1002. Se contesta la llamada y después de unos segundos se cuelga. En la consola aparecerán todas una serie de datos relacionados con 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 la 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 la 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 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 parte
455
Web para ver la estadísticas desde un Navegador, una comercial que incluye la parte Web.
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• Librería MySQL++
Primero se averigua la versión de libpcap instalada:
yum info libpcap
Como el numero de versión es inferior a 1, hay que instalar la librería desde la fuentes:
cd /usr/srcwget http://www.tcpdump.org/release/libpcap-1.2.1.tar.gztar -xf libpcap-1.2.1.tar.gzcd libpcap-1.2.1./configure --prefix=/usrmakemake install
456
Se continua con MySQL++
cd /usr7srcwget http://tangentsoft.net/mysql++/releases/mysql++-3.1.0.tar.gz tar -xf mysql++-3.1.0.tar.gzcd mysql++-3.1.0./configure --prefix=/usrmakemake install
Instalados los pre requisitos ya se puede compilar e instalar VoIPMonitor. Primero se descarga:
svn co https://voipmonitor.svn.sourceforge.net/svnroot/voipmonitor/trunk voipmonitor-svn
Se entra en la carpeta creada:
cd voipmonitor-svn
Se compila y se instala:
makemake install
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> GRANT ALL PRIVILEGES ON voipmonitor.* to 'voipuser'@'localhost' IDENTIFIED BY 'sesamo';
mysql> flush privileges;
mysql> quit
Se cargan las tablas en la base de datos:
mysql -u root -psesamo voipmonitor < cdrtable.sql
Se crea un archivo de configuración para el programa:
457
nano /etc/voipmonitor.conf
Se copian las lineas que siguen:
[general]# inicia la parte general de la configuracióninterface=any# el programa se pondrá a la escucha en todas las tarjetas de red presentes en el servidormanagerport=5029# puerto TCP para gestionar el programasipport=5060sipport=5061# puertos SIP donde voipmonitor se pondrá a la escucha. Se indica uno por linea# ringbuffer=10# Parámetro valido solamente para versiones del Kernel >= 2.6.31jitterbuffer_f1=yesjitterbuffer_f2=yesjitterbuffer_adapt=yes# tipos de jitterbuffer utilizados para el calculo del MOSrtp-firstleg=no# se capturará el flujo media de ambos canalessip-register=no# no se guardarán en la captura SIP, los mensajes de REGISTERnocdr=no# VoIPMonitos guardará los CDR de las llamadassavesip=yes# VoIPMonitos guardará los datos SIP en un archivosavertp=yes#VoIPMonitor guardará los paquetes RTP en un archivosavegraph=plain# Se guardarán los datos de los graficos en un archivo (en el caso se utilice la GUI)spooldir=/var/spool/voipmonitor# Carpeta donde se guardarán los datos de las llamadasmysqlhost=localhost# dirección IP o nombre de dominio del servidor MySQLmysqldb=voipmonitor# Nombre de la base de datosmysqltable=cdr# Nombre de la tablamysqlusername=voipuser# Nombre del usuario MySQL con los permisos para la base de datosmysqlpassword=sesamo# Password del usuario voipuser
Se guardan los cambios y se instala lo script para iniciar el servicio en automático:
458
cp config/init.d/voipmonitor /etc/init.d/chmod +x /etc/init.d/voipmonitorchkconfig --add voipmonitorchkconfig voipmonitor on
Se inicia el servicio:
service voipmonitor start
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 (serán dos).
459
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 1.8.X se han implementados dos nuevos 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á ser interceptado
• Las claves que intercambian el cliente y el servidor para instaurar el cifrado del flujo media, se envian a través de la señalización SIP. Si no se utiliza el cifrado del protocolo SIP y alguien logra interceptar este 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 certificado cliente, servidor y de la autoridad de certificación. Se crea la carpeta donde se guardarán las claves:
mkdir /etc/asterisk/keys
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-1.8.11.0/contrib/scripts/
Primero se crea el certificado de la autoridad de certificación y del servidor Asterisk:
./ast_tls_cert -C li374-112.members.linode.com -O "Campus VozToVoice" -d /etc/asterisk/keys
• 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
./ast_tls_cert -C li374-112.members.linode.com -O "Campus VozToVoice" -d /etc/asterisk/keys
No config file specified, creating '/etc/asterisk/keys/tmp.cfg'You can use this config file to create additional certs withoutre-entering the information for the fields in the certificateCreating /etc/asterisk/keys/ca.keyGenerating 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.crtEnter pass phrase for /etc/asterisk/keys/ca.key:Creating /etc/asterisk/keys/asterisk.keyGenerating RSA private key, 1024 bit long modulus....................................++++++.........++++++e is 65537 (0x10001)Creating signing requestCreating /etc/asterisk/keys/asterisk.crtSignature oksubject=/CN=li374-112.members.linode.com/O=Campus VozToVoiceGetting CA Private KeyEnter 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/keys/ca.crt -k /etc/asterisk/keys/ca.key -C blink1.li374-112.members.linode.com -O "Campus VozToVoice" -d /etc/asterisk/keys -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 y al mismo tiempo el dominio del servidor
• con la opción -O se indica el nombre de la empresa o de la institución
462
• 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 withoutre-entering the information for the fields in the certificateCreating /etc/asterisk/keys/blink1.keyGenerating RSA private key, 1024 bit long modulus.....................++++++.....++++++e is 65537 (0x10001)Creating signing requestCreating /etc/asterisk/keys/blink1.crtSignature oksubject=/CN=blink1.li374-112.members.linode.com/O=Campus VozToVoiceGetting CA Private KeyEnter 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=yestlsbindaddr=0.0.0.0tlscertfile=/etc/asterisk/keys/asterisk.pemtlscafile=/etc/asterisk/keys/ca.crttlscapath=/etc/asterisk/keystlsdontverifyserver=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]
463
type=friendaccountcode=1005language=essecret=pbx9095qualify=yesmailbox=1005@defaulthost=dynamicdtmfmode=rfc2833context=externasdirectmedia=nocallerid=Perengano <1001>callgroup=1pickupgroup=1disallow=allallow=ulawallow=alawallow=g729allow=h263cc_agent_policy=genericcc_monitor_policy=generictransport=tlsencryption=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:
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
464
Se guardan los cambios y se reinicia iptables:
service iptables 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:
465
• 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
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:
466
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,Macro(voicemail)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,Macro(voicemail)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
467
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")
Como la extensión 1000 (Softphone X-Lite) no soporta SIP TLS y SRTP, las dos variable de canal estarán vacías.
-- 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:
SoftPhone Blink ---------------------> Asterisk -------------------------> SoftPhone X-Lite
o:
SoftPhone X-Lite ---------------------> Asterisk -------------------------> SoftPhone Blink
El 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.
468
SIP TSL - SRTP SIP - RTP
SIP TSL - SRTPSIP - RTP
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.6.0-openjdk*
Terminada la instalación se controla la versión instalada:
java -versionjava version "1.6.0_20"OpenJDK Runtime Environment (IcedTea6 1.9.10) (rhel-1.23.1.9.10.el5_7-i386)OpenJDK Client VM (build 19.0-b09, mixed mode)
Se descarga el servidor jabber Openfire:
cd /opt
wget http://www.igniterealtime.org/downloadServlet?filename=openfire/openfire_3_7_1.tar.gz
se descomprime
tar -xf openfire_3_7_1.tar.gz
Se entra en la carpeta bin
cd /opt/openfire/bin
Se modifica el script de inicio:
nano openfire
modificando esta linea:# INSTALL4J_JAVA_HOME_OVERRIDE=
para que quede:
INSTALL4J_JAVA_HOME_OVERRIDE=/usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0
Se guardan los cambios y se inicia:
./openfire start
Se averigua que esté corriendo
./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
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
471
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:
service iptables 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:
472
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á:
473
Se configura el acceso a MySQL y la base de datos:
En seteos de perfil se elige la opción “por defecto”
474
Se configura el correo electrónico y la cuenta del administrador:
El servidor está listo para funcionar.
475
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, y se presiona Login:
Después de unos segundos:
476
Se pueden configurar más usuarios y grupos desde la pagina de administración
Si se quiere iniciar Openfire en automático:
cd /opt/openfire/bin/extra/redhat
nano openfire-sysconfig
Se modifican estas lineas:
#OPENFIRE_HOME=""#OPENFIRE_USER="daemon"#OPENFIRE_PIDFILE="/var/run/openfire.pid"#OPENFIRE_LOGDIR="/some/where/logs"#OPENFIRE_OPTS="-Xmx1024m"#JAVA_HOME=/usr/java/default
para que queden
OPENFIRE_HOME="/opt/openfire"OPENFIRE_USER="root"OPENFIRE_PIDFILE="/var/run/openfire.pid"OPENFIRE_LOGDIR="/var/log"
477
OPENFIRE_OPTS="-Xmx256m"JAVA_HOME=/usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0
Se guardan los cambios y se copia el archivo en la carpeta /etc/sysconfig:
cp openfire-sysconfig /etc/sysconfig/openfire
Ahora se instala el servicio:
cp openfire /etc/init.d/openfired
se vuelve ejecutable:
chmod +x /etc/init.d/openfired
y se añade a los servicios:
chkconfig --add openfiredchkconfig openfired on
Para averiguar si Openfire arranca 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 statusopenfire is running
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.
478
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ú: “Phone”. Se presiona para entrar en el menú de configuración del plugin.
Se escoge “Agregar nuevo mapeo” y se rellenan los campos:
479
• 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:
480
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.
Ahora se puede hacer una primera prueba. Desde la extensión 1001 se marca la extensión 1000. Spark debería empezar a timbrar:
481
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.
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 puesto el parámetro callevents=yes en la parte general del archivo sip.conf• 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 = sesamodeny=0.0.0.0/0.0.0.0permit=127.0.0.1/255.255.255.255read=system,call,agent,user,dtmf,reporting,cdr,dialplan,agi,cc,aocwrite=system,call,agent,user,config,command,reporting,otiginate,agi,aoc
Se actualiza la configuración de Asterisk:
/etc/init.d/asterisk reload
482
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:
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
483
En la pagina que aparece se configura como en la imagen que sigue:
• 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
484
consola de Asterisk:
asterisk -rvvvvvvvvvvvvvv
se digita el comando:
CLI> manager show connected
Username IP Address Start Elapsed FileDes HttpCnt Read Write openfire 127.0.0.1 1323817682 79 10 0 04079 04851
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:
Como cambiará en el cliente X-Lite:
485
24.4 Asterisk como cliente en Openfire
La configuración de Asterisk como cliente jabber en Openfire es parecida a la de GoogleTalk (párrafo 5.1). Se empieza con la modifica del archivo jabber.conf presente en la carpeta /etc/asterisk.
nano /etc/asterisk/jabber.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)
type=client ; Asterisk actuará como un cliente (las opciones son cliente, componente y server)
serverhost=localhost; el nombre de dominio o IP del servidor Openfire
username=asterisk@localhost/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
486
buddy=admin@localhost ; la lista de amigos, uno por línea
statusmessage=Asterisk server ; un mensaje personalizado del usuario
timeout=100 ;
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 Opnefire
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
487
Se termina presionando el botón “Create User”.
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> jabber show connected Jabber Users and their status: User: asterisk@localhost/openfire - Connected
Para ver la lista de amigos:
CLI> jabber show buddies Client: asterisk@localhost/openfire Buddy: admin@localhost Resource: None
En el menú “Sessions” de Openfire:
Se inicia el cliente Spark y se añade el usuario asterisk.
488
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 servidor:
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 →
489
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:
490
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:
491
Se entra en el menú Sessions > Server Session de ambos servidores donde debería aparecer:
Servidor A:
Servidor B:
492
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 '^]'.</stream:stream>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 autenticaciones 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:
493
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: dirección IP o nombre de dominio donde el Connection Manager aceptará las conexiones.
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
494
CMD="./cmanager.sh $1"
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”. Se abre el puerto 5262 TCP en el cortafuegos.
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 statusrunning pid is 5747Connection 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:
495
Desde un cliente XMPP se abre una conexión usando como dirección IP o nombre de Dominio la que se ha configurado en la linea “interface” del archivo manager.xml
496
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 quier 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 usar el esclavo para 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 hacer las consultas en el maestro, se hacen 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.144Base de datos a replicar: asteriskMaster
ServidorB:IP LAN: 192.168.128.145Esclavo
Base de datos replicada: asteriskcdr
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:
499
myslq> GRANT REPLICATION SLAVE ON *.* TO 'asterisk'@'192.168.128.145' IDENTIFIED BY 'sesamo';
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 = 10log_bin = /var/log/mysql/mysql-bin.logexpire_logs_days = 10max_binlog_size = 100Mbinlog_do_db = asteriskcdrsync_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• binlod_do_db: el nombre de la base de datos que se va a replicar• 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
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 la base de datos para luego importarla en el servidor MySQL esclavo:
mysql -u root -psesamo
Primero se selecciona la base de datos asteriskcdr:
mysql> use asteriskcdr
500
Segundo 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 | +------------------+----------+--------------+------------------+ | mysql-bin.000001 98 | asteriskcdr | | +------------------+----------+--------------+------------------+ 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 (98). 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:
cd /tmp
mysqldump -u root -psesamo asteriskcdr > asteriskslave.sql
se copia el archivo en el servidoB en la carpeta tmp:
scp asteriskslave.sql root@192.168.128.145:/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
501
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=20master-connect-retry=60replicate-do-db=asteriskcdrskip_slave_startread_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 vamos a replicar• 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 crea la base de datos asteriskcdr:
mysqladmin -u root -psesamo create asteriskcdr
se recuperan tablas y datos de la copia que está en la carpeta /tmp:
cd /tmp
mysql -u root -psesamo asteriskcdr < asteriskslave.sql
A este punto se crean los datos de acceso al servidor MySQL Master:
mysql -u root -psesamo
mysql> CHANGE MASTER TO MASTER_HOST='192.168.128.144',
502
MASTER_USER='asterisk', MASTER_PASSWORD='sesamo', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=98;
En MASTER_LOG_FILE Y MASTER_LOG_POS, se ponen los datos del servidor MySQL A que se habían anotado.
Antes de iniciar el esclavo, hay que abrir el puerto TCP 3306 en el servidor A. Se hace 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:
service iptables 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.142.248 Master_User: fulanoMaster_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000001 Read_Master_Log_Pos: 98 Relay_Log_File: mysqld-relay-bin.000002 Relay_Log_Pos: 235 Relay_Master_Log_File: mysql-bin.000001 Slave_IO_Running: Yes Slave_SQL_Running: Yes
503
Replicate_Do_DB: asteriskcdr 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: 98 Relay_Log_Space: 235 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 1 row in set (0.00 sec)
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
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 tress paquetes al servidorB (192.168.128.145) para actualizar las tablas CDR, CDR2 y CDR3 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 la base de datos de asteriskcdr. En éste se verá como utilizar la replicación MySQL Master-Master para la base de datos asteriskcdr solamente para la tabla CDR.
¿Qué diferencia hay entra una replicación Maestro-Esclavo y una Maestro-Maestro?
504
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.
Escenario:
ServidorA:IP 192.168.128.144Base de datos a replicar: asteriskcdr – Tabla: cdrMasterA SlaveA
ServidorB:IP 192.168.128.145Base de datos a replicar: asteriskcdr – Tabla: cdrMasterB SlaveB
La tabla CDR en el ServidorA ya existe y tiene 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 usarán estos dos parámetros:
• 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 id,calldate from cdr where dst=1000;+----+---------------------+| id | calldate |+----+---------------------+| 21 | 2011-12-14 13:21:42 |
505
| 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
bajo la etiqueta [mysqld] se pone:
server-id = 10auto_increment_increment = 10auto_increment_offset = 1log_bin = /var/log/mysql/mysql-bin.logexpire_logs_days = 10max_binlog_size = 100Mreplicate-do-table =asteriskcdr.cdrsync_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
506
En el caso de tres entradas en la tabla el resultado será:
ID 1ID 11ID 21
• Con replicate-do-table se define que la replicación es solamente para la tabla cdr de la base de datos asteriskcdr
Se reinicia mysql:
/etc/init.d/mysqld restart
Considerando que el servidor Asterisk tiene tiempo trabajando hay que crear una copia de la base de datos para luego importarla en el servidorB:
mysql -u root -psesamo
Primero se selecciona la base de datos asterisk:
mysql> use asteriskcdr
Segundo 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 |+------------------+----------+--------------+------------------+| mysql-bin.000001 | 98 | asterisk | |+------------------+----------+--------------+------------------+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 (98); 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:
cd /tmp
mysqldump -u root -psesamo asteriskcdr > cdr.sql
se copia el archivo en el servidorB en la carpeta tmp:
507
scp cdr.sql root@192.168.128.145:/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
ServidorB
Se crea la carpeta para guardar los Bynary log con los permisos para el usuario mysql:
mkdir /var/log/mysql
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> quit
Se importa la tabla cdr:
cd /tmp
mysql -u root -psesamo asteriskcdr < cdr.sql
Se averigua que efectivamente las tabla y los datos presentes se han guardado:
mysql -u root -psesamo
mysql> use asteriskcdr
mysql> select id,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 |
508
| 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:
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 = 20auto_increment_increment = 10auto_increment_offset = 2log_bin = /var/log/mysql/mysql-bin.logexpire_logs_days = 10max_binlog_size = 100Mreplicate-do-table =asteriskcdr.cdrsync_binlog =1
El auto_increment_offset es igual a 2. En el caso de tres entradas el ID sería:
ID 2ID 12ID 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;
509
mysql> SHOW MASTER STATUS;+------------------+----------+--------------+------------------+| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |+------------------+----------+--------------+------------------+| mysql-bin.000001 | 98 | | |+------------------+----------+--------------+------------------+1 row in set (0.00 sec)
mysql> quit
Para dar acceso a la base de datos al servidorA, hay que abrir el puerto TCP 3306 solamente para esa IP local:
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:
service iptables 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=98;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.142.248
510
Master_User: masterb Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000001 Read_Master_Log_Pos: 98 Relay_Log_File: mysqld-relay-bin.000002 Relay_Log_Pos: 235 Relay_Master_Log_File: mysql-bin.000001 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: asteriskcdr.cdr Replicate_Ignore_Table: Replicate_Wild_Do_Table:Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 98 Relay_Log_Space: 235 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: 01 row in set (0.00 sec)
Se sigue el mismo procedimiento para el ServidorA:
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=98;Query OK, 0 rows affected (0.10 sec)
mysql> START SLAVE;
mysql> SHOW SLAVE STATUS\G
511
*************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.146.90 Master_User: mastera Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000001 Read_Master_Log_Pos: 98 Relay_Log_File: mysqld-relay-bin.000002 Relay_Log_Pos: 235 Relay_Master_Log_File: mysql-bin.000001 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: asterisk.cdr Replicate_Ignore_Table: Replicate_Wild_Do_Table:Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 98 Relay_Log_Space: 235 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: 01 row in set (0.00 sec)
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.
El resultado en la base de datos:
mysql -u root -psesamo
mysql> use asteriskcdr
512
mysql> select id,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 id,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
mysql -u root -psesamo
mysql> use asteriskcdr
mysql> select id,calldate from cdr where dst=97; +----+---------------------+
513
| 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 id,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 sincronizadas. Funciona en el mismo modo de un sistema RAID1 con la sencilla diferencias que las copias de los datos se hacen a través de la red usando 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 hacer con dos servidores locales con las modificaciones oportunas.
Al momento de configurar el servidor Linode, se han creado 4 particiones:
514
La ultimas dos es las que se utilizarán para DRDB. Claramente las mismas particiones tienen que ser creadas el en segundo servidor de respaldo. Una vez terminada esta operación, tendremos los dos servidores Linode listos para la instalación y configuración de DRBD.
Servidor AIP publico: 69.164.201.178 IP Lan: 192.168.128.144Dominio: li115-178.members.linode.com
Servidor BIP publico: 96.126.115.16 IP Lan: 192.168.128.145Dominio: 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.com192.168.128.145 li340-16.members.linode.com
Se guardan los cambios y se averigua que efectivamente se logra localizar el servidor B:
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 ms64 bytes from li340-16.members.linode.com (192.168.128.145): icmp_seq=2 ttl=64 time=0.430 ms64 bytes from li340-16.members.linode.com (192.168.128.145): icmp_seq=3 ttl=64 time=0.405 ms64 bytes from li340-16.members.linode.com (192.168.128.145): icmp_seq=4 ttl=64 time=0.479 ms
515
64 bytes from li340-16.members.linode.com (192.168.128.145): icmp_seq=5 ttl=64 time=0.518 ms64 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 4997msrtt min/avg/max/mdev = 0.405/0.497/0.671/0.089 ms
Se efectua 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.com192.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 ms64 bytes from li115-178.members.linode.com (192.168.128.144): icmp_seq=2 ttl=64 time=0.422 ms64 bytes from li115-178.members.linode.com (192.168.128.144): icmp_seq=3 ttl=64 time=0.542 ms64 bytes from li115-178.members.linode.com (192.168.128.144): icmp_seq=4 ttl=64 time=0.420 ms64 bytes from li115-178.members.linode.com (192.168.128.144): icmp_seq=5 ttl=64 time=0.386 ms64 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 4996msrtt 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:
cd /usr/src
wget http://oss.linbit.com/drbd/8.3/drbd-8.3.7.tar.gz
tar -xf drbd-8.3.7.tar.gz
cd drbd-8.3.7
./configure --prefix=/ --with-km --with-xen
Se compila utilizando la ultimas versión de las fuentes del Kernel-XEN instalado en el servidor, es
516
decir:
uname -r2.6.18-308.1.1.el5xen
make KDIR=/usr/src/kernels/2.6.18-308.1.1.el5-xen-i686
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; } 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]; } 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
517
“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.
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 partof 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=128128+0 records in128+0 records out134217728 bytes (134 MB) copied, 1,2176 seconds, 110 MB/s
Se ejecuta otra vez el comando:
drbdadm create-md dataWriting meta data...initializing activity logNOT initializing bitmapNew drbd meta data block successfully created.success
Se configurara el programa para que el servicio arranque en automático:
chkconfig --add drbd
chkconfig drbd on
Para crear una primera sincronización entre los datos de las dos particiones de los dos servidores se
518
carga el modulo DRBD en el Kernel:
modprobe drbd
se averigua que efectivamente esté corriendo:
lsmod | grep drbddrbd 251364 0
Ahora se crea la conexión entre los dos servidores:
drbdadm attach data
drbdadm syncer data
drbdadm connect data
Se efectuá 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 root@li115-178.members.linode.com, 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)GIT-hash: ea9e28dbff98e331a62bcbcc63a6135808fe2917 build by root@li115-178.members.linode.com, 2011-12-15 11:24:58
1: cs:Connected ro:Primary/Secondary ds:UpToDate/UpToDate C r----
519
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 quiere 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
umount /home/data
En el caso que se quiera tener sincronizados los archivos de configuración de Asterisk, se copian
520
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 servidor que esté activo en ese momento.
25.4 Heartbeat
521
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 sepan 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 arrancando 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 MasterIP Asterisk Publico
IP servidor Asterisk Slave
Se utilizará la misma configuración que se presentó en el párrafo 25.3. Para resumir:
Servidor AIP publico: 69.164.201.178 IP Lan: 192.168.128.144
Servidor BIP 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, hay que configurarlo en una nueva tarjeta de red virtual:
nano /etc/sysconfig/network-scripts/ifcfg-eth0:2
Se copian las siguientes lineas:
DEVICE=eth0:2BOOTPROTO=noneONBOOT=yesIPADDR=173.255.196.191NETMASK=255.255.255.0
173.255.196.191 es la nueva IP adquirida. Se reinicia el servidor:
reboot
Luego 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” de la pagina de administración del Linode:
522
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. Este programa es presente en los repositorios "extras” de CentOS. Para activarlos:
nano /etc/yum.repos.d/CentOS-Base.repo
se modifica este bloque:
[extras] name=CentOS-$releasever - Extras mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extras #baseurl=http://mirror.centos.org/centos/$releasever/extras/$basearch/ gpgcheck=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
para que quede:
[extras] name=CentOS-$releasever - Extras mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extras baseurl=http://mirror.centos.org/centos/$releasever/extras/$basearch/ gpgcheck=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
Se guardan los cambios y se instala Heartbeat:
yum install heartbeat
Por algún raro motivo hay que repetir el comando dos veces:
523
yum install heartbeat
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-debuglogfile /var/log/ha-loglogfacility local0keepalive 2deadtime 120initdead 120ucast eth0 192.168.128.145udpport 694auto_failback onnode li115-178.members.linode.comnode li340-16.members.linode.com
Servidor B:
nano /etc/ha.d/ha.cf
debugfile /var/log/ha-debuglogfile /var/log/ha-loglogfacility local0keepalive 2deadtime 120initdead 120ucast eth0 192.168.128.144udpport 694auto_failback onnode li115-178.members.linode.comnode 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
524
deberá gestionar. Estos archivos tienen que ser iguales en ambos servidores:
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 dahdi asterisk
IMPORTANTE: tiene que estar todo el 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.
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 asteriskln -s /etc/init.d/dahdi dahdi
Ahora el problema. Todo parecía funcionar bien pero heartbeat no montaba la partición /dev/drbd1 y Asterisk no podía funcionar.
Revisando las cosas el script drbddisk (que viene con la instalación de Heartbeat) estaba mal configurado. Se resuelve de la siguiente forma:
nano /etc/ha.d/resource.d/drbddisk
525
Se cambia esta linea:
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 offchkconfig dahdi off
Esto porque es Heartbeat que se encarga de iniciar los dos programas.
chkconfig --add heartbeatchkconfig 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:
service iptables restart
Servidor B
nano /etc/sysconfig/iptables
después de este bloque:
526
# 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.144 --dport 694 -j ACCEPT
Se reinicia iptables:
service iptables 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 hace 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=statusst=activedt=1d4c0protocol=1src=li340-16.members.linode.com(1)srcuuid=9ku7IyMqS7uMVmJpcNsTCg==seq=274hg=4eea4a62ts=4eea4ec9ld=0.07 0.06 0.07 1/189 8883ttl=3auth=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.
527
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 arrancar la GUI, ésta añade macros y extensiones al plan de llamadas 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 hacer una copia de todos los archivo de configuración de Asterisk presentes en la carpeta /etc/asterisk:
mkdir /tmp/asterisk
cp /etc/asterisk/* /tmp/asterisk/
Para descargar la ultima versión disponible hay que instalar el programa SUBVERSION.
yum install subversion
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:
./configuremakemake 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=yeswebenabled=yesport=5038
bindaddr=0.0.0.0;tlsenable=no;tlsbindport=5039;tlsbindaddr=0.0.0.0;tlscertfile=/tmp/asterisk.pem;tlsprivatekey=/tmp/private.pemallowmultiplelogin=yesdisplayconnects=yestimestampevents=yes;channelvars = var1,var2,var3debug=noauthtimeout=60authlimit=20httptimeout=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=sesamowritetimeout=100read=system,call,agent,user,dtmf,reporting,cdr,dialplan,agi,cc,aocwrite=system,call,agent,user,config,command,reporting,otiginate,agi,aoc
Se guardan los cambios y se sigue con el archivo http.conf
mv /etc/asterisk/http.conf /etc/asterisk/http.conf.old
nano /etc/asterisk/http.conf
[general]enabled = yesenablestatic = yes bindaddr=0.0.0.0bindport=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
Después de este bloque:
# Apache
530
-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:
service iptables 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://li115-178.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: AsteriskPassword: sesamo
Se presiona el botón “Login”
Después de unos segundos aparecerá:
531
Se vuelve a la ventana terminal del servidor y se para y reinicia Asterisk:
service asterisk stopservice 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
El orden para configurar la GUI es:
• Crear las troncales en el menú Trunks• Crear los contextos para las llamadas saliente en el menú Outgoing Calling Rules• Crear el dialplan en el menú Dial Plans
532
• 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/asteriskcp http.conf /tmp/asterisk
rm -fr *
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.
533
CAPITULO XXVII
FreePBX
Personalmente no soy partidario de la 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. Antes, si se ha instalado, se remueve el paquete rpmforge-release:
yum remove rpmforge-release
yum install php-* httpd mod_ssl
Se añade el usuario Asterisk con home directory /var/lib/asterisk:
useradd -c "Asterisk PBX" -d /var/lib/asterisk asteriskuseradd: aviso: el directorio personal ya existe.No se copia ningún fichero del directorio skel en él.
Cambiamos 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/asteriskchown -R asterisk /var/log/asteriskchown -R asterisk /var/lib/asterisk/mohchown -R asterisk /var/lib/php/sessionchown -R asterisk /var/spool/asteriskchown -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/srcwget http://downloads.sourceforge.net/project/mpg123/mpg123/1.13.4/mpg123-1.13.4.tar.bz2tar -xf mpg123-1.13.4.tar.bz2cd mpg123-1.13.4./configure --prefix=/usrmakemake 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.confsed -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 -psesamoWelcome to the MySQL monitor. Commands end with ; or \g.Your MySQL connection id is 5Server version: 5.0.77 Source distributionType '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-2.9.0.tar.gz
Se descomprime el paquete y se entra en la carpeta creada:
tar -xf freepbx-2.9.0.tar.gz
cd freepbx-2.9.0
Se crean las tablas para las bases de datos asterisk y asteriskcdrdb:
mysql -u root -psesamo asterisk < SQL/newinstall.sql
536
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/sbin/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
537
pagina de administración del FreePBX y la dirección IP publica del servidor Linux, respectivamente):
nano /etc/amportal.conf
ARI_ADMIN_PASSWORD=ari_passwordAUTHTYPE=noneAMPWEBADDRESS=xx.xx.xx.xx
para que queden:
ARI_ADMIN_PASSWORD=sesamoAUTHTYPE=databaseAMPWEBADDRESS=IPservidor (poner la IP publica del servidor Linux)
Se guardan los cambios y se inicia nuevamente FreePBX:
/usr/sbin/amportal start
En el archivo rc.local se copia esta línea para que el arranque sea automático:
nano /etc/rc.local
/usr/sbin/amportal start
Se guardan los cambios y se entra a la pagina web para administrar FreePBX utilizando la siguiente dirección:
http://IPservidor
Se escoge el enlace “FreePBX Adminsitration”:
538
Se pone como usuario admin y como contraseña admin. Primero en el menú “Adminisitrators” se cambia la contraseña del usuario admin:
Se pone la nueva contraseña y se presiona el botón “Submit Changes”. Luego desde el menú izquierdo se selecciona “Module Admin”. Se averigua si hay actualizaciones y se instalan:
539
De la misma forma se pueden instalar los módulos que se necesiten. Se selecciona el menú “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.
540
Apéndice A
Instalar CentOS 5.8 en una maquina virtual con VirtualBox
En esta guía se ilustrará como instalar el sistema operativo CentOS 5.8 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/5.8/isos/i386/CentOS-5.8-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: CentOSLocalSistema Operativo: LinuxVersió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, mejor aun seleccionar 1GB (1024 Mb)
543
544
545
546
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:
547
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.
548
Se continua presionando la tecla Enter (Envío):
549
Se escoge el idioma.
El tipo de teclado.
550
El tipo de instalación (vía HTTP):
Se activa la tarjeta de red para las direcciones Ipv4
551
Nombre del sitio Web: mirror.centos.orgDirectorio CentOS: /centos/5.8/os/i386
Terminada la primera fase se iniciará la configuración del sistema:
552
Se borran todos los datos del disco virtual creado:
Se crean las particiones predefinidas:
553
Se confirma:
Se modifica la configuración de la tarjeta de red.
554
Configurando una IP fija.
Se crea un nombre de dominio, puerta de enlace (normalmente la IP del router) y DNS primario (la IP del router).
555
Se escoge la zona horaria:
Se crea una contraseña para el usuario root:
556
Se escoge el tipo de instalación (Sever) y se personalizan los paquetes que se instalarán:
Se entra en el menú Servidores y se dejan seleccionados solo los paquetes que aparecen en la imagen:
557
Se inicia la instalación del sistema operativo:
558
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 y en 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:
559
Ahora se puede iniciar nuevamente la maquina virtual. Al primer arranque aparecerá el siguiente menú:
Se entra en la configuración del cortafuegos:
560
Se deshabilita el cortafuegos y Selinux.
Se sale de la herramienta de configuración. Para terminar, se activa una DMZ en el router para la IP del servidor Linux. Un ejemplo:
561
Se vuelve a la maquina virtual y se actualiza el sistema:
yum -y update
Se reinicia el servidor
reboot
Ya se puede retomar el libro desde la pagina 9 con la creación de la clave RSA.
562
Apéndice B
Archivos de configuración
sip.conf
[general]allowguest=nocontext=defaultallowtransfer=yes;realm=mydomain.tldudpbindaddr=0.0.0.0:5060tcpenable=yestcpbindaddr=0.0.0.0:5060tcpauthtimeout=30tcpauthlimit=100srvlookup=yesmaxexpiry=3600minexpiry=60defaultexpiry=120mwiexpiry=3600maxforwards=70qualifyfreq=60preferred_codec_only=nodisallow=allallow=ulawallow=alawmohinterpret=defaultmohsuggest=defaultparkinglot=defaultlanguage=essendrpid=yerpid_update=yesprematuremedia=nouseragent=VozToVoice v. 1.0sdpsession=asterisksdpowner=asteriskdtmfmode=rfc2833videosupport=yesmaxcallbitrate=384callevents=yesauthfailureevents=yesalwaysauthreject=yesuse_q850_reason=yesrtptimeout=60rtpholdtimeout=300rtpkeepalive=0allowsubscribe=yes
subscribecontext=subscribenotifyringing=yesnotifyhold=yescallcounter=yest38pt_udptl=yes,fec,maxdatagram=400 faxdetect=yeslocalnet=localnet=10.8.0.0/255.255.255.0localnet=10.10.0.0/255.255.255.0externaddr=;externhost=prueba.dyndns.org;externrefresh=180nat=force_rportdirectmedia=no;media_address=0.0.0.0rtcachefriends=nortupdate=yestlsenable=yestlsbindaddr=96.126.125.112tlscertfile=/etc/asterisk/keys/serverA.pemtlscafile=/etc/asterisk/keys/ca.crttlscapath=/etc/asterisk/keystlsdontverifyserver=yes
register => serverA:pass1@IPserverB/serverB;register => fulano:sesamo@sip.provider1.com;register => fulano:sesamo@sip.provider1.com:5061;register => fulano:contraseña@sip.provider1.com/1234registertimeout=20registerattempts=10;mwi => 1234:password@mysipprovider.com/1234
[1000]accountcode=1000language=estype=friendsecret=pbx9090qualify=yesmailbox=1000@defaulthost=dynamicdtmfmode=rfc2833context=externasdirectmedia=nocallerid=callerid=Fulano <1000>callgroup=1pickupgroup=1disallow=all
565
allow=alawallow=g722allow=g729allow=h263cc_agent_policy=genericcc_monitor_policy=generic
[1001]type=friendaccountcode=1001language=essecret=pbx9091qualify=yesmailbox=1001@defaulthost=dynamicdtmfmode=rfc2833context=externasdirectmedia=nocallerid=zutano <1001>callgroup=1pickupgroup=1disallow=allallow=alawallow=g722allow=g729allow=h263cc_agent_policy=genericcc_monitor_policy=generic
[int-locales](!)type=friendlanguage=esqualify=yeshost=dynamicdtmfmode=rfc2833context=localesdirectmedia=nocallgroup=1pickupgroup=1disallow=allallow=alawallow=g722allow=g729allow=h263
[1002](int-locales)accountcode=1002
566
secret=pbx9092mailbox=1002@defaultcallerid=Mengano <1002>cc_agent_policy=genericcc_monitor_policy=generic
[justvoip] type=peerhost=sip.justvoip.comfromdomain=sip.justvoip.comfromuser=defaultuser=secret=qualify=yesdtmfmode=rfc2833context=from-justvoipdirectmedia=nolanguage=esnat=nodisallow=allallow=alawallow=g729
[spa3102]type=friendsecret=passwordqualify=yesnat=yeshost=dynamicdirectmedia=nocontext=from-spa3102dtmfmode=rfc2833language=escallerid=LineaTel <NumTel>allowtransfer=yesallowsubscribe=yessubscribecontext=subscribecallcounter=yesdisallow=allallow=alawallow=g729
[serverB]type=friendremotesecret=pass2context=internasqualify=yes
567
host=dynamiclanguage=esdisallow=allallow=gsmallow=ulawallow=alaw
[serverbvpn]type=peercontext=vpnhost=10.8.0.6disallow=allallow=g729allow=alawlanguage=esqualify=yesdtmfmode = rfc2833
[serverbtls]type=peercontext=from-tlshost=66.228.49.216disallow=allallow=alawlanguage=esqualify=yestransport=tlsencryption=yes
[1005]type=friendaccountcode=1005language=essecret=pbx9095qualify=yesmailbox=1005@defaulthost=dynamicdtmfmode=rfc2833context=externasdirectmedia=nocallerid=Perengano <1001>callgroup=1pickupgroup=1disallow=allallow=ulawallow=alawallow=g729
568
allow=h263cc_agent_policy=genericcc_monitor_policy=generictransport=tlsencryption=yes
iax.conf
[general]bindport=4569bindaddr=0.0.0.0nochecksums=nodelayreject=yesamaflags=documentationsrvlookup=yeslanguage=esmohinterpret=defaultmohsuggest=defautlbandwidth=highdisallow=allallow=alawallow=alawminregexpire=60maxregexpire=60encryption=yesforceencryption=notrunkmaxsize=128000trunkmtu=1240autokill=yescodecpriority=hostrtcachefriends=nortupdate=yesparkinglot=defaultcalltokenoptional=0.0.0.0/0.0.0.0requirecalltoken=auto
;register => marko:secretpass@tormenta.linux-support.net;register => joe@remotehost:5656 ;register => marko:[key]@tormenta.linux-support.net
[marko]type=friendhost=dynamicsecret=pbx9094context=externasmailbox=1234@default
569
qualify=yescallerid=markorequirecalltoken=auto
[serverb]type=friendhost=66.228.49.216trunk=yescontext=internasqualify=yes
[server1]type=userdbsecret=dundi/secretcontext=servera-localqualify=yesdisallow=allallow=ulawallow=alaw
extensions.conf
[general]static=yeswriteprotect=yseautofallthrough=yseextenpatternmatchnew=yseclearglobalvars=no
[globals]1000=SIP/1000JUST=SIP/justvoipmarko=IAX2/markoDYNAMIC_FEATURES=test1#blindxfer#automon#disconnect#atxfer#parkcall#automixmon
[from-didvoztovoice]exten => s,1,Answersame => n,Goto(IVR,s,2)same => n,Hangup
[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)
570
same => n,Wait(1)same => n,Playback(goodbye)same => n,Hangupsame => n(conf),Agi(googletts.agi,"${CALENDAR_EVENT(description)}",es)same => n,Confbridge(${CALENDAR_EVENT(location)},cM(default))same => n,Hangup
[test]switch => Realtime
[fax]exten => _X.,1,Dial(SIP/justvoip/${EXTEN})same => n,Hangup
exten => 1234,1,Answersame => n,Receivefax(/tmp/${UNIQUEID}.tif,df)same => n,Hangupexten => h,1,Noop(FAXSTATUS ${FAXSTATUS}, FAXERROR ${FAXERROR})same => n,Hangup
exten => 1235,1,Answersame => n,Wait(6)same => n,Dial(SIP/1000,45)exten => fax,1,Dial(IAX2/iaxmodem2)same => n,hangup
[servera-local]exten => 20,1,Answer()exten => 20,n,Playback(hello-world)exten => 20,n,Hangup()
[dundi-remoto]switch => DUNDi/serverb
[vpn]exten => 70,1,Answersame => n,Playback(demo-congrats)same => n,Hangup
[from-tls]exten => 71,1,Answersame => n,Noop(TLS = ${CHANNEL(secure_signaling)}, SRTP = ${CHANNEL(secure_media)})same => n,Playback(tt-monkeys)same => n,Hangup
[internas]exten => *30,1,CallCompletionRequest
571
same => n,Agi(googletts.agi,"Rellamada activada",es)same => n,Hangup
exten => *31,1,CallCompletionCancelsame => n,Agi(googletts.agi,"Rellamada anulada",es)same => n,Hangup
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
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
exten => _*1XXX,1, Set(CALLERID(num)=serverA)same => n,Dial(SIP/serverB/${EXTEN:1},30)same => n,Hangup()
exten => _*1100X,1,Dial(IAX2/serverb/${EXTEN:2})same => n,Hangup
exten => 50,1,Set(PBX=${ENV(LANG)})same => n,Noop(Idioma Servidor ${PBX})same => n,Hangup
exten => 51,1,Noop(Consulta en el calendario)same => n,Set(fin=$[${EPOCH}+10800])same => n,Set(id=${CALENDAR_QUERY(campusvoztovoice,${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,Endwhilesame => n,Hangup
572
exten => 70,1,Set(CALLERID(num)=openvpna)same => n,Dial(SIP/serverbvpn/${EXTEN})same => n,hangup
exten => 71,1,Set(CALLERID(num)=serveratls)same => n,Dial(SIP/serverbtls/${EXTEN})same => n,hangup
exten => 75,1,Answersame => n,Wait(1)same => n,Goto(IVR,s,1)
exten => 77,1,Set(CHANNEL(language)=es)same => n,agi(wakeup.php)same=> n,Hangup
exten => 97,1,Answersame => n,VoiceMailMain(${CALLERID(num)}@default)same => n,Hangup
exten => 98,1,VoicemailMainsame => n,Hangup
exten => 99,1,Directory(default,internas,e)same => n,Hangup
exten => 100,1,Noopsame => n,Dial(SIP/1000&SIP/1001&SIP/1002,30)same => n,Hangup
exten => 123,1,Answersame => n,Dumpchansame => n,Playback(hello-world)same => n,Hangup
exten => 150,1,Answersame => n,Playback(demo-echotest)same => n,Echosame => n,Playback(demo-echodone)same => n,Hangup
exten => 200,1,Answersame => n,Jabbersend(campus.voztovoice,voztovoicenet@gmail.com,Estamos escuchando MP3)same => n,MusicOnHold(mp3,60)same => n,Hangup
573
exten => 250,1,Agi(pruebaudio.php)same => n,Hangup
exten => 251,1,Agi(callerid.php)same => n,Hangup
exten => 252,1,Noopsame => n,AGI(agi://127.0.0.1:4573)same => n,Hangup
exten => 253,1,Noopsame => n,AGI(agi:async)same => n,Hangup
exten => 650,1,Answer()same => n,Festival(Asterisk y Festival trabajan junto. Chevere!!!)same => n,Hangup()
exten => 660,1,Answersame => 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,Hangupsame => n(nombre),Festival(El nombre del empleado es ${EMPNAME}. Hasta luego.)same => n,Hangup
exten => 670,1,Goto(encuesta,s,1)same => n,Hangup
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,Macro(voicemail)same => n,Hangup
exten => 1234,1,Dial(IAX2/marko,30)same => n,Macro(voicemail)same => n,Hangup
exten => 1235,1,Dial(IAX2/marko2,30)same => n,Macro(voicemail)same => n,Hangup
exten => _200[012],1,Agentlogin(${EXTEN})
574
same => n,Hangup
exten => 3000,1,Answersame => n,Queue(ventas,R)same => n,Hangup
exten => 3001,1,Answersame => n,Queue(ventas)same => n,Voicemail(1000@default)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 => 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/justvoip/0057XXXXXXXXXX)same => n,hangupsame => n(contestada),Hangup
exten => _8.,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
[conferencias]exten => 501,1,Page(SIP/1001&SIP/1002)same => n,Hangup
exten => 502,1,Page(SIP/1001&SIP/1002,d)same => n,Hangup
exten => _350[012],1,Meetme(${EXTEN},scM(default))same => n,Hangup
exten => 3510,1,Meetme(,DM(default))same => n,Hangup
575
exten => 3520,1,Set(confmax=10)same => n,Macro(meetme)same => n,Hangup
exten => 3530,1,Answersame => n,ConfBridge(3530,Mcs)same => n,Hangup
exten => _500[01],1,Meetme(${EXTEN})same => n,Hangup
[encuesta]exten => s,1,Answersame => 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
[auten]exten => _00.,1,NoOPsame => n,Authenticate(/tmp/pin.txt,am,4)same => n,Dial(SIP/justvoip/${EXTEN})same => n,Hangup
[subscribe]exten => 1000,hint,SIP/1000exten => 1001,hint,SIP/1001exten => 1002,hint,SIP/1002exten => 1004,hint,SIP/1004exten => marko,hint,IAX2/markoexten => marko2,hint,IAX2/marko2exten => 701,hint,park:701@parkedcallsexten => 702,hint,park:702@parkedcallsexten => 703,hint,park:703@parkedcallsexten => 704,hint,park:704@parkedcallsexten => 705,hint,park:705@parkedcallsexten => 706,hint,park:706@parkedcallsexten => 707,hint,park:707@parkedcalls
576
exten => 708,hint,park:708@parkedcallsexten => 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(campus.voztovoice,${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,NoOpsame => n,Dial(SIP/1000)same => n,Hangup
[from-pstn]exten => s,1,Dial(SIP/1000,45)exten => s,n,Hangup
[internacio]exten => _00X.,1,NoOpsame => n,Set(CDR(userfield)=${CHANNEL(peerip)})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)=justvoip)same => n,Set(GROUP(salida)=${CALLERID(num)})same => n,Set(trunksal=${GROUP_COUNT(justvoip@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 Justvoip)same => n,Gotoif($[${extsal} > 2 | ${trunksal} > 2]?busy)same => n,Dial(SIP/justvoip/${EXTEN})same => n,Hangupsame => n(busy),Playback(all-outgoing-lines-unavailable)same => n,Hangup
exten => _1XXXXXXXXXX,1,Dial(gtalk/campus.voztovoice/+${EXTEN}@voice.google.com)same => n,Hangup
exten => _NNXX.,1,Dial(gtalk/campus.voztovoice/+${EXTEN}@voice.google.com)same => n,Hangup
577
[externas]include => internasinclude => internacioinclude => parkedcallsinclude => testinclude => conferenciasinclude => dundi-remoto
[locales]include => internasinclude => auteninclude => parkedcallsinclude => testinclude => conferenciasinclude => dundi-remoto
[macro-disponible]exten => s,1,Set(estado=${DEVICE_STATE(SIP/${MACRO_EXTEN})})exten => s,n,Gotoif($["${estado}" = "NOT_INUSE"]?5)exten => s,n,Busyexten => s,n,Hangupexten => s,n,MacroExit
[macro-calendario]exten => s,1,Noop(${MACRO_EXTEN})same => n,GotoIf($[${MACRO_EXTEN} = 1000]?calendario)same => n,MacroExitsame => n(calendario),Set(estado=${CALENDAR_BUSY(campusvoztovoice)})same => n,Noop(Estado = ${estado})same => n,Gotoif($[${estado} = 1]?ocupado)same => n,MacroExitsame => n(ocupado),Agi(googletts.agi,"la extensión se encuentra ocupada, llame mas tarde. Gracias",es)same => n,Hangup
[macro-voicemail]exten => s,1,Goto(s-${DIALSTATUS},1)exten => s-BUSY,1,Voicemail(${MACRO_EXTEN}@default,b)same => n,Hangupexten => s-CANCEL,1,Hangupexten => s-CONGESTION,1,Congestionsame => n,Hangupexten => _s-.,1,Voicemail(${MACRO_EXTEN}@default,u)same => n,Hangup
[macro-meetme]exten => s,1,MeetMeCount(${MACRO_EXTEN},count)
578
same => n,Gotoif($[${count} > ${confmax}]?llena)same => n,MeetMe(${MACRO_EXTEN},D)same => n,Hangupsame => n(llena),Playback(conf-invalid)same => n,Hangup
#include IVR
IVR
[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)exten => i,2,Goto(IVR,s,2)exten => i,3,Hangupexten => 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 => 2,1,MusicOnHoldexten => 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,hangupexten => 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)
579
exten => s,4,BackGround(custom/prompt02)exten => s,5,WaitExten()exten => 1,1,Playback(demo-echotest)exten => 1,2,Echo()exten => 2,1,MusicOnHoldexten => 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,hangupexten => t,1,goto(IVR2,s,1)exten => h,1,Hangup
580
Apéndice C
Licencia GNU FDL
GNU Free Documentation LicenseVersion 1.3, 3 November 2008
Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. <http://fsf.org/> 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 otherfunctional and useful document "free" in the sense of freedom: toassure 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 wayto get credit for their work, while not being considered responsiblefor modifications made by others.
This License is a kind of "copyleft", which means that derivativeworks of the document must themselves be free in the same sense. Itcomplements the GNU General Public License, which is a copyleftlicense designed for free software.
We have designed this License in order to use it for manuals for freesoftware, because free software needs free documentation: a freeprogram should come with manuals providing the same freedoms that thesoftware does. But this License is not limited to software manuals;it can be used for any textual work, regardless of subject matter orwhether it is published as a printed book. We recommend this Licenseprincipally for works whose purpose is instruction or reference.
1. APPLICABILITY AND DEFINITIONS
This License applies to any manual or other work, in any medium, thatcontains a notice placed by the copyright holder saying it can bedistributed under the terms of this License. Such a notice grants aworld-wide, royalty-free license, unlimited in duration, to use thatwork under the conditions stated herein. The "Document", below,refers to any such manual or work. Any member of the public is alicensee, and is addressed as "you". You accept the license if youcopy, modify or distribute the work in a way requiring permissionunder copyright law.
A "Modified Version" of the Document means any work containing theDocument or a portion of it, either copied verbatim, or withmodifications and/or translated into another language.
A "Secondary Section" is a named appendix or a front-matter section ofthe Document that deals exclusively with the relationship of thepublishers or authors of the Document to the Document's overall
subject (or to related matters) and contains nothing that could falldirectly within that overall subject. (Thus, if the Document is inpart a textbook of mathematics, a Secondary Section may not explainany mathematics.) The relationship could be a matter of historicalconnection with the subject or with related matters, or of legal,commercial, philosophical, ethical or political position regardingthem.
The "Invariant Sections" are certain Secondary Sections whose titlesare designated, as being those of Invariant Sections, in the noticethat says that the Document is released under this License. If asection does not fit the above definition of Secondary then it is notallowed to be designated as Invariant. The Document may contain zeroInvariant Sections. If the Document does not identify any InvariantSections 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 thatthe Document is released under this License. A Front-Cover Text maybe 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 thegeneral public, that is suitable for revising the documentstraightforwardly with generic text editors or (for images composed ofpixels) generic paint programs or (for drawings) some widely availabledrawing editor, and that is suitable for input to text formatters orfor automatic translation to a variety of formats suitable for inputto text formatters. A copy made in an otherwise Transparent fileformat whose markup, or absence of markup, has been arranged to thwartor discourage subsequent modification by readers is not Transparent.An image format is not Transparent if used for any substantial amountof text. A copy that is not "Transparent" is called "Opaque".
Examples of suitable formats for Transparent copies include plainASCII without markup, Texinfo input format, LaTeX input format, SGMLor XML using a publicly available DTD, and standard-conforming simpleHTML, PostScript or PDF designed for human modification. Examples oftransparent image formats include PNG, XCF and JPG. Opaque formatsinclude proprietary formats that can be read and edited only byproprietary word processors, SGML or XML for which the DTD and/orprocessing tools are not generally available, and themachine-generated HTML, PostScript or PDF produced by some wordprocessors 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 materialthis License requires to appear in the title page. For works informats which do not have any title page as such, "Title Page" meansthe 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 ofthe Document to the public.
A section "Entitled XYZ" means a named subunit of the Document whosetitle either is precisely XYZ or contains XYZ in parentheses following
583
text that translates XYZ in another language. (Here XYZ stands for aspecific 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 asection "Entitled XYZ" according to this definition.
The Document may include Warranty Disclaimers next to the notice whichstates that this License applies to the Document. These WarrantyDisclaimers are considered to be included by reference in thisLicense, but only as regards disclaiming warranties: any otherimplication that these Warranty Disclaimers may have is void and hasno effect on the meaning of this License.
2. VERBATIM COPYING
You may copy and distribute the Document in any medium, eithercommercially or noncommercially, provided that this License, thecopyright notices, and the license notice saying this License appliesto the Document are reproduced in all copies, and that you add noother conditions whatsoever to those of this License. You may not usetechnical measures to obstruct or control the reading or furthercopying of the copies you make or distribute. However, you may acceptcompensation in exchange for copies. If you distribute a large enoughnumber of copies you must also follow the conditions in section 3.
You may also lend copies, under the same conditions stated above, andyou may publicly display copies.
3. COPYING IN QUANTITY
If you publish printed copies (or copies in media that commonly haveprinted covers) of the Document, numbering more than 100, and theDocument's license notice requires Cover Texts, you must enclose thecopies in covers that carry, clearly and legibly, all these CoverTexts: Front-Cover Texts on the front cover, and Back-Cover Texts onthe back cover. Both covers must also clearly and legibly identifyyou as the publisher of these copies. The front cover must presentthe full title with all words of the title equally prominent andvisible. You may add other material on the covers in addition.Copying with changes limited to the covers, as long as they preservethe title of the Document and satisfy these conditions, can be treatedas verbatim copying in other respects.
If the required texts for either cover are too voluminous to fitlegibly, you should put the first ones listed (as many as fitreasonably) on the actual cover, and continue the rest onto adjacentpages.
If you publish or distribute Opaque copies of the Document numberingmore than 100, you must either include a machine-readable Transparentcopy along with each Opaque copy, or state in or with each Opaque copya computer-network location from which the general network-usingpublic has access to download using public-standard network protocolsa 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
584
that this Transparent copy will remain thus accessible at the statedlocation until at least one year after the last time you distribute anOpaque copy (directly or through your agents or retailers) of thatedition to the public.
It is requested, but not required, that you contact the authors of theDocument well before redistributing any large number of copies, togive them a chance to provide you with an updated version of theDocument.
4. MODIFICATIONS
You may copy and distribute a Modified Version of the Document underthe conditions of sections 2 and 3 above, provided that you releasethe Modified Version under precisely this License, with the ModifiedVersion filling the role of the Document, thus licensing distributionand modification of the Modified Version to whoever possesses a copyof 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
585
the substance and tone of each of the contributor acknowledgements and/or dedications given therein.L. 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.M. Delete any section Entitled "Endorsements". Such a section may not be included in the Modified Version.N. Do not retitle any existing section to be Entitled "Endorsements" or to conflict in title with any Invariant Section.O. Preserve any Warranty Disclaimers.
If the Modified Version includes new front-matter sections orappendices that qualify as Secondary Sections and contain no materialcopied from the Document, you may at your option designate some or allof these sections as invariant. To do this, add their titles to thelist 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 containsnothing but endorsements of your Modified Version by variousparties--for example, statements of peer review or that the text hasbeen approved by an organization as the authoritative definition of astandard.
You may add a passage of up to five words as a Front-Cover Text, and apassage of up to 25 words as a Back-Cover Text, to the end of the listof Cover Texts in the Modified Version. Only one passage ofFront-Cover Text and one of Back-Cover Text may be added by (orthrough arrangements made by) any one entity. If the Document alreadyincludes a cover text for the same cover, previously added by you orby 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 explicitpermission from the previous publisher that added the old one.
The author(s) and publisher(s) of the Document do not by this Licensegive permission to use their names for publicity for or to assert orimply endorsement of any Modified Version.
5. COMBINING DOCUMENTS
You may combine the Document with other documents released under thisLicense, under the terms defined in section 4 above for modifiedversions, provided that you include in the combination all of theInvariant Sections of all of the original documents, unmodified, andlist them all as Invariant Sections of your combined work in itslicense notice, and that you preserve all their Warranty Disclaimers.
The combined work need only contain one copy of this License, andmultiple identical Invariant Sections may be replaced with a singlecopy. If there are multiple Invariant Sections with the same name butdifferent contents, make the title of each such section unique byadding at the end of it, in parentheses, the name of the originalauthor or publisher of that section if known, or else a unique number.Make the same adjustment to the section titles in the list ofInvariant Sections in the license notice of the combined work.
586
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 sectionsEntitled "Endorsements".
6. COLLECTIONS OF DOCUMENTS
You may make a collection consisting of the Document and otherdocuments released under this License, and replace the individualcopies of this License in the various documents with a single copythat is included in the collection, provided that you follow the rulesof this License for verbatim copying of each of the documents in allother respects.
You may extract a single document from such a collection, anddistribute it individually under this License, provided you insert acopy of this License into the extracted document, and follow thisLicense in all other respects regarding verbatim copying of thatdocument.
7. AGGREGATION WITH INDEPENDENT WORKS
A compilation of the Document or its derivatives with other separateand independent documents or works, in or on a volume of a storage ordistribution medium, is called an "aggregate" if the copyrightresulting from the compilation is not used to limit the legal rightsof the compilation's users beyond what the individual works permit.When the Document is included in an aggregate, this License does notapply to the other works in the aggregate which are not themselvesderivative works of the Document.
If the Cover Text requirement of section 3 is applicable to thesecopies of the Document, then if the Document is less than one half ofthe entire aggregate, the Document's Cover Texts may be placed oncovers that bracket the Document within the aggregate, or theelectronic equivalent of covers if the Document is in electronic form.Otherwise they must appear on printed covers that bracket the wholeaggregate.
8. TRANSLATION
Translation is considered a kind of modification, so you maydistribute translations of the Document under the terms of section 4.Replacing Invariant Sections with translations requires specialpermission from their copyright holders, but you may includetranslations of some or all Invariant Sections in addition to theoriginal versions of these Invariant Sections. You may include atranslation of this License, and all the license notices in theDocument, and any Warranty Disclaimers, provided that you also includethe original English version of this License and the original versionsof those notices and disclaimers. In case of a disagreement betweenthe translation and the original version of this License or a noticeor disclaimer, the original version will prevail.
587
If a section in the Document is Entitled "Acknowledgements","Dedications", or "History", the requirement (section 4) to Preserveits Title (section 1) will typically require changing the actualtitle.
9. TERMINATION
You may not copy, modify, sublicense, or distribute the Documentexcept as expressly provided under this License. Any attemptotherwise to copy, modify, sublicense, or distribute it is void, andwill automatically terminate your rights under this License.
However, if you cease all violation of this License, then your licensefrom a particular copyright holder is reinstated (a) provisionally,unless and until the copyright holder explicitly and finallyterminates your license, and (b) permanently, if the copyright holderfails to notify you of the violation by some reasonable means prior to60 days after the cessation.
Moreover, your license from a particular copyright holder isreinstated permanently if the copyright holder notifies you of theviolation by some reasonable means, this is the first time you havereceived notice of violation of this License (for any work) from thatcopyright holder, and you cure the violation prior to 30 days afteryour receipt of the notice.
Termination of your rights under this section does not terminate thelicenses of parties who have received copies or rights from you underthis License. If your rights have been terminated and not permanentlyreinstated, receipt of a copy of some or all of the same material doesnot give you any rights to use it.
10. FUTURE REVISIONS OF THIS LICENSE
The Free Software Foundation may publish new, revised versions of theGNU Free Documentation License from time to time. Such new versionswill be similar in spirit to the present version, but may differ indetail to address new problems or concerns. Seehttp://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 thisLicense "or any later version" applies to it, you have the option offollowing the terms and conditions either of that specified version orof any later version that has been published (not as a draft) by theFree Software Foundation. If the Document does not specify a versionnumber of this License, you may choose any version ever published (notas a draft) by the Free Software Foundation. If the Documentspecifies that a proxy can decide which future versions of thisLicense can be used, that proxy's public statement of acceptance of aversion permanently authorizes you to choose that version for theDocument.
11. RELICENSING
588
"Massive Multiauthor Collaboration Site" (or "MMC Site") means anyWorld Wide Web server that publishes copyrightable works and alsoprovides prominent facilities for anybody to edit those works. Apublic wiki that anybody can edit is an example of such a server. A"Massive Multiauthor Collaboration" (or "MMC") contained in the sitemeans 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 siteunder 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 ofthe License in the document and put the following copyright andlicense 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 othercombination of the three, merge those two alternatives to suit thesituation.
If your document contains nontrivial examples of program code, werecommend releasing these examples in parallel under your choice offree software license, such as the GNU General Public License,to permit their use in free software.
589