Download Libro A2BSIP - version 1.0.pdf...
A2BSIP v. 1.0 A2Billing 2.1.0 OpenSIPs 1.11.4 CentOS 6.6 64bit Asterisk 11.17.0 Abril 2015
By
VozToVoice
www.voztovoice.org
Convenciones tipográficas. Negrita = comandos escritos 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 se está trabajando en la consola de Asterisk mysql> indica que se está trabajando en la consola del cliente MySQL redis 127.0.0.1:6379> indica que se está trabajando en la consola del cliente Redis
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 A de este libro.
Copyright (C)
2014-2018
Andrea Sannucci
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
INDICE Capitulo I – VPS Linode ….........................................................................................................
1
1.1 Preparación del VPS 1.1.1 Servidor Linux CentOS 6.6 Local 1.2 SSH y Clave RSA 1.2.1 Clave RSA en Windows 1.2.2 Clave RSA en Linux 1.2.3 Configuración servidor SSH 1.3 Configuración del VPS
1 7 10 10 14 15 17
Capitulo II - Instalación de Asterisk …...................................................................................... 23 2.1 Utilidades, librerías, dependencias 2.2 DAHDI 2.3 LibPRI 2.4 App_fax, GoogleTalk, LibiCAL y SRTP 2.5 Instalación de Asterisk
23 26 27 28 31
Capitulo III – Instalación de A2Billing ….................................................................................. 39 3.1 Preparación del sistema 3.2 Instalación del demonio Callback 3.3 Configuración de Asterisk 3.3.1 sip.conf 3.3.2 extensions.conf 3.3.3 Asterisk Realtime 3.4 Configuración del Firewall 3.5 Primer acceso
39 46 48 48 51 52 55 59
Capitulo IV – Configuración Base A2Billing............................................................................... 64 4.1 System Settings 4.2 Configuración de los Proveedores 4.3 Creación de los planes de llamadas y de las tarifas 4.4 Configuración de los métodos de pago 4.5 Configuración para la facturas 4.6 Plantillas de los correos electrónicos 4.7 Creación de un cliente 4.8 Registro de un nuevo cliente desde la pagina Web i
65 96 101 109 111 113 114 129
4.9 Creación de una cuenta POSTPAGO 4.10 Crear Revendedores
134 136
Capitulo V - Configuración Avanzada A2Billing …...............................................................
144
5.1 Distintos CallPlan 5.2 El sistema de soporte 5.3 Paquetes de llamadas 5.4 El Parámetro LCR Mode 5.5 El sistema de facturación 5.6 Subscription services 5.7 Account Service
144 153 156 162 165 168 171
Capitulo VI – Integración de A2Billing con OpenSIPs …..................................................... 6.1 Instalación de OpenSIPs 6.2 Configuración de OpenSIPs 6.2.1 Bloque Globales 6.2.2 Bloque Módulos 6.2.3 Parámetros Globales 6.2.4 Tipos de rutas 6.2.5 Operadores 6.2.6 Declaraciones 6.2.7 Funciones 6.2.8 Variables 6.2.9 Script Flags 6.2.10 Transformaciones 6.3 OpenSIPs como Load Balancer 6.4 OpenSIPs como Registrar 6.4.1 Módulos 6.4.2 Creación de la vista de la tabla cc_sip_buddies 6.5 OpenSIPs y llamadas entre extensiones 6.6 RTPProxy 6.7 OpenSIPs presencia y Mensajes Instantáneos 6.7.1 Presencia 6.7.2 Mensajes Instantáneos (MI) 6.8 OpenSIPs Autenticación sobre IP 6.9 Números Geográficos 6.9.1 Integración DIDs entre A2Billing y OpenSIPs 6.10 A2Billing como sistema de tarjetas telefónicas
177 177 186 186 188 189 190 191 193 195 197 198 199 199 218 219 225 231 258 265 265 271 279 288 288 297
6.11 CallBack (Rellamada) 6.11.1 Rellamada desde la pagina del cliente 6.11.2 Rellamada con numero de acceso 6.12 Añadir extensiones a un cliente 6.13 Conteo de canales
309 311 313 315 318
ii
Capitulo VII – Seguridad del servidor ….................................................................................. 328 7.1 Poner en seguridad el servidor Web 7.2 Seguridad en OpenSIPs 7.2.1 Fail2ban 7.2.2 Bloquear IP por países 7.2.3 SIP OPTIONS
328 332 332 336 340
Capitulo VIII – Monitoreo del sistema …................................................................................... 344 8.1 Monitoreo desde A2Billing 8.1.1 Monitoreo calidad llamadas 8.1.2 Monitoreo con script y un sistema de TTS 8.2 Monitoreo con Nagios y SNMP 8.2.1 Asterisk y SNMP 8.2.2 Nagios 8.2.3 NDOutils 8.2.4 PNP4NAGIOS 8.3 Monitoreo OpenSIPs 8.4 Monitoreo calidad de las llamadas con pre-dial handlers y hangup-handlers 8.5 Monitoreo calidad de las llamadas con VoIPMonitor 8.6 CDR-STATS
344 344 347 354 354 356 369 371 377 384 390 392
Capitulo IX – Trucos y consejos …..........................................................................................
401
9.1 Cambiar la moneda predefinida 9.2 Rellamada sin cobrar en ningún caso la primera llamada 9.3 Nginx en lugar de Apache 9.4 Guardar la IP del llamante en el CDR 9.5 Cambiar el numero de las tarjetas 9.6 Añadir nuevas troncales desde la pagina de administración de A2Billing 9.7 Modificar el tamaño del campo destination en los reportes de las llamadas 9.8 Campo destination en la tabla cc_call 9.9 Registros de Asterisk 9.10 Cambio nombre pestaña Navegador 9.11 Aumentar el numero de decimales en los reportes de llamadas 9.12 Actualizar A2Billing a una nueva versión
401 402 405 410 411 412 414 415 416 418 418 419
Capitulo IX – Resolución de problemas …................................................................................. 424 10.1 Pagina Web en blanco iii
424
10.2 Recuperar password administrador A2Billing 10.3 Tarificación errada de las llamadas
425 425
Apéndice A – Archivo de configuración de OpenSIPS
428
Apéndice B – Arquitectura de cuatro servidores B.1 Servidor Web B.1.1 Servidor Web Cortafuegos B.2 Servidor OpenSIPs B.2.1 Servidor OpenSIPs Cortafuegos B.3 Replicación Maestro-Maestro A2Billing B.3.1 Servidor Web B.3.2 Servidor OpenSIPs B.3.3 Tabla subscriber_v1 B.4 Servidores Asterisk1 y Asterisk2 B.4.1 Asterisk PBX B.4.2 Asterisk Realtime B.4.3 Asterisk Cortafuegos
440 442 449 451 467 470 470 472 478 480 480 488 492
Apéndice C – GNU Free Documentation License
496
Apéndice D – POODLE y el protocolo SSLv3
506
iv
Capitulo I VPS Linode La parte que se presenta a seguir es valida solamente para un VPS Linode. Para una instalación en un servidor local o un servidor remoto dedicado (no virtualizado), véase el párrafo 1.1.1. 1.1 Preparación del VPS Los VPS de Linode, utilizan como sistema de virtualización Xen y vienen con un Kernel personalizado. Para poder trabajar con el ultimo Kernel disponible de la versión de CentOS instalada, se modificará la configuración del servidor instalando el sistema de arranque GRUB y luego iniciando el servidor con la opción pv-grub. De esta forma el servidor se iniciará con el Kernel configurado en el archivo menu.lst que habrá que crear. Al momento de adquirir el servidor Linode, se selecciona el tipo de VPS, el centro de datos donde se quiere instalar (en este caso Dallas) y se presiona el botón “Add this Linode”:
El nuevo VPS estará disponible:
Se selecciona el enlace indicado en la imagen y en la nueva ventana el enlace “Deploy an Image”:
En la nueva ventana se selecciona el Sistema operativo (CentOS 6.5 64bit), se configura la memoria de Swap en 512Mb y se configura la contraseña del usuario root que se utilizará sucesivamente para acceder al VPS desde remoto:
Terminada la configuración se presiona el botón “Deploy”. Empezará el proceso de instalación y configuración del sistema operativo. Una vez que termine, 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 64 bit (3.19.1-x86_64linode53). De esta versión no hay las fuentes disponibles y eso imposibilita la instalación de DAHDI y, en general, de todos los programas que se instalan como módulos del Kernel. Por eso en los próximos 2
párrafos se verá como instalar en el servidor Linode, la ultima versión disponible del Kernel Linux y el sistema de arranque GRUB. Una vez que el servidor esté corriendo, como indicado en la imagen que sigue, que aparece en el lado derecho de la pagina de administración de Linode, se puede acceder al servidor con el programa PuTTy (un cliente SSH):
Para conocer la dirección IP del servidor Linode, se entra en la siguiente pagina, donde aparecen todos los datos de configuración de red del servidor:
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:
3
En “Host Name (or IP address) se pone la dirección IP publica 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” se pone 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 en lugar de Windows, se abre una ventana terminal y para conectarse al servidor remoto se ejecuta el siguiente comando: ssh root@IPservidor El resultado será:
La primera cosa que hay que hacer es actualizar el sistema: yum update -y Se instalan los repositorios de Fedora que se utilizarán más adelante para instalar algunos paquetes que no vienen con los repositorios estándar de CentOS: rpm -Uvh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm Se desactivan los nuevos repositorios para activarlos solamente cuando se necesiten: nano /etc/yum.repos.d/epel.repo
4
En el primer bloque del archivo se modifica el parámetro: enabled=1 para que quede: enable=0 Se guardan los cambios. Se instala la ultima versión disponible del Kernel y el sistema de arranque GRUB: yum install kernel grub -y Se averigua la versión del Kernel que se ha instalado: rpm -q kernel kernel-2.6.32-504.12.2.el6.x86_64 y con esos datos se configura GRUB: nano /boot/grub/grub.conf Se copian las lineas que siguen: #boot=/dev/xvda default=0 timeout=5 title CentOS (2.6.32-504.12.2.el6.x86_64) root (hd0) kernel /boot/vmlinuz-2.6.32-504.12.2.el6.x86_64 root=/dev/xvda initrd /boot/initramfs-2.6.32-504.12.2.el6.x86_64.img Se guardan las modificaciones y se crea un enlace simbólico del archivo que se acaba de crear: ln -s /boot/grub/grub.conf /boot/grub/menu.lst IMPORTANTE: como la versión del Kernel puede cambiar en el tiempo, hay que modificar el archivo grub.conf, con los datos de la versión realmente instalada. 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:
5
En la nueva pagina se modifican los parámetros como indicado en las dos siguientes imágenes:
En Boot Settings – Kernel se selecciona “pv-grub-x86_64”
En Filesystem/Boot Helpers se modifican las dos opciones indicadas en la imagen. Para terminar se guardan los cambios presionando el botón “Save Changes”. Se regresará a la pagina principal del servidor Linode y de ahí se reinicia:
Para averiguar que efectivamente el sistema arranca utilizando el Kernel Linux instalado y el gestor de arranque GRUB, en la pagina de Linode se entra en el menú “Remote access” y luego se sigue el enlace “Launch Lish Ajax Console” que permite acceder al servidor desde una consola local. Se abrirá una nueva ventana y después de unos segundos aparecerá esta imagen:
6
1.1.1 Servidor Linux CentOS 6.6 Local En el caso de un servidor Linux local, la instalación se realiza desde cero partiendo de un CD de instalación que contenga el sistema operativo CentOS 6.6 64bit. La imagen se puede descargar desde esta pagina. Al momento de escoger el tipo de instalación, se selecciona “minimal”. A lo largo de la instalación se configurará el idioma, el país del teclado, la zona horaria, la contraseña de root, etc. Una vez terminada la configuración se reiniciará el servidor y se podrá acceder con el mismo programa (PuTTY) indicado en el párrafo anterior. Normalmente cuando CentOS se instala en local, el cortafuegos viene configurado por defecto y arranca con una configuración básica. Si se quiere, se puede mover la configuración predefinida: mv /etc/sysconfig/iptables /etc/sysconfig/iptables.old y reiniciar iptables: service iptables restart Otra opción es desactivar el cortafuegos y utilizar el router para definir los puertos que se querrá dejar abiertos. Otra operación que hay que ejecutar es desactivar Selinux. Primero se instala el editor NANO: yum install nano -y luego se abre el archivo de configuración de Selinux: nano /etc/selinux/config Modificar las dos opciones presentes de forma que el archivo quede de la siguiente manera:
7
SELINUX=disabled SELINUXTYPE=targeted Se guardan los cambios y se actualiza el sistema: yum update -y Si se quiere configurar el servidor con una IP estática se instala la relativa utilidad: yum install system-config-network-tui y se ejecuta: system-config-network En la ventana que aparece se escoge “device configuration”:
Se selecciona la tarjeta de red instalada en el servidor:
Se configura la IP estática:
8
Static IP: dirección IP que se quiere asignar al servidor (tiene que estar dentro del rango configurado en el router) Netmask: normalmente el valor es 255.255.255.0 Default Gateway IP: dirección IP del router Primary DNS Server: dirección IP del router Secondary DNS Server: se puede dejar en blanco Se presiona el botón Ok y se vuelve a la pagina anterior donde se escoge el botón Save y en la pagina principal se escoge DNS configuration:
En la pagina que sigue se escoge un nombre de dominio y se configura nuevamente el DNS primario:
9
Se presiona el botón OK y en la pagina que sigue el botón Save&Quit. De esta forma se sale de la aplicación. Se reinicia el servidor: reboot 1.2 SSH y clave RSA RSA es un sistema criptográfico de clave publica che permite la configuración de conexiones seguras. Como en todo sistema de clave pública, cada usuario posee dos claves de cifrado: una pública y otra privada. Cuando se quiere enviar un mensaje, el emisor busca la clave pública del receptor, cifra su mensaje con esa clave, y una vez que el mensaje cifrado llega al receptor, este se ocupa de descifrarlo usando su clave privada. 1.2.1 Clave RSA en Windows Para crear la clave RSA se descarga el programa PuTTygen: http://the.earth.li/~sgtatham/putty/latest/x86/puttygen.exe Se ejecuta:
En “Number of bits in a generated key” se pone 2048 y luego se presiona el botón “Generate”. Para la 10
creación de la clave se necesita generar una serie aleatoria de números y esto se realiza moviendo el ratón en el cuadro que aparece bajo la linea “Key”:
Hay que seguir moviendo el ratón hasta que la barra que aparece no llegue al final de la linea. Terminada la operación se tendrá disponible la clave RSA (publica y privada):
11
IMPORTANTE: para aumentar la seguridad de la clave privada, se puede asociar una contraseña. La contraseña se escribe en la casilla “Key passphrase” y se repite en “Confirm passphrase”. Se guarda la clave privada en una carpeta del ordenador local presionando el botón “Save private key”(en este caso se nombra claveprivada):
Para continuar se selecciona todo el texto que aparece en la imagen que sigue, se presiona el botón derecho del ratón y se escoge en el menú “copiar”:
12
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:
13
Se guarda el archivo presionado la tecla CTRL junto a la tecla X. Se asigna al archivo recién creado los permisos de lectura y escritura solamente para el usuario root: chmod 600 /root/.ssh/authorized_keys Ya se puede continuar con la configuración del servidor SSH (párrafo 1.2.3). 1.2.2 Clave RSA en Linux Se accede al servidor Linux LOCAL como usuario root y e la ventana terminal se escribe: cd /root mkdir .ssh se permite el acceso a la carpeta creada solamente al usuario root: chmod 700 .ssh se entra en la carpeta: cd .ssh Se crea la clave RSA ssh-keygen -t rsa Enter file in which to save the key (/root/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /root/.ssh/id_rsa. Your public key has been saved in /root/.ssh/id_rsa.pub. The key fingerprint is: 2e:86:eb:d0:8e:2d:49:1f:0e:83:a8:b2:45:e7:2b:26 root@li215-240 The key's randomart image is: +--[ RSA 2048]----+ |... . S | |o.++.. . | |..o*+.o . | |E.==o+ . | |o+.+* | 14
+-----------------+ [root@li215-240 .ssh]# ls -l total 8 -rw------- 1 root root 1675 Mar 11 20:06 id_rsa -rw-r--r-- 1 root root 396 Mar 11 20:06 id_rsa.pub Cuando el sistema lo solicita (lineas en negrita), se puede configurar la clave con una contraseña. Se crearán dos archivos: • •
id_rsa que contiene la clave privada id_rsa.pub que contiene la clave publica
El segundo archivo se copia en el servidor Linode remoto: scp id_rsa.pub root@IPservidorremoto:/tmp Con este comando se copia la clave publica en la carpeta /tmp del servidor remoto. Luego se añade la clave al archivo authorized_keys en la carpeta /root/.ssh cat /tmp/id_rsa.pub >> /root/.ssh/authorized_keys Se borra la clave publica: rm /tmp/id_rsa.pub y se cambian los permisos del archivo authorized_keys: chmod 600 /root/.ssh/authorized_keys 1.2.3 Configuración servidor SSH Terminada la operación de creación y configuración de las claves RSA, hay que modificar algunos parámetros del servidor SSH para permitir el acceso al VPS solamente al usuario root si se autentica con la clave RSA; además, para aumentar la seguridad, se cambia el puerto predefinido para el acceso SSH (22 TCP), escogiendo otro (15000 TCP). Esto se realiza modificando el archivo de configuración del servidor SSH: nano /etc/ssh/sshd_config Se buscan estas lineas (para buscar un texto con el editor NANO hay que presionar la tecla CTRL junto a la tecla W): #Port 22 #RSAAuthentication yes PasswordAuthentication yes 15
y se modifican para que queden: Port 15000 RSAAuthentication yes PasswordAuthentication no Se guardan los cambios y se reinicia el servidor SSH: /etc/init.d/sshd restart Se abre otra instancia del cliente SSH:
Se pone la IP del servidor Linode, come puerto el 15000 y se asigna un nuevo nombre a esta nueva conexión.
16
En la barra 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 utilizará la sesión Linode2, botón “Load” y luego botón “Open”. Debe aparecer esta ventana:
Una vez que se haya escrito el nombre de usuario root en “login as:”, automáticamente el cliente se conectará al servidor autenticándose con la clave RSA creada. 1.3 Configuración del VPS Para iniciar la configuración del VPS, se modifica la hora predefinida del servidor: rm /etc/localtime rm: remove regular file `/etc/localtime'? Y 17
Se crea un enlace simbólico a la hora de Colombia (personalizar según su país): ln -s /usr/share/zoneinfo/America/Bogota /etc/localtime se averigua que la hora esté correctamente configurada con el comando: date Mon Oct 6 10:50:52 COT 2014 Para que la hora se actualice de manera automática se instala el servidor NTP (Network Time Protocol): yum install ntp -y Se configura para que se inicie automáticamente al arrancar el servidor Linux: chkconfig ntpd on y se inicia: service ntpd start Starting ntpd:
[ OK ]
Para modificar el idioma predefinido (ingles) y ponerlo en español (de Colombia): nano /etc/sysconfig/i18n se modifica esta linea: LANG="en_US.UTF-8" para que quede: LANG="es_CO.iso88591" Para ver la lista de idiomas disponibles y de esta forma personalizar la configuración, el comando es: locale -a Para activar el nuevo idioma basta salir y volver a entrar al servidor con PuTTy. Como la IP publica en Linode se asigna a través de un servidor DHCP y esto puede causar problemas si hay modificaciones de la configuración del servidor por parte de Linode, es buena practica configurar la IP publica de forma estática. Para realizar este cambio, se modifica el siguiente archivo: nano /etc/sysconfig/network-scripts/ifcfg-eth0
18
Se comenta el contenido previo y se añaden las siguiente lineas de forma que el archivo quede: #DEVICE="eth0" #BOOTPROTO="dhcp" #IPV6INIT="yes" #IPV6_AUTOCONF="yes" #ONBOOT="yes" #TYPE="Ethernet" DEVICE=eth0 BOOTPROTO=none IPV6INIT="no" IPV6_AUTOCONF="no" ONBOOT=yes IPADDR=45.56.76.75 NETMASK=255.255.255.0 GATEWAY=45.56.76.1 45.56.76.75 es la IP publica del servidor Linode (personalizar). Se guardan los cambios. En el servidor Linode es posible crear una IP privada que se puede utilizar para intercambiar datos y conexiones entre distintos VPS Linode presentes en el mismo centro de datos. Esto puede ser muy útil, por ejemplo, cuando se quiera compartir un servidor MySQL entre dos servidores y/o cuando algunos servicios se configuran en un servidor y los demás servidores acceden utilizando la IP privada. Hay que tener en cuenta que todo el trafico que pase por la IP privada no viene contabilizado en el consumo mensual de banda. En este caso la IP Privada se utilizará también para enviar la señalización SIP desde OpenSIPs hacia Asterisk cuando se necesite. Para configurar la IP privada se entra nuevamente en el menú “Remote Access” y se crea:
Aparecerá:
Con esos datos se configura una tarjeta de red virtual de la siguiente manera: nano /etc/sysconfig/network-scripts/ifcfg-eth0:1 19
Se pegan las siguientes lineas: DEVICE=eth0:1 BOOTPROTO=none ONBOOT=yes IPADDR=192.168.160.142 NETMASK=255.255.128.0 Personalizar la linea IPADDR con la IP privada asignada por Linode. Se guardan los cambios. Se continua configurando el subdominio asociado al Linode. Este dato aparece siempre en el menú “Remote Access”:
Se abre este archivo: nano /etc/sysconfig/network y se modifica esta linea: HOSTNAME=localhost.localdomain para que quede: HOSTNAME=li926-75.members.linode.com Personalizar con el dominio asignado por Linode. Para terminar se configuran algunos parámetros y alias para los comandos que más se utilizarán a lo largo del libro: nano .bash_profile al final del archivo se pegan las lineas que siguen: export EDITOR=/usr/bin/nano export PS1='\[\033[0;35m\]\H\[\033[0;33m\] \w\[\033[00m\]: ' alias free="free -m" alias aste="asterisk -rvvvvvvvvvvvvvvvvvv" alias sip="nano /etc/asterisk/sip.conf" alias ext="nano /etc/asterisk/extensions.conf" alias oscfg="nano /etc/opensips/opensips.cfg" alias oslog="nano /var/log/opensips.log" alias ostail="tail -500f /var/log/opensips.log" alias load="opensipsctl fifo lb_list"
20
Se recarga la configuración de la consola Linux: source .bash_profile Ya se puede reiniciar el servidor remoto: reboot
21
CAPITULO II Instalación de Asterisk En este libro no se abordarán todas las configuraciones de Asterisk por motivos de espacio y porque las funcionalidades que se utilizarán para la instalación y configuración de A2Billing son mínimas. Para aquellos que quieran profundizar el tema, aconsejo el libro dedicado a Asterisk 11.X presente en el sitio web de VozToVoice. 2.1 Utilidades, librerías, dependencias Antes de la compilación e instalación de Asterisk, se instalarán una serie de librerías y dependencias que permitirán obtener una instalación de casi todos los módulos disponibles en la PBX. Se empieza con VORBIS que es una librería para la compresión/descompresión audio: yum install libvorbis libvorbis-devel vorbis-tools libogg libogg-devel -y Para el formato audio GSM se instalan los relativos paquetes: yum install gsm gsm-devel gsm-tools -y se sigue con CURL que es un cliente que permite recibir o enviar archivos utilizando los protocolos HTTP, HTTPS, FTP, GOPHER, DICT, TELNET: yum install curl curl-devel libidn-devel -y se instalan todas las librerías y dependencias que se necesitan para compilar las fuentes: yum install gcc ncurses-devel make gcc-c++ compat-libtermcap zlib-devel libtool bison \ bison-devel openssl-devel bzip2-devel wget newt-devel subversion flex gtk2-devel -y a seguir para crear y gestionar las bases de datos, MySQL: yum install mysql mysql-server mysql-devel -y Si en lugar de MySQL se quiere utilizar POSTGRESQL: yum install postgresql postgresql-devel postgresql-docs postgresql-libs postgresql-odbc postgresql-server -y
Como la base de datos interna de Asterisk desde la versión 11.X se basa en SQLite, se instala el paquete del programa y el paquete de desarrollo:
yum install sqlite sqlite-devel -y UNIXODBC que es la implementación Linux de los API ODBC que permiten conectarse a muchos sistemas de gestión de base de datos (ej: MySQL): yum install unixODBC unixODBC-devel mysql-connector-odbc libtool-ltdl-devel -y Se instala FESTIVAL, que es un sistema de text to speech (disponible con las voces en español): yum install festival festival-devel hispavoces-pal-diphone hispavoces-sfl-diphone -y Para las librerías de pjproject incluidas en Asterisk 11.X, se instala libuuid: yum install libuuid libuuid-devel uuid uuid-devel -y Se continua con la instalación de otros formatos audio: SPEEX y WAW: yum install speex speex-devel wavpack wavpack-devel -y Una vez terminada esta parte se empieza a instalar una serie de programas desde las fuentes. IMPORTANTE: Para todos los programas que se instalan desde las fuentes, antes de descargarlos, averiguar si hay una versión más reciente disponible. El primero es 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 Se descomprime: tar -xf lame-3.99.5.tar.gz Se entra en la carpeta creada: cd lame-3.99.5 Se inicia la compilación: ./configure --prefix=/usr --libdir=/usr/lib64 La mayoría de los programas que se compilan desde las fuentes se instalan por defecto en la carpeta /usr/local. Es por eso que en la linea del configure se especifica que la carpeta donde se quiere que se instalen es la /usr. Lo mismo pasa con las librerías del programa. Como el sistema es 64bit se especifica 24
la carpeta donde se quiere que se instalen las librerías make el comando make compila las fuentes creando todos los archivos ejecutables y librerías que luego se instalarán con el comando que sigue: make install con make install se instala el programa y las librerías compiladas. Se continua con LIBMAD que es un MPEG audio decodificador de alta calidad: cd /usr/src wget http://prdownloads.sourceforge.net/mad/libmad-0.15.1b.tar.gz tar -xf libmad-0.15.1b.tar.gz cd libmad-0.15.1b ./configure --prefix=/usr --libdir=/usr/lib64 Para que la compilación tenga éxito hay que modificar una linea del Makefile: nano +129 Makefile CFLAGS = -Wall -g -O -fforce-mem -fforce-addr -fthread-jumps -fcse-follow-jumps -fcse-skipblocks -fexpensive-optimizations -fregmove -fschedule-insns2 para que quede: CFLAGS = -Wall -g -O -fforce-addr -fthread-jumps -fcse-follow-jumps -fcse-skip-blocks -fexpensive-optimizations -fregmove -fschedule-insns2 se continua con la compilación e instalación: make make install Se termina esta primera parte con SOX que es un programa que permite la manipulación de archivos audio y la posibilidad de transformarlos de un formato a otro: cd /usr/src wget http://downloads.sourceforge.net/project/sox/sox/14.4.1/sox-14.4.1.tar.gz 25
tar -xf sox-14.4.1.tar.gz cd sox-14.4.1 ./configure --prefix=/usr --libdir=/usr/lib64 Al finalizar el configure aparecerá esta tabla donde se encontrarán todos los formatos audio que se podrán manipular con SOX:
Se termina con la compilación e instalación: make make install 2.2 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). Aunque su instalación ya no es indispensable ya que para las conferencias audio existe la aplicación ConfBridge que es mucho más completa, se instalará para tener todos los módulos disponibles. Se instala el paquete de desarrollo del Kernel: yum install kernel-devel -y Se continua con la ultima versión disponible de DAHDI-Linux:
26
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.10.0.1 make make install Se termina con la ultima versión disponible de DAHDI-Tools: cd /usr/src wget http://downloads.asterisk.org/pub/telephony/dahdi-tools/dahdi-tools-current.tar.gz tar -xf dahdi-tools-current.tar.gz cd dahdi-tools-2.10.0.1 ./configure make make install make config Como no se van a instalar tarjetas (en el caso del servidor remoto), se pueden comentar todo los controladores que aparecen el el archivo /etc/dahdi/modules. Luego se puede iniciar DAHDI: /etc/init.d/dahdi start Loading DAHDI hardware modules: Running dahdi_cfg:
[ OK ]
No hardware timing source found in /proc/dahdi, loading dahdi_dummy Running dahdi_cfg: [ OK ] 2.3 LIBPRI En el caso que se quiera instalar tarjetas digitales en el servidor Asterisk (E1, T1, ISDN), después de instalar DAHDI, hay que instalar la librería libpri: cd /usr/src wget http://downloads.asterisk.org/pub/telephony/libpri/libpri-1.4.15.tar.gz
27
se descomprime: tar -xf libpri-1.4.15.tar.gz se entra en la carpeta: cd libpri-1.4.15 se compila y se instala: make make install 2.4 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, IKSEMEL que permite implementar el protocolo XMPP en Asterisk y de esta forma conectarse a GoogleTalk y/o a cualquier servidor con protocolo XMPP (otro ejemplo es Openfire), LibiCAL que permite conectar Asterisk a los calendarios que utilizan el protocolo iCAL y libSRTP que permite cifrar el flujo media de las llamadas. Para SpanDSP se necesita instalar primero las librerías libtiff: yum install libtiff libtiff-devel libxml2 libxml2-devel -y se continua con SpanDSP desde los repositorios EPEL: yum --enablerepo=epel install spandsp spandsp-apidoc spandsp-devel -y El protocolo XMPP permite conexione seguras entre cliente y servidor utilizando el protocolo TLS; para ese efecto se instala, antes de IKSEMEL las relativas librerías: yum install gnutls gnutls-devel gnutls-utils -y se continua con IKSEMEL (desde los repositorios EPEL): yum --enablerepo=epel install iksemel iksemel-devel iksemel-utils -y Se continua con la preparación del sistema con unos programas más. Primero un servidor de correo electrónico, SENDMAIL: yum install sendmail sendmail-devel sendmail-cf -y
28
Se remueve el servidor de correo electrónico predefinido POSTFIX: service postfix stop yum remove postfix -y Se configura para que arranque en automático: chkconfig sendmail on El subdominio configurado en el párrafo 1.3, 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. Si se necesita que sea alcanzable desde remoto (para recibir correos electrónicos) hay que abrir el archivo de configuración de Sendmail: nano /etc/mail/sendmail.mc buscar esta linea (para buscar un texto con el editor Nano hay que presionar la combinación de teclas CTRL-W): DAEMON_OPTIONS(`Port=smtp,Addr=127.0.0.1, Name=MTA')dnl y modificar como sigue: DAEMON_OPTIONS(`Port=smtp,, Name=MTA')dnl se guardan los cambios y se vuelve a compilar la configuración de Sendmail: make -C /etc/mail se inicia el servidor de correo: /etc/init.d/sendmail start OpenLDAP es la versión open source del protocolo Lightweight Directory Access. Normalmente se utiliza para crear un directorio de usuarios que puede ser consultado y/o modificado desde remoto. Muchos programas implementan la posibilidad de conectarse a un servidor OpenLDAP y Asterisk, desde la versión 1.6.X, presenta esta posibilidad: yum install compat-openldap openldap openldap-clients openldap-devel openldap-servers -y SNMP es el Protocolo Simple de Administración de Red y sirve para controlar y monitorear el 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 -y 29
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: yum --enablerepo=epel install radiusclient-ng radiusclient-ng-devel radiusclient-ng-utils -y 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. yum install lua lua-devel -y Para terminar se compilan los paquetes que permiten utilizar las nuevas funcionalidades de Asterisk. Primero LIBICAL que permite la implementación del protocolo iCalendar (RFC5546) en Asterisk a través del modulo res_calendar: yum install libical libical-devel -y Luego NEON que es una librería que permite la implementación del protocolo WebDAV en Asterisk: yum install neon neon-devel -y Por ultimo la librería libSRTP que permite implementar en Asterisk el cifrado del flujo media a través del protocolo SRTP (RFC3711). Para descargarlas se utilizará el programa GIT: yum install git words -y Luego se descargan las fuentes: cd /usr/src git clone https://github.com/cisco/libsrtp libsrtp Se entra en la carpeta creada: cd libsrtp Se compila e instala: ./configure --prefix=/usr CFLAGS=-fPIC --libdir=/usr/lib64 make make runtest make install
30
2.5 Instalación de Asterisk Terminada la preparación del servidor, se inicia con la instalación de Asterisk. Se descarga la ultima versión 11.X disponible: cd /usr/src wget http://downloads.asterisk.org/pub/telephony/asterisk/asterisk-11.17.0.tar.gz tar -xf asterisk-11.17.0.tar.gz cd asterisk-11.17.0 ./configure --libdir=/usr/lib64 make 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:
Desde la versión 11.X, la aplicación MeetMe (conferencias audio) está desactivada. Asegurarse seleccionarla para que el modulo sea compilado (menú izquierdo Applications):
El menú “Channel Event Logging” que como se verá más adelante, permite complementar el CDR (call detail record) con nuevas informaciones relacionadas con las llamadas:
31
En “Resource modules” se controla que los módulos relacionados con las funciones calendario y cifrado del flujo media estén activados:
Para servidores virtualizados, en el menú “Compiler Flags” de desactiva el parámetro BUILD_NATIVE (si está activado):
Se seleccionan todos los módulos en el menú “Utilities” y “AGI Samples”:
32
En “Core Sound Packages”, “Music On Hold File Packages” y “Extra Sound Packages” se seleccionan todos los paquetes disponibles. Se guarda la configuración presionando la tecla tabulador hasta posicionarse sobre “Save & Exit”. Se termina con la compilación e instalación: make Si a lo largo de la compilación aparece este error: make[1]: *** [format_mp3.o] Error 1 make: *** [addons] Error 2 se continua con: contrib/scripts/get_mp3_source.sh y luego otra vez el make: make se instala Asterisk: make install se instalan los archivos de configuración predefinidos: make samples se configura el script de arranque de Asterisk: make config Terminada la instalación, se procede con 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:
33
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 poner en seguridad el servidor MySQL se ejecuta el programa: mysql_secure_installation Se contestan las preguntas somo sigue: Enter current password for root (enter for none): sesamo OK, successfully used password, moving on... Change the root password? [Y/n] n ... skipping. Remove anonymous users? [Y/n] y ... Success! Disallow root login remotely? [Y/n] y ... Success! Remove test database and access to it? [Y/n] y - Dropping test database... Reload privilege tables now? [Y/n] y ... Success! Cleaning up... All done! If you've completed all of the above steps, your MySQL installation should now be secure. Thanks for using MySQL! Se configura la zona horaria en MySQL: mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -psesamo mysql Warning: Unable to load '/usr/share/zoneinfo/iso3166.tab' as time zone. Skipping it. Warning: Unable to load '/usr/share/zoneinfo/zone.tab' as time zone. Skipping it.
34
nano /etc/my.cnf Bajo la etiqueta [mysqld] se añade (personalizar): default-time-zone = America/Bogota Se reinicia el servidor MySQL: service mysqld restart Se crea la base de datos para guardar los registros de las llamadas de Asterisk. Se entra en el cliente de MySQL: mysql -u root -psesamo se crea la base de datos asteriskcdr: mysql> create database asteriskcdr; se selecciona: mysql> use asteriskcdr se crea la tabla cdr (copiando y pegando las lineas que siguen): mysql> CREATE TABLE cdr ( calldate datetime NOT NULL default '0000-00-00 00:00:00', clid varchar(80) NOT NULL default '', src varchar(80) NOT NULL default '', dst varchar(80) NOT NULL default '', dcontext varchar(80) NOT NULL default '', channel varchar(80) NOT NULL default '', dstchannel varchar(80) NOT NULL default '', lastapp varchar(80) NOT NULL default '', lastdata varchar(80) NOT NULL default '', duration int(11) NOT NULL default '0', billsec int(11) NOT NULL default '0', disposition varchar(45) NOT NULL default '', amaflags int(11) NOT NULL default '0', accountcode varchar(20) NOT NULL default '', peeraccount varchar(20) NOT NULL default '', uniqueid varchar(32) NOT NULL default '', linkedid varchar(80) NOT NULL default '', userfield varchar(255) NOT NULL default '', KEY callerid (clid) );
35
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 (solamente si se necesita acceder a la base de datos desde otro servidor): 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=127.0.0.1 dbname=asteriskcdr table=cdr password=sesamo user=asterisk port=3306 sock=/var/lib/mysql/mysql.sock Los datos: 1. [global] – etiqueta inicial del bloque 36
2. 3. 4. 5. 6. 7. 8.
hostname - nombre de dominio o IP del servidor MySQL (en este caso local) dbname - nombre de la base de datos table - nombre de la tabla password - contraseña del usuario que tiene los permisos para acceder a la base de datos user - nombre del usuario que tiene los permisos para acceder a la base de datos port – puerto donde MySQL recibirá las conexiones (predefinido 3306) sock – archivo que se crea cuando se inicia MySQL. Se necesita indicar para una correcta conexión en el caso en que en hostname se indique “localhost”.
Se guardan los cambios y se inicia Asterisk: /etc/init.d/asterisk start se averigua que esté corriendo: /etc/init.d/asterisk status asterisk (pid 2403) is running... se entra en la consola: asterisk -rvvvvvvvvvvvvvvvv se controla que la conexión a la base de datos esté activa: CLI> cdr mysql status Connected to asteriskcdr@localhost, port 3306 using table cdr for 59 seconds. Wrote 0 records since last restart. Se sale de la consola: CLI> quit Executing last minute cleanups
37
Capitulo III Instalación A2Billing A2billing es un Softswitch de clase 4 y clase 5. Un softswitch de clase 4 es un sistema capaz de enrutar una gran cantidad de llamadas y permite la conexión entre distintos operadores; un softswitch de clase 5 es un sistema utilizado para brindar servicios de valor añadido a los usuarios finales. A2Billing es el único sistema de facturación para Asterisk distribuido bajo una licencia Open Source (GNU GPL) y basado en MySQL o PostgreSQL para las base de datos y PHP como lenguaje de programación. Se puede utilizar: • • • • •
Como sistema de tarjetas telefónicas a través de números de acceso telefónicos; Como sistema de venta de trafico telefónico al por mayor (Wholesale) Como sistema de facturación de llamadas Como sistema de venta de números geográficos (DID) Como sistema para la gestión de revendedores
3.1 Preparación del sistema A2billing requiere por lo menos la versión 5.2 de PHP. En la versión de CentOS 6.5 está disponible la versión 5.3 que es la que se instalará junto al servidor Web Apache y el modulo SSL (para conexiones seguras al servidor Web). yum install php php-gd php-mysql php-process httpd mod_ssl php-cli php-soap -y Luego se instala php-mcrypt activando el repositorio epel: yum --enablerepo=epel install php-mcrypt -y Terminada esta operación, se configura la zona horaria en el archivo de configuración de PHP (php.ini) nano +946 /etc/php.ini Se modifica la linea para que quede (en el caso de Colombia): date.timezone = America/Bogota En el mismo archivo se busca esta linea: upload_max_filesize = 2M
y se modifica para que quede: upload_max_filesize = 8M De esta forma se podrán cargar los archivos de tarifas que tengan un tamaño de hasta de 8 MegaBytes Siempre en el mismo archivo, se busca esta linea: error_reporting = E_ALL & ~E_DEPRECATED y se modifica para que quede: error_reporting = E_ALL & ~E_NOTICE de esta forma en los LOG del servidor web aparecerán solamente los errores, si presntes, relacionados con el lenguaje PHP. Se guardan los cambios y se descarga la ultima versión disponible de A2Billing: cd /usr/local/src wget https://github.com/Star2Billing/a2billing/archive/v2.1.0.tar.gz Se descomprime: tar -xf v2.1.0.tar.gz se renombra la carpeta creada: mv a2billing-2.1.0 a2billing Se entra en el cliente MySQL: mysql -u root -psesamo se crea la base de datos a2billing: mysql> create database a2billing; Query OK, 1 row affected (0.00 sec) se otorgan los permisos de acceso a la base de datos creada al usuario a2user identificado con la contraseña sesamo desde local: mysql> GRANT ALL PRIVILEGES ON a2billing.* TO 'a2user'@'localhost' IDENTIFIED BY 'sesamo'; Query OK, 0 rows affected (0.00 sec) se actualizan los permisos:
40
mysql> flush privileges; Query OK, 0 rows affected (0.00 sec) se sale del cliente MySQL: mysql> quit Bye Se crean las tablas en la base de datos a2billing utilizando el script presente en la siguiente carpeta: cd a2billing/DataBase/mysql-5.x/ se ejecuta: ./install-db.sh Se insertan los datos como mostrado en la imagen que sigue:
Para resumir: Database Name: a2billing Hostname: localhost Username: root Password: sesamo Se instalan las locuciones distribuidas con el programa (ingles, francés, español, portugués y ruso): cd /usr/local/src/a2billing/addons/sounds/ utilizando el siguiente script: ./install_a2b_sounds.sh 41
La verdad la calidad de las locuciones en español no son muy buenas y algunas faltan del todo. En la misma carpeta se encuentra el archivo Audio_text.info que contiene todos los nombres de las locuciones disponibles con relativas frases. Puede ser una buena ayuda para grabar las propias. Se continua la instalación copiando el archivo de configuración de a2billing en la carpeta /etc: cp /usr/local/src/a2billing/a2billing.conf /etc/ se abre con el editor: nano /etc/a2billing.conf se modifican estas lineas: [database] hostname = localhost port = user = a2billing_dbuser password = a2billing_dbpassword dbname = a2billing_dbname dbtype = mysql para que queden: [database] hostname = localhost port = 3306 user = a2user password = sesamo dbname = a2billing dbtype = mysql Se guardan los cambios. Por defecto A2billing trabaja con Asterisk en Realtime, es decir que las extensiones SIP y IAX2 se guardan en la base de datos a2billing y Asterisk accede a ellas a través de la configuración del modulo de Realtime. Existe también la posibilidad de guardar la configuración de las extensiones en archivos de texto. Para este tipo de configuración se crean dos archivos que son los que a2billing utilizará para guardar las extensiones SIP y IAX2: touch /etc/asterisk/additional_a2billing_iax.conf touch /etc/asterisk/additional_a2billing_sip.conf se asignan los permisos de escritura/lectura para estos dos archivos al usuario y grupo apache, es decir el servidor Web: chown -Rf apache:apache /etc/asterisk/additional_a2billing_iax.conf 42
chown -Rf apache:apache /etc/asterisk/additional_a2billing_sip.conf A2Billing para recargar la configuración de Asterisk (en el caso que las extensiones se guarden en los archivos que se acaban de crear) y para generar las llamadas de callback se apoya al AMI (Asterisk Manager Interface) de la PBX. Es por eso que hay que configurar el archivo manager.conf. Se abre: nano /etc/asterisk/manager.conf Se cambian las siguientes tres lineas: enabled = no ;allowmultiplelogin = yes ;displayconnects = yes para que queden: enabled=yes allowmultiplelogin = yes dislplayconnects=yes El usuario predefinido en la configuración de A2billing para conectarse al AMI de Asterisk es myasterisk con contraseña mycode. Para evitar de trabajar con configuraciones predefinidas, se cambiaran estos datos respectivamente con asterisk y sesamo: [asterisk] secret=sesamo deny=0.0.0.0/0.0.0.0 permit=127.0.0.1/255.255.255.255 read = system,call,log,verbose,agent,user,config,dtmf,reporting,cdr,dialplan write = system,call,agent,user,config,command,reporting,originate Se guardan los cambios y se continua con los script AGI presentes en el paquete de A2Billing. Uno se utiliza para realizar las llamadas (a2billing.php) y el segundo para monitorear el servidor (a2billing_monitoring.php). Se entra en la carpeta que contiene los AGI: cd /usr/local/src/a2billing/AGI se crean dos enlaces simbólicos de los dos AGI en la carpeta /var/lib/asterisk/agi-bin que es donde Asterisk los busca de manera predefinida: ln -s /usr/local/src/a2billing/AGI/a2billing.php /var/lib/asterisk/agi-bin/a2billing.php ln -s /usr/local/src/a2billing/AGI/a2billing_monitoring.php /var/lib/asterisk/agi-bin/a2billing_monitoring.php
Como los AGI se apoyan en una serie de librerías contenidas en la carpeta /lib, se crea un enlace simbólico también a esta carpeta: ln -s /usr/local/src/a2billing/AGI/lib /var/lib/asterisk/agi-bin/lib 43
Se vuelven ejecutables los dos archivos: chmod +x /var/lib/asterisk/agi-bin/a2billing.php chmod +x /var/lib/asterisk/agi-bin/a2billing_monitoring.php Una vez terminada esta parte se crean una series de carpetas. La primera es donde se guardarán los archivos temporales y los script de A2Billing: mkdir -p /var/lib/a2billing/script la segunda donde se guardará el proceso del servicio de callback: mkdir -p /var/run/a2billing Ahora ya se puede crear un enlace simbólico a las carpetas que se necesitan para la parte Web de A2billing que son: • • • •
admin (para la conexión de los administradores) customer (para la conexión de los clientes) agent (para la conexión de los agentes/revendedores) common (librerías compartidas por los tres tipos de usuarios)
ln -s /usr/local/src/a2billing/admin/ /var/www/html/admin ln -s /usr/local/src/a2billing/agent/ /var/www/html/agent ln -s /usr/local/src/a2billing/customer/ /var/www/html/customer ln -s /usr/local/src/a2billing/common/ /var/www/html/common Se cambian los permisos en las tres carpetas que siguen que es donde se guardarán los archivos temporales para cada tipo de usuario: chmod 755 /usr/local/src/a2billing/admin/templates_c chmod 755 /usr/local/src/a2billing/customer/templates_c chmod 755 /usr/local/src/a2billing/agent/templates_c Se cambia el usuario y grupo que tiene acceso a todas las carpetas creadas (el servidor Web Apache): chown -R apache:apache /var/www/html/ chown -R apache:apache /var/www/html/admin/ chown -R apache:apache /var/www/html/agent/ chown -R apache:apache /var/www/html/customer/ chown -R apache:apache /var/www/html/common/ Los registros de las actividades de A2Billing se guardan en una serie de archivos que hay que crear antes de acceder por primera vez al programa. Primero se crea la carpeta: mkdir /var/log/a2billing 44
luego los archivos: touch /var/log/a2billing/cront_a2b_alarm.log touch /var/log/a2billing/cront_a2b_autorefill.log touch /var/log/a2billing/cront_a2b_batch_process.log touch /var/log/a2billing/cront_a2b_archive_data.log touch /var/log/a2billing/cront_a2b_bill_diduse.log touch /var/log/a2billing/cront_a2b_subscription_fee.log touch /var/log/a2billing/cront_a2b_currency_update.log touch /var/log/a2billing/cront_a2b_invoice.log touch /var/log/a2billing/cront_a2b_check_account.log touch /var/log/a2billing/a2billing_paypal.log touch /var/log/a2billing/a2billing_epayment.log touch /var/log/a2billing/a2billing_api_ecommerce_request.log touch /var/log/a2billing/a2billing_api_callback_request.log touch /var/log/a2billing/a2billing_api_card.log touch /var/log/a2billing/a2billing_agi.log Se cambian los permisos para que el usuario apache (el servidor Web) pueda escribir en ellos: chown apache:apache /var/log/a2billing/* A2biblling necesita que se ejecuten una serie de script para monitorear el sistema y para elaborar algunas funciones (ejemplo: pagos, facturas, etc.). Estos script se añaden al cron del sistema para el usuario root: crontab -e Al final del archivo se pega el siguiente bloque de lineas: # A2Billing # Para actualizar la tasa de cambio de las monedas 0 6 * * * php /usr/local/src/a2billing/Cronjobs/currencies_update_yahoo.php # Para el pago se servicios subscritos 0 6 1 * * php /usr/local/src/a2billing/Cronjobs/a2billing_subscription_fee.php # Para notificaciones cuando el credito del cliente es más bajo de lo indicado 0 * * * * php /usr/local/src/a2billing/Cronjobs/a2billing_notify_account.php # Para el pago de los numeros geograficos asociados a los clientes 0 2 * * * php /usr/local/src/a2billing/Cronjobs/a2billing_bill_diduse.php # Para el pago de servicios periodicos 0 12 * * * php /usr/local/src/a2billing/Cronjobs/a2billing_batch_process.php # Para la generación de las facturas de los clientes 0 6 * * * php /usr/local/src/a2billing/Cronjobs/a2billing_batch_billing.php # Para la generación de llamadas automaticas utilizadas en las campañas # */5 * * * * php /usr/local/src/a2billing/Cronjobs/a2billing_batch_autodialer.php # Para la gestión de las alarmas que se pueden configurar en A2Billing 45
0 * * * * php /usr/local/src/a2billing/Cronjobs/a2billing_alarm.php # Para archivar los datos de las llamadas más viejos de lo indicado en la configuración de A2Billing 0 12 * * * php /usr/local/src/a2billing/Cronjobs/a2billing_archive_data_cront.php # Para recargar el crédito de un cliente en automatico 0 6 1 * * php /usr/local/src/a2billing/Cronjobs/a2billing_autorefill.php Se deja comentada la linea con a2billing_batch_autodialer.php ya que no se van a utilizar las campañas de llamadas (funcionalidad declarada obsoleta por los desarrolladores). Se guardan las modificaciones e se reinicia Cron: /etc/init.d/crond restart 3.2 Instalación del demonio CallBack El demonio para el Callback es el que permite utilizar el sistema de rellamada de A2Billing. El programa es escrito en el lenguaje de programación Python y es por eso que primero hay que instalar unos paquetes que se necesitan para la compilación: yum install python-setuptools MySQL-python python-devel -y Luego, a través de easy_install, se instala el programa sqlalchemy: easy_install sqlalchemy Una vez satisfechas estas dependencias, se puede empezar con la compilación y instalación del programa de callback: cd /usr/local/src/a2billing/CallBack/callback-daemon-py/dist/ tar -xf callback_daemon-1.0.prod-r1528.tar.gz cd callback_daemon-1.0.prod-r1528 se compila: python setup.py build python setup.py bdist_egg easy_install dist/callback_daemon-1.0.prod_r1528-py2.6.egg Compilado el programa se instala come servicio a través de uno script presente en el paquete de A2Billing: cd /usr/local/src/a2billing/CallBack/callback-daemon-py/callback_daemon Se copia el script: 46
cp a2b-callback-daemon.rc /etc/init.d/a2b-callback-daemon Se vuelve ejecutable: chmod +x /etc/init.d/a2b-callback-daemon Se añade a la lista de servicios: chkconfig --add a2b-callback-daemon Por defecto el servicio guarda los registros en la carpeta /var/log y tiene que arrancar después de MySQL y Asterisk. Para ese efecto hay que abrir el archivo: nano /etc/init.d/a2b-callback-daemon y cambiar estas lineas: # chkconfig: 2345 40 60 LOG='/var/log/a2b-callback-daemon.log' para que queden: # chkconfig: 2345 95 60 LOG='/var/log/a2billing/a2b-callback-daemon.log' Se guardan las modificaciones y se configura para que arranque en automático con el sistema: chkconfig a2b-callback-daemon on Ahora ya se puede iniciar el servicio: /etc/init.d/a2b-callback-daemon start a2b_callback_daemon está parado Starting a2b-callback-daemon:
[ OK ]
y controlar que esté funcionando: tail -f /var/log/a2billing/a2b-callback-daemon.log "2011-04-23 19:10:52,297 - root - MainThread - INFO - waiting..." "2011-04-23 19:10:57,308 - root - MainThread - INFO - waiting..." "2011-04-23 19:11:02,322 - root - MainThread - INFO - waiting..." "2011-04-23 19:11:07,355 - root - MainThread - INFO – waiting..." Se sale del comando tail con CTRL-C
47
IMPORTANTE: cada vez que se reinicia Asterisk hay que reiniciar el servicio de callback ya que pierde la conexión a la AMI de Asterisk. 3.3 Configuración de Asterisk Como ya se ha dicho anteriormente, en esta guía no se explicarán las configuraciones de Asterisk pero es importante saber que los archivos que se modifican son solamente los que se necesitan para que A2Billing funcione. 3.3.1 sip.conf En el archivo sip.conf se configurará la troncal para sacar las llamadas hacia el proveedor VoIP. Se renombra el sip.conf predefinido: mv /etc/asterisk/sip.conf /etc/asterisk/sip.conf.old se crea uno nuevo: nano /etc/asterisk/sip.conf se pegan las siguientes lineas: [general] context=default allowguest=no allowtransfer=no match_auth_username=yes realm=asterisk udpbindaddr=0.0.0.0:5090 tcpenable=no tcpbindaddr=0.0.0.0:5090 tcpauthtimeout=30 tcpauthlimit=100 transport=udp srvlookup=yes pedantic=yes maxexpiry=3600 minexpiry=60 defaultexpiry=120 mwiexpiry=3600 maxforwards=70 qualifyfreq=20 qualifygap=200 keepalive=yes 48
disallow=all allow=ulaw allow=alaw mohinterpret=default mohsuggest=default language=es relaxdtmf=no sendrpid = yes prematuremedia=no progressinband=no useragent=VozToVoice 2.0 promiscredir=no dtmfmode = rfc2833 videosupport=yes maxcallbitrate=384 callevents=yes alwaysauthreject=yes rtptimeout=60 rtpholdtimeout=300 allowsubscribe=yes subscribecontext=subscribe notifyringing=yes notifyhold=yes callcounter = yes t38pt_udptl = yes,fec,maxdatagram=400 faxdetect=yes directmedia=no sdpsession=A2Billing sdpowner=a2billing externaddr=IPservidor localnet=192.168.160.0/255.255.255.0 Antes de guardas los cambio, personalizar las siguientes Lineas: • • • •
useragent: nombre que se quiere dar a la PBX externaddr: IP publica del servidor localnet: rango de IP locales en el caso que en el servidor se haya configurado la IP privada (como es el caso) importante saber que el puerto de escucha de Asterisk UDP y TCP será el 5090 ya que el 5060 lo utilizerá OpenSIPs
Siempre en el mismo archivo se añaden los datos para configurar las troncales. En este caso se crean dos de ejemplo con el mismo proveedor; una utilizando un servidor, otra utilizando otro servidor de respaldo. En las dos la autenticación será con usuario y contraseña. Para un sistema en producción configurar las troncales de sus proveedores). Si quieren utilizar una cuenta de prueba, pueden abrir una con la empresa VozToVoice. Recibirán un dólar de crédito para las pruebas.
49
[voztovoice1] type=peer port=5060 host=sip.voztovoice.eu defaultuser=usuario fromuser=usuario secret=contraseña dtmfmode=rfc2833 disallow=all context=from-trunk canreinvite=no allow=ulaw allow=alaw qualify=yes [voztovoice2] type=peer port=5060 host=sip1.voztovoice.eu defaultuser=usuario fromuser=usuario secret=contraseña dtmfmode=rfc2833 disallow=all context=from-trunk canreinvite=no allow=ulaw allow=alaw qualify=yes • • •
defaultuser: nombre de usuario de la cuenta creada fromuser: nombre de usuario de la cuenta creada secret: contraseña asociada al nombre de usuario de la cuenta creada
Para terminar, se incluye el archivo que se ha creado en el primer párrafo y que contendrá las extensiones creadas en A2Billing en el caso que no se utilice el Realtime: #include additional_a2billing_sip.conf Se guardan los cambios y se hace lo mismo con el archivo iax.conf en el caso que se quiera configurar también extensiones IAX2: echo "#include additional_a2billing_iax.conf" >> /etc/asterisk/iax.conf
50
3.3.2 extensions.conf Se sigue con el dialplan. Se renombra el archivo extensions.conf predefinido: mv /etc/asterisk/extensions.conf /etc/asterisk/extensions.conf.old Se crea uno nuevo: nano /etc/asterisk/extensions.conf se pegan las lineas que siguen: [general] static = yes writeprotect = no autofallthrough = yes extenpatternmatchnew = true clearglobalvars = no userscontext=default [globals] ; Variables globales y se incluye el contexto para las llamadas con el AGI de a2billing: [a2billing] exten => _X.,1,NoOp(A2Billing Start) same => n,Agi(a2billing.php,1) same => n,Hangup exten => h,1,Hangup Se guardan los cambios y se averigua que efectivamente el dialplan englobado esté presente. Se entra en la consola de Asterisk: asterisk -rvvvvvvvvvvvvvv se recarga el dialplan: CLI> dialplan reload aparecerán muchas lineas porque hay partes de dialplan escritas en otros lenguajes que son leídas por Asterisk. Si no se van a utilizar, es mejor desactivar los respectivos módulos. Se sale de la consola de Asterisk: CLI> quit
51
Se abre el siguiente archivo: nano /etc/asterisk/modules.conf y al final se añaden las lineas que siguen: noload => pbx_lua.so noload => pbx_ael.so Se guardan los cambios y se reinicia Asterisk y luego el sistema de callback: service asterisk restart service a2b-callback-daemon restart Luego se revisa el contexto recién creado. Para acceder a la consola de Asterisk se utiliza el alias creado a lo largo del párrafo 1.3: aste CLI> dialplan show a2billing debe aparecer: [ Context 'a2billing' created by 'pbx_config' ] 'h' => 1. Hangup() [pbx_config] '_X.' => 1. NoOp(A2Billing Start) [pbx_config] 2. Agi(a2billing.php,1) [pbx_config] 3. Hangup() [pbx_config] -= 2 extensions (4 priorities) in 1 context. =CLI> quit Se sale de la consola de Asterisk. 3.3.3 Asterisk Realtime Las extensiones creadas a través del sistema de facturación se guardarán en la base de datos de A2Billing. Para que Asterisk las pueda leer y actualizar, hay que configurar Asterisk utilizando su funcionalidad, llamada Realtime, que le permite interactuar con base de datos para la configuración, en este caso, de las extensiones SIP e IAX. En este libro la configuración se realizará utilizando ODBC en lugar de utilizar directamente MySQL. Esto con el objetivo de obtener un mejor rendimiento y una más alta estabilidad. El primer paso es configurar ODBC para la conexión a MySQL:
52
mv /etc/odbcinst.ini /etc/odbcinst.old nano /etc/odbcinst.ini se añaden las siguientes lineas: [MySQL] Description = ODBC for MySQL Driver = /usr/lib64/libmyodbc5.so Setup = /usr/lib64/libodbcmyS.so FileUsage = 1 Si el sistema CentOS instalado es de 32bit, la configuración del bloque sería: [MySQL] Description = ODBC for MySQL Driver = /usr/lib/libmyodbc5.so Setup = /usr/lib/libodbcmyS.so FileUsage = 1 Se guardan los cambios y se continua con la conexión a la base de datos a2billing: nano /etc/odbc.ini se añaden las siguientes lineas: [a2billing] Description = MySQL a2billing Driver = MySQL Database = a2billing Server = localhost User = a2user Password = sesamo Port = 3306 Option = 3 Se guardan los cambios y se prueba la conexión utilizando los datos configurados en odbc.ini (base de datos, usuario, contraseña del usuario): isql a2billing a2user sesamo Tiene que aparecer: +---------------------------------------+ | Connected! | | | 53
| sql-statement | | help [tablename] | | quit | | | +---------------------------------------+ SQL> Para salir: SQL> quit Se pasa a Asterisk. En la PBX la configuración Realtime con ODBC se efectúa en dos archivos: • •
extconfig.conf res_odbc.conf
El el primero se define que las extensiones SIP e IAX deberán ser configuradas en Realtime utilizando ODBC y la base de datos a2billing: nano /etc/asterisk/extconfig.conf se modifican estas lineas: ;iaxusers => odbc,asterisk ;iaxpeers => odbc,asterisk ;sippeers => odbc,asterisk para que queden: iaxusers => odbc,a2b,cc_iax_buddies iaxpeers => odbc,a2b,cc_iax_buddies sippeers => odbc,a2b,cc_sip_buddies Se guardan los cambios. cc_iax_buddies y cc_sip_buddies son las tablas de la base de datos A2billing donde están guardadas las extensiones creadas en el sistema de facturación. A2b es el nombre de la etiqueta que se configurará en el archivo res_odbc.conf. Para terminar se configura el archivo res_odbc.conf: nano /etc/asterisk/res_odbc.conf al final del archivo se añaden las siguientes lineas: [a2b] enabled => yes dsn => a2billing username => a2user password => sesamo 54
pre-connect => yes sanitysql => select 1 idlecheck => 3600 connect_timeout => 10 La conexión funciona de la siguiente manera. En el archivo extconfig.conf se define la conexión a la base de datos utilizando el nombre que aparece como etiqueta del bloque presente en el archivo res_odbc.onf (en este caso el nombre es a2b). En el archivo res_odbc.conf en el parámetro dsn se pone el nombre de la etiqueta del bloque configurado en el archivo odbc.ini (a2billing). En el archivo odbc.ini se define la conexión a la base de datos MySQL (en este caso la base de datos se llama a2billing). Se reinicia Asterisk, el sistema de callback y se averigua que la conexión esté funcionando: /etc/init.d/asterisk restart service a2b-callback-daemon restart asterisk -rvvvvvvvvvvvvvvvvv CLI> odbc show la respuesta debe ser: ODBC DSN Settings ----------------Name: a2b DSN: a2billing Last connection attempt: 1969-12-31 19:00:00 Pooled: No Connected: Yes Se sale de la consola de Asterisk: CLI> quit 3.4 Configuración del Firewall Para proteger el servidor Linux de accesos no autorizados hay que instalar un firewall (cortafuegos) y abrir los puertos que A2Billing 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 A2Billing se encuentra instalado en un computador local conectado a Internet a través de un router hay dos opciones:
55
• •
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
Para instalar iptables: yum install iptables -y 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 y/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 vengan procesados y enviados con una prioridad más alta)
Las reglas se definen una por linea y serán procesadas por IPtables siguiendo la misma secuencia. Cuando no se especifica diversamente, todas las reglas aplicarán a la tabla filter. Se acepta todo el trafico en entrada con destino la interfaz lookpack: iptables -A INPUT -i lo -j ACCEPT Se rechaza (REJECT) todo el trafico entrante con destino 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 para el protocolo SMTP (puerto 25 tcp) solamente si se ha 56
configurado el acceso desde remoto al programa SendMail: iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 25 -j ACCEPT Se deja pasar todo el trafico en entrada para el protocolo HTTP (puerto 80 tcp): iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT Se deja pasar todo el trafico en entrada para el protocolo HTTPs (puerto 443 tcp): iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT Se deja pasar todo el trafico en entrada destinado al puerto udp 4569 (protocolo IAX2): iptables -A INPUT -p udp --dport 4569 -j ACCEPT Se bloquea el trafico sobre el puerto 5060 para los más conocidos programas de escaneo de servidores SIP utilizados para ataques y fraudes de llamadas: iptables -A INPUT -p udp -m udp --dport 5060 -m string --string "friendly-scanner" --algo bm -j DROP
iptables -A INPUT -p udp -m udp --dport 5060 -m string --string "sipcli" --algo bm -j DROP iptables -A INPUT -p udp -m udp --dport 5060 -m string --string "VaxSIPUserAgent/3.0" --algo bm -j DROP
iptables -A INPUT -p udp -m udp --dport 5060 -m string --string "sipvicious" --algo bm -j DROP Solamente ahora se deja pasar todo el trafico en entrada destinado al puerto udp 5060 (protocolo SIP) utilizado por OpenSIPs: iptables -A INPUT -p udp --dport 5060 -j ACCEPT Se deja pasar el trafico hacia Asterisk (puerto 5090), para las troncales configuradas en el archivo sip.conf: iptables -A INPUT -p udp --dport 5090 -s sip.voztovoice.eu -j ACCEPT iptables -A INPUT -p udp --dport 5090 -s sip1.voztovoice.eu -j ACCEPT y para que los usuarios puedan registrarse directamente en Asterisk. Una vez instalado y configurado OpenSIPs, como las extensiones se registrarán directamente en el Proxy SIP, esta linea se quitará: iptables -A INPUT -p udp --dport 5090 -j ACCEPT Se deja pasar todo el trafico en entrada destinado a los puertos udp que van de 10000 a 20000 (protocolo RTP):
57
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 REJECT iptables -A FORWARD -j REJECT Se averigua el estado de las reglas definidas con el comando: iptables -L -v Chain INPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 2235 329K ACCEPT all -- lo any anywhere anywhere 0 0 REJECT all -- !lo any anywhere loopback/8 unreachable 7 1690 ACCEPT all -- any any anywhere anywhere RELATED,ESTABLISHED 0 0 ACCEPT tcp -- any any anywhere anywhere 0 0 ACCEPT tcp -- any any anywhere anywhere 0 0 ACCEPT tcp -- any any anywhere anywhere 0 0 ACCEPT tcp -- any any anywhere anywhere 0 0 ACCEPT tcp -- any any anywhere anywhere 0 0 ACCEPT tcp -- any any anywhere anywhere dpt:cslistener 0 0 ACCEPT udp -- any any anywhere anywhere 0 0 0 0
0 DROP 0 DROP 0 DROP 0 DROP
udp udp udp udp
-----
0 0 ACCEPT 0 0 ACCEPT 0 0 ACCEPT 0 0 ACCEPT 0 0 ACCEPT 0 0 ACCEPT 0 0 REJECT unreachable
any any any any
any any any any
anywhere anywhere anywhere anywhere
anywhere anywhere anywhere anywhere
reject-with icmp-portstate state NEW tcp dpt:hydap state NEW tcp dpt:smtp state NEW tcp dpt:http state NEW tcp dpt:https state NEW tcp dpt:8008 state NEW tcp udp dpt:iax
udp dpt:sip STRING match "friendly-scanner" ALGO name bm TO 65535 udp dpt:sip STRING match "sipcli" ALGO name bm TO 65535 udp dpt:sip STRING match "VaxSIPUserAgent/3.0" ALGO name bm TO 65535 udp dpt:sip STRING match "sipvicious" ALGO name bm TO 65535
udp -- any any anywhere anywhere udp -- any any voztovoice.eu anywhere udp -- any any sip1.voztovoice.eu anywhere udp -- any any anywhere anywhere udp -- any any anywhere anywhere icmp -- any any anywhere anywhere all -- any any anywhere anywhere
udp dpt:sip udp dpt:5090 udp dpt:5090 udp dpt:5090 udp dpts:ndmp:dnp icmp echo-request reject-with icmp-port-
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 0
58
0 REJECT
all -- any any
anywhere
anywhere
reject-with icmp-port-unreachable
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 2242 331K ACCEPT all -- any any anywhere anywhere Para guardar los cambios: service iptables save iptables: Guardando las reglas del cortafuegos en /etc/sysconfig/iptables [ OK ] Se inicia el servicio: service iptables start Para iniciar IPtables automáticamente: chkconfig iptables on Se configura el inicio automático también para el servidor Web: chkconfig httpd on Ahora que se ha terminado con la configuración del servidor y de A2Billing se reinicia el sistema para averiguar que todos los servicios arranquen correctamente: reboot 3.5 Primer acceso Reiniciado el servidor se vuelve a entrar con el cliente SSH y se accede a la consola de Asterisk: asterisk -rvvvvvvvvvvvvvv desde un navegador web se entra a la pagina de administración de A2Billing: http://IPservidor/admin o la pagina segura (mejor): https://IPservidor/admin Debe aparecer:
59
Los datos por defecto para acceder son: User: root Password: changepassword Lo primero que hay que hacer es crear un nuevo administrador y borrar el predefinido. Se entra en el menú ADMINS y luego en “Add Search”:
En la pagina que aparece se escoge “ADD Administrator”
En la nueva pagina se rellenan los campos indicados (personalizar):
60
Se guardan las modificaciones presionando el botón “Confirm Data”. Se regresará a la pagina anterior y ya se podrá borrar el usuario root:
y confirmando con el botón “DELETE” en la pagina siguiente:
61
Ya se puede salir del programa:
y volver a entrar con los datos del nuevo administrador:
62
Capitulo IV Configuración base A2Billing Una vez en la pagina de administración de A2Billing, se tendrán disponibles dos bloques de menú. Uno en la parte de arriba de la pagina:
• •
•
HOME: para volver a la pagina de inicio de A2Billing DASHBOARD: es una pagina compuesta de distintos bloques: • ACCOUNT INFO: informaciones relacionadas con las cuentas de los clientes • REFILLS INFO: informaciones sobre las recargas realizadas • CALL INFO TODAY: informaciones sobre las llamadas, costes y ganancias • SYSTEM INFO: informaciones del sistema • PAYMENTS INFO: informaciones de los pagos realizados por los clientes • LATEST NEWS: un canal de noticias gestionado por los desarrolladores de A2Billing donde se pueden leer las ultimas novedades relacionadas con los programas. NOTIFICATION: es este bloque aparecerá la palabra “New” cada vez que se verifique un determinado evento. Ejemplos: • Se ha registrado un nuevo usuario • Se ha creado un nuevo tiquete de soporte • Un revendedor ha solicitado el pago de su comisión • Un cliente ha modificado el desvío de un numero geográfico adquirido
Uno en la parte derecha:
La parte más tediosa y al mismo tiempo más importante de la configuración de A2Billing es la que tiene que ver con las variables globales del sistema de facturación. A través de estas variables se configuran, entre otras cosas, el sistema de pago, el callback (rellamada), la interfaz del cliente y algunos datos de configuración de Asterisk. Para simplificar esta parte, se presentarán las variables como aparecen en los distintos grupos del menú “SYSTEM SETTINGS” de A2Biling. La configuración inicial que se adoptará es para un sistema Wholesale, es decir para la venta de trafico telefónico a clientes y revendedores. En el capitulo V dedicado a la configuración avanzada, se verá como configurar A2Billing como sistema de tarjetas telefónicas; este tipo de configuración se utiliza normalmente a través de números de acceso telefónicos. 4.1 System Settings Desde la pagina de administración de A2Biling se selecciona el menú “System Settings” y luego “Global List” come aparece en la imagen que sigue:
En la nueva pagina se empieza la configuración escogiendo en el menú desplegable “Global” y presionando el Botón “Search”:
65
Aparecerá la lista de las variables globales. En la tabla que sigue el significado de cada una y el valor a configurar. En negrita las variables que hay que modificar. Titulo
Valor
Descripción
Card Number length
5-20
Longitud numérica de la Tarjeta de llamada que es también el PIN che se utilizará con la configuración de tarjetas telefónicas y el numero de extensión que se utilizará para las llamadas entre extensiones desde OpenSIPs
Card Alias length
5
Longitud del Alias de tarjeta. El alias lo utiliza el cliente para acceder a su pagina personal y para las llamadas entre clientes configurados en A2Billing. En este caso como las llamadas entre clientes se realizarán a nivel de OpenSIPs, se utilizará el Card Number length. El Card Alias Lenght se utilizará como contraseña del buzón de voz.
Voucher length
15
Longitud de los Voucher. Los voucher se utilizan para recargar las cuentas de los clientes
Base Currency
usd
Moneda predefinida del sistema de facturación (en este caso dolares estadounidenses)
Invoice Image
asterisk01.jpg
Logo para las facturas (no aplica). Se verá más adelante como se configura correctamente.
Admin Email
[email protected]
e-Mail del administrador del sistema (personalizar con una cuenta real).
66
Titulo
Valor
Descripción
7
Días disponibles para el cliente para renovar (pagar) un DID antes de eliminarlo de su cuenta.
Manager Host
localhost
Host/IP para conectarse a la AMI de Asterisk
Manager User ID
asterisk
Usuario para la conexión a la AMI de Asterisk como creado en el archivo manager.conf de Asterisk
Manager Password
sesamo
Contraseña del usuario creado en el manager.conf de Asterisk.
Use SMTP Server
no
Se utiliza el servidor de correo electrónico interno en lugar de un servidor externo.
localhost
Dirección IP o nombre de dominio del servidor de correo electrónico. En este caso se utilizará Sendmail instalado en el sistema.
DID Billing Days to pay
SMTP Host
SMTP UserName
Se deja en blanco
SMTP Password
Se deja en blanco
Use Realtime
Go To Customer
yes
Se usará Asterisk Realtime para guardar las extensiones en la base de datos
https://IPservidor/customer
URL pagina clientes (poner la IP del servidor Linode o de su servidor local). Este parámetro permite acceder a las cuentas de los clientes directamente desde la pagina de administración de A2Billing.
SMTP Secure
Para enviar los correos electrónico no se utilizará una conexión segura. Esto porque el servidor reside en el mismo servidor Linux.
SMTP Port
25
Puerto del servidor de correo electrónico. Predefinido 25
Server GMT
GMT-05:00
Zona horaria (para Colombia). Personalizar
67
Titulo Invoice Template Path Outstanding Template Path Sales Template Path Enable CDR local cache
Path for the CDR cache file
Base Country Base Language
Descripción
../invoice/
Carpeta de las plantillas para las facturas
../outstanding/
Carpeta de las plantillas para facturas pendientes
../sales/
Carpeta de las plantillas para facturas pagadas
No
Se activa en el caso se quiera guardar los datos de las llamadas en una base de datos SQLite
/etc/asterisk/cache_a2billing
Archivo donde se guardarían los datos de las llamadas en el caso se utilice una base de datos SQLlite
COL
País donde se encuentra la empresa
es
Asterisk Version Global Days to bill anniversary
Valor
before
1_11 month
3
Idioma predefinido locuciones Versión de Asterisk Facturar un servicio de suscripción el numero de días indicados en este parámetro antes de su fecha de vencimiento.
En el caso se quiera utilizar un servidor de correo electrónico externo el lugar del SENDMAIL instalado, los parámetros que hay que cambiar son (para Gmail): Use SMTP Server SMTP Host
Yes smtp.gmail.com
SMTP UserName
[email protected]
SMTP Password
password
SMTP Secure
ssl
SMTP Port
465
Se sigue con callback. Tema de este libro no son las campañas de llamadas realizadas por agentes/clientes que se pueden gestionar con A2Billing (modulo declarado obsoleto por lo desarrolladores de A2Billing). Lo que interesa, es conocer la configuración de las rellamadas (CallBack) para los clientes (en negrita las modificaciones):
68
Titulo
Valor
Descripción
Context Callback
a2billing-callback
Contexto que hay que configurar en el dialplan de Asterisk para la rellamada
Extension
1000
Extensión que el sistema utilizará en una llamada de callback
Wait before callback
10
Segundos que el sistema esperará antes de iniciar la rellamada
Avoid Repeat Duration
30
Numero de segundos antes que una rellamada pueda ser reenviada desde la pagina Web del cliente
Time out
60
Si dentro de 60 segundos la rellamada no se establece, se considera terminada sin éxito
Answer on Call
No
Para gestionar la respuesta de una rellamada se pone en no. De esta forma la segunda llamada no se iniciará hasta que la primera no sea contestada.
No of Predictive Calls
10
Numero de llamadas que se lanzan cuando un Agente presiona el botón de llamada (no aplica)
Delay for Availability
1
Numero de días para que un numero llamado sea nuevamente disponible en una campaña (no aplica)
PD Context
a2billing-predictivedialer
Contexto que hay que configurar en el dialplan de Asterisk para el sistema de llamadas automático (no aplica)
Max Time to call
5400
Numero máximo de segundos de
69
duración de una llamada generada con el sistema automático (no aplica) PD Caller ID
123456
Identificativo de llamada saliente para las rellamadas y las campañas (personalizar)
Callback CallPlan ID
1
El ID del Callplan que se utilizará para las rellamadas cuando se utiliza el sistema allcallback.
Server Group ID
1
Para las rellamadas se pueden configurar más de un grupo de servidores Asterisk. Si se utiliza solamente uno se pone la ID del grupo como aparece en el menú CALLBACK → Server Group. Si se utiliza más de un grupo se indican los ID de los grupos, separados por una coma.
Audio Intro
prepaid-callback_intro
Locución que se escuchará cuando se inicia una rellamada
Context Campaign's Callback
a2billing-campaign-callback
Contexto para la rellamadas de una campaña (no aplica)
Default Context forward Campaign's Callback
campaign
Contexto donde transferir las llamadas de una campaña cuando se contesten (no aplica)
Terminada la configuración de este grupo se continua con webcustomerui:
Titulo
Valor
Return URL distant Forget Password
WebPhone Server 70
Descripción Dirección Web alternativa si se verifica un error cuando el cliente intenta recuperar su contraseña de acceso.
localhost
Antes, en la pagina personal de
los clientes estaba presente un webphone que se podía utilizar para efectuar llamadas. En las ultimas versiones se ha quitado CallerID Limit
5
Return URL distant Login
Numero máximo de identificativos de llamada que un cliente puede asociar a su cuenta personal Dirección Web alternativa si se verifica un error después que el usuario se ha autenticado.
Notifications Modules
Yes
Visualiza un menú en la pagina personal del cliente que le permite configurar una alerta cuando su crédito está por debajo del valor configurado
Se sigue con sip-iax-info donde se define la configuración de los parámetros de configuración de la cuenta SIP que los clientes pueden ver en su pagina personal y que les permite configurar su teléfono SIP/IAX2 o su PBX:
Titulo
Valor
Descripción
Trunk Name
linode
Nombre de la troncal como aparecerá al cliente (personalizar con el nombre de su empresa)
Codecs Allowed
alaw,ulaw
Codec disponibles para los clientes
Host
IPservidor
Dirección IP del servidor Linode o mejor aún, nombre de dominio
IAX Parms
canreinvite = no
Parámetros adicionales para IAX2
SIP Parms
trustrpid = yes | sendrpid = yes | canreinvite = no
Parámetros adicionales para SIP. Se pueden indicar más separados por el carácter |
71
Para los últimos dos parámetros el cambio hay que realizarlo directamente desde la base de datos ya que en la ultimas versiones de A2Billling se han implementado toda una serie de controles de seguridad que no permiten modificar parámetros donde aparezcan caracteres especiales (en este caso el símbolo de =). se accede a MySQL: mysql -u root -psesamo se selecciona la base de datos a2billing: mysql> use a2billing y se modifican los dos parámetros finales del grupo: mysql> update cc_config set config_value='directmedia = yes' where id='54'; mysql> update cc_config set config_value='trustrpid = yes | sendrpid = yes | directmedia = yes ' where id='55'; Se sale de cliente MySQL: mysql> quit Se continua con epayment_method donde se configuran todos los parámetros relacionados con los métodos de pago disponibles. En esta parte se configuran también los accesos a las paginas seguras del portal de los clientes.
Titulo Enable
Valor Yes
HTTP Server Customer
HTTPS Server Customer 72
Descripción Se activa el modulo de pago que permite a los clientes efectuar recargas directamente desde su pagina personal utilizando distintos métodos (ej: PayPal) En producción se deja el parámetro en blanco. Se utilizará solamente la web segura
https://IPservidor
Dirección IP del servidor Linode
o de su servidor local o nombre de dominio Server Customer IP/Domain
IPservidor
Dirección IP del servidor Linode o de su servidor local o nombre de dominio
Secure Server Customer IP/Domain
IPservidor
Dirección IP del servidor Linode o de su servidor local o nombre de dominio
Application Customer Path
/customer/
Carpeta web clientes
Secure Application Customer Path
/customer/
Carpeta web clientes
Application Customer Physical Path
/customer/
Carpeta web clientes
Secure Application Customer Physical Path
/customer/
Carpeta web clientes
Enable SSL
Yes
Acceso seguro activado para el proceso de pago.
HTTP Domain
IPservidor
Dirección IP del servidor Linode o de su servidor local o nombre de dominio
Directory Path
/customer/
Carpeta web clientes
Payment Amount
5:10:20:25:50
Valores (en dolares) que los clientes pueden escoger para recargar su cuenta
Item Name
Compra Recarga
Un nombre para la operación de recarga (personalizar). Aparecerá cuando el cliente acceda a la pagina de pago del método utilizado
Currency Code
USD
Moneda utilizada para los pagos (se puede personalizar)
Paypal Payment URL
https://www.paypal.com/cgibin/webscr
Gateway PayPal para los pagos
Paypal Verify URL
ssl://www.paypal.com
URL de verifica para PayPal
Authorize.NET Payment URL
https://secure.authorize.net/gate way/transact.dll
URL para los pagos con Authorize.Net
PayPal Store Name
VozToVoice
Nombre de la tienda/empresa que aparecerá al momento del pago (Personalizar)
73
Transaction Key
asdf1212fasd121554sd4f5s45sdf Clave de seguridad aleatoria para los pagos
Secret Word
Si para los pagos se utiliza Skrill, aquí hay que indicar la clave secreta de la cuenta
Payment Amount
100:200:500:1000
Valores (en dolares) que los revendedores pueden escoger para recargar su cuenta
Charge for the paypal extra fees
Yes
Con Yes se asumen los costos de las comisiones que cobra PayPal. Con No las comisione de PayPal se cobran a los clientes
PlugnPay Payment URL
https://pay1.plugnpay.com/paym URL para pagos con el servicio ent/pnpremote.cgi PlugnPay
HTTP Server Agent
En producción se deja el parámetro en blanco. Se utiliza solamente web segura
HTTPS Server Agent
https://IPservidor
Dirección IP del servidor Linode o de su servidor local o nombre de dominio.
Secure Server Agent IP/Domain
IPservidor
Dirección IP del servidor Linode o de su servidor local o nombre de dominio
Application Agent Path
/agent/Public/
Carpeta web acceso revendedores
Secure Application Agent Path
/agent/Public/
Carpeta web acceso revendedores
Application Agent Physical Path /agent/Public/
Carpeta web acceso revendedores
Secure Application Agent Physical Path
/agent/Public/
Carpeta web acceso revendedores
Paypal Amount Subscription
10
PayPal permite pagos de forma recurrente y automática. Este parámetro indica el valor que se recargará en la cuenta del cliente
Paypal Subscription Time period 1 number
Este parámetro indica cada cuantos (días, semanas. meses, años) se efectuará el pago automático. Depende del próximo parámetro.
Paypal Subscription Time period M
D = Día W = Semana M = mes Y
74
= año Enable PayPal subscription
Yes
Con Yes se habilitan los pagos recurrentes en la pagina personal de los clientes, con no se deshabilitan
Paypal Subscription account
[email protected]
Correo Electrónico de la cuenta de PayPal que se utilizará para los pagos recurrentes (personalizar)
En en próximo menú, signup, se configuran todos los parámetros relacionados con la creación de nuevos clientes. Es aquí que se define si los clientes se pueden registrar desde una pagina Web, que tipo de datos se les pedirá, que planes de llamadas pueden escoger y si se les regala un crédito de prueba inicial. A diferencia de los clientes, los revendedores no se pueden registrar por su cuenta. Solo los administradores pueden crear las cuentas de los revendedores.
Titulo
Valor
Descripción
Enable
Yes
Los clientes se pueden registrar desde la pagina Web de A2Billing
Captcha Security
Yes
Se añade un bloque para evitar registros no deseados (SPAM)
Credit
1
A cada nuevo cliente se le otorga un dólar de crédito (personalizar)
CallPlan ID List
1,2
Numero ID de los planes de llamadas que un cliente puede escoger al momento de registrarse
Card Activation
No
No = Las cuentas de los clientes tendrán que ser activadas por un administrador. Ayuda a evitar fraudes
Access Type
0
Con 0 el cliente podrá efectuar una llamada a la vez. Con uno más de una llamada a la vez.
75
Paid Type
0
Tipo de tarjeta que se creará 0 = prepago 1= postpago
Credit Limit
0
Utilizado solo para tarjetas postpago. Indica el crédito disponible predefinido que tendrá cada nueva tarjeta PostPago creada en el sistema
Run Service
0
A la nuevas cuentas creadas, por defecto, no se aplicarán cargos adicionales (si configurados)
Enable Expire
0
Tarjeta. 0 = no se vence 1 = se vence
Date Format
DD-MM-YYYY HH:MM:SS
Formato de la fecha en que las nuevas cuentas creadas se vencen. El formato predefinido es: YYYY-MM-DD HH:MM:SS Ejemplo: 2030:12:31 00:00:01. Se deja vacío.
Expire Limit
0
Numero de días después de los cuales la cuenta creada se vence. 0 = nunca
Create SIP
Yes
Se creará una cuenta SIP
Create IAX
No
No se creará una cuenta IAX2. El protocolo IAX2 no es muy utilizado en los softphone y teléfonos VoIP de escritorio.
Activate Card
No
Para confirmar la creación de la cuenta el cliente recibirá un correo electrónico con un enlace para que confirme su registro. Si está en Yes el cliente no tendrá que confirmar la cuenta.
Customer Interface URL
https://IPservidor/customer/
Dirección web que aparecerá al cliente en el correo electrónico que recibirá una vez que haya confirmado su cuenta. IP servidor = dirección IP del servidor Linode o de su servidor local
Asterisk Reload
No
Como las extensiones SIP se guardan en una base de datos no
76
hace falta recargar la configuración de Asterisk cada vez que se cree una nueva cuenta. Si no se trabaja con Asterisk Realtime hay que configurar este parámetro con Yes Language field
Yes
El cliente puede escoger el idioma
Currency field
Yes
El cliente puede escoger el tipo de moneda
Last Name Field
Yes
Se le pedirá el apellido
First Name Field
Yes
Se le pedirá el nombre
Address Field
Yes
Se le pedirá la dirección
City Field
Yes
Se le pedirá la ciudad
State Field
Yes
Se le pedirá la región/departamento
Country Field
Yes
Se le pedirá el País/Nación
Zipcode Field
No
No se le pedirá el código Postal
Timezone Field
Yes
Podrá escoger la zona horaria
Phone Field
Yes
Se le pedirá el teléfono
Fax Field
No
No se le pedirá el numero del FAX
Company Name Field
No
No se le pedirá el nombre de su empresa
Company Website Field
No
Ni la Web de su empresa
VAT Registration Number Field
No
Ni el numero de referencia para el pago de los impuesto que se añadiría a la facturas.
Traffic Field
No
No se le mostrará el campo para definir el tipo de trafico que tiene planeado realizar
Traffic Target Field
No
Sobre que tipo de destinaciones sería ese trafico.
Si se quiere efectuar una primera prueba, en una nueva pestaña del navegador, se pone la siguiente dirección (sostituir IPServidor con la IP de su servidor Linode o servidor local): https://IPservidor/customer 77
y cuando aparece esta pagina:
Se presiona el enlace en la linea “To sign up Click here”. Aparecerá la pagina para registrarse:
Como se puede ver, a los nuevos clientes se les pedirán solamente los datos que se acaban de configurar en el menu “signup”. Como faltan algunas partes de la configuración de A2Billing, el 78
cliente no puede todavía registrarse. Se regresa a la pestaña del navegador donde se estaba anteriormente configurando A2Billing y se continua con el menú backup. En este menú se configurarán todos los parámetros relacionados con las copias de seguridad de la base de datos a2billing y con el archivo de los registros de las llamadas.
Titulo
Valor
Descripción
Backup Path
/tmp
Carpeta donde se guardarán las copias de backup de la base de datos a2billing
GZIP Path
/bin/gzip
Posición del programa gzip
GunZip Path
/bin/gunzip
Posición del programa gunzip
MySql Dump Path
/usr/bin/mysqldump
Posición del programa mysqldump
PGSql Dump Path
/usr/bin/pg_dump
Posición del programa pg_dump
MySql Path
/usr/bin/mysql
Posición del programa MySQL
PSql Path
/usr/bin/psql
Posición del programa PostgreSQL
Archive Calls
12
Los archivos de las llamadas anteriores a los 12 meses se archivarán en otra tabla de la base de datos “a2billing” y no podrán ser consultados más por los clientes. En el caso que el sistema tenga mucho trafico, es aconsejado bajar este valor a 6 meses
Se sigue con el menú webui donde se configuran, entre otras cosas, la grabación de las llamadas, la música de espera personalizada, como exportar algunos tipos de datos en archivos con formato CSV y la configuración de la venta de DID en el caso se tenga una cuenta con el proveedor DIDX.net, que es el único proveedor de números geográficos cuyas API están implementadas en A2Billing.
79
Titulo
Valor
Descripción
SIP File Path
/etc/asterisk/additional_a2billing_sip.conf Carpeta y nombre del archivo donde se guardarán las extensiones SIP creadas en A2Billing si no se utiliza el Asterisk Realtime
IAX File Path
/etc/asterisk/additional_a2billing_iax.conf Como el anterior para las extensiones IAX2
API Security Key
Ae87v56zzl34v
A2billing suporta unas API para consultas web. Esta es la clave para utilizar las API.
Authorized IP
127.0.0.1
Direcciones IP que pueden acceder a las API (separadas con un punto y coma). En esta caso solamente localhost o 127.0.0.1
Admin Email
[email protected]
Correo electrónico del administrador (personalizar)
MOH Directory
/var/lib/asterisk/mohmp3
Carpeta para la música de espera personalizada (No aplica)
MOH Classes
10
Clases de música en espera que se utilizarán. (No aplica).
Display Help
No
No se mostrarán las ayudas en las paginas de A2Billing
Max File Upload Size
8192000
Tamaño máximo (en Byte) de los archivos de las tarifas que se cargan en A2Billing. En el caso
80
que se quiera aumentar el valor, hay que modificar este parámetro: upload_max_filesize en el archivo de configuración de PHP (php.ini) que normalmente se encuentra en la carpeta /etc. Una vez efectuado el cambio hay que reiniciar el servidor Web. service httpd restart Audio Directory Path
/var/lib/asterisk/sounds/a2billing
No se utiliza (obsoleto)
Max Audio File Size
8192000
Tamaño máximo de los archivos audio que se podrán cargar en el sistema
Extensions Allowed
gsm, mp3, wav
Formatos audio permitidos
Music Files Allowed
mp3
Formato audio de los archivos audio cargados para la música de espera.
Link Audio
No
No se creará un enlace en los registros de las llamadas a los archivos de las llamadas grabadas
Monitor Path
/var/spool/asterisk/monitor
Carpeta donde se guardarán las llamadas grabadas
Monitor Format
gsm
Formato audio de las llamadas grabadas
Currency
usd, eur, cad, hkd
Monedas predefinidas brindadas a los clientes
Card Export Fields
card.id, username, useralias, lastname, Si se exportan las tarjetas credit, tariff, activated, language, inuse, de los clliente en un currency, sip_buddy, iax_buddy archivo CSV, estos son los campos que aparecerán en el archivo exportado.
Voucher Export Fields
voucher, credit, tag, activated, usedcardnumber, usedate, currency
81
Campos exportados de los vouchers
Advance Mode
No
Si activado se mostrarán campos adicionales en la creación de los RATECARD
SIP/IAX Delete
Yes
Cuando se elimina un cliente, automáticamente se borrarán las extensiones SIP/IAX2 asociadas.
Card Show Fields
id:,username:, useralias:, lastname:,id_group:, id_agent:, credit:, tariff:, status:, language:, inuse:, sip_buddy:, iax_buddy:, nbused:,
Orden de los campos mostrados en la pagina de administración de los clientes
PNL Pay Phones
(8887798764,0.02,0.06)
Para crear reportes de llamadas a números de pago, se puede indicar aquí los números completos (o solamente el prefijo) y el costo de compra y de venta
PNL Toll Free Numbers
(6136864646,0.1,0),(6477249717,0.1,0)
Lo mismo para los números gratuitos
DIDX ID
708XXX
Si se dispone de una cuenta con DIDx, aquí se indica la ID de la cuenta (para la compra de los números geográficos)
DIDX PASS
XXXXXXXXXX
En este parámetro se indica la contraseña de la cuenta DIDX.net
DIDX MIN RATING
3
El rating mínimo (calidad) que tiene que tener el vendedor del DID según la clasificación de DIDX (de 1 a 5)
DIDX RING TO
didx
Extensión donde enviar las llamadas entrantes de los números adquiridos con DIDX
Card Serial Pad Length
3
Números de 0 de relleno para las tarjetas creadas como pertenecientes a una serie. Si se pone 3 el
82
resultado será 001. Véase menú CUSTOMERS → Card Series Rate Export Fields
destination,dialprefix,buyrate,rateinitial Campos de las tarifas que ,initblock se exportará en el archivo CSV
El el próximo menú se configurarán algunos valores básicos de las extensiones. Estos valores serán los predefinidos cada vez que se creará una nueva extensión SIP y/o IAX
Titulo
Valor
Descripción
Type
friend
Puede ser user, peer y friend
Allow
alaw,ulaw
Codec audio permitidos
Context
a2billing
Contexto asociado a cada extensión creada. El mismo que se ha creado en el archivo extensions.conf y es donde llegará cualquier llamada efectuada por un cliente del sistema.
Nat
force_rport,comedia
Como la mayoría de las extensiones se conectarán desde remoto y detrás de un router, se pone NAT=force_rport,comedia (Desde la versión 11.X de Asterisk estos son los dos nuevos parámetros)
AMA Flag
billing
Parámetro que se guardará en los registros de las llamadas y identificará todas las llamadas efectuadas utilizando A2Billing
Qualify
no
En Asterisk Realtime este parámetro se pone en no
Host
dynamic
Para extensiones remotas sin autenticación sobre IP
83
DTMF Mode
RFC2833
Protocolo para el envío de los tonos (DTMF) a lo largo de una llamada
En el menú log-files se definen los nombres de todos los archivos donde se guardarán los distintos tipos de registros relacionados con la actividad de A2Billing. No se necesita ningún tipo de cambio ya que así se han definidos durante la instalación de A2Billing. Se presentan solamente para tener un cuadro completo de la configuración de A2Billing.
Titulo
Valor
Alarm Log File
/var/log/a2billing/cront_a2b_alarm.log
Auto refill Log File
/var/log/a2billing/cront_a2b_autorefill.log
Bactch Process Log File
/var/log/a2billing/cront_a2b_batch_process.log
Archive Log File
/var/log/a2billing/cront_a2b_archive_data.log
DID Billing Log File
/var/log/a2billing/cront_a2b_bill_diduse.log
Descripción
Subscription Fee Log File /var/log/a2billing/cront_a2b_subscription_fee.log Currency Cront Log File
/var/log/a2billing/cront_a2b_currency_update.log
Invoice Cront Log File
/var/log/a2billing/cront_a2b_invoice.log
Cront Log File
/var/log/a2billing/cront_a2b_check_account.log
Paypal Log File
/var/log/a2billing/a2billing_paypal.log
EPayment Log File
/var/log/a2billing/a2billing_epayment.log
ECommerce Log File
/var/log/a2billing/a2billing_api_ecommerce_request.log
Callback Log File
/var/log/a2billing/a2billing_api_callback_request.log
Webservice Card Log File /var/log/a2billing/a2billing_api_card.log AGI Log File
/var/log/a2billing/a2billing_agi.log
La parte más importante de la configuración de A2Billing es el menú agi-conf1 donde se definirán todos los parámetros que utilizará el AGI de A2Billing para las llamadas.
84
Titulo Call to free DID Command Params
Valor Dial ,60,L(%timeout%:61000:30000)
Descripción Opciones para la aplicación Dial de Asterisk para las llamadas a números geográficos configurados en el sistema por los cuales no se cobran las llamadas entrantes.
Description
Wholesale
Un nombre para este perfil
Asterisk Version
1_11
Versión de Asterisk utilizada
Answer Call
No
El AGI no contestará la llamada
Play Audio
No
Se deshabilita el utilizo de las locuciones audio
Say GoodBye
No
No se utilizará la locución Goodbye al terminar una llamada
Play Language Menu
No
No se presentará el IVR para escoger el idioma
Force Language
Fuerza el uso de un idioma para las locuciones. No aplica para Wholesale
Intro Prompt
Locución de personalizada.
introducción
Min Call Credit
0.5
Crédito mínimo para iniciar una llamada. Ayuda a no tener saldos negativos
Min Bill Duration
0
Duración mínima para que la llamada sea cobrada. 0 = se cobra a partir del momento en que es contestada.
Not Enough Credit
No
Con yes; si el cliente no tiene suficiente crédito en la tarjeta que está utilizando, se le permitirá seleccionar otra. No, no se le permite
85
Titulo
Valor
Descripción
New Caller ID
No
Si el precedente parámetro está en Yes y este parámetro también, se asocia el CallerID del cliente a la nueva tarjeta
Use DNID
Yes
Con Yes: si la variable DNID contiene el numero marcado (en Asterisk es así), al cliente no se le pide que ingrese el numero a marcar
Not Use DNID
2400,2300
Lista de números que si marcados enviarán la llamada a la locución que solicitará el numero a marcar seguido de la tecla numero aunque el parámetro anterior esté configurado con Yes.
Try Count
1
Numero de intentos permitidos al cliente para marcar un numero (para Wholesale tiene que ser 1)
Force CallPlan
Para forzar el utilizo de un Callplan determinado (no se utiliza en este caso)
Say Balance After Auth
No
No se anuncia el crédito disponible después de la autenticación
Say Balance After Call
No
No se anuncia el crédito disponible al terminar la llamada
Say Rate
No
No se anuncia el costo de la llamada
Say Duration
No
No se anuncia la duración máxima de la llamada en base al crédito disponible
Auto Set CLID
No
No se configura el CallerID en automático
Force CLID
86
Si el parámetro anterior está en yes y este contiene un numero, ese numero se utiliza como identificativo de llamada para las llamadas salientes.
Titulo
Valor
Descripción
CLID Sanitize
CID
Si el parámetro anterior no está configurado, en este parámetro se configura cual numero se utilizará para el identificativo de las llamadas salientes del cliente: • NO: desactivado • CID: uno de los números configurados por el cliente como identificativos de llamada • DID: uno de los números geográficos adquiridos por el cliente • BOTH: el identificativo de llamada puede ser o un DID del cliente o uno de los números configurados por el cliente.
CLID Enable
No
No se autentica el cliente en base a su CallerID
Ask PIN
No
No se le pide al cliente de introducir su PIN
FailOver LCR/LCD Prefix
No
Si en un CallPlan están presentes dos tarifas distintas para terminar la llamada (ejemplo prefijos 573 y 57) y se llama a un celular de Colombia, el sistema intentará sacar la llamada con la primera tarifa (573). Si no tiene éxito, se intentará utilizar la segunda tarifa (57). Con No se desactiva esta funcionalidad
Auto CLID
No
Si el cliente no se puede autenticar con el CallerID se le pedirá su numero de tarjeta e automáticamente se asociará al numero de tarjeta el CallerId del teléfono de donde está
87
Titulo
Valor
Descripción llamando el cliente. Con NO se desactiva.
Auto CLID Security
No
Con yes se controla que el CallerID del cliente esté asociado con la tarjeta que está utilizando para la llamada.
SIP Call
No
Se habilita para permitir llamadas entre las extensiones SIP/IAX2 configuradas en el sistema y asociadas a los clientes.
SIP Call Prefix
555
Prefijo que hay que anteponer al numero de extensión SIP/IAX2 que se quiere llamar (funciona si SIP CALL = Yes)
Direct Call
No
Si se habilita no se presentará una locución para marcar un numero. Si este numero empieza por 555 la llamada sera cursada hacia la extensión SIP/IAX marcada; de otra forma se cursará normalmente
IVR Voucher Refill
No
Si está en Yes se permite recargar las tarjetas utilizando un voucher
IVR Voucher Prefix
8
Dígito a marcar desde el menú de tarjetas prepago para recargar la cuenta con un voucher
IVR Low Credit
No
Si está en Yes y el crédito disponible del cliente es menor que el valor definido en el parámetro “Min Call Credit”, se presentará en automático el IVR para recargar la tarjeta utilizando un voucher
Dial Command Params
,60,rL(%timeout%:61000:30000) Opciones para el comando Dial de Asterisk. La opción r que aparece en la linea genera un timbrado falso. En algunos dispositivos este timbrado puede generar problemas de
88
Titulo
Valor
Descripción facturación de la llamada. En esos casos, se quita la r de la linea de configuración del parámetro.
SIP/IAX Params
Dial
Command ,60,L(3600000:61000:30000)
Opciones para el comando Dial para llamadas entre extensiones:Duración máxima de este tipo de llamadas 3600000 mili segundos = 1 hora
Outbound Call
No
Forma de marcar el numero: No = SIP/Proveedor/numero – Yes = SIP/numero@IPProveedor
Failover Retry Limit
1
Numero de intentos de cursar la llamada utilizando las troncales de respaldo
Max Time
3600
Numero máximo de segundos de duración de una llamada cuya tarifa es igual o inferior a 0
Send Reminder
No
Yes = se envía un correo electrónico al cliente cuando su crédito es inferior al valor del parámetro “ Min Call Credit”
Record Call
No
Yes = se grabará el audio de todas las llamadas
Monitor File Format
gsm
Formato audio utilizado para grabar las llamadas
AGI Force Currency
Indicando una moneda el crédito disponible se anunciará en la moneda indicada en este parámetro en lugar de la moneda configurada por el cliente en su pagina personal
Currency Associated
usd:dollars,mxn:pesos,eur:euros, Locuciones para las monedas cop:pesos,all:credit configuradas
Option Local Dialing
No
89
No añadir el prefijo internacional del cliente si el numero marcado contiene un 0 inicial. Con Yes se añade
Titulo
Valor
Descripción
Max time to Call a DID no 3600 billed
Tiempo de duración de una llamada a un Numero geográfico configurado en el sistema para el cual no se cobran las llamadas entrantes. 3600 segundos = 1 hora.
File Enter Destination
prepaid-enter-dest
Locución utilizada para pedir al cliente el numero a marcar
Menu Language Order
es:en:fr
Lista de idiomas disponibles en el IVR que permite escoger un idioma para las locuciones
Bill Callback
Yes
Se cobrará la llamada de Callback del primer canal aunque el segundo canal no ha contestado o no se ha podido establecer la llamada
International prefixes
011,00,09
Prefijos internacionales que se quitarán del numero marcado por el cliente si el CallPlan lo prevea
Extra charge DIDs
1800,1900
Cargos adicionales para DID que empiecen con 1800 0 1900 (por minuto)
Extra charge DID fees
0,0
Se indican los costos, por minuto, de llamadas a los números que empiecen con el prefijo indicado en el parámetro anterior.
Extra charge DID buy fees
0,0
Se indican los costos adicionales para la compra de números cuyo prefijo está presente en el parámetro “Extra charge DIDs”
Max Time For Unlimited Calls 3600
Tiempo máximo de duración de una llamada incluida en un paquete de minutos gratuitos cuyo paquete tiene configurado en el parámetro PACKAGE TYPE el valor “Unlimited calls”
Max Time For Free Calls
Tiempo máximo de duración de
90
3600
Titulo
Valor
Descripción una llamada incluida en un paquete de minutos gratuitos cuyo paquete tiene configurado en el parámetro PACKAGE TYPE el valor “Number of Free calls”.
CallPlan threshold Deck switch
Este parámetro se utiliza para pasar un cliente de un Call Plan a otro en el momento en que haya utilizado n segundos del primero. Los valores se indican de la siguiente forma: ID Call Plan : segundos (coma) ID segundo Call Plan : segundos. Ejemplo: 1:3600,2:7200
Disable annoucement the No second of the times that the card can call
Yes = no anuncia el numero de segundos si el cliente tiene disponible para la llamada más de un minuto
Currency Cents Association
Define las locuciones que se utilizarán para los centavos según la moneda.
usd:prepaid-cents,eur:prepaidcents,gbp:prepaid-pence,all:credit
Default Accountcode
Si en este parámetro se indica el numero de un cliente, o ACCOUNTCODE, todas las llamadas que utilizarán este agiconf se cobrarán a ese cliente. Esto dependiendo de la configuración del parámetro “Default Accountcode Behaviour” que aparece más adelante. Se deja vacío
Verbosity
3
Configura el nivel de verbosidad de los registros de A2Billling 3 = INFO
Logging
3
Lo mismo para lo registros de LOG 3 = INFO
Dial Balance reservation
0.25
Crédito que se reserva para cada llamada en el caso de clientes que pueden utilizar más de una canal a la vez. Ayuda a prevenir la presencia de saldos
91
Titulo
Valor
Descripción negativos
Option CallerID update
No
Yes = Se permite al cliente de actualizar su CallerID antes de realizar una llamada.
Auto Create Card
No
Si está en yes y el CallerID del cliente se captura, se generará una nueva tarjeta de llamadas con asociado ese CallerID
Auto Create Card Length
10
Longitud del numero de tarjeta generado automáticamente
Auto Create Card Type
PREPAID
Tipo de tarjeta generada automáticamente (PREPAID = prepago; POSTPAID = postpago)
Auto Create Card Credit
0
Crédito disponible en la tarjeta creada automáticamente (si es prepago)
Auto Create Card Limit
0
Si es una tarjeta postpago, aquí se fija el limite de crédito disponible para la tarjeta generada automáticamente
Auto Create Card TariffGroup
1
ID del Call Plan que se utilizará para la tarjeta generada automaticamente
Busy Timeout
3
Tiempo, en segundos, de duración del tono de ocupado
Callback Reduce Balance
1
Monto que se quitará al crédito disponible del cliente para asegurarse que la llamada de callback tenga crédito suficiente.
IVR Locking option
No
Si está en Yes permite al cliente configurar un segundo código para acceder a su cuenta
IVR Account Information
No
Si está en Yes permite al cliente consultar una serie de datos relacionados con su cuenta
IVR Speed Dial
No
Si está en Yes permite al cliente configurar los números de marcado rápido
92
Titulo
Valor
Descripción
Play rate lower one
0
Si está en Yes anuncia el valor de la llamada aunque el costo sea menor de un centavo
Callback Beep for Destination
No
= Yes a lo largo de una llamada de callback, el cliente escuchará un beep cuando la llamada se establece.
Callback CID Prompt Confirm No PhoneNumber
Si está en Yes a quien inicia una llamada de callback se le pedirá de confirmar su numero
LCR Mode
Este parámetro ha sido añadido desde la versión 2.0 de A2Billing. Si el valor es 0 A2billing busca el prefijo que más se acerca al numero marcado en todas las RateCard presentes en un CallPlan y escoge la ruta más barata. Si el valor es 1 A2Billing busca en cada RateCard presente en un CallPlan el prefijo que más se acerca al numero marcado y entre todos los encontradas, escoge la ruta más barata. Más adelante se mostrará como se utiliza esta nueva funcionalidad.
1
Default Accountcode Behaviour No
Si está en Yes utiliza el ACCOUNTCODE definido en el parámetro “Default Accountcode” aunque la llamada tenga asociado un ACCOUNTCODE. Si está en no aplicará este ACCOUNTCODE solamente para las llamadas que no tengan uno asociado.
Si se quiere activar la configuración para permitir las llamadas entre extensiones. En el agi-conf1 se modifican estos parámetros:
SIP Call 93
No
Se
habilita
para
permitir
llamadas gratuitas entre las extensiones SIP/IAX SIP Call Prefix
555
Prefijo que hay que anteponer al numero de extensión SIP/IAX que se quiere llamar
Direct Call
No
Si se habilita no se presentará una locución para marcar un numero. Si este numero empieza por 555 la llamada sera cursada hacia la extensión SIP/IAX marcada; de otra forma se cursará normalmente
SIP Call
Yes
Se habilita para permitir llamadas gratuitas entre las extensiones SIP/IAX
SIP Call Prefix
555
Prefijo que hay que anteponer al numero de extensión SIP/IAX que se quiere llamar
Direct Call
Yes
Si se habilita no se presentará una locución para marcar un numero. Si este numero empieza por 555 la llamada sera cursada hacia la extensión SIP/IAX marcada; de otra forma se cursará normalmente
Para que queden:
Para llamar de una extensión a otra habrá que marcar 555 + el parámetro que aparece en esta columna de cada cliente:
94
Si por ejemplo el primer cliente de la lista quiere llamar el segundo, tendrá que marcar: 555 837943829751935 El parámetro LOGIN que se llama también ALIAS, se puede modificar en cualquier momento y esto permite simplificar los números que deben marcar los clientes para llamarse entre ellos. En este caso, como las llamadas entre extensiones se realizarán a nivel de OpenSIPs, esta configuración no aplica. En el menú notifications, se configurará la parte relacionada con los avisos que se enviarán a los clientes cuando su crédito se está agotando. Aquí se definen los distintos valores que el cliente puede escoger y cada cuando enviar los avisos. Para que este modulo sea activo, el cliente tiene que configurarlo en su pagina personal.
Titulo
Valor
Descripción
List of possible values to notify
1:3:5:10:20:50:100:500:1000
Valores que el cliente puede escoger (1 dólar, 3 dolares, etc)
Notications Cron Module
1
Con 0 se deshabilita el modulo
Notications Delay
1
Cada cuantos días enviar la notifica. Si se configura con 0, la notifica se enviará cada vez que se ejecute el cron relativo (por defecto a la medianoche de cada día)
En dashboard se configura la posición de distintos cuadros que aparecerán en la pagina de administración de A2Bbilling cuando se presione el siguiente menú:
95
Titulo
Valor
Descripción
Enable info module about customers
LEFT
Modulo clientes
Enable info module about refills
CENTER
Modulo recargas
Enable info module about payments
CENTER
Modulo Pagos
Enable info module about calls
RIGHT
Modulo Llamadas
Enable info module about system
LEFT
Modulo Info sistema
Enable news module
NONE
Modulo novedades acerca del programa
Para terminar en el ultimo menú, webagentui, se configuran dos parámetros que definen lo que puede o no puede hacer un agente desde su pagina personal.
Titulo
Valor Descripción
Personal Info
1
El revendedor puede modificar sus datos personales. Con 0 no puede
Authorize Remittance Request
1
Con 1 se habilita en la pagina del revendedor el enlace para solicitar el pago de sus comisiones. Con 0 se deshabilita.
Terminada la configuración de los parámetros del sistema de facturación, se puede empezar con la creación de los proveedores que se utilizarán para terminar las llamadas con sus relativas tarifas. 4.2 Configuración de los Proveedores Para poner en marcha A2Billing hay que seguir este orden: • • • 96
Configurar los proveedores Configurar las troncales Configurar los Callplan
• • • •
Configurar los RateCard Asociar los Ratecards a los Callplan Importar las tarifas Crear los clientes
Siguiendo la lista, se empieza configurando los proveedores: En el menú de la izquierda de la pagina de administración de A2Billing se selecciona Providers → Providers:
En la pagina que aparece, se selecciona “Add Provider” y se rellenan los campos con los siguientes valores:
Se confirma la creación del nuevo proveedor presionando el Botón “Confirm Data”. Luego se pasa a la configuración de las troncales utilizando el siguiente menú:
En la pagina que aparece, se selecciona “Add Trunk” y se rellenan los campos con los siguientes valores:
97
Una pequeña explicación de los valores: VOIP PROVIDER: el nombre del proveedor como se ha configurado en PROVIDERS → Providers LABEL: una etiqueta que identifique esta troncal ADD PREFIX: como se verá al momento de configurar las tarifas, normalmente estas se añaden utilizando los códigos de los países sin el 00 por delante. Cuando se marca un numero, para que el AGI pueda buscar en la base de datos una ruta para el destino, se quita al numero marcado (si presentes) los prefijos definidos en este parámetro del grupo agi-conf1: International prefixes
011,00,09
Prefijos internacionales que se quitarán si el CallPlan lo prevea
Una vez que a2billing haya encontrado la ruta para la llamada, hay que volver a poner los dos 00 si el proveedor exige que las sintaxis para marcar un numero sea: 00 + código país + numero. Es por eso que en este campo se pone 00. En el caso que el proveedor venda distintos tipos de rutas (Oro, 98
Platino,Premium, CLI) será el mismo proveedor que indicará que tipo de prefijo hay que poner delante del numero marcado para salir con una tarifa en lugar de otra. PROVIDER TECH: aquí se define que tipo de protocolo se utiliza para la troncal que se está configurando. En este caso SIP. Puede ser SIP, IAX2, DAHDI PROVIDER IP: en este campo se indica la IP del proveedor o mejor aun la etiqueta inicial de la troncal como se ha definido en el archivo sip.conf. En este caso voztovoice1 es la troncal configurada FAILOVER TRUNK: como esta es la primera troncal que se define, no se puede seleccionar ninguna troncal de respaldo MAXIMUM CONNECTIONS: numero máximo de canales que brinda el proveedor. En este caso 30 STATUS: La troncal está activada Se guarda la configuración presionando el botón “Confirm data”. Se vuelve nuevamente al menú Trunks y se configura la segunda troncal de la siguiente forma:
99
Los únicos dos campos que varían son: LABEL y PROVIDER IP. En el primero se pone una etiqueta para la segunda troncal y en el segundo el nombre voztovoice2 como configurado en el sip.conf. Se presiona el botón “Confirm Data”. Ahora en la lista de troncales aparecerá:
Se borra la que venía con la instalación de A2Billing y se confirma presionando el botón Delete:
Es siempre una buena practica tener configurada una troncal de respaldo en el caso que la primera no esté funcionando. Algunos proveedores proveen este servicio brindando dos troncales con distintas IP. La primera se utiliza como principal y la segunda como respaldo. En este caso se utilizará la segunda troncal como respaldo de la primera. Se vuelve al menú Trunks y se selecciona el icono para modificar la primera troncal:
En la pagina que aparece, en el campo: FAILOVER TRUNK se selecciona voztovoice2:
100
Se guardan los cambios presionando el botón “Confirm Data”. 4.3 Creación de los planes de llamadas y de las tarifas Siguiendo la lista indicada en el párrafo anterior, se continua con la creación de los Callplan, Ratecard y la importación de las tarifas. Para crear un Callplan se entra en el menú RATES → Callplan
En la nueva pagina se selecciona “Add Callplan”. Aparecerá la siguiente ventana:
Los campos: NAME: nombre del Callplan. En este caso Base. LCR TYPE: en este campo se define si se escogerán las rutas más baratas desde el punto de vista del vendedor o del cliente. En este caso desde el punto de vista del vendedor. PACKAGES: se puede añadir al Callplan un paquete de minutos gratuitos o de llamadas gratuitas. En este caso se deja el valor predefinido ya que todavía no se han creados paquetes de este tipo. REMOVE INTER PREFIX: como ya se ha dicho anteriormente, antes de buscar una ruta hay que quitar los prefijos si están presentes en el numero marcado, como definido en este parámetro del agi101
conf1: International prefixes
011,00,09
Prefijos internacionales que se quitarán si el CallPlan lo prevea
Esto para que A2billing pueda buscar en la tabla de las tarifas la ruta para la llamada que se está cursando. Una vez encontrada la ruta, se volverá a poner los dos 00 como indicado en la configuración de las dos troncales. Se termina presionando el botón “Confirm Data” Se pasa al menú RateCards y se escoge “Add RateCard”. En la ventana que aparece se configura la RateCard:
Los campos: TARIFFNAME: el nombre que se asigna a la tarifa. Como esta tarifa se asociará al CallPlan Base que se acaba de crear, se escoge el nombre Base1 para acordarse que la Ratecard está asociada con ese CallPlan START DATE: fecha de inicio de vigencia de las tarifas. Si no se cambia será la fecha en que se ha creado. EXPIRY DATE: fecha de vencimiento de la tarifa. Como los proveedores suelen actualizar las tarifas periódicamente, cuando se carga una nueva RateCard con las nuevas tarifas, habrá que indicar la fecha exacta en que la RateCard se vencerá (caducará). 102
DESCRIPTION: en este campo se puede añadir una descripción de la tarifa. DNID PREFIX: si se quiere que esta tarifa se utilice solamente para determinados prefijos (ejemplo 573 para los celulares colombianos), hay que indicarlo aquí. Predefinido es el valor all (todos los prefijos). CALLERID PREFIX: parecido al campo precedente pero desde el punto de vista del identificador de llamada. Si por ejemplo se quiere que solo los clientes cuyo CALLERID empieza con 57 (Colombia) puedan utilizar esta tarifa hay que indicarlo en este campo. Predefinido es el valor all (todos los CALLERID) Para guardar los cambios se presiona el botón “Confirm Data”. IMPORTANTE: en algunos casos cuando se crea una nueva RateCard, el sistema en el parámetro EXPIRY DATE pone una serie de 0 como aparece en la imagen:
En estos casos hay que modificar el parámetro manualmente sino las llamadas no se cursarán. Ahora para indicar a A2Billing que esta Ratecard se debe utilizar con el Callplan Base que se ha creado anteriormente, se vuelve al menú Call plan y se modifica el CallPlan:
Aparecerá:
103
Se selecciona la RateCard Base1 y se presiona el botón “ADD RATECARD”. La pagina cambiará de esta forma:
La RateCard Base1 será parte del Callplan Base. Para guardar los cambios se presiona el botón “Confirm Data”. Se ha configurado un Callplan para los clientes y una RateCard para el Callplan. Falta solamente ingresar las tarifas. Para hacerlo hay dos métodos: • •
el manual (una a una) importando un archivo en formato CSV con todas las tarifas configuradas.
Este archivo debe contener por lo menos los siguientes datos: • • •
Prefijo Nombre del destino Tarifa de venta
Estos tres valores aunque sean suficientes para poder empezar a vender trafico telefónico, no son la mejor opción en los siguientes casos: 1. si se quiere ver en las estadísticas de las llamadas el valor de lo que se está ganando 2. si para algunos destinos la tarificación no es por segundo 3. si se quiere diferenciar la tarificación que aplica el proveedor de la que se aplica a los clientes. Por esta serie de motivos el archivo debe tener las siguientes columnas: • • • • • • • •
prefijo nombre destino tarifa de venta tarifa de compra duración mínima de la llamada que cobra el proveedor tarificación que aplica el proveedor duración mínima de la llamada que se cobrará al cliente tarificación que se aplica al cliente
Para cargar las tarifas en A2billing se utilizará OpenOffice y se buscará un proveedor de llamadas que permite descargar las tarifas desde su pagina web. En este caso se ha escogido SipTraffic. Se entra en la pagina de SipTraffic: se sigue el enlace “View our Rates”, se selecciona “See USD rates“ y para terminar se bajan las tarifas (Bronze):
104
Se guarda el archivo en el computador local. Antes de abrirlo hay que modificar la configuración de OpenOffice de forma que la división entre enteros y decimales se realice con el punto en lugar de la coma. Para eso se abre OpenOffice Calc y se selecciona el menú “Herramientas → Opciones”. En la ventana que aparece, se escoge “Configuración de idioma → Idiomas”. En el lado derecho de la ventana la configuración debe ser:
Se presiona el botón aceptar y se abre el archivo bajado del sitio web de SipTraffic. En la parte baja aparecen dos hojas: • •
Rates Numberplan
Se selecciona la hoja numberplan y se modifica de la siguiente forma:
En la primera columna se ponen los prefijos, en la segunda los nombres de los destinos, en la tercera la siguiente formula =(D1*1.15) que luego se copia en todas las celdas de la columna C. De esta forma se aumenta el valor de las llamadas de un 15% que representará la ganancia. En la columna D aparecerá el costo de las llamadas que aplica el proveedor. Las columnas C y D deben tener cinco cifras decimales. En las columnas E,F,G,H, respectivamente: • • • •
duración mínima de la llamada que cobra el proveedor tarificación que aplica el proveedor duración mínima de la llamada que se cobrará al cliente tarificación que se aplica al cliente
Como la tarificación para México es por minuto, en la hoja hay que buscar las lineas donde aparecen los distintos destinos de México y modificar la ultima cuatros columnas como da imagen: 105
Terminadas las modificaciones, se selecciona el menú “Archivo → Guardar como” y selecciona el formato CSV:
Se presiona el botón Guardar. En la nueva ventana:
Se presiona el botón “Mantener el formato actual”. En la siguiente ventana las opciones deben quedar de la siguiente forma:
106
Se presiona el botón Aceptar. De esta forma ya se tiene listo el archivo para cargarlo en A2Billing. En la pagina de administración se escoge el menú “RATES → Import”. Se seleccionan los distintos valores como se muestra en la imagen que sigue:
Se continua en la parte más abajo de la pagina presionando el botón Examinar:
y en la ventana que aparece se escoge el archivo que se acaba de guardar en formato CSV. Una vez seleccionado se presiona “Import RateCard”. El sistema empezará a importar las tarifas en la base de datos. Después de algunos segundos aparecerá esta pagina:
107
Donde se podrá comprobar si las tarifas se están importando correctamente. Una vez que se haya hecho este tipo de control se continua presionando el botón “Continue to import the RateCard”. Si aparece este error:
Significa que el archivo tiene un tamaño de más de 8Mb que es el limite que se ha configurado en el parametro: Max File Upload Size en SYSTEM SETTINGS → Global List → webui. Para que se puedan cargar las tarifas se modifica el parámetro y se pone un valor más alto. Luego se modifica la siguiente linea del archivo php.ini: nano +878 /etc/php.ini Cambiando el parámetro: upload_max_filesize = 8M Con el numero de MegaBytes configurados en A2Billing. Se guardan los cambio y se reinicia el servidor Web: service httpd restart 108
Se vuelve a la pagina de administración de A2Billing y se intenta cargar las tarifas nuevamente. Si no aparecen más errores, en el menú Rates:
estarán todas las tarifas que se acaba de importar. Si aparece este error en el navegador:
Hay que abrir el archivo CSV con un editor de texto y guardar el contenido en formato TXT sin ningún tipo de formateo. Luego se vuelve a importar las tarifas al sistema. 4.4 Configuración de los métodos de pago Terminada la parte dedicada a las tarifas y los planes de llamadas, para poner en marcha el sistema de facturación, faltan todavía unos pasos: • • • •
configurar los sistemas de pago modificar las plantillas de los correos que utiliza el sistema modificar los datos que aparecerán en las facturas de los clientes crear por lo menos un cliente
Se entra en el menú BILLING → Payment Methods:
109
En la nueva pagina estará la lista de métodos soportados por A2Biling:
El único que se utilizará para los fines de este libro, es PayPal. Por eso hay que desactivar todos los demás. Se entra en la configuración del primero de la lista presionando el botón “View Detail”:
En la nueva pagina se desactiva el método de pago seleccionando el botón “False”:
y confirmando la modifica presionando el botón “Update” que aparece al final de la pagina. Se sigue el mismo procedimiento para los pagos con Moneybookers (ahora Skrill). Para terminar se entra en el método de pago con PayPal y se añade el correo electrónico que se ha utilizado al momento de registrarse en PayPal. Ejemplo:
110
Se guardan las modificaciones presionando el botón “Update”. 4.5 Configuración para las facturas Cada vez que un cliente realice un pago/recarga, se emitirá una factura. En la factura aparecerán los datos de la empresa que está facturando. Para definir estos datos hay que entrar en el menú INVOICES → Configuration:
En la nueva pagina se rellenan los campos con los datos de la empresa que va a facturar. En la imagen que sigue un ejemplo de como se debe hacer:
111
Se guardan los cambios presionando el botón “Save”. Para añadir un logo a las facturas de la pagina de administración de A2Billing, se copia la imagen en la carpeta: /var/www/html/admin/Public/templates/default/images/ Luego se modifica el siguiente archivo: nano /var/www/html/admin/Public/A2B_invoice_view.php y después de esta linea: se añade el siguiente bloque:
112
logo.jpg es el nombre del archivo gráfico del logo de la empresa que se ha cargado anteriormente (personalizar). Se guardan los datos. Para que aparezca el logo también en la pagina de los clientes se copia la imagen del logo en esta carpeta: /var/www/html/customer/templates/default/images/ Luego se modifica el siguiente archivo: nano /var/www/html/customer/A2B_invoice_view.php y después de esta linea: se añade: Se guardan los cambios. 4.6 Plantillas de los correos electrónicos Las plantillas de los correos electrónicos, que se encuentran en la pagina de administración de A2Billing, se necesitan para enviar correos predefinidos a los clientes. Para que reflejen los datos de la empresa, hay que personalizarlos. Si en el sistema se va a utilizar solamente un idioma, se puede modificar las plantillas predefinidas que vienen en inglés. Si se quiere tener las plantillas en más idiomas, hay que traducirlas utilizando el botón “Translate” y luego escoger el idioma. Se entra en el menú MAIL → Mail Templates:
113
Se empieza modificando la primera plantilla de la lista “signup”. Este correo electrónico se enviará a un nuevo cliente para que pueda confirmar la cuenta que acaba de crear. En la imagen que sigue aparece un ejemplo de como modificar la plantilla. La parte evidenciada es la más importante porque es donde se define la dirección web donde se encuentra la carpeta customer en el servidor Linode (sostituir IPlinode con la dirección IP o nombre de dominio del servidor Linode o del servidor local):
Para guardar la modificaciones se presiona el botón “Confirm Data”. Se continua con las demás plantillas y se personalizan siguiendo el patrón de la primera. 4.7 Creación de un cliente Como se ha visto en los párrafos anteriores, los clientes se pueden registrar en autonomía utilizando la pagina web dedicada . En este párrafo se verá como crear un cliente desde la pagina de administración de A2Billing. Más adelante se efectuará una prueba de registro utilizando la pagina de los clientes. Para crear un nuevo cliente se entra en el menú CUSTOMERS → Add::Search: 114
Se presiona el enlace “Add Customer”:
En en la pagina que sigue, se rellenan todos los campos creando un cliente para las pruebas:
En el primer bloque aparecen las siguientes informaciones: ACCOUNT NUMBER: es el numero de la tarjeta del nuevo cliente generada automáticamente por el sistema. Este numero es también el PIN que el cliente tendrá que marcar en el caso que el sistema se lo pida: es también el numero de extensión que habrá que configurar para conectarse al servidor Asterisk. La longitud predefinida es 5, como indicado en el parámetro “Card Number length” in SYSTEM SETTINGS → Global List → Global WEBUI LOGIN: es el numero que el cliente tendrá que ingresar para poder acceder a su cuenta personal desde la pagina Web de los clientes. En lugar de este numero, para acceder a la pagina web personal, el cliente puede utilizar también el correo electrónico que ha indicado al momento de registrarse. Si activado en el agi-conf1, este numero representa también el numero a marcar para llamadas entre extensiones. Mientras el ACCOUNT NUMBER una vez creado no se puede modificar, el WEBUI LOGIN se puede personalizar en cualquier momento. La longitud predefinida es 5, como 115
indicado en el parámetro “Card Alias length” in SYSTEM SETTINGS → Global List → Global WEBUI PASSWORD: es la clave para acceder a la cuenta personal desde la pagina Web de los clientes y también para registrarse al servidor Asterisk. Es generada automáticamente por A2Billing. BALANCE: es el crédito disponible. En este caso no se asigna ningún crédito al nuevo cliente CUSTOMER GROUP: los clientes tienen que pertenecer a un grupo. Más adelante se verá para que sirven, como se utilizan y como se configuran. En este caso se selecciona el predefinido DEFAULT SERIAL: se utiliza si al cliente se aplica un determinado tipo de tarjeta prepago (no aplica)
En el segundo bloque se indican los datos personales del cliente.
116
El tercer bloque está dedicado al estado del cliente: PAYMENT TYPE: se indica el tipo de tarjeta. En este caso prepago (PREPAID CARD) CALL PLAN: es el plan de llamadas que utilizará el cliente. Base es el que se ha configurado anteriormente y, por ahora, el único disponible. DIDGROUP: en el caso que el cliente esté asociado a un grupo de números geográficos que pueda adquirir, en este parámetro se indica el nombre del grupo TIMEZONE: zona horaria del cliente (en este caso Bogotá) LANGUAGE: idioma predefinido para el cliente 117
CURRENCY: moneda en que el cliente manejará su cuenta. STATUS: es el estado de la cuenta. ACTIVE significa que la cuenta está activa y se puede utilizar. LOCK: es posible asociar a la cuenta un segundo PIN (clave) LOCK PIN: es la clave si LOCK está activado SIMULTANEOUS ACCESS: es posible permitir al cliente de efectuar más de una llamada a la vez. En este caso con SIMULTANEOUS ACCESS el cliente podrá cursar más de una llamada a la vez. Si se selecciona INDIVIDUAL ACCESS el cliente podrá cursar solamente una llamada a la vez. RUN SERVICE: es posible aplicar costos adicionales a la cuenta del cliente. Pueden ser, por ejemplo, por cada llamada o basados en el tiempo. En este caso no se activan CREDIT LIMIT: aplica solamente a clientes postpago e indica un monto máximo que el cliente puede gastar cada mes. CREDIT LIMIT NOTIFICATION: si se quiere enviar al cliente una notificación cuando el crédito de su cuenta se está agotando en este parámetro se indica un valor en dolares entre los definidos anteriormente en el System Settings. Si, por ejemplo se escoge 5, cuando el crédito del cliente sea menor que 5 dolares, se le enviará una notificación. Se deja vacío. PERMITTED NOTIFICAYIONS BY EMAIL: si se selecciona, cuando el crédito del cliente esté por debajo del valor indicado en el parámetro anterior, recibirá una notificación al correo electrónico indicado en el próximo parámetro. Se deja en No. EMAIL NOTIFICATION: Dirección de correo electrónico donde el cliente recibirá la notificaciones relacionadas con el crédito bajo. CAMPAIGN: si queremos permitir al cliente de gestionar campañas (llamadas a clientes tipo call center) en este campo tenemos que definir la campaña que podrá utilizar el cliente (no aplica). FIRST USE DATE: en este campo aparecerá fecha y hora de cuando el cliente ha utilizado por primera vez la tarjeta ENABLE EXPIRY: se puede definir una duración máxima para la tarjeta basada en tres tipos di opciones: • EXPIRY DATE - Una fecha predefinida • EXPIRY DAYS SINCE FIRST USE - Un numero de días que empiezan a contar después del primer uso • EXPIRY DAYS SINCE CREATION - Un numero de días que empiezan a contar desde la creación del cliente EXPIRY DATE: fecha en que la tarjeta se vence si ENABLE EXPIRY se ha activado con la opción EXPIRY DATE 118
EXPIRY DAYS: numero de días después de los cuales la tarjeta se vencerá si en el parámetro ENABLE EXPIRY se haya activado EXPIRY DAYS SINCE FIRST USE o EXPIRY DAYS SINCE CREATION CREATE SIP CONFIG: con yes se creará una extensión SIP asociada al cliente CREATE IAX CONFIG: con no, no se creará una extensión IAX2 asociada al cliente. Por defecto el sistema está configurado para crear la cuenta IAX2. Si no se va a utilizar extensiones IAX2, lo mejor es desactivar por defecto su creación. Se realiza modificando la linea 777 de este archivo: nano +776 /usr/local/src/a2billing/admin/Public/form_data/FG_var_card.inc se pone 0 en lugar del 1 presente. Se guardan los cambios. Si ahora se crea un nuevo usuario, la opción CREATE IAX CONFIG estará desactivada por defecto. MAC ADDRESS: utilizado en el caso que se quiera asociar al cliente el MAC ADDRESS del dispositivo utilizado para realizar las llamadas. IN USE: en este campo aparecerán el numero de llamadas activas del cliente MAX CONCURRENT CALLS: el numero de llamadas simultaneas permitidas al cliente en el caso el parámetro SIMULTANEOUS ACCESS esté configurado con la opción SIMULTANEOUS ACCESS. Como dice la legenda esta funcionalidad todavía no está implementada (no funciona). Se verá más adelante como implementarla apoyándose a un Servidor NoSQL (Redis).
En los bloques presentes en la imagen de arriba se configuran los últimos parámetros: AUTOREFILL: si está en yes la cuenta del cliente se recargará automáticamente hasta llevar el crédito al valor indicado en el parámetro que sigue. INITIAL BALANCE: el valor del crédito del cliente cada vez que se ejecutará un autorefill. Ejemplo: 119
si el crédito del cliente es de 2 dolares y INITIAL BALANCE es configurado con 20, la cuenta del cliente se recargará con 18 dolares para que el total sea de 20 dolares. INVOICE DAY: de forma predefinida el sistema genera las facturas cada primer día del mes. En este parámetro se indica el día del mes en que se generará la factura para este cliente. VAT: Es el impuesto que se aplicará a las facturas del cliente. En Colombia se llama IVA y es del 16% . Cuando el cliente realice una recarga de 10 dolares el total que tendrá que pagar son 10 dolares más el 16%, es decir 11.6 dolares. VAT REGISTRATION NUMBER: el numero de registro de la empresa del cliente o código fiscal. En Colombia se llama RUT o NIT. DISCOUNT: si se quiere aplicar un descuento al cliente, en este parámetro se indica el porcentaje. Es valido solamente para cuentas postpago. Los demás campos que aparecen en la pagina se pueden dejar, por el momento, con sus valores predefinidos. Para guardar la configuración se presiona el botón “Confirm Data”. En la pagina de los clientes se podrá ver el nuevo cliente creado:
Una explicación de las columnas más importantes: BA = Balance; crédito disponible USE: muestra en tiempo real los canales utilizados por el cliente SIP: Yes, hay una extensión SIP asociada al cliente IAX: No, no hay una extensión IAX2 asociada al cliente ACD: numero de llamadas totales contestadas realizadas por el cliente Los Iconos: LUPA: para ver un resumen de los datos del cliente LAPIZ: para modificar los datos de la cuenta del cliente X: Para borrar el cliente SIP: para crear una cuenta SIP para el cliente en el caso que no exista IAX: para crear una cuenta IAX para el cliente en el caso no exista BILLETES: Para realizar operaciones sobre el crédito del cliente (recargas, pagos, etcétera) LIBRETA: para inscribir el cliente a un pago recurrente 120
SOBRE: para enviar un correo electrónico al cliente En este caso se selecciona el icono BILLETES para recargar la cuenta del cliente:
CUSTOMER ID: numero ID del cliente PAYMENT DATE: Fecha en que se realizó el pago/recarga PAYMENT AMOUNT: valor del pago/recarga DESCRIPTION: una descripción para la operación CREATE ASSOCIATE REFILL: se creará una factura para la recarga CREATE AGENT COMMISSION: en el caso que el cliente esté asociado a un revendedor, si se selecciona la casilla, se reconoce la comisión al revendedor. PAYMENT TYPE: tipo de pago Para completar la recarga se presiona el botón “Confirm Data”. Ahora en el menú BILLING → Customers Balance → Refills, aparecerá la recarga recién realizada. En el menú INVOICES → Invoices aparecerá la factura de la recarga. Se vuelve al menú CUSTOMERS → Add :: Search y se selecciona el icono del lápiz:
121
Seleccionando el enlace de la imagen, presente en alto a la derecha, se entrará directamente a la pagina del cliente. En el menú derecho se selecciona INVOICE → View Invoices. Aparecerá la linea de la factura relacionada con la recarga realizada. Si se selecciona el icono de la lupa:
Se verá la factura con el icono de la empresa y todos los datos del cliente. Al momento de la creación del cliente, se ha creado una cuenta SIP. Para ver los datos y la configuración de la cuenta, se ingresa al menú CUSTOMERS → VoIP Settings y luego se selecciona el icono lápiz.
122
123
Como se puede ver, algunos datos los genera en automático A2Billing, otros se toman de los configurados en SYSTEM SETTINGS → Global List → peer_friend. Por ultimo algunos más se toman de la configuración de los valores por defecto de la tabla cc_sip_buddies de A2Billing. De los datos presentes por defecto hay que modificar por lo menos: • • • • •
124
CANREINVITE RTPTIMEOUT RTPHOLDTIMEOUT CANCALLFORWARD RTPKEEPLIVE
Se entra en el cliente MySQL: mysql -u root -psesamo mysql> use a2billing Se modifican: mysql> alter table cc_sip_buddies alter canreinvite set default 'no'; mysql> alter table cc_sip_buddies alter rtptimeout set default '60'; mysql> alter table cc_sip_buddies alter rtpholdtimeout set default '120'; mysql> alter table cc_sip_buddies alter cancallforward set default 'no'; mysql> alter table cc_sip_buddies alter rtpkeepalive set default '15'; Se sale del cliente MySQL: mysql> quit Para ver los datos que tiene que utilizar el cliente para configurar su SoftPhone, Teléfono SIP o troncal, se vuelve a entrar en la cuenta del cliente y se selecciona el menú SIP/IAX INFO:
Como se puede una parte de la información viene en inglés y no es correcta (ejemplo los codecs). Esto se puede modificar abriendo el siguiente archivo:
125
nano +147 /var/www/html/customer/A2B_entity_sipiax_info.php y cambiando las siguientes lineas: context= ; change for proper context allow= ; we support ulaw,alaw,ilbc,gsm,g723.1,g726,g729a
Para que queden: context= disallow=all allow= ; soportamos alaw,ulaw,g729 Importante la linea vacía entre context y disallow. Se guardan los cambios y se accede nuevamente, desde la pagina del cliente, al menú SIP/IAX INFO:
Los datos necesarios para la configuración del dispositivo son: USERNAME : 09148 SECRET: 65245yveo3bduuhi6swu HOST: 45.56.76.75 PUERTO: 5090 (donde escucha Asterisk)
126
Con esos datos se configura el X-Lite . Se descarga el programa desde la pagina web de la empresa que lo desarrolla: http://www.counterpath.com/x-lite-download.html Se instala y se abre. Se entra en el menú Softphone → Account Settings y se configura la cuenta:
127
En el parámetro Domain modificar la IP que aparece con la IP publica del servidor. Después de la IP publica del servidor se indica el puerto de escucha de Asterisk. Se presiona en botón OK y se espera que el SoftPhone se conecte a Asterisk:
Si no aparece ningún error, el SofPhone estará conectado. Desde la consola de Asterisk se puede averiguar con el siguiente comando: CLI> sip show peer 09148 load cambiando 09148 con el numero del cliente generado por el sistema. La respuesta será una larga lista de todos los parámetros configurados para esa extensión. Ahora se puede realizar la primera llamada. Hay tres formas de marcar: código país + numero 00 + código país + numero 011 + código país + numero Un ejemplo: marcar el numero de atención al cliente de la compañía aérea Avianca (Colombia): 005714013434 Una vez terminada la llamada se regresa a la pagina de administración de A2Billing y se selecciona el menú CALL REPORTS → CDRs
Aparecerá la llamada que se acaba de hacer:
128
Con la prueba de la llamada, se ha averiguado que el sistema de facturación está funcionando correctamente. 4.8 Registro de un nuevo cliente desde la pagina Web Los clientes, como se ha definido en la configuración de A2Billing, se pueden registrar desde una pagina Web dedicada. Se entra a la pagina: https://IPservidor/customer
Si se quiere que la pagina aparezca siempre en español, se modifica este archivo: nano /usr/local/src/a2billing/customer/templates/default/index.tpl Y se personaliza la pagina para que quede:
129
Luego se selecciona la opción indicada para registrarse. En la nueva pagina se rellenan los campos personalizandolos:
Para terminar se presiona el botón Registrarse. Como respuesta se recibirá el siguiente mensaje:
130
El nuevo cliente recibirá, porque así se ha configurado, un correo electrónico con un enlace para confirmar la activación de su cuenta:
Se selecciona el enlace y se pega en una nueva ventana del navegador. El resultado será:
131
Volviendo a la pagina de administración, en el bloque NOTIFICATION aparecerá la palabra NEW que indica che hay alguna novedad en el sistema:
Se selecciona con un click ese bloque:
Seleccionando el icono evidenciado se entrará directamente en la cuenta del nuevo cliente donde se modifica el parámetro STATUS de NEW a ACTIVE:
Se guardan los cambios presionando el botón “CONFIRM DATA”. Ahora se puede desactivar la notifica volviendo a seleccionar el Menú NOTIFICATION y luego el botón NEW que aparece en la ultima columna. La palabra NEW se transformará en una X que permite borrar la linea de notificación. Ahora el cliente podrá acceder a su pagina personal:
132
En el menú de la derecha de la pagina personal del cliente, están presentes las funcionalidades activas para el cliente mismo. Estas funcionalidades se definen en el grupo DEFAULT presente en el menú CUSTOMERS → Groups de la pagina de administración de A2Billing. Se pueden modificar en cualquier momento de la siguiente forma. Se entra en ese menú y se selecciona el icono para modificar el grupo DEFAULT:
En la nueva pagina presionando la tecla CTRL se añaden o quitan las funcionalidades. Para este ejemplo: • •
se desactiva la funcionalidad AUTODIALER se desactiva la posibilidad de adquirir números geográficos (DID)
Tiene que quedar de esta manera:
Se confirma presionando el botón “CONFIRM DATA”. Claramente se pueden crea distintos grupos y asociar los clientes a los grupos creados según el tipo de funcionalidades que se quiere que el cliente pueda utilizar. Ejemplo: si para algunos clientes no se quiere que puedan utilizar el sistema de callback presente en la pagina del cliente, se desactiva la linea CALL BACK.
133
4.9 Creación de una cuenta POSTPAGO Para terminar esta parte dedicada a la creación de los clientes, se creará un nuevo usuario con cuenta POSTPAGO. A seguir los datos utilizados:
Como la cuenta es POSTPAGO no se añade crédito:
Los datos del cliente:
134
Como la cuenta es POSTPAGO en el parámetro PAYMENT TYPE se selecciona “POSTPAID CARD”. En SIMULTANEOUS ACCESS se selecciona SIMULTANEOUS ACCESS que quiere decir que el cliente podrá realizar más de una llamada a la vez:
En CREDIT LIMIT se pone 50 dolares que es el valor máximo que puede consumir el cliente POSTPAGO hasta que no se genere una nueva factura: 135
Se crea solamente una cuenta SIP:
La factura se generará cada primer día del mes, se aplicara un impuesto del 16% y un descuento del 5%. Se guarda la configuración presionando el botón “Confirm Data”. Ahora para probar la cuenta POSTPAGO se configura la extensión SIP creada para esa cuenta en el X-Lite y se realiza una llamada al mismo numero utilizado anteriormente. El resultado será:
El saldo será negativo ya que el cliente pagará su cuenta cuando se genere la factura, es decir cada primer día del mes. 4.10 Crear Revendedores El sistema A2Billing brinda la posibilidad de crear revendedores. A los revendedores se le asigna una comisión sobre las tarifas y tienen las posibilidad de poder crear y recargar sus propios clientes. De esta forma un revendedor ganará sobre todo el trafico generado por sus clientes. Solo los administradores pueden crear nuevos revendedores. Para hacerlo se entra en el menú AGENTS → Add :: Search y se selecciona ADD Agent. En la nueva pagina se crea un nuevo revendedor.
136
LOGIN: nombre de usuario PASSWORD: contraseña PERMISSIONS: las funcionalidades activadas para el revendedor. Se activan manteniendo presionada la tecla CTRL y seleccionándolas una a una. En este caso se seleccionan todas. ACTIVE: yes. La cuenta está activada BALANCE: el crédito que tiene disponible el revendedor. Se añaden 50 dolares de crédito. COMMISSION BALANCE: la ganancia actual del revendedor CURRENCY: la moneda con que se pagará el revendedor COMMISSION PERCENTAGE: la comisión reconocida al revendedor: 5% THRESHOLD REMITTANCE: el valor de ganancias mínimo para que el revendedor pueda solicitar sus comisiones VAT: impuestos si aplican
137
LANGUAGE: el idioma predefinido para el revendedor. En la parte que sigue de la pagina, aparecen todos los datos personales del revendedor que hay que personalizar. Terminada la configuración se presiona el botón “Confirm Data”. Se vuelve a entrar en la pagina del agente creado:
Se define que planes de llamadas se asocian al agente ya que el revendedor no puede cargar y/o utilizar sus propias tarifas. En este caso el Plan Base:
Terminada la configuración del plan de llamadas, se guardan los cambios presionando el botón “CONFIRM DATA”. En A2Billing es posible crear una dirección web donde los nuevos clientes que se registren, sean asociados directamente a un revendedor. Esto se realiza a través de una clave que identificará el revendedor en la pagina de registro de los nuevos clientes. Antes de crear la clave es obligatorio crear un nuevo grupo en el menú CUSTOMERS → Groups. Se selecciona ADD Group y en la pagina que aparece se crea el nuevo grupo con estos parámetros:
138
Se asocia el nuevo grupo al revendedor agente1. Para guardar los datos se presiona el botón CONFIRM DATA. Ahora se puede crear la clave para el revendedor accediendo al menú AGENTS → Signup URLs y seleccionando el enlace “ADD Signup KEY”. En la nueva pagina se selecciona el agente, el plan de llamadas y el grupo que se acaba de crear:
Se guardan los datos presionando el botón “ADD URL KEY”. Aparecerá la dirección web que deberá utilizar el revendedor para hacer registrar sus propios clientes:
Si se copia la dirección Web y se pega en una nueva pestaña del navegador, aparecerá la pagina de registro para un nuevo usuario. Se crea un nuevo usuario:
139
se confirma presionando el botón “Registrarse”. A partir de este momento el nuevo cliente seguirás los mismos pasos presentados anteriormente para confirmar su cuenta. Entrando en la pagina de administración del revendedor: https://IPservidor/agent
Modificando: nano /usr/local/src/a2billing/agent/Public/templates/default/index.tpl Se traduce al español:
140
Se accede con los datos asignados al revendedor. Se verá que el nuevo cliente es parte de los clientes de este revendedor; menú CUSTOMERS → List customers:
En este caso es el mismo agente que puede activar la cuenta del cliente:
Una vez que el cliente esté activo la cuenta la puede recargar directamente el cliente, el agente o el administrador. Si lo hace el agente, escoge el siguiente menú:
y en la ventana que sigue:
se escoge primero el icono con el circulo negro y se selecciona el cliente que se quiere recargar, luego se pone el valor, una descripción y presiona el botón “ADD CREDIT”. El resultado será:
141
Como la recarga la realizó el agente, automáticamente recibirá la comisión del 5% sobre ese valor (menú MY ACCOUNT → Account Information):
El administrador puede realizar una recarga al mismo cliente utilizando el icono de los billetes que aparece al final de la linea del cliente que quiere recargar. Al mismo tiempo puede decidir si reconocer o no la comisión al agente seleccionando Yes en la linea del parámetro: “CREATE AGENT COMMISSION”.
El resultado en la pagina del agente será:
Si el cliente realiza la recarga con unos de los métodos de pago implementados, el resultado será el mismo. Como el administrador, también el revendedor puede crear nuevos usuarios desde el menú CUSTOMERS → List Customers y seleccionando Add Customer. Si quiere que cuando el revendedor cree un cliente, por defecto se cree solamente una extensión SIP: nano +758 /usr/local/src/a2billing/agent/Public/form_data/FG_var_card.inc Se cambia el 1 presente en la linea con un 0 y se guardan los cambios. 142
Capitulo V Configuración avanzada A2Billing 5.1 Distintos CallPlan Para crear nuevos CallPlan en A2billing el procedimiento es parecido al que se utilizó para crear el primero, es decir: • • • •
crear las troncales crear el callplan crear la Ratecard importar las tarifas
Los proveedores utilizan distintos prefijos para diferenciar las rutas de las llamadas según las tarifas que se quieren utilizar. En el caso de SipTraffic, se encuentran estos prefijos en la pagina del Proveedor bajo el menu FAQ → 1. General → What different routes do you offer?:
Como se puede leer para la ruta Grey (que seria la Bronze, un error en la pagina del proveedor) hay que anteponer al numero a marcar el prefijo 00001, para la ruta Silver los dos 00 tradicionales y para la ruta Platinum el prefijo 00000. El primer error. Al momento de configurar la troncal para la ruta Base de A2billing en el parámetro ADD_PREFIX se ha puesto 00. Como esa ruta se basa en las tarifas Bronze de SipTraffic, hay que efectuar la corrección. En el menú Providers → Trunks se modifican las dos troncales presentes modificando el parámetro ADD_PREFIX. El resultado debe ser:
Ahora se crean dos troncales más, una para las tarifas Silver y otra para la tarifa Gold utilizando la nueva troncal. Se presiona el enlace Add Trunk y se define la nueva troncal de esta forma:
En esta troncal el parámetro ADD_PREFIX es 00 que corresponde a las tarifas Silver de SipTraffic. Se guardan los cambios y se crea la troncal para las tarifas Gold de SipTraffic (con prefijo 00000):
145
Si para estás dos ruta se quiere crear las correspondientes troncales de respaldo, se crearían dos troncales más, indicando en LABEL voztovoice-premium2 y voztovoice-platino2 respectivamente; los datos a modificar serían PROVIDER IP donde se pondría voztovoice2 para las dos. Una vez creadas, se modificaría la troncal voztovoice-premium y en FAILOVER TRUNK se escogería voztovoicepremium2. Para terminar se modificaría la troncal voztovoice-platino y en FAILOVER TRUNK se escogería voztovoice-platino2. Ahora se crean dos nuevos CallPlan (Premium y Platino) desde el menú RATES → Call Plan. El resultado será:
Se continua creando dos RateCard nuevas en el menú RATES → RateCards. La Premium1 y la Platino1: 146
El resultado de las RateCards disponibles:
147
Se asocian las nuevas RateCards a los respectivos CallPlan; se entra en menú RATES → Call Plan y se modifica el CallPlan Premium:
Se continua con el CallPlan Platino:
Para terminar hay que importar las tarifas Silver y Gold de SipTraffic creando los respectivos archivos CSV como se ha visto en el párrafo 4.3 y importándolos desde el menú RATES → Import. Para las tarifas Premium:
148
Para las tarifas Platino:
Para terminar en el menú RATES → Rates se controla que estén las tres tarifas:
149
Si se entra en el menú CUSTOMERS → Add :: Search y se crea un nuevo usuario, a este nuevo usuario se le podrá asociar uno de los tres CallPlan disponibles:
Problema: si se intenta registrar un nuevo usuario desde la pagina web: https://IPServidor/customer/signup.php al momento de escoger un CallPlan, estarán disponibles solamente Base y Premium. Solución: Para que estén disponibles los tres hay que modificar el parámetro que sigue del grupo signup, menú SYSTEM SETTINGS → Global List:
CallPlan ID List
1,2
Numero ID de los planes de llamadas que un cliente puede escoger al momento de registrarse
1,2,3
Numero ID de los planes de llamadas que un cliente puede escoger al momento de registrarse
Para que quede:
CallPlan ID List
Los números 1, 2 y 3 son los que aparecen en la columna ID del menú RATES → Call Plan. Ahora el cliente podrá escoger entre los tres. Los proveedores cambian periódicamente las tarifas. Normalmente cuando salen las tarifas nuevas, en el archivo que se recibe, se indica la fecha en que serán vigentes. En este ejemplo se verá como cargar las nuevas tarifas para la RateCard Base suponiendo que sean vigentes a partir de la fecha 01 noviembre 2013. Se entra en el menú Rate → RateCards y se crea una nueva con el enlace ADD RateCard. En el parámetro START DATE hay que indicar la fecha en que las tarifas serán vigentes. El resultado: 150
Esta nueva RateCard se nombrará Base2 para indicar que es parte del CallPlan Base y que es la segunda serie de tarifas de ese CallPlan (la Base1 ya existe). Como para la Base1 hay que importar las tarifas. Para la prueba, se utilizará el mismo archivo CSV utilizado para la Base1 con la configuración que aparece en la imagen que sigue:
Ya que esta RateCard empieza a funcionar desde el primero de Noviembre de 2013, hay que indicar que la vieja RateCard Base1 se vence el 31 de Octubre 2013 a las 23:59. Para eso se modifica la Ratecard Base1 cambiando el parámetro EXPIRY DATE de esta forma: 151
Para terminar se añade la nueva RateCard Base2 al CallPlan Base:
Para conocer en cualquier momento cual es la Rate Card activa, se puede utilizar el Simulator. Se entra en el menú RATES → Simulator y en la pagina que aparece se rellenan los campos de la siguiente manera:
Se presiona el botón “Simulate” y aparecerá:
152
En la tabla se verá que para la llamada al numero indicado se utilizará el Call Plan Base y la Rate Card Base1. Si se realiza la misma prueba cuando sea vigente la Rate Card Base2, la nueva RateCard aparecerá en la linea tariffname. 5.2 El sistema de soporte A2Billing tiene un sistema de soporte para clientes y revendedores basado en los “tickets”. Los clientes o los revendedores, desde su pagina personal, pueden abrir tiquetes de soporte. Los administradores podrán ver y contestar los tiquetes creados. Según el tipo de incidencia, ésta se puede enviar a una dirección de correo electrónico en lugar de otra. Esto se realiza creando, por ejemplo, dos SUPPORT BOX distintas. Una para el departamento administrativo y otra para el departamento de soporte técnico. Se entra en el menú SUPPORT → Support boxes y se modifica la SUPPORT BOX presente:
de modo que quede:
Se personaliza el correo electrónico presente, se guardan los cambios y se crea otra para el soporte técnico:
153
Se personaliza el correo electrónico presente, se guardan los cambios y se entra en el menú SUPPORT → Ticket Components. En este menú se crean distintos objetos y se enrutan según el tema. En este caso se crearán 4 distintos objetos, dos de carácter administrativo (recargas y pagos) y dos técnicos (VoIP configuración y Callback). Se crea el primero modificando la entrada presente (DEFAULT):
Como se ve en la imagen todos los tickets abiertos con este objeto se enrutarán hacia el Support Box “Administración” En “USER TYPE” se puede definir si este componente es para los clientes, para los revendedores o ambos. Se continua con pagos:
Se crean los dos de soporte técnico:
154
Para probar el sistema se entra en la pagina personal de unos de los clientes creados. Desde el menú SUPPORT se crea un ticket escogiendo entre los 4 componentes creados. Un ejemplo:
Se presiona el botón CREATE para crear el ticket. Se vuelve a la pagina de administración donde aparecerá una nueva notificación:
Si se selecciona:
Seleccionando el enlace evidenciado se entrará directamente en la pagina del tiquete creado:
155
Se contesta y si se quiere cerrar el tiquete en el parámetro STATUS se selecciona “FIXED”. Para actualizarlo se presiona el Botón “UPDATE”. En en menú SUPPORT → Customers Tickets, aparecerá:
Una vez terminada la operación acordarse siempre de borrar la notificación para que no quede en la barra NOTIFICATION. A la casilla de correo electrónico del cliente llegará una copia del tiquete creado y de la respuesta del departamento de Soporte. Lo mismo al correo electrónico
[email protected] 5.3 Paquetes de llamadas Una de las funcionalidades más interesantes de A2Billing es la posibilidad de crear paquetes de minutos/llamadas que luego se pueden ofrecer a los clientes. Un típico ejemplo es cuando se vende un plan mensual de llamadas a Colombia donde se incluye un determinado número de minutos gratuitos a fijos y/o celulares. Una limitación intrínseca de A2Billing es que no se pueden diferenciar los minutos gratuitos a celulares de los minutos gratuitos a fijos o crear distintos paquetes y asociarlos a un mismo Call Plan.
156
Para empezar con la configuración se entra en el menú PACKAGE OFFER → Add → Add Package:
Los parámetros disponibles: LABEL: Un nombre que se asigna al paquete PACKAGE TYPE: acepta tres distintas opciones: • • •
UNLIMITED CALLS: el paquete incluirá llamadas ilimitadas. En este caso en el parámetro FREE UNITS habrá que poner 0 (cero) que significa que las llamadas serán ilimitadas. NUMBER OF FREE CALLS: el paquete incluirá un numero determinado de llamadas gratuitas FREE SECONDS: el paquete incluirá un numero determinado de segundos de llamadas gratuitas
BILLING TYPE: si se quiere cobrar por el paquete, en este parámetro se define si el cobro se efectuará cada mes o cada semana (opciones Monthly y Weekly) STARTING DAY: si el parámetro anterior es Monthly, en este parámetro se indicará el día del mes en que el plan se activa y/o se vuelven a recargar los minutos/llamadas configurados. Si el parámetro anterior es Weekly, se indicará el día de la semana en que el plan se activa e/o se vuelven a recargar los minutos/llamadas configurados. En este caso los valores aceptados va de 1 a 7 (1 Lunes, 7 Domingo) FREE UNITS: el numero de llamadas o segundos incluidos en el plan según la configuración del parámetro PACKAGES TYPE. En este caso se ha configurado un paquete con nombre Colombia que incluye 10 minutos de llamadas al mes y que empieza cada primer día de cada mes. Se guarda la configuración presionando el Botón “Confirm Data” que aparece en la pagina. El programa volverá a la pagina anterior donde aparecerá el paquete que se acaba de crear:
157
Se selecciona en la parte derecha de la linea:
En la nueva ventana habrá que seleccionar los destinos que estarán incluidos en el plan (en este caso, fijos y celulares de Colombia):
Primero se selecciona el icono +: En la nueva ventana los destinos se pueden seleccionar uno a uno:
Para que el resultado sea (en el caso de llamadas genéricas a fijos de Colombia):
158
Si ahora se va a la ventana terminal y se entra en MySQL: mysql -u root -psesamo Se selecciona la base de datos a2billing: mysql> use a2billing Se seleccionan todas las rutas presentes en el paquete: mysql> select * from cc_package_rate; El resultado:
¿Qué significa? Que al paquete de llamadas han sido añadidas todas las rutas presentes en las cuatro Rate Cards configuradas (dos Base, una Premium y una Platino). Para averiguarlo: mysql> select id,idtariffplan,dialprefix,buyrate,rateinitial from cc_ratecard where id='3417';
159
Bajo la columna “idtariffplan” aparece el numero de ID de la RateCards configurada. Esto significa que si se borra una ratecard para crear una nueva, automáticamente las tarifas presentes en el paquete de minutos no aplicarán para la tarifa borrada. Otra forma de añadir las rutas al paquete es utilizar el siguiente enlace:
En el menú que se despliega se seleccionan las siguientes opciones:
Se selecciona la casilla PREFIX y se pone 57, se selecciona la casilla “Begins with”. Se termina presionando el Botón “BATCH ASSIGNED”; se cierra la ventana:
Aparecerán todos los prefijos de Colombia incluidos en el paquete. Si no se selecciona la RATECARD, las rutas que aplicarán al paquete serán aquellas presentes en la RateCard con id más bajo, en este caso la base1 (la primera que se creó). Esto quiere decir que si se intenta asignar el paquete de minutos, como se verá más adelante, a los CallPlan Premium o Platino, el paquete no aplicará. Ahora que el paquete está listo se asocia al CallPlan Base. Se entra en el menú RATES → Call Plan y se escoge el CallPlan Base:
160
En el parámetro PACKAGES se escoge el paquete que se acaba de crear. Se termina presionando el Botón “Confirm Data”. A partir de este momento, todos los clientes cuyo CallPlan es Base tendrán el paquete disponible y utilizable. Para averiguarlo, se efectúa una llamada a un fijo o celular de Colombia. Terminada la llamada se entra en el menú PACKAGE OFFER → Details:
Aparecerá una entrada con los siguientes datos: CARDID: numero de ID de cliente CARDNUMBER: numero de tarjeta del cliente PACKAGE: el paquete utilizado (en este caso Colombia) USED MINUTES: numero de minutos utilizados (15 segundos) NB PERFORMED: numero de llamadas efectuadas por ese cliente: 1 Si el mismo cliente efectúa una segunda llamada a un fijo/celular de Colombia, la misma pagina cambiará de la siguiente forma:
Para averiguar que efectivamente el paquete no aplica a los CallPlan Premium y Platino, se añade el paquete de minutos al CallPlan Platino. Luego se asigna a un cliente ese CallPlan y se realiza una llamada utilizando las credenciales de ese cliente. En los reportes de llamadas:
161
La llamada ha sido cobrada normalmente aunque se haya añadido al CallPlan Platino, el paquete Colombia:
Para cobrar el paquete se puede crear un Subscriptions Service o un Account Services, como se verá en los parrafos 5.9 y 5.10. 5.4 El Parámetro LCR Mode Como se ha visto en la configuración de los agi-conf, desde la versión 1.9.5 de A2billing es presente un nuevo parámetro: LCR Mode. Si el valor es 0 A2billing busca el prefijo que más se acerca al numero marcado en todas las RateCards presentes en un CallPlan y escoge la ruta más barata. Si el valor es 1 A2Billing busca en cada RateCard presente en un CallPlan el prefijo que más se acerca al numero marcado y entre todos los encontrados, escoge aquel que tiene asociada la tarifa más barata. Para ver como funciona, se efectúa una primera prueba. Se añade al CallPlan Base la RateCard Premium1:
Luego desde el X-lite configurado con los datos de configuración del primer cliente, se marca un 162
numero fijo o de celular de Colombia. En los datos de la llamada:
Como se puede notar, la tarifa de venta que se ha aplicado es 0.068 y la troncal VozToVoice-1. En este caso se ha llamado un 57315 (Movistar Colombia). Ahora si en el menú RATES → Rates se mira los costos de las distintas RateCards:
Como era imaginable, se ha utilizado la RateCard Base1 (la más barata). La segunda prueba es crear una nueva RateCard Prueba1:
y añadir la nueva RateCard al CallPlan Base:
163
Luego volver a entrar en el Menú RATES → Rates y en la casilla a lado de la casilla “SELECT TRUNK” seleccionar la RateCard Prueba1 y luego presionar el botón Search; sucesivamente el enlace “Add Rate”. En la nueva ventana se crea una nueva tarifa utilizando los datos que aparecen en la imagen que sigue:
164
Se confirma la creación presionando el botón “Confirm Data” que aparece al final de la pagina. De este forma se ha creado una nueva tarifa para todas las llamadas cuyo prefijo empiece con 5731. Como esta tarifa es más barata de la Base1 y incluye también llamadas a números de Movistar Colombia (57315), debería ser la elegida por el sistema cuando se vuelva a marcar el mismo numero de la primera prueba. Desde X-Lite se vuelve a marcar el numero de celular:
efectivamente esta es la tarifa que el A2Billing ha escogido. 5.5 El sistema de facturación El sistema de facturación es el corazón de A2Billing y es donde se maneja toda la parte contable del sistema. Los menú importantes y que se analizarán en este párrafo, son BILLING y INVOICES.
VOUCHERS: es el menú donde se crean los Vouchers para recargar las cuentas PREPAGO CUSTOMERS BALANCE: aparecen todos los datos contables de las cuentas de los clientes (facturas, pagos, facturas a pagar). De esta forma es posible conocer la situación contable de los clientes de forma resumida:
165
TRANSACTIONS: es donde aparecen todos los pagos realizados por los clientes con los sistemas activados en la plataforma (ejemplo PayPal) BILLINGS: en este menú aparecen todos las facturas y los recibos generados por el sistema. De manera predefinida el sistema crea nuevas entradas, para cada cliente, según el valor del parámetro INVOICE DAY presente en la cuenta del cliente mismo. Si el cliente es PREPAGO, el sistema creará un recibo con todos los gastos realizados hasta la fecha, si el cliente es POSTPAGO, creará un nueva factura que el cliente tendrá que pagar dentro de 7 días pena la suspensión automática de la cuenta. En cualquier momento es posible generar un nuevo recibo/factura desde el enlace Add Billing. En la pagina que aparece se selecciona el cliente y en el segundo campo que aparece la fecha actual. Se crea presionando el botón CONFIRM DATA:
En este caso, como el cliente con ID 1 es PREPAGO, se creará un recibo (menú INVOICES → Receipts:
REFILLS: aparecerán todas las recargas realizadas por los clientes, administradores PAYMENTS: aparecerán todos los pagos realizados por los clientes. A cada pago será asociada la correspondiente operación en REFILLS:
166
E-PAYMENT LOG: es el menú donde estarán presentes todos los registros de los pagos realizados por los clientes con los métodos disponibles en la plataforma. Un ejemplo:
CHARGES: En este menú aparecerán todos los costos para servicios adicionales contratados por el cliente: DID, pagos recurrentes:
AGENTS BALANCE: a partir de este menú empiezan una serie de entradas dedicadas a los revendedores. En este primer menú aparecerán todos los datos contables de cada revendedor, uno por linea:
COMMISSIONS: en este menú estarán presentes todas las operaciones que hayan generado una comisión para el revendedor:
REMITTANCE REQUEST: aquí es donde aparecen todos los pagos de las comisiones solicitadas por los revendedores y aceptadas por un administrador del sistema: TRANSACTIONS: es donde aparecen todos los pagos realizados por los revendedores con los sistemas activados en la plataforma (ejemplo PayPal) 167
REFILLS: aparecerán todas las recargas realizadas por los revendedores PAYMENTS: aparecerán todos los pagos realizados por los revendedores. A cada pago será asociada la correspondiente operación en REFILLS E-PAYMENT LOG: es el menú donde estarán presentes todos los registros de los pagos realizados por los revendedores con los métodos disponibles en la plataforma Pasando al menú INVOICES:
RECEIPTS: son los recibos generados por el sistema y que no tienen valor contable sino son el comprobante de los gastos realizados desde la generación del recibo anterior INVOICES: son la facturas generadas por el sistema y representan la parte contable. En el caso de cuentas PREPAGO, se generará una factura para cada recarga realizada por el cliente. En el caso de cuentas POSTPAGO, son los gastos generados por el cliente hasta la creación de la factura. Algunos ejemplos:
5.6 Subscription services Los servicios de suscripción permiten al administrador del sistema crear paquetes de ofertas mensuales a las que el cliente se puede suscribir al momento del registro y/o solicitando el servicio. El primer paso es crear uno entrando en el menú RECUR SERVICE → Subscriptions Services → Add SUBSCRIPTION SERVICE:
168
LABEL: una etiqueta que describa el servicio FEE: el costo mensual del servicio STATUS: activo o inactivo START DATE: fecha de creación del servicio STOP DATE: fecha de vencimiento del servicio EMAIL TO SEND REPORT: dirección de correo electrónico donde enviar los reportes relacionados con el servicio (personalizar) Se confirma la creación presionando el botón “CONFIRM DATA”. Ahora que el servicio se ha creado, hay dos forma de añadir suscriptores: • •
añadiendo los clientes manualmente creado un Subscriptions SIGNUP que permite al cliente escoger el servicio al momento del registro
Para la primera opción se entra en el menú RECUR SERVICE → Subscribers y se selecciona el enlace Add SUBSCRBER:
169
ACCOUNT ID: numero del cliente ID SUBSCRIPTION SERVICE: el paquete al que se va a subscribir el cliente. En este caso Colombia. START DATE: fecha actual STOP DATE: fecha en que se vencerá la suscripción PRODUCT LABEL: Una descripción que será la que aparecerá en el recibo del cliente cuando le será cobrado el servicio. Se confirma la creación con CONFIRM DATA Para la segunda opción se entra en el menú RECUR SERVICE → Subscriptions SIGNUP y se crea una nueva entrada:
LABEL: la etiqueta que describe el servicio: ACTIVATED: Yes o No SUBSCRIPTIONS OPTIONS: el paquete que se quiere utilizar con esta entrada (Colombia) DESCRIPTION: una descripción del servicio como aparecerá al nuevo cliente al momento del registro CALL PLAN: el call plan asociados al servicio. Como el paquete de minutos creado anteriormente es para el CallPlan Base, se selecciona ese CallPlan. Se guarda la configuración presionando el botón CONFIRM DATA Ahora si un cliente entra en la pagina de registro, le aparecerá:
170
Esto antes que se le pidan sus datos. Como se puede ver el cliente no tiene la posibilidad de rechazar la oferta y pasar a la pagina con el formulario con los datos de registro. En este caso hay dos opciones: 1. Crear distintos SUBSCRIPTIONS Service y SUBSCRIPTIOS SIGNUP de modo que el cliente pueda escoger el que más le interese 2. Crear un SUBSCRIPTIONS Service y un SUBSCRPTION SIGNUP que no tenga costo y que permita al cliente registrarse sin tener que escoger obligatoria mente un servicio. En el caso que el cliente escoja un servicio de pago y cree la cuenta, automáticamente el sistema le cobrará el primer pago del servicio. Como el cliente todavía no tiene crédito en su cuenta (la acaba de crear), cuando ingrese a su cuenta encontrará la factura a pagar y su STATUS será WAITING SUBSCRPTION PAYMENT. IMPORTANTE: el sistema cobra los Subscription service cada primer día del mes; esto sin tener en cuenta el día en que el cliente ha subscrito realmente el servicio. 5.7 Account Service Los Account Service permiten a los administradores crear toda una serie de cobros en las cuentas de los clientes. La diferencia con los Subscriptions Service es que estos pagos aplican a un grupo especifico de usuarios según el grupo de pertenencia y/o según su CallPlan. Otra diferencia es que son pagos que se basan en una serie de parámetros de configuración. Por ultimo en la cuenta del cliente, para que los Account Services apliquen, este parámetro:
tiene que estar en yes. Para mostrar como funciona, se crea el primero:
171
NAME: el nombre del servicio AMOUNT CREDIT: el valor que se cobrará para el servicio RULE: En este parámetro se pueden escoger distintas opciones: • • •
Apply service every Y Days: el servicio se cobrará cada Y días Apply service if card not used in last X days: el servicio se cobrará si la cuenta no ha sido utilizada en los últimos X días Apply service if card has been used in the last X days: el servicio se cobrará si la cuenta ha sido utilizada en los últimos X días
DAY NUMBER (X): este parámetro se configura solamente si en RULE se ha seleccionado la segunda o la tercera opción. En este caso se deja vacío PERIOD (Y): este parámetro se configura si en RULE se ha seleccionado la primera opción disponible. En este caso se pone every 7 days; se cobrará cada 7 días STOP MODE: cuando se deja de cobrar el servicio: • 172
Never: nunca
• •
Account balance below zero: cuando el crédito del cliente está por debajo de cero Max number of cycle reach: cuando se ha alcanzado el numero de ciclos indicados en el parámetro che sigue
MAX NUMBER OF CYCLES BY CARD: el numero máximo de veces que se puede cobrar el servicio a un Cliente/tarjeta STATUS: Active/Inactive EMAIL TO SEND REPORT: dirección de correo electrónico donde enviar los reportes relacionados con el servicio (personalizar) CALL PLAN: el servicio aplicará solamente a los clientes que estén asociados con el Call Plan Base (se puede indicar que sea por cualquier Call Plan seleccionando --ANY--) OPERATE MODE: hay dos opciones: • •
Allow be charged into negative balance: se permite que el servicio sea cobrado aunque el crédito del cliente es negativo Do partial charge but never go into negative balance: en el caso el cliente no tenga crédito suficiente para pagar el servicio, se le cobra parcialmente hasta llevar su crédito a 0.
SKIP GROUP: hay dos opciones: • •
List of group below: se indicará una lista de grupos a que no aplica el servicio. Los grupos son los que se ha creado en el menú CUSTOMERS → Groups Any group: el servicio aplicará a cada grupo configurado en CUSTOMERS → Groups
Se guardan los cambios presionando en botón CONFIRM DATA. Aparecerá el nuevo servicio configurado: Presionado el botón View Details, aparecerá una ventana con todos los datos contables del servicio:
Un ejemplo practico: se quiere cobrar un paquete de minutos semanalmente para los usuarios con cuenta Premium. Primero se crea el paquete de minutos desde el menú PACKAGE OFFER → Add: 173
Se continua asociando las rutas al nuevo paquete de minutos:
Se selecciona la RATECARD y PREFIX indicando que las rutas empiezan con 57. Como esta incluyen los celulares, luego se quitan de la lista de las rutas del paquete. Luego se asocia el paquete a la Call Plan Premiun desde el menú RATES → Call Plan, añadiéndolo de la siguiente manera:
Por ultimo se crea un nuevo servicio desde RECUR SERVICE → Account Service:
174
En este caso, como el servicio se estaría cobrando después de su utilizo, para la primera semana habría que realizar el cobro manualmente creando una recarga con valor negativo en la cuenta del cliente.
175
Capitulo VI Integración de A2Billing con OpenSIPs En este capitulo se verá como integrar A2Billing con OpenSIPs. Al terminar el capitulo tendremos activos e integrados los siguientes servicios: • • • • • • •
Balanceamiento de carga de las llamadas entre uno o más servidores Asterisk Registros de las extensiones en OpenSIPs Llamadas entre extensiones con buzón de voz desde OpenSIPs Presencia y mensajes instantáneos entre extensiones Autenticación sobre IP de los clientes a nivel de OpenSIPs Gestión de los números geográficos entre A2Billing y OpenSIPs Gestión de un sistema de tarjetas telefónicas entre A2Billing y OpenSIPs
Para llegar a esa configuración, se inicia con la instalación de OpenSIPs. 6.1 Instalación de OpenSIPs OpenSIPs es un servidor SIP Proxy Open Source que permite procesar cualquier tipo de solicitud SIP. No es un servidor media aunque en las ultimas versiones se han implementado módulos que van hacia esa dirección. Es modular con un core muy liviano. Esto permite ir añadiendo módulos según el tipo de configuración que se necesite. Los módulos se cargan directamente desde el archivo de configuración respetando las dependencias que cada uno tiene. En la documentación oficial de OpenSIPs se explica, para cada modulo, las dependencias, la configuración y en que parte del script de configuración de OpenSIPs se pueden utilizar las funciones activadas por el modulo. Las funcionalidades más importantes de OpenSIPs son: • • • • • • • • • •
Servidor Proxy, Servidor Registrar, Servidor Location, Servidor Redirect Procesamiento de las peticiones SIP de forma Statefull y Stateless Soporte para los protocolos de trasporte UDP, TCP, TLS,SCTP IPv4 e IPv6 Soporte para los registros DNS SRV y NAPTR Soporte Multi dominio Autenticación vía Digest (RFC2617) y sobre IP Servidor de presencia Soporte para NAT para trafico SIP y RTP Balanceamiento de carga y respaldo
En esta parte se verá como instalar OpenSIPs y realizar las modificaciones básicas del archivo de configuración de forma que se pueda iniciar el programa sin errores.
Se deberían instalar los paquetes para la compilación de Opensips, el servidor MySQL, ODBC y GIT para descargar las fuentes del programa. Como muchos paquetes ya se han cargado a lo largo de la instalación de Asterisk, se instalan solamente aquellos que todavía hacen falta: yum install xmlrpc-c-devel lynx pcre pcre-devel gdb -y Se descarga la ultima versión disponible de OpenSIPs de la rama 1.11: cd /usr/src git clone https://github.com/OpenSIPS/opensips.git -b 1.11 opensips_1_11 Se entra en la carpeta creada: cd opensips_1_11 Se ejecuta el comando que permite la configuración e instalación a través de un menú gráfico: make menuconfig en el menú que aparece:
se escoge la opción “Configure Compile Options”:
en el siguiente menú se selecciona “Configure Excluded Modules”:
178
Se seleccionan los módulos que aparecen en las dos imágenes. Se vuelve al menú anterior con la tecla ←
179
Se selecciona el menú “Configure Install Prefix”:
y se pone la / come carpeta de instalación. Se presiona la tecla Enter dos veces y se selecciona la opción “Save Changes”:
Se presiona la tecla Enter hasta que no aparezcan más notificaciones en la linea de comando. Se vuelve al menú anterior con la tecla ←
En el menú principal se selecciona “Generate Opensips Script”:
Se selecciona “Load-Balancer Script”:
180
luego “Configure Load-Balancer Script:
Se seleccionan los parámetros que aparecen en la imagen de arriba y se vuelve al menú anterior con la tecla ←
Se selecciona el menú “Save Load-Balancer Script”
Luego “Generate Load-Balancer Script” y se vuelve al menú principal presionando dos veces la tecla ←
En el menú principal se selecciona “Compile And Install OpensSIPs”. Empezará la compilación e 181
instalación de Opensips. Terminada la operación aparecerá el siguiente mensaje:
Se presiona la tecla Enter y se volverá el menú Principal:
Para salir del menuconfig se selecciona la opción “Exit & Save Changes” y se presiona la tecla Enter hasta volver al prompt de Linux. Se instala el script de arranque para Opensips: cd packaging/fedora nano opensips.init Se modifica esta línea: opensips=/usr/sbin/$prog para que quede: opensips=/sbin/$prog Se guardan los cambios y se continua con la configuración: chmod 755 opensips.init cp opensips.init /etc/init.d/opensips chkconfig --add opensips chkconfig opensips on Se crean usuario y grupo “opensips” requeridos por el script de arranque: groupadd opensips
182
mkdir /var/run/opensips useradd -d /var/run/opensips/ -s /bin/false -g opensips opensips useradd: aviso: el directorio personal ya existe. No se copia ningún fichero del directorio skel en él. chown -R opensips.opensips /var/run/opensips Se copia el archivo de configuración creado a lo largo de la instalación: cd /usr/src/opensips_1_11/etc El nombre cambia porque se basa en la fecha de creación pues prestar mucha atención al archivo creado en su sistema: cp opensips_loadbalancer_2015-3-10_19\:29\:27.cfg /etc/opensips/opensips.cfg cp: ¿sobreescribir «/etc/opensips/opensips.cfg»? (s/n) y Se modifica el archivo de configuración de OpenSIPs; lo importante, por ahora, es saber que se divide en tres bloques: • • •
el primer bloque es donde se configuran los parámetros globales de OpenSIPs el segundo bloque es donde se configuran los módulos con relativas opciones el tercer bloque es el script que procesará cada petición SIP que llegue al servidor
cd /etc/opensips/ nano opensips.cfg Se cambian estas dos lineas: listen=udp:127.0.0.1:5060 # CUSTOMIZE ME disable_tcp=no para que queden: listen=udp:IPPUBLICA:5060 disable_tcp=yes En la primera linea se pone OpenSIPs a la escucha en el puerto 5060 y la dirección del IP Publica del servidor. En la segunda linea se desactiva como protocolo de trasporte TCP. Se borra la linea que sigue (ya que no se va a utilizar el protocolo de transporte TCP): listen=tcp:127.0.0.1:5060 # CUSTOMIZE ME se continua modificando esta linea: 183
mpath="/usr/local/lib/opensips/modules/" para que quede: mpath="/lib64/opensips/modules/" De esta forma se indica a OpenSIPs donde tiene que buscar los módulos compilados. Si se presta atención al archivo de configuración para los módulos ACC, DIALOG y LOAD BALANCER hay una linea donde se indica que la configuración se guardará/buscará en una base de datos. Esa base de datos hay que crearla y es lo que se hará una vez terminada la configuración. Se guardan los cambios. Para guardar los registros de la actividad de Opensips en un archivo dedicado, se modifica la configuración de Rsyslog: nano /etc/rsyslog.conf antes de esta linea: local7.*
/var/log/boot.log
se pone: local0.*
-/var/log/opensips.log
Se guardan los cambios y se crea el archivo opensips.log: touch /var/log/opensips.log se reinicia rsyslog: /etc/init.d/rsyslog restart Se continua con la creación de la base de datos opensips que se realiza a partir de la configuración de un archivo especifico. Se renombra el predefinido: mv /etc/opensips/opensipsctlrc /etc/opensips/opensipsctlrc.old Se crea uno nuevo: nano /etc/opensips/opensipsctlrc se copian las lineas que siguen: SIP_DOMAIN=li926-75.members.linode.com DBENGINE=MYSQL DBHOST=localhost 184
DBNAME=opensips DBRWUSER=opensips DBRWPW="opensipsrw" DBROOTUSER="root" INSTALL_EXTRA_TABLES=ask INSTALL_PRESENCE_TABLES=ask ALIASES_TYPE="DB" OSIPS_FIFO="/tmp/opensips_fifo" VERIFY_ACL=1 PID_FILE=/var/run/opensips.pid Antes de guardar los cambios hay que modificar la primera linea y en lugar de li92675.members.linode.com se pone el nombre de dominio asociado al servidor Linode que se está utilizando. Se guardan los cambios. La aplicación para crear la base de datos es opensipsdbctl. Ejecutando el comando sin opciones aparecerán todos los comandos disponibles. Para crear la base de datos, se utiliza create: opensipsdbctl create MySQL password for root: INFO: test server charset INFO: creating database opensips ... INFO: Core OpenSIPS tables succesfully created. Install presence related tables? (y/n): y INFO: creating presence tables into opensips ... INFO: Presence tables succesfully created. Install tables for imc cpl siptrace domainpolicy carrierroute userblacklist b2b registrant call_center? (y/n): y INFO: creating extra tables into opensips ... INFO: Extra tables succesfully created. Primero se solicitará la contraseña de root (sesamo) de MySQL; luego si se quieren crear también las tablas para el modulo de presencia y para otros módulos disponibles en OpenSIPs, se contesta con yes a las dos preguntas. Ahora que la base de datos está creada, el paso a seguir es averiguar que la configuración de OpenSIPs esté sin errores. El comando para realizar esta operación es: opensips -c /etc/opensips/opensips.cfg El resultado será: Mar 10 19:47:02 [17043] WARNING:core:warn: warning in config file //etc/opensips/opensips.cfg, line 47, column 13-16: tls support not compiled in Listening on udp: 45.56.76.75 [45.56.76.75]:5060 Aliases:
185
Mar 10 19:47:02 [17043] NOTICE:core:main: config file ok, exiting... Ya se puede iniciar OpenSIPs: service opensips start Iniciando opensips:
[ OK ]
Si no aparecen errores significa que el programa se ha iniciado con éxito. Se puede revisar el archivo de LOG para ver si hay algún problema: nano /var/log/opensips.log o con el alias: oslog El servidor OpenSIPs está instalado y funcionando. 6.2 Configuración de OpenSIPs En el párrafo anterior se ha visto una primera configuración de OpenSIPs. En este párrafo se completará la información intentando explicar más detalladamente el archivo de configuración. Como se ha dicho anteriormente, el archivo se divide en tres bloques: • • •
el primer bloque es donde se configuran los parámetros globales de OpenSIPs el segundo bloque es donde se configuran los módulos con relativas opciones el tercer bloque es el script que procesará cada petición SIP que llegue o salga del servidor
6.2.1 Bloque Globales Analizando los parámetros globales que aparecen en el archivo de configuración: •
•
186
debug=3 Con este parámetro se indica el nivel de detalle que se quiere enviar al LOG del programa. Los valores que se pueden utilizar: • -3 Alerta • -2 Critico • -1 Error • 1 Advertencia • 2 Noticia • 3 Información • 4 Debug. El nivel de debug se activa cuando se presentan problemas y se quiere analizar en detalle el funcionamiento de OpenSIPs log_stderror=no significa que eventuales errores del programa no se enviarán al salida estándar de Linux para los errores (stderr)
• •
•
log_facility=LOG_LOCAL0 significa que los registros de LOG de OpenSIPs se enviarán a la salida LOG_LOCAL0 que es la que se ha configurado en el archivo de configuración de Rsyslog y que permite tener un archivo de LOG dedicado (opensips.log) fork=yes OpenSIPs se iniciará en segundo plano y se creará un proceso para cada IP de escucha configurada y un proceso para cada protocolo de transporte configurado. Este valor se multiplica por el numero indicado en el parámetro children y así se obtendrá el valor total de los procesos activos; si por ejemplo se configura OpenSIPs para que escuche sobre el protocolo UDP, para una sola IP, el numero de procesos será 2 multiplicado el valor del parámetro children. Si fork=no se puede configurar solamente una IP de escucha y OpenSIPs se iniciará con un solo proceso. children=4 El numero de procesos hijos que se ejecutarán al iniciar OpenSIPs. Normalmente este valor es más que suficiente.
Con el comando: ps aux | grep /sbin/opensips Aparecerá:
8 entradas. Cuatros procesos hijos para la IP y cuatros procesos hijos para el protocolo de transporte. •
•
• •
auto_aliases=no OpenSIPs no buscará eventuales alias del dominio donde está escuchando si en el parámetro listen se ha configurado un nombre de dominio en lugar de una IP. Al mismo tiempo no realizará una consulta de tipo “Reverse DNS” si en el parámetro listen se ha configurado una IP. El Reverse DNS permite conocer el dominio asociado a una IP. listen=udp:IPPublico:5060 la linea donde se configura el protocolo de transporte, la IP y el puerto de escucha de OpenSIPs. Se indica uno por linea y OpenSIPs escuchará en todos si y solamente si fork=yes. Si esta linea no se configura, OpenSIPs escuchará en todas las IPv4 y IPv6 presentes en el servidor (puerto predefinido 5060). disable_tcp=yes si no se quiere utilizar el protocolo TCP como protocolo de trasporte de la señalización SIP disable_tls=yes si no se quiere utilizar el protocolo TLS (señalización cifrada) como protocolo de trasporte de la señalización SIP
Si no se configura diversamente, cuando OpenSIPs enviará un mensaje SIP actuando como un UAs (User Agent Server) la cabecera Server: presente en el mensaje SIP aparecerá de la siguiente forma: Server: OpenSIPS (1.11.3-notls (x86_64/linux))
187
Cuando actuará como UAc (User Agent Client): User-Agent: OpenSIPS (1.11.3-notls (x86_64/linux)). Si no se quiere que aparezca el tipo y versión del Proxy que se está utilizando, se pueden añadir dos nuevas entradas en el bloque de los parámetros globales de la configuración de OpenSIPs. Se abre el archivo: oscfg y después de esta linea: disable_tls=yes se añaden las lineas que siguen: user_agent_header="User-Agent: VozToVoice Proxy Agent" server_header="Server: VozToVoice Proxy Server" Antes de guardar los cambios, personalizar los valores. Luego se reinicia OpenSIPs: service opensips restart 6.2.2 Bloque Módulos En este bloque se configuran los módulos cuyas funciones se utilizarán en el tercer bloque del archivo de configuración de OpenSIPs. El primer parámetro que se configura es mpath y se utiliza para indicar la carpeta donde se encuentran los módulos compilados a lo largo de la instalación de OpenSIPs. En este caso: mpath="/lib64/opensips/modules/" Luego se inicia a cargar los módulos y las respectivas opciones. El orden en que se cargan los módulos es muy importante ya que algunos dependen de otros; esto quiere decir que no se pueden cargar módulos antes de los de que dependen. Como en el párrafo 6.3 se hablará del modulo LOAD BALANCER, se toma este modulo como ejemplo. En la documentación de OpenSIPs cada modulo viene con un documento dedicado que normalmente se divide en: 1. Una descripción del modulo y sus funcionalidades 2. Las dependencias del modulo. En este caso: • el modulo DIALOG • el modulo TM que permite a OpenSIPs actuar como Statefull Proxy. Este modulo se necesita solamente si en el modulo LOAD BALANCER se utiliza el probing, es decir la 188
3.
4.
5. 6. 7.
funcionalidad de enviar un paquete SIP (normalmente OPTIONS) para saber si el destino está activo • un modulo de tipo DataBase (en este caso MySQL) ya que la configuración del servidor/es Asterisk que se utilizará para el balancemiento de carga se configura en la base de datos. Los parámetros que se pueden configurar con el modulo. Algunos ejemplos: • db_url el enlace que apunta a la base de datos donde se encuentra la tabla para la configuración de las reglas del balanceamiento de carga • probing_interval cada cuanto segundos enviar un mensaje SIP para averiguar si el destino está activo • probing_method el tipo de mensaje SIP que se enviará para averiguar el estado del destino. Predefinido OPTIONS. Puede ser también INFO • probing_form La dirección SIP que se utilizará para enviará el paquete OPTIONS Las funciones que se activarán cargando el modulo y que se podrán utilizar en el script de configuración de OpenSIPs • Un ejemplo de función activada por el modulo y que se utilizará más adelante es load_balance(grp,resources[,alg]) Si el modulo exporta o no estadísticas que luego se pueden ver a través de comandos específicos. Las funciones exportadas a la “consola” MI de OpenSIPs. Esta consola nos permite ejecutar comandos a través de los cuales realizar consultas o modificaciones de la configuración del modulo. Por ultimo una parte dedicada a las pseudo-variables exportadas por el modulo. Las pseudovariables son variables donde se almacenan determinados valores relacionados con el procesamiento de las peticiones SIP y/o con el funcionamiento interno de OpenSIPs y de sus funciones o, como en este caso, generadas por los módulos. Normalmente son de sola lectura y solamente en algunos casos de lectura/escritura.
Una vez configurados todos los módulos que se utilizarán, inicia el tercer bloque de configuración de OpenSIPs que es donde se procesarán todas las peticiones SIP recibidas/enviadas. En este bloque se pueden configurar dos tipos distintos de rutas: • top routes (rutas principales). Estas rutas se utilizan para procesar las peticiones SIP, las repuestas y los eventuales errores generados por una transacción • sub-routes (rutas secundarias o sub-rutas). Estas rutas se utilizan “llamándolas” desde una ruta principal y son parecidas a las subrutinas que se utilizan en Asterisk. 6.2.3 Parámetros Globales Al cargar el corazón de OpenSIPs se activarán una serie de: • • •
Palabras clave Valores Parámetros
Todos estos valores se encuentran en la documentación de OpenSIPs y se pueden utilizar en el script de 189
configuración de OpenSIPs. Algunos ejemplos de palabras claves que se utilizarán en este libro: •
method es la variable que permite conocer el método SIP de la solicitud que se está procesando:
if(method=="REGISTER") { log("La solicitud SIP es un mensaje REGISTER \n"); } •
$retcode es la variable que contiene el valor numérico devuelto por la función utilizada en el script o el código devuelto por una sub-ruta llamada desde una ruta principal.
if load_balance("1","channel") { log("El código devuelto es $retcode \n"); } •
uri es la variable que permite realizar una comparación con la URI presente en la cabecera To: de la solicitud SIP (Request URI)
if(uri=~"sip:
[email protected]") { log("Esta es un solicitud para los usuarios del dominio opensips.org\n"); } Los valores presentes en el corazón de OpenSIPs se pueden utilizar en sentencias (if) para realizar consultas contra las palabras claves del corazón de OpenSIPs: •
myself hace referencia a todos los dominios, direcciones IP y alias configurados en el bloque de los parámetros globales del archivo de configuración de OpenSIPs.
if(uri==myself) { log("La solicitud es para ser procesada localmente \n"); } Si la parte de la Request URI presente después de la arroba es una de las configuradas entonces la solicitud SIP será procesada como una solicitud local. La Request URI corresponde a la cabecera To: de la solicitud SIP. 6.2.4 Tipos de Rutas La ruta de procesamiento principal es route, de hecho el tercer bloque del archivo de configuración de OpenSIPs inicia con: route{ 190
Otras rutas que se pueden utilizar son: •
•
• • • •
• •
branch_route es una ruta que contiene una serie de acciones que OpenSIPs realizará por cada branch de una petición SIP. Se crean distintos branch de una petición SIP cuando, por ejemplo, la misma extensión está registrada desde distintos dispositivos y OpenSIPs crea un INVITE para cada uno de ellos. failure_route es una ruta que contiene una serie de acciones que se ejecutarán para cada transacción SIP cuyo resultado es una respuesta de error con código SIP >= 300. En el caso del balanceamiento de carga, si un recurso no está disponible, se puede configurar esta ruta para intentar sacar la llamada a través de otro recurso. onreply_route es una ruta que puede contener una serie de acciones a ejecutar antes que OpenSIPs envié una respuesta a la petición SIP recibida. Ejemplo: añadir una cabecera más a la petición SIP antes de enviarla, en nuestro caso, al servidor Asterisk. error_route es una ruta que se ejecuta automáticamente cuando se verifica un error al momento de parsear (examinar todas las cabeceras presentes) la petición SIP recibida. Muy útil para individuar errores presentes en las peticiones SIP recibidas. local_route es una ruta que se ejecuta automáticamente cuando una nueva petición SIP ha sido generada internamente por el modulo TM de OpenSIPs. startup_route es una ruta para ejecutar determinadas acciones cuando se inicia OpenSIPs pero antes que éste inicie a procesar las peticiones SIP. Muy útil si se quieren cargar determinados datos en la cache de memoria o configurar determinadas variables. No se puede utilizar para procesar peticiones SIP. timer_route es una ruta que se ejecuta cada N segundos definidos en la declaración de la ruta misma. No se puede utilizar para procesar peticiones SIP. event_route es una ruta que se ejecuta cuando la interfaz de eventos de OpenSIPs detecta que se ha presentado el evento declarado en la ruta. Para declarar el evento para el cual la ruta es responsable se define después de la ruta. Ejemplo: event_route[E_PIKE_BLOCKED]
De la mayoría de estas rutas veremos algunos ejemplos a lo largo del libro. 6.2.5 Operadores Los operadores permiten realizar una serie de operaciones en el archivo de configuración. Pueden ser: • •
Asociaciones: asignar un valor a una variable. Ejemplos: • $var(a) = 123; • $var(b) = “fulano”; Operaciones sobre cadenas. Ejemplos: • $var(a) = “prueba” • $var(b) = “sip:” + $var(a) + “@” + “voztovoice.org”; El resultado sería sip:
[email protected]
Todos los operadores que se pueden utilizar para este tipo de operaciones: • 191
+ más
- menos / dividir * multiplicar % modulo
• • • •
Las operaciones que siguen se ejecutan a nivel de bit y solo se pueden realizar sobre valores numéricos. Trabajan directamente con el sistema binario donde un byte está compuesto por 8 bits que pueden estar en cero (no activado) y uno (activado). En la primera linea los valores numéricos de cada bit cuando esté en 1. Si hay más de un bit en uno el valor de cada bit se suma para obtener el valor final. 128
64
32
16
8
4
2
1
0
0
0
0
0
0
0
0
Algunos ejemplos: 00001000 tendrá el valor numérico 8 00001001 tendrá el valor numérico 9 (8 + 1) 10000000 tendrá el valor numérico 128 | operación de bit a bit de tipo OR
•
& operación de bit a bit de tipo AND
•
^ operación de bit a bit de tipo XOR
192
•
•
~ operación de bit a bit de tipo NOT
•
> operación de bit a bit de tipo correr a la derecha por el numero de posiciones indicadas en la segunda casilla de la imagen:
6.2.6 Declaraciones Las distintas declaraciones que se pueden utilizar para el procesamiento de las peticiones SIP.
193
La primera es la típica if-else. Si se verifica una determinada condición ejecutar una determinada acción sino ejecutar otra. El else se puede omitir y no es obligatorio. Todos los ejemplos a seguir son tomados de la documentación de OpenSIPs: if (expr) { acción; } else { acción; } El comando Switch. La mayoría de las funciones que se utilizan en el script de OpenSIPs devuelven un valor numérico que se almacena en la pseudo-variable $retcode (código devuelto). Se puede utilizar este comando para ejecutar una serie de acciones según el valor numérico de esa variables: route { route(my_logic); switch($retcode) { case -1: log("Procesar los SIP INVITE aquí \n"); break; case 1: log("Procesar los SIP INVITE aquí \n"); break; case 2: case 3: log("Procesar los SIP SUBSCRIBE y NOTIFY aquí \n"); break; default: log("Procesar cualquier otro tipo de solicitud aquí \n"); } El comando While se utiliza para ejecutar un determinado ciclo hasta que no se cumpla una determinada condición: $var(i) = 0; while($var(i) < 10) { xlog("conteo: $var(i)\n"); $var(i) = $var(i) + 1; } El comando for each se utiliza para mostrar todo el contenido de una matriz. Si por ejemplo se quieren ver todas las cabeceras de tipo Via contenidas en un petición SIP: for ($var(via) in $(hdr(Via)[*])) xlog("Encontrada cabecera: \"Via\" $var(via)\n"); 194
Otros comandos que pueden ser muy útiles a la hora de construir el script de OpenSIPs, son los operadores lógicos: • • • • • • • • • • • •
== es igual a != no es igual a =~ la expresión regular que sigue empareja con la declaración que precede el operador !~ la expresión regular que sigue no empareja con la declaración que precede el operador > mayor a >= mayor o igual a < menor a use opensips y se mira la estructura de la tabla load_balancer utilizada para la configuración del modulo en OpenSIPs: mysql> desc load_balancer; El resultado:
200
Los valores: • • • • •
•
id: numero progresivo creado automáticamente por MySQL group_id: los recursos disponibles en los distintos servidores Asterisk se pueden dividir en distintos grupos o se pueden crear grupos distintos de servidores Asterisk dst_uri: se indica la IP del servidor Asterisk usando la sintaxis: sip:IPAsterisk:port. Si el puerto es el 5060, se omite resources: los recursos disponibles en el servidor Asterisk que se está configurando probe_mode: se utiliza para averiguar si el recurso está disponible y puede contener tres valores: • 0: desactivado • 1: se envían los paquetes OPTIONS solamente si el recurso se ha desactivado utilizando la función lb_disble activada por este modulo • 2: se envían los paquetes OPTIONS siempre description: una descripción del recurso.
Ya se puede añadir el primer recurso: mysql> insert into load_balancer (group_id,dst_uri,resources,probe_mode,description) values ('1','sip:IPPrivada:5090','channel=50','2','Asterisk1'); Antes de presionar la tecla Envío, cambiar IPAsterisk con la IP privada del servidor (puerto 5090). El nombre del recurso que se ha insertado en la tabla es channel. Podría ser llamadas, canales, etc. Lo importante es que ese nombre luego se refleje en la configuración del script de OpenSIPs y más exactamente en esta linea: if ( !load_balance("1","channel")) { El numero después del nombre del recurso: channel=50 representa el numero de llamadas simultaneas máxima que se enviarán a Asterisk. Este valor hay que personalizarlo y calibrarlo según el tipo de servidor que se está utilizando. Se sale del cliente mysql: 201
mysql> quit Para poder averiguar el estado del modulo, hay unos cuantos comandos disponibles que se pueden ejecutar utilizando la “consola” de OpenSIPs. El primero es: opensipsctl fifo lb_list que debería devolver la lista de servidores y recursos configurados para el modulo. No aparecerá nada. ¿Pórque? Porque no se ha recargado la configuración del modulo que lo que hace es leer la tabla load_balancer y cargar la configuración presente en la memoria de cache de OpenSIPs. El comando para recargar la configuración es: opensipsctl fifo lb_reload Ejecutando nuevamente el comando anterior: opensipsctl fifo lb_list El resultado: Destination:: sip:192.168.160.142:5090 id=1 group=1 enabled=yes auto-re=on Resources:: Resource:: channel max=50 load=0 Aparecerán los datos del servidor que se acaba de configurar. En algunos casos, el resultado puede ser: Destination:: sip:192.168.160.142:5090 id=1 group=1 enabled=no auto-re=on Resources:: Resource:: channel max=50 load=0 Esto significa (la parte en negrita) que el recurso (el servidor Asterisk) no se encuentra disponible. Como el servidor OpenSIPs envía paquetes SIP OPTIONS para conocer el estado del recurso, la primera hipótesis es que Asterisk no esté contestando como debería (200 OK) a ese paquete OPTIONS. Se entra en la consola de Asterisk y se activa el debug SIP: aste CLI> sip set debug on después de unos segundos: OPTIONS sip:192.168.160.142:5090 SIP/2.0 202
Via: SIP/2.0/UDP 45.56.76.75:5060;branch=z9hG4bK8773.309e94a1.0 To: sip:192.168.160.142:5090 From: ;tag=e7db02436b21b8177dfe3e60dcf3bb20-2856 CSeq: 10 OPTIONS Call-ID:
[email protected] Max-Forwards: 70 Content-Length: 0 User-Agent: VozToVoice Proxy Agent --- (9 headers 0 lines) --Sending to 45.56.76.75:5060 (no NAT) Looking for s in default (domain 192.168.160.142) SIP/2.0 404 Not Found Via: SIP/2.0/UDP 45.56.76.75:5060;branch=z9hG4bK8773.309e94a1.0;received=45.56.76.75 From: ;tag=e7db02436b21b8177dfe3e60dcf3bb20-2856 To: sip:192.168.160.142:5090;tag=as2ae50347 Call-ID:
[email protected] CSeq: 10 OPTIONS Server: VozToVoice 2.0 Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH, MESSAGE Supported: replaces, timer Accept: application/sdp Content-Length: 0 El primer bloque es el paquete SIP enviado por OpenSIPs y el ultimo bloque el paquete SIP de la respuesta enviada por Asterisk a OpenSIPs (404 Not Found). OpenSIPs considera esa respuesta negativa y desactiva el recurso. El problema se puede solucionar de dos formas: • •
Añadiendo el contexto default que aparece en el segundo bloque en el dialplan de Asterisk Añadiendo un nuevo parámetro en la configuración del modulo LOAD BALANCER en el archivo de configuración de OpenSIPs.
Se utilizará la segunda solución. Se abre el archivo de configuración de OpenSIPs y en el bloque del modulo LOAD BALANCER se añade esta linea: modparam("load_balancer", "probing_reply_codes", "404") para que el bloque quede: #### LOAD BALANCER module loadmodule "load_balancer.so" modparam("load_balancer", "db_url", "mysql://opensips:opensipsrw@localhost/opensips") # CUSTOMIZE ME 203
modparam("load_balancer", "probing_method", "OPTIONS") modparam("load_balancer", "probing_interval", 30) modparam("load_balancer", "probing_reply_codes", "404") Con esa linea se le dice a OpenSIPs que aunque reciba como respuesta al paquete SIP OPTIONS enviado un 404 Not Found, considere el recurso como disponible. Se guardan los cambios y se reinicia OpenSIPs: service opensips restart Después de unos segundos se ejecuta: opensipsctl fifo lb_list Destination:: sip:192.168.160.142:5090 id=1 group=1 enabled=yes auto-re=on Resources:: Resource:: channel max=50 load=0 Ya se puede realizar una primera prueba. Se abre el X-Lite (que se había configurado con una cuenta creada en A2Billing) y se modifica la configuración de esta forma:
204
Se modifica el parámetro Domain con la IP publica del servidor (puerto 5060) que es donde está a la escucha OpenSIPs y se deselecciona el parámetro Register porque todavía no se ha configurado OpenSIPs como Registrar. Se presiona el botón OK. Ahora se realiza una llamada nuevamente al numero de Avianca 005714013434. A lo largo de la llamada: opensipsctl fifo lb_list Destination:: sip:10.128.88.190:5090 id=1 group=1 enabled=yes auto-re=on Resources:: Resource:: channel max=50 load=1 205
Como se puede ver el sistema ha funcionado correctamente (la parte en negrita); load=1 significa que en el servidor Asterisk se está utilizando un recurso channel de los 50 disponibles. El diagrama de flujo de la llamada será: X-Lite INVITE ----------------------------> 401 Unauthorized
401 Unauthorized
Trying INVITE ----------------------------> alter table acc add Llamante char(20); mysql> alter table acc add Llamado char(20); los mismos campos se crean en la tabla missed_calls que es donde se guardarán los registros de las llamadas perdidas siempre y cuando el script de OpenSIPs se configure para guardar este tipo de datos: mysql> alter table missed_calls add Llamante char(20);
208
mysql> alter table missed_calls add Llamado char(20); Se sale del cliente MySQL y se reinicia OpenSIPs: mysql> quit service opensips restart Se realiza una nueva llamada desde X-Lite y una vez terminada se vuelve a MySQL: mysql -u root -psesamo mysql> use opensips mysql> select id,method,from_tag,to_tag,sip_code,sip_reason,time,duration,setuptime,created,Llamante,Llamado from acc;
el resultado:
En este caso hay muchos más datos disponibles. En la columna duration de la linea INVITE aparece el tiempo de duración (en segundos) de la llamada desde que ha sido contestada. En setuptime siempre de la linea INVITE aparece el tiempo (en segundos) que ha tardado el destino en contestar. En Llamante y Llamado de la dos lineas, aparece el numero de extensión que ha llamado y el numero llamado respectivamente. Otros datos. En la columna created del INVITE aparece el momento en que se ha iniciado la llamada. En la columna time del INVITE aparece el momento en que la llamada ha sido contestada (OpenSIPs ha recibido un 200 OK por parte de Asterisk), en la columna time de la linea BYE aparece el momento en que la llamada se ha terminado. Como se ha dicho, la conversación ha tenido una duración de 24 segundos. Si se entra en la pagina de administración de A2Billing, menú CALL REPORTS → CDRs, aparecerá:
209
Aunque para las llamadas salientes están disponibles los reportes de A2Billing, esta solución puede ser muy útil cuando se hablará de las llamadas entre extensiones ya que se podrá tener un registro de este tipo de llamadas, cosa que no es posible ni en Asterisk ni en A2Billing ya que las llamadas no pasarán por la PBX. La verdad es que parece todo muy sencillo. En poco tiempo se ha configurado OpenSIPs como Load Balancer. En el archivo de configuración es muy útil añadir comentarios que permitan realizar un seguimiento de lo que está pasando en OpenSIPs. Esto se realiza añadiendo unas lineas que digan a OpenSIPs que envíe esos comentarios al archivo de LOG predefinido. Antes de crear el nuevo archivo, se saca una copia del viejo. Esta es una operación que hay realizar siempre porque si algo no funciona se puede volver a la configuración anterior: mv /etc/opensips/opensips.cfg /etc/opensips/opensips.cfg.1 Se crea el nuevo: nano /etc/opensips/opensips.cfg En el archivo de configuración que sigue se quitaron los comentarios presentes y se añadieron los nuevos: ####### Global Parameters ######### debug=3 log_stderror=no log_facility=LOG_LOCAL0 fork=yes children=4 auto_aliases=no listen=udp:IPPublica:5060 disable_tcp=yes disable_tls=yes user_agent_header="User-Agent: VozToVoice Proxy Agent" server_header="Server: VozToVoice Proxy Server" ####### Modules Section ######## #set module path mpath="/lib64/opensips/modules/" 210
#### SIGNALING module loadmodule "signaling.so" #### StateLess module loadmodule "sl.so" #### Transaction Module loadmodule "tm.so" modparam("tm", "fr_timeout", 5) modparam("tm", "fr_inv_timeout", 30) modparam("tm", "restart_fr_on_each_reply", 0) modparam("tm", "onreply_avp_mode", 1) #### Record Route Module loadmodule "rr.so" modparam("rr", "append_fromtag", 0) #### MAX ForWarD module loadmodule "maxfwd.so" #### SIP MSG OPerationS module loadmodule "sipmsgops.so" #### FIFO Management Interface loadmodule "mi_fifo.so" modparam("mi_fifo", "fifo_name", "/tmp/opensips_fifo") modparam("mi_fifo", "fifo_mode", 0666) #### URI module loadmodule "uri.so" modparam("uri", "use_uri_table", 0) #### MYSQL module loadmodule "db_mysql.so" #### AVPOPS module loadmodule "avpops.so" #### ACCounting module loadmodule "acc.so" modparam("acc", "early_media", 0) modparam("acc", "report_cancels", 0) modparam("acc", "detect_direction", 0) modparam("acc", "failed_transaction_flag", "ACC_FAILED") modparam("acc", "db_flag", "ACC_DO") 211
modparam("acc", "db_missed_flag", "ACC_MISSED") modparam("acc", "cdr_flag", "CDR_FLAG") modparam("acc", "db_extra", "Llamante=$fU;Llamado=$tU") modparam("acc", "db_url", "mysql://opensips:opensipsrw@localhost/opensips") #### DIALOG module loadmodule "dialog.so" modparam("dialog", "dlg_match_mode", 1) modparam("dialog", "default_timeout", 21600) modparam("dialog", "db_mode", 2) modparam("dialog", "db_url","mysql://opensips:opensipsrw@localhost/opensips") #### LOAD BALANCER module loadmodule "load_balancer.so" modparam("load_balancer","db_url","mysql://opensips:opensipsrw@localhost/opensips") modparam("load_balancer", "probing_method", "OPTIONS") modparam("load_balancer", "probing_interval", 30) modparam("load_balancer", "probing_reply_codes", "404") ####### Routing Logic ######## route{ if (!mf_process_maxfwd_header("10")) { xlog("L_ERROR","Superado el numero máximo de FORWARD Permitidos"); sl_send_reply("483","Too Many Hops"); exit; } if (has_totag()) { xlog("L_NOTICE", "La transacción tiene un tag en la cabecera To:"); if (loose_route()) { if ( $DLG_status!=NULL && !validate_dialog() ) { xlog("L_ERROR", "El Dialogo $rm de $si (CALLERID=$ci) no es valido"); ## exit; } if (is_method("BYE")) { setflag(ACC_DO); setflag(ACC_FAILED); xlog("L_NOTICE", "Recibido un BYE dentro de un dialogo"); } else if (is_method("INVITE")) { xlog("L_NOTICE", "Recibido un re-INVITE dentro de un dialogo"); 212
record_route(); } route(RELAY); } else { if ( is_method("ACK") ) { if ( t_check_trans() ) { xlog("L_NOTICE", "Recibido un ACK dentro de un dialogo"); t_relay(); exit; } else { exit; } } sl_send_reply("404","Not here"); xlog("L_ERROR", "Recibida una petición sin Dialogo asociado"); } exit; } #### INITIAL REQUESTS # CANCEL processing if (is_method("CANCEL")) { if (t_check_trans()) xlog("L_NOTICE", "Recibido un CANCEL relacionado con una transacción valida");
t_relay(); exit; } else if (!is_method("INVITE")) { send_reply("405","Method Not Allowed"); xlog("L_ERROR", "Solicitud recibida $rm no es un INVITE"); exit; } if ($rU==NULL) { sl_send_reply("484","Address Incomplete"); xlog("L_ERROR", "El usuario $rU no es valido"); exit; } t_check_trans(); # preloaded route checking if (loose_route()) { xlog("L_ERR","Attempt to route with preloaded Route's [$fu/$tu/$ru/$ci]"); if (!is_method("ACK")) sl_send_reply("403","Preload Route denied"); 213
exit; } # record routing record_route(); setflag(ACC_DO); setflag(CDR_FLAG); setflag(ACC_MISSED); if ( !load_balance("1","channel")) { send_reply("500","No Destination available"); exit; } xlog("L_NOTICE", "Llamada de $fu IP $si $sp a $tu para $du"); t_on_failure("GW_FAILOVER"); route(RELAY); } route[RELAY] { if (!t_relay()) { sl_reply_error(); }; exit; } failure_route[GW_FAILOVER] { if (t_was_cancelled()) { exit; } # failure detection with redirect to next available trunk if (t_check_status("(408)|([56][0-9][0-9])")) { xlog("Failed trunk $rd/$du detected \n"); if ( load_balance("1","channel") ) { t_on_failure("GW_FAILOVER"); t_relay(); exit; } xlog("L_ERROR", "Recurso $du no disponible"); 214
send_reply("500","All GW are down"); } } local_route { if (is_method("BYE") && $DLG_dir=="UPSTREAM") { acc_db_request("200 Dialog Timeout", "acc"); } } Antes de guardar el nuevo archivo, hay que modificar la linea: listen=udp:IPPublica:5060 cambiando IPPublica con la IP publica del servidor. Se guardan los cambios y se controla que el archivo no contenga errores: opensips -c /etc/opensips/opensips.cfg Mar 10 23:39:25 [26241] WARNING:core:warn: warning in config file //etc/opensips/opensips.cfg, line 12, column 13-16: tls support not compiled in Listening on udp: 45.56.76.75 [45.56.76.75]:5060 Aliases: Mar 10 23:39:25 [26241] NOTICE:core:main: config file ok, exiting... Perfecto. Ya se puede reiniciar OpenSIPs: service opensips restart Analizando el bloque donde se utiliza el modulo LOAD BALANCER: if ( !load_balance("1","channel")) { send_reply("500","No Destination available"); exit; } xlog("L_NOTICE", "Llamada de $fu IP $si $sp a $tu para $du /n"); t_on_failure("GW_FAILOVER"); route(RELAY); } Después de una serie de controles y pasajes el paquete SIP llegará a este bloque. Por la configuración que lo precede, llegarán solamente INVITEs iniciales. Los re-INVITEs llegarán al bloque que inicia con if (has_totag()) y los demás paquetes SIP (REGISTER, SUBSCRIBE, etc) serán descartados. 215
¿Qué pasa en este bloque? Se utiliza la función load_balance del modulo LOAD BALANCER Esta función tiene la siguiente sintaxis: load_balance(grp,resources[,alg]) • • •
grp: grupo de servidores o recursos según los datos presentes en la tabla de MySQL resource: el tipo de recurso/s alg: algoritmo utilizado para calcular la disponibilidad de los recursos. El valor puede ser 0 que significa que los recursos se calcularán utilizando su valor absoluto; 1 que significa que los recursos se calcularán según un porcentaje. Si el valor no se declara, el predefinido es 0.
Un ejemplo: hay dos servidores Asterisk; uno puede cursar 50 llamadas y otro 20. con alg=0 las primeras 30 llamadas llegarán al primer servidor luego la 31 al segundo, la 32 al primero la 33 al segundo, etcétera. Si alg=1 este calculo se realizará en porcentaje. El primer servidor tiene alrededor del 70% de los recursos, el segundo alrededor del 30%. Esto quiere decir que cada 10 llamadas, 7 llegarán al primer servidor y 3 al segundo. Retomando el bloque: if ( !load_balance("1","channel")) { send_reply("500","No Destination available"); exit; } xlog("L_NOTICE", "Llamada de $fu IP $si $sp a $tu para $du /n"); t_on_failure("GW_FAILOVER"); route(RELAY); } se puede notar que delante de la función load_balance hay un ! que es el operador lógico que se ha visto en el párrafo 6.2.6 y cuyo significado es NOT. La linea en su complejo se lee de esta forma: si no hay recursos de tipo channel disponibles en los servidores del grupo uno, (la opción alg no se declara pues es 0) envía como respuesta el mensaje SIP 500, ninguna destinación disponible. Con exit se termina el procesamiento de la petición SIP y se sale del script. Si hay recursos channel disponibles se saltará el bloque y se continuará con el que sigue. En el caso que la llamada no tenga éxito débito a una respuesta SIP negativa por parte del servidor Asterisk (códigos de error 4XX, 5XX o 6XX, se ejecutara la función t_on_failure que justamente tiene esta tarea. Luego se envía el INVITE a la “subrutina” RELAY. En esta subrutina hay: route[RELAY] { if (!t_relay()) { sl_reply_error(); }; 216
exit; } y el significado es: si no se puede procesar la transacción hacia el destino de manera Statefull, devolver el tipo de error recibido a OpenSIPs para que pueda elaborarlo en la ruta t_on_failure. Se termina de procesar el script con exit. Ahora se realiza una segunda prueba. En la pagina de administración de A2BIlling se modifica la cuenta configurada en X-Lite cambiando el parámetro STATUS de ACTIVE a CANCELLED. Se realiza una llamada al mismo numero. La llamada no se podrá realizar. Asterisk, ya que la cuenta no está activa contestará con un 603 Declined. En este caso se activará la subrutina t_on_failure("GW_FAILOVER") donde hay: failure_route[GW_FAILOVER] { if (t_was_cancelled()) { exit; } if (t_check_status("(408)|([56][0-9][0-9])")) { xlog("Failed trunk $rd/$du detected \n"); if ( load_balance("1","channel") ) { t_on_failure("GW_FAILOVER"); t_relay(); exit; } send_reply("500","All GW are down"); } } La segunda linea controla si la transacción ha sido anulada. Si es así se termina el procesamiento de la transacción: if (t_was_cancelled()) { exit; } Si la respuesta que devuelve el servidor Asterisk es un error de tipo 408 o que va de 500 a 699, se ejecutará este bloque: if (t_check_status("(408)|([56][0-9][0-9])")) { 217
xlog("Failed trunk $rd/$du detected \n"); if ( load_balance("1","channel") ) { t_on_failure("GW_FAILOVER"); t_relay(); exit; } xlog("L_ERROR", "Recurso $du no disponible"); send_reply("500","All GW are down"); } Donde OpenSIPs contestará con un: ("500","All GW are down"). De hecho esta es la respuesta que encontramos en la captura: SIP/2.0 500 All GW are down. Via: SIP/2.0/UDP 186.119.63.238:27632;received=186.119.63.238;branch=z9hG4bK-d8754z4e3cbc551e429361-1---d8754z-;rport=27632. To: ;tag=9b5caedbc2793bce6354d46c848604bb-84de. From: "74478";tag=4c5ee962. Call-ID: MTYyMzNjZTIxNDhhMGYxZDAwYmExZjU1OWI4MTk1ZjI. CSeq: 2 INVITE. Server: VozToVoice Proxy Server. Content-Length: 0. Si el código de error es de otro tipo, OpenSIPs intentará sacar la llamada nuevamente con la función load_balance utilizando nuevamente el recurso channel. Aunque parezca que no tenga mucho sentido, puede ser que en el segundo intento se haya liberado un recurso y la llamada tenga éxito. 6.4 OpenSIPs como Registrar OpenSIPs puede actuar como Registrar Server, es decir que puede guardar en un Location Server los datos de registro recibidos a través del método SIP REGISTER. En la configuración del modulo es posible indicar cuantos AOR (Address Of Record) están permitidos por cada usuario/extensión. Esto quiere decir que la misma extensión se puede registrar desde distintos dispositivos. Hasta el momento OpenSIPs no actúa como Registrar Server; de hecho se puede realizar una prueba para averiguarlo. En el servidor OpenSIPs se activa el comando tail para el el LOG del Proxy; se utilizará el alias definido en el archivo .bash_profile: ostail Luego se abre el softphone donde se ha configurado la extensión utilizada para las llamadas y se modifica la configuración activando la casilla “Register with domain and receive calls”:
218
Se presiona el botón OK. El registro fallará y en LOG de OpenSIPs aparecerá: Solicitud recibida REGISTER no es un INVITE Los pasos a seguir para aceptar y guardar los registros de los usuarios en OpenSIPs son: • • •
Activar los módulos relacionados Crear una vista de la tabla cc_sip_buddies para la tabla de OpenSIPs donde se guardarán las credenciales de cada usuario, como configuradas en A2Billing Modificar el script de OpenSIPs
6.4.1 Módulos El primer modulo que hay que configurar es REGISTRAR. Si se consulta el manual de OpenSIPs, se verá que este modulo tiene como dependencias dos módulos más: • •
SIGNALING USERLOC
Esto significa que los dos módulos hay que cargarlos antes del modulo REGISTRAR. El primero ya está activado y aparece de esta forma en el archivo de configuración de OpenSIPs: oscfg #### SIGNALING module loadmodule "signaling.so" El segundo hay que configurarlo y mirar primero que dependencias tiene. La única dependencia es una base de datos si se quieren almacenar los AOR de las extensiones en una tabla. Como la base de datos que se está utilizando es MySQL y el modulo ya está cargado: 219
#### MYSQL module loadmodule "db_mysql.so" se puede continuar con su configuración. Este modulo se utiliza como Location Service y todos los registros de las extensiones se guardarán, por defecto, en la tabla location de la base de datos opensips. Paso a paso la configuración: • • • •
primero se pone una descripción para el modulo: • #### LOCATION module luego se carga el modulo: • loadmodule "usrloc.so" se configura el primer parámetro del modulo definiendo un Flag de tipo branch que se añadirá a los registros de extensiones que se encuentran detrás de una NAT (cuando se necesite): • modparam("usrloc", "nat_bflag", "NAT_BFLAG") el enlace para que el modulo se conecte a la base de datos opensips: •
•
modparam("usrloc", "db_url", "db_url","mysql://opensips:opensipsrw@localhost/opensips")
El modo base de datos permite decidir como y cuando se guardarán los registros de las extensiones en la base de datos: • 0: se deshabilita completamente el uso de la base de datos y los registros se guardarán solamente en la cache de memoria de OpenSIPs • 1: cualquier cambio de registro a nivel de cache de memoria se reflejará inmediatamente en la base de datos. Vuelve un poco más lento el sistema pero garantiza la consistencia de los datos en caso de un crash o reinicio del sistema • 2: Todos los cambios se ejecutan en la cache de memoria y la base de datos se actualiza después del tiempo definido en un temporizador que se puede configurar como opción del modulo. Esto vuelve más rápido el sistema pero no garantiza la consistencia de los datos en caso de crash o reinicio del sistema • 3: No se utiliza la cache de memoria y todos los datos/consultas se guardan solamente en la base de datos. Es el método más lento pero garantiza una consistencia de los datos completa. Se utilizará esta opción: • modparam("usrloc", "db_mode", 3)
Con estos datos ya se puede configurar el modulo. Se guarda una copia del archivo de configuración de OpenSIPs: cp /etc/opensips/opensips.cfg /etc/opensips/opensips.cfg.2 Se abre el archivo de configuración de OpenSIPs: oscfg y después de este bloque: #### LOAD BALANCER module loadmodule "load_balancer.so" 220
modparam("load_balancer", "db_url","mysql://opensips:opensipsrw@localhost/opensips") modparam("load_balancer", "probing_method", "OPTIONS") modparam("load_balancer", "probing_interval", 30) modparam("load_balancer", "probing_reply_codes", "404") se añade: #### LOCATION module loadmodule "usrloc.so" modparam("usrloc", "nat_bflag", "NAT_BFLAG") modparam("usrloc", "db_url","mysql://opensips:opensipsrw@localhost/opensips") modparam("usrloc", "db_mode", 3) Se continua con el modulo REGISTRAR. De este modulo nos interesan solamente las siguientes opciones y de hecho de esta forma se configurará: #### REGISTRAR module loadmodule "registrar.so" modparam("registrar", "max_contacts", 5) Los datos según la linea en que aparecen: • • •
una descripción comando para cargar el modulo numero de registros permitidos por cada extensión (5).
Ese bloque se añade después del bloque del modulo LOCATION. Se guardan los cambios y se averigua si el archivo de configuración contiene algún error: opensips -c /etc/opensips/opensips.cfg Mar 11 10:16:59 [32136] WARNING:core:warn: warning in config file //etc/opensips/opensips.cfg, line 12, column 13-16: tls support not compiled in Listening on udp: 45.56.76.75 [45.56.76.75]:5060 Aliases: Mar 11 10:16:59 [32136] NOTICE:core:main: config file ok, exiting... Con el modulo REGISTRAR se activa la función que nos permitirá guardar los registros de las extensiones en la tabla location de la base de datos MySQL opensips: save(domain [,flags ,[aor]]) • •
221
domain: puede contener el valor del dominio aceptado para los registros o, como en este caso, el nombre de la tabla donde se guardarán los registros (location) flags: puede contener una serie de valores que determinan el modo y la forma en que el registro se guardará. Los flags se pueden indicar o dejar la opción vacía
AOR: se utiliza si se quiere guardar el registro de forma personalizada, si el parámetro no está presente se tomará como AOR el valor de la cabecera To: de la solicitud SIP REGISTER recibida
•
Con estos datos se puede modificar el script de configuración de OpenSIPs para aceptar solicitudes SIP de tipo REGISTER. Se abre el archivo de configuración: oscfg se modifica este bloque: if (is_method("CANCEL")) { if (t_check_trans()) t_relay(); xlog("L_NOTICE", "Recibido un CANCEL relacionado con una transacción valida");
exit; } else if (!is_method("INVITE")) { send_reply("405","Method Not Allowed"); xlog("L_ERROR", "Solicitud recibida $rm no es un INVITE"); exit; } para que quede: if (is_method("CANCEL")) { if (t_check_trans()) t_relay(); xlog("L_NOTICE", "Recibido un CANCEL relacionado con una transacción valida");
exit; } if (is_method("REGISTER")) { xlog("L_NOTICE", "recibido un REGISTER de: $ru"); save("location"); exit; } if (!is_method("INVITE")) { send_reply("405","Method Not Allowed"); xlog("L_ERROR", "Solicitud recibida $rm no es un INVITE"); exit; } El Bloque donde se aceptan los registros de las extensiones tiene que estar antes del bloque donde se descartan todas las solicitudes SIP que no sean INVITEs. Se guardan los cambios y se controla la configuración de OpenSIPs: 222
opensips -c /etc/opensips/opensips.cfg Mar 11 10:19:22 [405] WARNING:core:warn: warning in config file //etc/opensips/opensips.cfg, line 12, column 13-16: tls support not compiled in Listening on udp: 45.56.76.75 [45.56.76.75]:5060 Aliases: Mar 11 10:19:22 [405] NOTICE:core:main: config file ok, exiting... Se reinicia OpenSIPs: service opensips restart Se instala Ngrep (un programa que permite la captura de paquetes que pasan por el servidor): yum --enablerepo=epel install ngrep -y y se activa la captura de los paquetes sobre el puerto 5060 guardando los datos en el archivo registerOS: ngrep -W byline port 5060 > /tmp/registerOS Se intenta nuevamente el registro desde el softphone configurado con la extensión configurada en A2Billing. Una vez que la extensión esté registrada, se cierra la captura y se mira el resultado Se encontrarán solamente dos Bloque: X-Lite REGISTER
OpenSIPs ---------------------------------> use opensips mysql> select * from location; aparecerán los datos de registro de la extensión. mysql> quit Los dos módulos que todavía hace falta configurar son: •
•
AUTH: este modulo brinda tres funciones indispensables para autenticar un usuario: • www_challenge: es una función que genera una cabecera SIP WWW-Authorize que indica a la extensión como registrarse correctamente al servidor OpenSIPs • proxy_challenge: parecida a la anterior pero valida para la autenticación de los INVITEs. La función genera una cabecera Proxy-Authorize que permitirá a la extensión validar sus credenciales y de esta forma sacar las llamadas. • consume_credentials: elimina la cabecera Proxy-Authorization que contiene las credenciales de autenticación de la extensión una vez que la extensión se haya autenticado. Se utiliza para INVITE y, aunque no indispensable, se puede utilizar para REGISTER. Esto para evitar que OpenSIPs, cuando genera el INVITE para la llamada hacia Asterisk, siga enviando esa cabecera (seguridad). AUTH_DB: este modulo activa las funciones para autenticar las extensiones contra una tabla de la base de datos opensips que contiene los datos de las extensiones mismas. Las funciones importantes activadas son: • www_authorize: averigua si las credenciales de la extensión que está intentando registrarse son validas. Realiza esta operación comparando las credenciales con las que están contenidas en la tabla que se declara junto a la función. • proxy_authorize: realiza la misma operación para los INVITEs
El segundo modulo (AUTH_DB) tiene como dependencia el primer modulo (AUTH); es por ese motivo que en el archivo de configuración de OpenSIPs, bloque módulos, se configurarán respetando ese orden. Se abre nuevamente el archivo de configuración de OpenSIPs: oscfg y después de este bloque: #### MYSQL module loadmodule "db_mysql.so" Se añade: 224
#### AUTH module loadmodule "auth.so" ##### AUTH_DB module loadmodule "auth_db.so" modparam("auth_db", "db_url", "mysql://opensips:opensipsrw@localhost/opensips") Se guardan los cambios y se averigua nuevamente que la configuración esté correcta: opensips -c /etc/opensips/opensips.cfg Para poder autenticar los REGISTER y los INVITE a nivel de OpenSIPs se necesita crear una tabla donde estén las credenciales de las extensiones configuradas en A2Billing. Es por eso que ya se puede pasar al segundo punto, es decir la creación de una vista en la base de datos de OpenSIPs de la tabla cc_sip_buddies presente en A2Billing 6.4.2 Creación de la vista de la tabla cc_sip_buddies Ahora que los módulos están configurados, se pasa a la creación de la vista de la tabla cc_sip_buddies de A2Billing en una nueva tabla en OpenSIPs. La nueva tabla es la que OpenSIPs utilizará para buscar las credenciales de cada extensión. El esquema es igual a la tabla predefinida de opensips que es subscriber: mysql -u root -psesamo mysql> use opensips mysql> desc subscriber:
Una paréntesis. A lo largo de la creación de la vista se puede optar para utilizar la IP Publica del servidor o el nombre de dominio asociado al servidor mismo (si hay uno) En el primer caso, las extensiones se podrán registrar SOLAMENTE utilizando la IP Publica, en el segundo caso el dominio. Si se escoge utilizar la IP Publica y se intenta registrar una extensión utilizando el dominio, el registro 225
no tendrá éxito. Es recomendable utilizar un nombre de dominio ya que si en algún momento se necesita cambiar de servidor con una nueva IP Publica, si se asocia a esa nueva IP el “viejo” dominio, las extensiones podrás seguir registrándose sin problemas. Se crea la vista (modificar dominio.org con el nombre de dominio del VPS Linode): mysql> CREATE VIEW opensips.subscriber_v1 AS SELECT id AS id, name AS username, 'dominio.org' AS domain, secret AS password, md5(concat(username, ':', 'dominio.org', ':', secret)) AS ha1, md5(concat(username, '@', 'dominio.org', ':', 'dominio.org', ':', secret)) AS ha1b, name AS rpid from a2billing.cc_sip_buddies; La nueva tabla contendrá todos valore de las extensiones SIP configuradas en A2Billing. Se puede comprobar con el comando: mysql> select * from subscriber_v1; Cada tabla presente en la base de datos opensips tiene un valor de versión que OpenSIPs utiliza para su validación. En el caso de la tabla subscriber este valor es: mysql> select * from version where table_name='subscriber';
Se asigna el mismo valor a la nueva tabla subscriber_v1: mysql> INSERT INTO version (table_name,table_version) VALUES ('subscriber_v1','7'); El resultado: mysql> select * from version where table_name='subscriber_v1';
226
Ya se puede salir del cliente MySQL: mysql> quit Completado el segundo punto, se puede empezar con el tercero, es decir realizar las modificaciones del script de OpenSIPs de forma que las extensiones configuradas en A2BIlling se puedan registrar con sus credenciales en OpenSIPs. Se abre el archivo de configuración: oscfg se modifica este bloque: if (is_method("REGISTER")) { xlog("L_NOTICE", "recibido un REGISTER de: $ru"); save("location"); exit; } para que quede: if (is_method("REGISTER")) { $var(autent_cod) = www_authorize("", "subscriber_v1"); if ( $var(autent_cod) == -1 || $var(autent_cod) == -2 ) { xlog("L_NOTICE","error de autent para $fU@$fd desde $si causa $var(autent_cod)");
sl_send_reply("403","Te he pillado"); exit; } if ( $var(autent_cod) < 0 ) { www_challenge("", "0"); exit; } save("location"); consume_credentials(); xlog("L_NOTICE","Usuario $fU Registrado"); exit; } Una explicación de las lineas que aparecen en el primer bloque: • •
227
En la primer linea se averigua que la solicitud recibida es de tipo REGISTER. Si es así se continua con la demás lineas del bloque. En la segunda linea se asocia a la variable autent_cod el valor del resultado de la ejecución de la función www_authorize que, como vimos, se utiliza para validar las credenciales de la extensión que está intentando registrarse. Como es el primer REGISTER enviado por la extensión las credenciales no estarán presentes, pues la función debería devolver un -4. Los
• • • •
códigos negativos tienen este significado: • -5 error genérico • -4 las credenciales no están presentes en la solicitud • -3 stale nonce, el nonce que aparece en la cabecera con las credenciales enviadas por la extensión no es más valido • -2 usuario valido pero contraseña incorrecta • -1 el usuario no existe Este tipo de validación se realiza hacia la tabla subcriber_v1 que sería la vista de la tabla cc_sip_buddies de la base de datos A2Billing En la segunda linea se lee el valor contenido en la variable $var(autent_cod) y si este valor es igual a -1 o -2 se pasa a la linea que sigue En la tercera linea se envía una linea al LOG de OpenSIPs que luego se utilizará con Fail2Ban para bloquer las IPs que están intentando registrarse con credenciales falsas En la cuarta linea se envía una respuesta SIP que le comunica al atacante que lo hemos pillado :) Ya que la extensión no se ha podido registrar correctamente, se sale del script.
En el segundo bloque: if ( $var(autent_cod) < 0 ) { www_challenge("", "0"); exit; } Si el valor contenido en la variable $var(autent_cod) es inferior a 0 se envía una respuesta de tipo “401 Unauthorized”. El paquete contendrá una cabecera WWW-Authenticate para que la extensión pueda registrarse correctamente utilizando los datos contenidos en esa cabecera junto a sus credenciales. Para terminar en el ultimo bloque se guarda el registro de la extensión en la tabla location de OpenSIPs y se envía al LOG de opensips la linea que aparece; la variable $fU contiene la parte usuario de la cabecera From:, es decir, el numero de extensión que se acaba de registrar. Se guardan las modificaciones y se controla que el script de configuración no contenga errores: opensips -c /etc/opensips/opensips.cfg Mar 11 10:40:20 [7178] WARNING:core:warn: warning in config file //etc/opensips/opensips.cfg, line 12, column 13-16: tls support not compiled in Listening on udp: 45.56.76.75 [45.56.76.75]:5060 Aliases: Mar 11 10:40:20 [7178] NOTICE:core:main: config file ok, exiting... Se reinicia OpenSIPs: service opensips restart Se activa nuevamente la captura con Ngrep guardando los paquetes en un nuevo archivo: 228
ngrep -W byline port 5060 > /tmp/registerOS2 y se abre abre X-Lite para que se registre a OpenSIPs utilizando, en el parámetro Domain, el nombre de dominio en lugar de la IP Publica del servidor. Una vez que se haya registrado, se termina la captura de los paquetes y se mira lo que ha pasado: X-Lite REGISTER REGISTER
OpenSIPs ---------------------------------> 190.67.240.78:25067 SIP/2.0 401 Unauthorized. Via: SIP/2.0/UDP 190.67.240.78:25067;received=190.67.240.78;branch=z9hG4bK-d8754z66f8340652c48b59-1---d8754z-;rport=25067. To: "09148";tag=5c39c8172281004ff3f4fdccfdbb433a.50ba.
From: "09148";tag=195d3556. Call-ID: M2E0NTU1ODMyMDRjN2M4MDA0MTZmOTdiZjA2YWIwNzU. CSeq: 1 REGISTER. WWW-Authenticate: Digest realm="li926-75.members.linode.com", nonce="5500628d00000001bf10422b51a9d9a9bb161b71cd16e536".
Server: VozToVoice Proxy Server. Content-Length: 0. X-Lite envía un segundo REGISTER (la cabecera CSeq pasa de 1 a 2) con las credenciales completas 229
para registrarse (contenidas en la cabecera Authorization): U 190.67.240.78:25067 -> 45.56.76.75:5060 REGISTER sip:li926-75.members.linode.com SIP/2.0. Via: SIP/2.0/UDP 190.67.240.78:25067;branch=z9hG4bK-d8754z-a8fd8b2e4dba016d-1--d8754z-;rport. Max-Forwards: 70. Contact: . To: "09148". From: "09148";tag=195d3556. Call-ID: M2E0NTU1ODMyMDRjN2M4MDA0MTZmOTdiZjA2YWIwNzU. CSeq: 2 REGISTER. Expires: 3600. Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO. User-Agent: X-Lite 4.7.1 74247-ddd1fa7b-W6.1. Authorization: Digest username="09148",realm="li92675.members.linode.com",nonce="5500628d00000001bf10422b51a9d9a9bb161b71cd16e536",uri="s ip:li92675.members.linode.com",response="e1c8563623215506624d422b5144b6e0",algorithm=MD5. Content-Length: 0. OpenSIPs contestará con 200 OK: U 45.56.76.75:5060 -> 190.67.240.78:25067 SIP/2.0 200 OK. Via: SIP/2.0/UDP 190.67.240.78:25067;received=190.67.240.78;branch=z9hG4bK-d8754za8fd8b2e4dba016d-1---d8754z-;rport=25067. To: "09148";tag=5c39c8172281004ff3f4fdccfdbb433a.81fb. From: "09148";tag=195d3556. Call-ID: M2E0NTU1ODMyMDRjN2M4MDA0MTZmOTdiZjA2YWIwNzU. CSeq: 2 REGISTER. Contact: ;expires=3381, ;expires=3600. Server: VozToVoice Proxy Server. Content-Length: 0.. A partir de este momento la extensión estará registrada. Como cada extensión se puede registrar hasta desde 5 dispositivos distintos, se configura un segundo Softphone con los mismos datos. El resultado: mysql -u root -psesamo mysql> use opensips mysql> select username,contact,user_agent from location;
230
Si la extensión en A2Billing está configurada para que pueda sacar más de una llamada a la vez, se debe poder realizar llamadas desde cualquiera de las dos extensiones o de las dos al mismo tiempo. Si se intenta registrar la extensión con una contraseña incorrecta. En el LOG de OpenSIPs aparecerá: error de autent para
[email protected] desde 190.67.240.78 causa -2 La causa -2 es “usuario valido pero contraseña incorrecta”. Se utilizará la salida del LOG más adelante para la configuración de Fail2Ban. 6.5 OpenSIPs y Llamadas entre extensiones Ahora que las extensiones se registran correctamente en OpenSIPs y son localizables, podemos configurar OpenSIPs para que permita las llamadas entre extensiones. Como OpenSIPs puede actuar como Relay Server, es decir procesar las peticiones por las cuales no es responsable, la primera operación que hay que realizar es modificar el archivo de configuración de forma que OpenSIPs procese solamente las solicitudes enviadas al dominio/IP por el cual es responsable. Se realiza una copia del archivo de configuración: cp /etc/opensips/opensips.cfg /etc/opensips/opensips.cfg.3 Se utilizará la palabra clave “uri” que sirve para ejecutar operaciones en la Request URI de una solicitud SIP y el parámetro “myself” que hace referencia a las IPs, dominios y alias servidos por OpenSIPs. Se abre el archivo de configuración de OpenSips: oscfg y después de este bloque: if (loose_route()) { xlog("L_ERR","Attempt to route with preloaded Route's [$fu/$tu/$ru/$ci]"); if (!is_method("ACK")) sl_send_reply("403","Preload Route denied"); exit; } se añade: if(!uri==myself) { xlog("La solicitud no es local. Descartada"); sl_send_reply("404","Not Here"); 231
exit; } Que se lee: si el dominio/IP contenido en la Request URI no es uno para los cuales OpenSIPs es responsable, se contesta con un “404 Not Here” y se termina el procesamiento del script. Como las extensiones se registran y sacan las llamadas utilizando el nombre de dominio, hay que indicarlo en la configuración de OpenSIPs como alias de la IP Publica. Después de esta linea: listen=udp:IPPublica:5060 se añade: alias="dominio.org":5060 Se cambia dominio.org con el nombre del dominio del serviodor. Se guardan los cambios y, como siempre, se averigua que la configuración esté correcta: opensips -c /etc/opensips/opensips.cfg Luego se reinicia OpenSIPs: service opensips restart se mira el LOG de OpenSIPs: ostail y se realiza una prueba. Desde X-Lite se intenta llamar un usuario con un dominio totalmente inventado:
En el LOG de OpenSIPs aparecerá: La solicitud no es local. Descartada Con esto hay la certeza que OpenSIPs procesará solamente peticiones SIP por las cuales es responsable. Ahora el paso a seguir es autenticar todos los INVITE recibidos por OpenSIPs. De esta forma antes que una extensión pueda realizar una llamada (a otra extensión o a un numero telefónico) tendrá que 232
autenticarse en OpenSIPs. De esta forma ya no se necesitará ese tipo de autenticación en Asterisk. Para la autenticación se utilizarán las siguientes funciones que se han explicado en párrafo 6.4 (OpenSIPs como Registrar): proxy_authorize proxy_challenge consume_credentials
• • •
Se abre nuevamente el archivo de configuración de OpenSIPs: oscfg y después de este bloque: if(!uri==myself) { xlog("La solicitud no es local. Descartada"); sl_send_reply("404","Not Here"); exit; } se añade: if (is_method("INVITE")) { $var(invite_cod) = proxy_authorize("", "subscriber_v1"); if ( $var(invite_cod) == -1 || $var(invite_cod) == -2 ) { xlog("L_NOTICE","error de autent para $fU@$fd desde $si causa $var(invite_cod)");
sl_send_reply("403","Te he pillado"); exit; } if ( $var(invite_cod) < 0 ) { proxy_challenge("", "0"); exit; } xlog("L_NOTICE","INVITE del Usuario $fU Autenticado"); consume_credentials(); } La primera linea es redundante ya que las peticiones que llegan a este bloque deberían ser solamente INVITEs; se pone para volver el bloque más completo y comprensible. Las lineas importantes: •
233
en la segunda linea se asocia a la variable $var(invite_cod) el resultado de la función proxy_authorize. Los posibles valores numéricos negativos son: • -5 error genérico • -4 las credenciales no están presentes en la solicitud • -3 stale nonce, el nonce que aparece en la cabecera con las credenciales enviadas por la extensión no es más valido
• • • •
• -2 usuario valido pero contraseña incorrecta • -1 el usuario no existe Este tipo de validación se realiza hacia la tabla subcriber_v1 que es la vista de la tabla cc_sip_buddies de la base de datos A2Billing y que contiene los datos de las extensiones En la tercera linea se lee el valor contenido en la variable $var(autent_cod) y si este valor es igual a -1 o -2 se pasa a la linea que sigue En la cuarta linea se envía una linea al LOG de OpenSIPs que luego se utilizará con Fail2Ban para bloquer las IPs que están intentando realizar llamadas con credenciales falsas En la quinta linea se envía una respuesta SIP que comunica al atacante que lo hemos pillado :) Se sale del script
La solicitud llega al segundo bloque si la variable $var(autent_cod) contiene un valor negativo y es el INVITE inicial: if ( $var(invite_cod) < 0 ) { proxy_challenge("", "0"); exit; } En este bloque se utiliza la función proxy_challenge para enviar la cabecera proxy_authorize que contiene los datos necesarios para que la extensión pueda autenticar su INVITE inicial. Una vez que la extensión haya enviado un segundo INVITE con sus credenciales correctas se termina el bloque con: xlog("L_NOTICE","INVITE del Usuario $fUAutenticado"); consume_credentials(); } Se envía al LOG de OpenSIPs un mensaje que indica que el usuario ha autenticado correctamente su INVITE inicial y se utiliza la función consume_credentials para evitar que OpenSIPs, cuando genere el INVITE hacia el destino, siga manteniendo esa cabecera (seguridad). Se guardan los cambios y se averigua que el archivo de configuración esté exente de errores: opensips -c /etc/opensips/opensips.cfg Se reinicia OpenSIPs: service opensips restart Ahora que los INVITEs se autentican a nivel de OpenSIPs, ya no hace falta hacerlo a nivel de Asterisk. De hecho en la base de datos de A2Billing, existe una tabla que es una vista de la tabla cc_sip_buddies (cc_sip_buddies_empty). Esa tabla contiene los mismos datos de la tabla cc_sip_buddies, con la diferencia que el campo secret (que contiene la contraseña) está vacío:
234
mysql -u root -psesamo mysql> use a2billing mysql> select name,secret from cc_sip_buddies;
mysql> select name,secret from cc_sip_buddies_empty;
Para que Asterisk no solicite los datos de autenticación nuevamente, se modificará la configuración del Asterisk RealTime utilizando la vista de la tabla cc_sip_buddies. Se sale del cliente MySQL: mysql> quit Se abre el archivo que sigue: nano /etc/asterisk/extconfig.conf se modifica la siguiente linea: sippeers => odbc,a2b,cc_sip_buddies para que quede: sippeers => odbc,a2b,cc_sip_buddies_empty
235
Se guardan los cambios y se reinicia Asterisk: service asterisk restart A partir de este momento, como en la configuración de las extensiones ya no está presente la contraseña, Asterisk no debería solicitar más ningún tipo de autenticación. Ahora, como la PBX no solicitará la autenticación de INVITE recibidos, si un atacante lograra conocer el numero de una extensión configurada, podría sacar llamadas enviándolas directamente a Asterisk. Es por eso que se pone en seguridad la PBX modificando la configuración de IPtables e indicando que solamente aceptará solicitudes SIP que procedan de OpenSIPs o de las troncales de los proveedores. Se abre la configuración de IPTABLES: nano /etc/sysconfig/iptables se borra la siguiente linea: -A INPUT -p udp -m udp --dport 5090 -j ACCEPT Se guardan los cambios y se reinicia el servicio: service iptables restart iptables: Poniendo las cadenas de la política ACCEPT: filte[ OK ] iptables: Guardando las reglas del cortafuegos: [ OK ] iptables: Descargando módulos: [ OK ] iptables: Aplicando reglas del cortafuegos: [ OK ] Ya se puede realizar una primera prueba intentando registrar una extensión directamente en Asterisk. Debería salir un error de tipo TimeOut ya que la IP de la extensión no tiene acceso a Asterisk. Lo mismo debería pasar si se intenta sacar una llamada directamente con Asterisk. Se vuelve a configurar el Softphone con las credenciales de una extensión configurada en A2Billing apuntando al servidor OpenSIPs. Una vez que la extensión esté registrada, se llama un numero fijo o celular, se contesta la llamada y se cuelga. El diagrama de flujo de la llamada será: X-Lite INVITE ACK INVITE
OpenSIPs -------------------------------> -------------------------------> 190.67.240.78:17213 SIP/2.0 403 Te he pillado. Via: SIP/2.0/UDP 190.67.240.78:17213;received=190.67.240.78;branch=z9hG4bK-d8754zf2dc2f58bb69d532-1---d8754z-;rport=17213. To: ;tag=5c39c8172281004ff3f4fdccfdbb433a.83b1.
From: "09148";tag=560cbc79. Call-ID: ZTY0NjEzNDcxOTJmZmY5NjMzMzg0YWNiZDZlZjhhODQ. CSeq: 2 INVITE. Server: VozToVoice Proxy Server. Content-Length: 0.. Se vuelve a poner la contraseña correcta. Ahora OpenSIPs autentica todos los INVITEs entrantes por los cuales es responsable y descarta todos los demás. El paso a seguir es diferenciar las llamadas (INVITEs) entrantes para las extensiones de las llamadas para fijos y celulares. Para este tipo de configuración, hay que modificar los parámetros del modulo URI y luego crear un nuevo bloque en el 237
script de OpenSIPs. Para modificar el modulo URI se abre el archivo de configuración: oscfg Se cambia este bloque: #### URI module loadmodule "uri.so" modparam("uri", "use_uri_table", 0) para que quede: #### URI module loadmodule "uri.so" modparam("uri", "db_url", "mysql://opensips:opensipsrw@localhost/opensips") modparam("uri", "db_table", "subscriber_v1") modparam("uri", "use_uri_table", 0) Con las dos lineas añadidas se activarán una serie de funciones que se utilizarán en el nuevo bloque de configuración. Siguiendo con el script y después de este bloque: if (is_method("INVITE")) { $var(invite_cod) = proxy_authorize("", "subscriber_v1"); if ( $var(invite_cod) == -1 || $var(invite_cod) == -2 ) { xlog("L_NOTICE","error de autent para $fU@$fd desde $si causa $var(invite_cod)");
sl_send_reply("403","Te he pillado"); exit; } if ( $var(invite_cod) < 0 ) { proxy_challenge("", "0"); exit; } xlog("L_NOTICE","Usuario $fU Autenticado"); consume_credentials(); } Se añade: if (db_does_uri_exist()) { xlog("L_NOTICE","El usuario $tU existe código: $retcode"); if (lookup("location","m")) { xlog("L_NOTICE","El usuario $tU existe y está conectado código: $retcode");
} else { xlog("L_NOTICE","El usuario $tU existe pero no está conectado código: $retcode");
prefix("EU"); 238
rewritehostport("IPPrivada:5090"); } record_route(); setflag(ACC_DO); setflag(CDR_FLAG); setflag(ACC_MISSED); t_on_failure("timeout"); route(RELAY); } La diferentes lineas: • • •
• • • • • • • • • •
En la primera linea gracias a la nueva configuración del modulo URI, se averigua con la función db_does_uri_exist si la parte antes de la arroba @ de la Request URI corresponde a un usuario valido presente en la tabla subscriber_v1. Si así fuera en la segunda linea se envía al LOG de OpenSIPs "El usuario $tU existe código: $retcode". La variable $retcode debería contener el valor 1 En la tercera linea se utiliza la función lookup activada por el modulo REGISTRAR para extraer el valor del usuario contenido en la Request URI y luego buscar ese usuario en todas las entradas presentes en la tabla location de la base de datos de OpenSIPs. En la tabla location, como explicado anteriormente, se guardan todos los registros de las extensiones que en su momento se han registrado en OpenSIPs. Si la función no encuentra un usuario devuelve el valor -1. Si uno o más usuarios se encuentran, la Request URI se reescribe con esos datos y se salta al bloque que inicia con record_route(); sino se sigue con la sucesiva linea En esa linea se envía al LOG de OpenSIPs la frase "El usuario $tU existe pero no está conectado código: $retcode". La variable $retcode debería contener el valor numérico -1 En la linea que sigue se añade a la parte usuario de la Request URI el valor EU (extensión no disponible) Con la función rewritehostport se reescribe la parte después de la @ de la Request URI indicando la IP privada del servidor y el puerto (5090) que sería donde está a la escucha Asterisk También en este caso se continua con el ultimo bloque desde la linea record_route(); En esa linea se dice a OpenSIPs que añada una cabecera Record-Route de forma que se mantenga en el medio de todas las transacciones SIP. Statefull Proxy En la linea que sigue se activa una bandera para tener un registro de la llamada como declarado en la configuración del modulo ACC En la linea que sigue se activa una bandera para obtener algunos datos importantes para el reporte de las llamadas como indicado en la configuración del modulo ACC En la linea que sigue se activa una bandera para las llamada no completadas como indicado en la configuración del modulo ACC con la función t_on_failure("timeout") si la llamada no tiene éxito (el llamado no contesta dentro del tiempo definido, está en otra conversación o el llamado anula la llamada) se enviará la transacción a esa ruta. Por ultimo en la ruta(RELAY) se utiliza la función t_relay para procesar la transacción de manera Statefull
Para completar la configuración falta crear la ruta t_on_failure("timeout"). Se añade después de este 239
bloque: route[RELAY] { if (!t_relay()) { sl_reply_error(); }; exit; } el siguiente bloque: failure_route[timeout] { if (t_was_cancelled()) { xlog("L_NOTICE", "La transacción ha sido anulada"); exit; } if (t_check_status("408")) { prefix("EU"); } else if (t_check_status("486")) { prefix("EO"); } rewritehostport("IPPrivada:5090"); record_route(); t_relay(); exit; } • •
• •
En le primer bloque con la función t_was_canncelled se controla si el llamado ha terminado (CANCEL) la llamada antes de contestarla En el segundo bloque se ejecuta este tipo de control. Si la llamada falla porque se agota el tiempo predefinido para que el llamado conteste, se generará un respuesta de tipo 408 Request Timeout, si el llamado está en otra conversación se generará una respuesta de tipo 486 Busy Here. En el primer caso se añade el prefijo EU (extensión no disponible) a la Request URI; en el segundo caso se añade el prefijo EO (extensión ocupada) a la Request URI: en ambos casos se cambia la parte después de la arroba @ de la Request URI con IP privada del servidor y puerto 5090 que es donde está a la escucha Asterisk Con t_relay se procesa la transacción de manera Statefull Con exit; se termina el procesamiento del script.
Se guardan los cambios y se averigua que la configuración esté correcta: opensips -c /etc/opensips/opensips.cfg Si todo sale bien, se reinicia OpenSIPs: service opensips restart 240
Ahora en Asterisk hay que "capturar" las llamadas procedentes de OpenSIPs en el caso que las llamadas entre extensiones no tengan éxito. Esas llamadas se enviarán al buzón de voz que se va a configurar por cada extensión. Esta operación se realiza creando una vista de la tabla cc_card de la base de datos a2billing que contiene todos los datos necesarios para la configuración de los buzones de voz. Se accede al cliente MYSQL: mysql -u root -psesamo se activa la base de datos a2billing: mysql> use a2billing; se crea la vista: mysql> create view a2billing.cc_voicemail AS select id AS uniqueid, 'default' AS context, username AS mailbox, useralias AS password, lastname AS fullname, email AS email, '' AS pager, 'Yes' AS attach, 'wav' AS attachfmt, 'VozToVoice' AS serveremail, language AS language, 'co' AS tz from a2billing.cc_card; Query OK, 0 rows affected (0.00 sec) La contraseña del buzón de voz será igual al parámetro LOGIN que aparece en el menú CUSTOMERS -> Add :: Search de la pagina de administración de A2Billing. Se mira que datos se han creado en la tabla: mysql> select * from cc_voicemail; Para la zona horaria, necesaria para indicar a que hora se ha recibido el mensaje de voz, se ha configurado co para Colombia. Ese zona horaria luego hay que configurarla en el archivo de configuración de Asterisk voicemail.conf. Los cambios a realizar en ese archivo no son parte de este libro pero es bastante sencillo adaptarlo a sus propias exigencias. Ya se puede salir del cliente MySQL: mysql> quit Ahora se configuran los buzones de voz en Asterisk Realtime Como la conexión a la base de datos 241
A2Billing ya existe, el único archivo que hay que modificar es extconfig.conf. Se abre el archivo: nano /etc/asterisk/extconfig.conf se modifica esta linea: ;voicemail => odbc,asterisk para que quede: voicemail => odbc,a2b,cc_voicemail Se guardan los cambios y se reinicia asterisk: service asterisk restart se entra en la consola, se deshabilita la aplicación voicemail y se vuelve a cargar: aste CLI> module unload app_voicemail CLI> module load app_voicemail Si no aparecen errores significa que todo está bien. Se sale de la consola de Asterisk: CLI> quit Falta modificar el dialplan: nano /etc/asterisk/extensions.conf en el contexto a2billing se añaden los dos siguientes bloques: exten => _EUXXXXX,1,NoOp(Extensión no disponible) same => n,Voicemail(${EXTEN:2}@default,u) same => n,Hangup exten => _EOXXXXX,1,NoOp(Extensión ocupada) same => n,Voicemail(${EXTEN:2}@default,b) same => n,Hangup El primero se utiliza para enviar la llamada al buzón de voz de la extensión llamada si esta no se encuentra disponible o no ha contestado la llamada dentro del tiempo predefinido. El segundo se utiliza para enviar la llamada al buzón de voz de la extensión llamada si esta se encuentra ocupada. Por ultimo se añade un bloque para que los usuarios puedan acceder a su buzón de voz: 242
exten => 97,1,NoOp(Buzón de voz) same => n,VoicemailMain(${CALLERID(num)}@default) same => n,Hangup Se guardan los cambios y se recarga el dialplan: aste CLI> dialplan reload Ya se puede empezar a realizar las primeras pruebas. Se configura un segundo dispositivos con los datos de configuración de una de las extensiones configuradas en A2Billing. Se activa la captura de los paquetes: ngrep -W byline port 5060 > /tmp/llamadaEX Se realiza una llamada desde una extensión a otra. El resultado: X-Lite INVITE ACK INVITE
OpenSIPs -------------------------------> -------------------------------> select id,method,from_tag,to_tag,duration,setuptime,created,Llamante,Llamado from acc; 243
Se realiza una segunda llamada y cuando la extensión llamada esté timbrando, desde la misma extensión se rechaza la llamada que llegará al buzón de voz en Asterisk donde el llamante podrá dejar un mensaje. En la consola de Asterisk: Executing [EO09148@a2billing:1] NoOp("SIP/55011-00000009", "Extensión ocupada") in new stack Executing [EO09148@a2billing:2] VoiceMail("SIP/55011-00000009", "09148@default,b") in new stack > 0x7fa280013f30 -- Probation passed - setting RTP source address to 190.67.244.14:25354 -- Playing 'vm-theperson.alaw' (language 'es') -- Playing 'digits/0.alaw' (language 'es') -- Playing 'digits/9.alaw' (language 'es') -- Playing 'digits/1.alaw' (language 'es') -- Playing 'digits/4.alaw' (language 'es') -- Playing 'digits/8.alaw' (language 'es') -- Playing 'vm-isonphone.alaw' (language 'es') -- Playing 'vm-intro.alaw' (language 'es') -- Playing 'beep.alaw' (language 'es') -- Recording the message x=0, open writing: /var/spool/asterisk/voicemail/default/58777/tmp/lxKbrr format: wav49, 0x7fa26800ed78 x=1, open writing: /var/spool/asterisk/voicemail/default/58777/tmp/lxKbrr format: gsm, 0x7fa2680094c8 x=2, open writing: /var/spool/asterisk/voicemail/default/58777/tmp/lxKbrr format: wav, 0x7fa268009ae8 == Using SIP RTP CoS mark 5 == Spawn extension (a2billing, EO09148, 2) exited non-zero on 'SIP/55011-00000009'
Para que la extensión pueda escuchar el mensaje de voz dejado, hay que modificar nuevamente el archivo de configuración de OpenSIPs: oscfg antes de este bloque: if ( !load_balance("1","channel")) { send_reply("500","No Destination available"); exit; } se añade: if ($rU=="97") { rewritehostport("IPPrivada:5090"); route(RELAY); exit; } Se modifica IPPrivada con la IP Privada del servidor. Si un usuario marca 97 se cambiará la IP y el 244
puerto de la Request URI para que la llamada vaya al servidor Asterisk (IP Privada, puerto 5090). Se guardan los cambios y se averigua que la configuración sea correcta: opensips -c /etc/opensips/opensips.cfg Si no salen errores se reinicia OpenSIPs: service opensips restart Falta una cosa; en el softphone que ha recibido el mensaje de voz no aparece el típico icono indicando que hay un mensaje presente en el buzón de voz de la extensión configurada. Esto se debe al hecho que el NOTIFY que notifica la presencia del mensaje de voz, se genera a nivel de Asterisk solamente cuando la extensión se registra en la PBX; esto siempre y cuando la misma extensión se haya subscrito a Asterisk para recibir este tipo de notificaciones. Para poder solucionar este tipo de problema, hay que modificar la configuración de OpenSIPs y de las extensiones en A2Billing. Se abre el archivo: oscfg antes de este bloque: if (is_method("REGISTER")) { $var(autent_cod) = www_authorize("", "subscriber_v1"); if ( $var(autent_cod) == -1 || $var(autent_cod) == -2 ) { xlog("L_NOTICE","error de autent para $fU@$fd desde $si causa $var(autent_cod)"); sl_send_reply("403","Te he pillado"); exit; } se añade: if(is_method("SUBSCRIBE")) && (avp_check("$hdr(Event)", "eq/message-summary/i")) { rewritehostport("IPPrivada:5090"); if (!t_relay()) { t_reply("500", "Server internal error"); } exit; } que se lee: si se recibe una solicitud SIP de tipo SUBSCRIBE y la cabecera Event: contiene el valor message-summary, se cambia la parte después de la arroba de la Request URI y se procesa la transacción de manera Statefull. Modificar IPPrivada con la IP privada del servidor. Un paquete SIP SUBSCRIBE con la cabecera: Event: message-summary 245
es el que utiliza una extensión para subscribirse para recibir notificaciones cuando hay un mensaje de voz presente en su buzón. Se guardan los cambios y se controla que la configuración sea correcta: opensips -c /etc/opensips/opensips.cfg Si todo está bien se reinicia OpenSIPs: service opensips restart Ahora se modifica la configuración de la extensión que ha recibido el correo de voz en la pagina de administración de A2Billing, menú CUSTOMERS → VoIP Settings. Se selecciona el lápiz en la linea de la extensión y en el parámetro MAILBOX, se añade:
09148 es el numero de la extensión y default es el contexto configurado cuando se ha creado la vista cc_voicemail en la base de datos a2billing. Se presiona el Botón “CONFIRM DATA” y luego el enlace:
para recargar la configuración en Asterisk. Terminada la configuración se pasa a X-Lite, menú Softphone → Account Settings. En la pestaña Voicemail se pone:
Antes de presionar el botón OK, se inicia la captura de paquetes: 246
ngrep -W byline port 5060 > /tmp/VoiceMail Se presiona el botón OK y se termina la captura SIP. Entre los paquetes de REGISTER, aparecerá el SUBSCRIBE enviado por X-Lite: U 190.67.240.78:23390 -> 45.56.76.75:5060 SUBSCRIBE sip:
[email protected] SIP/2.0. Via: SIP/2.0/UDP 190.67.240.78:23390;branch=z9hG4bK-d8754z-cdca9634be9a5d6c-1---d8754z-;rport.
Max-Forwards: 70. Contact: . To: "09148". From: "09148";tag=563ce43c. Call-ID: OGUxNWM2MWMyMWVlYmI0MzU1NTdlN2M1Y2IxMjYwNjE. CSeq: 1 SUBSCRIBE. Expires: 300. Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO. Supported: eventlist. User-Agent: X-Lite 4.7.1 74247-ddd1fa7b-W6.1. Event: message-summary. Content-Length: 0. con relativa respuesta enviada por OpenSIPs que a su vez la recibió de Asterisk: U 45.56.76.75:5060 -> 190.67.240.78:23390 SIP/2.0 200 OK. Via: SIP/2.0/UDP 190.67.240.78:23390;received=190.67.240.78;branch=z9hG4bK-d8754z-cdca9634be9a5d6c-1--d8754z-;rport=23390.
From: "09148";tag=563ce43c. To: "09148";tag=as3ea167d2. Call-ID: OGUxNWM2MWMyMWVlYmI0MzU1NTdlN2M1Y2IxMjYwNjE. CSeq: 1 SUBSCRIBE. Server: VozToVoice 2.0. Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH, MESSAGE. Supported: replaces, timer. Expires: 300. Contact: ;expires=300. Content-Length: 0. Para tener la certeza que todo ha salido bien, se entra en la consola de Asterisk: aste y se escribe:
247
CLI> sip show subscriptions
Como se ha dicho anteriormente Asterisk envía los paquete NOTYFY solamente cuando la extensión se registra. Es por este motivo que los paquetes SIP REGISTER recibidos por OpenSIPs se reenviarán a Asterisk una vez que el usuario se haya autenticado correctamente. La función que permite este tipo de operación es t_replicate y es parte del modulo TM (TRANSACTION MODULE). Se vuelve a abrir el archivo de configuración de OpenSIPs: oscfg y se modifica este bloque: if (is_method("REGISTER")) { $var(autent_cod) = www_authorize("", "subscriber_v1"); if ( $var(autent_cod) == -1 || $var(autent_cod) == -2 ) { xlog("L_NOTICE","error de autent para $fU@$fd desde $si causa $var(autent_cod)"); sl_send_reply("403","Te he pillado"); exit; } if ( $var(autent_cod) < 0 ) { www_challenge("", "0"); exit; } save("location"); consume_credentials(); xlog("L_NOTICE","Usuario $fU Registrado"); exit; } para que quede: if (is_method("REGISTER")) { $var(autent_cod) = www_authorize("", "subscriber_v1"); if ( $var(autent_cod) == -1 || $var(autent_cod) == -2 ) { xlog("L_NOTICE","error de autent para $fU@$fd desde $si causa $var(autent_cod)"); sl_send_reply("403","Te he pillado"); exit; } if ( $var(autent_cod) < 0 ) { 248
www_challenge("", "0"); exit; } save("location"); consume_credentials(); xlog("L_NOTICE","Usuario $fU Registrado"); t_replicate("sip:IPPrivada:5090"); exit; } Se ha añadido la linea t_replicate("sip:IPPrivada:5090"). Esta linea no hace nada más que reenviar el REGISTER recibido y autenticado a Asterisk. Hay que cambiar IPPrivada con la IP privada del servidor. Se guardan los cambios y se averigua que la configuración de OpenSIPs esté bien: opensips -c /etc/opensips/opensips.cfg se reinicia OpenSIPs: service opensips restart Se abre nuevamente el X-Lite y cuando esté registrado aparecerá:
indicando que hay dos mensaje de voz en el buzón de la extensión configurada. Ahora si se da click en el icono, automáticamente se debería acceder al buzón de voz. Cuando el sistema lo solicite, el usuario deberá ingresar la contraseña presente en el columna LOGIN de la pagina CUSTOMERS → Add :: Search; sería el nombre de usuario que el cliente utiliza para acceder a su pagina personal. Una consideración final. Las llamadas que llegan a Asterisk para la parte del buzón de voz, no se están contando como recurso ocupado en la configuración del balanceamiento de carga. Esto podría ocasionar problemas ya que se podría verificar la situación que se están enviando llamadas a un recurso que resulta disponible cuando en la realidad no lo está. Es por eso que se modifica nuevamente el archivo de configuración de OpenSIPs: oscfg 249
después de cada linea: rewritehostport("IPPrivada:5090"); presente en el archivo, se añade la siguiente linea: lb_count_call("$rd","$rp","1","channel"); Esta función activada por el modulo LOAD BALANCER, permite contar recursos utilizados sin utilizar la función load_balance. El significado de los distintos parámetros: • • • •
$rd: el dominio o la IP contenida en la Request URI $rp. El puerto contenido en la Request URI 1: el grupo de recursos que se utilizará entre los configurados channel: el nombre del recurso:
Se guardan los cambios y se controla que el archivo de configuración esté correcto: opensips -c /etc/opensips/opensips.cfg Se reinicia OpenSIPs: service opensips restart Desde una extensión registrada se marca nuevamente 97. El resultado: opensipsctl fifo lb_list Destination:: sip:10.128.88.190:5090 id=1 group=1 enabled=yes auto-re=on Resources:: Resource:: channel max=50 load=1 En distintas ocasiones se ha hablado de tiempo predefinido de duración de un intento de llamada, pero ¿Donde se configura ese tiempo? Ese valor está presente en el bloque de configuración del modulo TM (en negrita): #### Transaction Module loadmodule "tm.so" modparam("tm", "fr_timeout", 5) modparam("tm", "fr_inv_timeout", 30) modparam("tm", "restart_fr_on_each_reply", 0) modparam("tm", "onreply_avp_mode", 1) El valor es en segundos. Se intentará llamar cualquier numero por 30 segundos, si dentro de ese tiempo 250
el llamado no contesta, OpenSIPs generará un CANCEL. Como el timeout de las llamadas en A2Billing es de 60 segundos, se modifica el valor para adaptarlo al valor de A2Billing. El bloque quedaría: #### Transaction Module loadmodule "tm.so" modparam("tm", "fr_timeout", 5) modparam("tm", "fr_inv_timeout", 60) modparam("tm", "restart_fr_on_each_reply", 0) modparam("tm", "onreply_avp_mode", 1) Se guardan los cambios y se reinicia OpenSIPs. service opensips restart Con la mayoría de los teléfonos SIP/Softphone, las llamadas entre extensiones funcionan sin problemas aunque los mismos teléfonos se encuentren detrás de una NAT. En algunos casos se presentan problemas de audio como es el ejemplo del Softphone Jitsi. A seguir se verá como solucionar ese tipo de problema y, en general, como añadir módulos y funcionalidades que permitan solucionar problemas de este tipo en OpenSIPs. Primero se descarga el Softphone desde la pagina de los desarrolladores, se instala y se inicia. Aparecerá:
Se ponen los datos de una extensión presente en A2Billing modificando dominio.org con el nombre de dominio asociado al servidor, y se presiona el botón “Sign In”. Después de un rato la extensión estará registrada. Se entra en el menú Tools → Options, se selecciona la cuenta que se acaba de crear y se presiona el botón “Edit” En la pestaña Security se deselecciona la casilla “Enable support to encrypt calls”; en la pestaña Encodings se selecciona la casilla “Override global encodings settings” y se seleccionan los siguientes codec Audio/Video:
251
Se presiona el botón “Next”. Aparecerá un resumen de las opciones de configuración. Se continua con el botón “Sign In” y se vuelve a la pagina principal del programa. Se realiza una primera llamada a un numero fijo/celular. La llamada funcionará perfectamente. Se realiza una segunda prueba llamando una extensión en X-Lite o 3CX. En Jitsi muy probablemente no se escuchará el audio entrante. Vamos a realizar una captura de la llamada: ngrep -W byline port 5060 > /tmp/llamadaJITSI Se vuelve a llamar la extensión configurada en X-Lite y después de contestar la llamada, se cuelga. Se abre el archivo de captura y se verá que Jitsi en su INVITE inicial, parámetro c= del protocolo SDP indica su IP privada en lugar de la IP publica. Ese parámetro se utiliza para comunicar al otro dispositivo (en este caso X-Lite) en que IP se quiere recibir el flujo media; como la IP es privada Jitsi no recibirá el flujo media correctamente (en negrita la parte importante): v=0. o=82264-jitsi.org 0 0 IN IP4 186.112.195.212. s=-. c=IN IP4 192.168.1.11. t=0 0. m=audio 22304 RTP/AVP 9 0 8. a=rtpmap:9 G722/8000. a=rtpmap:0 PCMU/8000. a=rtpmap:8 PCMA/8000. a=extmap:1 urn:ietf:params:rtp-hdrext:csrc-audio-level. a=extmap:2 urn:ietf:params:rtp-hdrext:ssrc-audio-level. a=rtcp-22305xr:voip-metrics. m=video 22306 RTP/AVP 96 99. a=recvonly. a=rtpmap:96 H264/90000. a=fmtp:96 profile-level-id=4DE01f;packetization-mode=1. 252
a=imageattr:96 send * recv [x=[0-1366],y=[0-768]]. a=rtpmap:99 H264/90000. a=fmtp:99 profile-level-id=4DE01f. a=imageattr:99 send * recv [x=[0-1366],y=[0-768]]. Para solucionar el problema hay que instalar el modulo NATHELPER y modificar el script de OpenSIPs. Este modulo tiene como dependencia el modulo USRLOC que ya está configurado pues se puede seguir con su configuración. Se abre el archivo de configuración de OpenSIPs: oscfg y después de este bloque: #### REGISTRAR module loadmodule "registrar.so" modparam("registrar", "max_contacts", 5) se añade: #### NATHELPER modules loadmodule "nathelper.so" modparam("nathelper", "natping_interval", 10) modparam("nathelper", "ping_nated_only", 0) modparam("nathelper", "received_avp", "$avp(received_nh)") • • • •
•
en la primera linea una descripción en la segunda linea se carga el modulo en la tercera linea se configura cada cuantos segundos OpenSIPs enviará un ping a los dispositivos que se encuentran detrás de una NAT. en la cuarta linea se configura que el ping se envíe a todos los dispositivos registrados. Si el valor es 1 se envía solamente a los dispositivos que se encuentran detrás de una NAT. OpenSIPs para saber si un dispositivo se encuentra o no detrás de una NAT, consultará la tabla LOCATION de OpenSIPs y mirará si está presente una bandera que indica que el dispositivo se encuentra detrás de un NAT. Esa bandera se activa con el modulo USRLOC en la ultima linea se indica la variable AVP que contendrá la IP, puerto y protocolo creada por la función fix_nated_register, que veremos más adelante; permite al modulo REGISTRAR de guardar esos valores en la columna received de la tabla location. Esto siempre y cuando la misma variable se configura en el modulo REGISTRAR. Para ese efecto, se retoma la configuración del modulo REGISTRAR:
#### REGISTRAR module loadmodule "registrar.so" modparam("registrar", "max_contacts", 5) y se modifica para que quede: 253
#### REGISTRAR module loadmodule "registrar.so" modparam("registrar", "max_contacts", 5) modparam("registrar", "received_avp", "$avp(received_nh)") Luego después de esta linea: route{ se añade: force_rport(); if (nat_uac_test("23")) { if (is_method("REGISTER")) { fix_nated_register(); setbflag(NAT); } else { fix_nated_contact(); setflag(NAT); } } Una explicación de las funciones presentes en el nuevo bloque: • force_rport. Añade el parámetro rport (RFC3581), si no está presente, en la primera cabecera Via presente en la solicitud SIP recibida. Esto antes de reenviarla, permitiendo a OpenSIPs conocer de forma exacta el puerto donde devolver las respuestas. • En la segunda linea se controla si el dispositivo se encuentra detrás de una NAT basándose en una serie de averiguaciones definidas en el numero presente entre paréntesis (“23”). Ese numero es la suma de las distintas operaciones que se van a realizar sobre la solicitud SIP recibida. En este caso es la suma de: ◦ 1 se averigua si la cabecera Contact: contiene una IP privada basándose en la RFC1918. ◦ 2 la dirección IP presente en la cabecera Via: se compara con la IP de donde procede la solicitud ◦ 4 se controla la primera cabecera Via presente en la solicitud SIP para averiguar si está presente una IP privada (RFC1918) ◦ 16 se controla si el puerto de donde procede la solicitud SIP es diferente al puerto presente en la cabecera Via Sumando todos los valores: 1 + 2 + 4 + 16 el resultado es 23 que es el valor presente en la función nat_uac_test. Si uno de los controles tiene éxito, se continua con la linea que sigue sino se salta completamente el bloque. • •
254
en la tercera linea se averigua si la solicitud es un REGISTER. Si así fuera se continua con la linea que sigue sino se pasa al bloque que inicia con } else { en la cuarta linea se utiliza la función fix_nated_register para guardar en la tabla location los datos de registro de la extensión basados en la IP publica real de la extensión misma. Estos
• • • •
datos se guardarán cuando termine el registro de la extensión. En la quinta linea se activa una bandera de tipo branch con nombre NAT. Esta bandera estará disponible a lo largo de toda la transacción SIP y puede ser utilizada en el script. La linea } else { significa: si el método SIP no es REGISTER En la séptima linea con la función fix_nated_contact se reescribe la cabecera Contact con los datos reales de IP, puerto y protocolo de donde procede la solicitud SIP en la ultima linea se crea una bandera de tipo transacción que también puede ser utilizada a lo largo del script.
Se guardan los datos y se controla que la configuración esté bien: opensips -c /etc/opensips/opensips.cfg [Mar 11 19:13:22 [9972] WARNING:core:warn: warning in config file //etc/opensips/opensips.cfg, line 13, column 13-16: tls support not compiled in Listening on udp: 45.56.76.75 [45.56.76.75]:5060 Aliases: *: li926-75.members.linode.com:5060 Mar 11 19:13:22 [9972] NOTICE:core:main: config file ok, exiting... Se reinicia OpenSIPs: service opensips restart Se vuelve a activar la captura de los paquetes: ngrep -W byline port 5060 > /tmp/llamadaJITSI2 y se realiza nuevamente una llamada desde Jitsi hacia otra extensión. Esta vez el audio funcionará sin problemas. Esto porque OpenSIPs antes de reenviar el INVITE a X-Lite realizará las correcciones del caso como se puede ver en el paquete SDP (en negrita las lineas importantes): v=0. o=82264-jitsi.org 0 0 IN IP4 186.112.195.212. s=-. c=IN IP4 186.112.195.212. t=0 0. m=audio 15454 RTP/AVP 9 0 8. a=rtpmap:9 G722/8000. a=rtpmap:0 PCMU/8000. a=rtpmap:8 PCMA/8000. a=extmap:1 urn:ietf:params:rtp-hdrext:csrc-audio-level. a=extmap:2 urn:ietf:params:rtp-hdrext:ssrc-audio-level. a=rtcp-15455xr:voip-metrics. m=video 15456 RTP/AVP 96 99. 255
a=recvonly. a=rtpmap:96 H264/90000. a=fmtp:96 profile-level-id=4DE01f;packetization-mode=1. a=imageattr:96 send * recv [x=[0-1366],y=[0-768]]. a=rtpmap:99 H264/90000. a=fmtp:99 profile-level-id=4DE01f. a=imageattr:99 send * recv [x=[0-1366],y=[0-768]]. a=nortpproxy:yes. a=direction:active. a=oldmediaip:192.168.1.11. Ahora se activa nuevamente la captura de paquetes: ngrep -W byline port 5060 > /tmp/llamadaJITSI3 y se realiza una llamada desde X-Lite hacia Jitsi. Tendremos nuevamente el mismo problema. Jitsi no recibirá el audio. Si miramos la captura encontraremos la parte importante (en negrita): U 186.112.195.212:22117 -> 107.170.186.192:5060 SIP/2.0 200 OK. CSeq: 2 INVITE. Call-ID: OWY3MDQxMGMzZjAxYzRiNTUyZGNjNTBiOTY3NmY1Yjg. From: "74478" ;tag=9bf0f73a. To: ;tag=2cc15714. Via: SIP/2.0/UDP 107.170.186.192:5060;branch=z9hG4bK11e2.d590cc86.0,SIP/2.0/UDP 186.112.195.212:22013;received=186.112.195.212;branch=z9hG4bK-d8754z-c8a15472ee3b056b-1$ Record-Route: . Contact: "82264" . User-Agent: Jitsi2.6.5390Windows 7. Content-Type: application/sdp. Content-Length: 181. . v=0. o=82264-jitsi.org 0 0 IN IP4 186.112.195.212. s=-. c=IN IP4 192.168.1.11. t=0 0. m=audio 16696 RTP/AVP 0 9 8. a=rtpmap:0 PCMU/8000. a=rtpmap:9 G722/8000. a=rtpmap:8 PCMA/8000. El parámetro c= del paquete SDP del 200OK enviado por parte de Jitsi contiene la IP privada en lugar de la IP publica. Para solucionar hay que configurar OpenSIPs para que antes de reenviar el 200OK de Jitsi a X-Lite, modifique esa linea. En este caso se utilizará una ruta de tipo on_reply. Se abre el archivo de configuración de OpenSIPs: 256
oscfg Se modifica este bloque: route[RELAY] { if (!t_relay()) { sl_reply_error(); }; exit; } para que quede: route[RELAY] { if (is_method("INVITE")) { t_on_reply("handle_nat"); } if (!t_relay()) { sl_reply_error(); }; exit; } De esta forma se le dice a OpenSIPs que antes de enviar cualquier respuesta a una solicitud SIP de tipo INVITE, vaya a la ruta de tipo on_reply con nombre handle_nat. Como esa “subrutina” no existe se crea después de este bloque : route[RELAY] { if (is_method("INVITE")) { t_on_reply("handle_nat"); } if (!t_relay()) { sl_reply_error(); }; exit; } y sería: onreply_route[handle_nat] { if(status=="200") && has_body("application/sdp") { if (nat_uac_test("8")) { xlog("Detect NAT on 200 OK $ru\n"); fix_nated_sdp("7"); 257
} } } Que se lee. Si el paquete recibido por OpenSIPs es un 200OK y contiene un paquete SDP, OpenSIPs realiza un control de NAT de tipo 8 y si encuentra una IP privada en ese paquete, realiza la corrección utilizando la función fix_nated_sdp. Se guardan los cambios y, como siempre, se averigua que la configuración esté correcta: opensips -c /etc/opensips/opensips.cfg Mar 11 19:17:59 [11482] WARNING:core:warn: warning in config file //etc/opensips/opensips.cfg, line 13, column 13-16: tls support not compiled in Listening on udp: 45.56.76.75 [45.56.76.75]:5060 Aliases: *: li926-75.members.linode.com:5060 Mar 11 19:17:59 [11482] NOTICE:core:main: config file ok, exiting... Se reinicia OpenSIPs: service opensips restart y se realiza nuevamente una llamada de X-Lite a Jitsi. El audio debería funcionar sin problemas. IMPORTANTE: En el caso en que no se puede registrar Jitsi a OpenSIPs, realizar todos los pasos indicado en este párrafo y configurar Jitsi nuevamente.
6.6 RTPProxy En el caso en que todas las configuraciones presentadas hasta el momento, para las llamadas entre extensiones, no den los frutos esperados es decir que se siguen experimentando problemas de audio, se instala un Proxy RTP; en este caso RTPProxy. Este programa se encarga de enviar/recibir el flujo audio de una extensión a otra, evitando que vaya directo cuando las extensiones que se están llamando se encuentran detrás de un NAT. Normalmente se utiliza también cuando hay llamadas entre extensiones registradas hacia la IPPrivada del servidor y extensiones registradas hacia la IPPublica. Un ejemplo de este escenario es cuando se instala el servidor localmente y hay extensiones que se registran desde la red local y extensiones que se registran desde remoto. En este caso, RTPProxy se utilizará solamente para las llamadas entre extensiones. Primero se instala desde los repositorios EPEL: yum --enablerepo=epel install rtpproxy
258
luego se configura creando el archivo de configuración como lo buscará el programa: nano /etc/sysconfig/rtpproxy donde se pone: OPTIONS="rtpproxy -F -l IPPublica -s udp:localhost:12221 -m 30000 -M 40000 -d DBUG:LOG_LOCAL1"
Antes de guardar los cambios se modifica IPPublica con la IP Publica del servidor. Para conocer el significado de las distintas opciones: man rtpproxy Las más importantes: -l direcciones IPs versión 4 donde se pondrá a la escucha el programa. Si se indican 2 separadas por un / RTPProxy trabajará en modo puente, es decir que enviará el flujo media de una IP a otra y viceversa. -s protocolo de transporte, dirección ip y puerto donde RTPProxy se pondrá a la escucha de comandos enviados desde otros programas (por ejemplo OpenSIPs) -m puerto UDP inicial del rango de puertos que RTPProxy utilizará para el flujo media -M puerto UDP final del rango de puertos que RTPProxy utilizará para el flujo media -d el nivel de DEBUG que se configurará en el programa y la salida para el LOG Se continua modificando la configuración de IPTABLES para abrir los puertos UDP de 30000 a 40000 (los utilizados por RTPProxy) nano /etc/sysconfig/iptables Después de esta linea: -A INPUT -p udp -m udp --dport 10000:20000 -j ACCEPT se pone: ##### RTPProxy -A INPUT -p udp -m udp --dport 30000:40000 -j ACCEPT Se guardan los cambios y se reinicia Iptables: service iptables restart Se modifica Rsyslog para guardar el LOG de RTPProxy en un archivo separado: 259
nano /etc/rsyslog.conf Antes de esta linea: local7.*
/var/log/boot.log
se pone: local1.*
-/var/log/rtpproxy.log
Se guardan los cambios y se crea el archivo indicado en la configuración de Rsyslog touch /var/log/rtpproxy.log Se reinicia el servicio: /etc/init.d/rsyslog restart Se inicia el Proxy RTP: service rtpproxy start En el archivo de LOG del programa debería aparecer: tail -f /var/log/rtpproxy.log Mar 28 11:40:37 li926-75 rtpproxy[25870]: INFO:main: rtpproxy started, pid 25870 que indica que el programa se ha iniciado correctamente. Se configura para que se inicie en automático: chkconfig rtpproxy on y se pasa a la configuración de OpenSIPs. Como se ha dicho anteriormente el Proxy RTP se utilizará solamente para las llamadas entre extensiones. Se abre el archivo de configuración de OpenSIPs: oscfg se añade la configuración del modulo. Después de este bloque: #### NATHELPER modules loadmodule "nathelper.so" modparam("nathelper", "natping_interval", 10) modparam("nathelper", "ping_nated_only", 0) modparam("nathelper", "received_avp", "$avp(received_nh)") 260
se pone: #### RTP Proxy loadmodule "rtpproxy.so" modparam("rtpproxy", "rtpproxy_sock", "udp:localhost:12221") En la primera linea una descripción, en la segunda se carga el modulo y en la tercera se conecta OpenSIPs a RTPProxy utilizando los datos presentes en el archivo de configuración y exactamente aquellos contenidos en la opción -s. Como el Proxy RTP se utilizará solamente para las llamadas entre extensiones, el flujo media de las llamadas a números telefónicos y buzón de voz pasará por Asterisk. Se modifica este bloque: if (db_does_uri_exist()) { xlog("L_NOTICE","El usuario $tU existe código: $retcode"); if (lookup("location","m")) { xlog("L_NOTICE","El usuario $tU existe y está conectado código: $retcode"); } else { xlog("L_NOTICE","El usuario $tU existe pero no está conectado código: $retcode");
prefix("EU"); rewritehostport("192.168.160.142:5090"); lb_count_call("$rd","$rp","1","channel"); } record_route(); setflag(ACC_DO); setflag(CDR_FLAG); setflag(ACC_MISSED); t_on_failure("timeout"); route(RELAY); } Para que quede: if (db_does_uri_exist()) { xlog("L_NOTICE","El usuario $tU existe código: $retcode"); if (lookup("location","m")) { xlog("L_NOTICE","El usuario $tU existe y está conectado código: $retcode"); } else { xlog("L_NOTICE","El usuario $tU existe pero no está conectado código: $retcode");
prefix("EU"); rewritehostport("192.168.160.142:5090"); lb_count_call("$rd","$rp","1","channel"); } record_route(); setflag(ACC_DO); setflag(CDR_FLAG); 261
setflag(ACC_MISSED); t_on_failure("timeout"); if (isbflagset(NAT)) setflag(NAT); route(RELAY2); } Se crea la ruta RELAY2. Después de este bloque: route[RELAY] { if (is_method("INVITE")) { t_on_reply("handle_nat"); } if (!t_relay()) { sl_reply_error(); }; exit; } Se añade: route[RELAY2] { if (is_method("INVITE")) { if (isflagset(NAT)) { rtpproxy_offer("ro"); } t_on_reply("handle_nat"); } if (isflagset(NAT)) { add_rr_param(";nat=yes"); } if (!t_relay()) { sl_reply_error(); }; exit; } En el primer bloque se averigua si la solicitud SIP es un INVITE; si así es, se averigua si la bandera de mensaje contiene el valor NAT; si así es se llama la función rtpproxy_offer activada por el modulo rtpproxy. Las dos opciones presentes tienen el siguiente significado: • • 262
r: se averigua que la dirección IP presente en el paquete SDP sea atendible. Si esta opción no estuviera presente se utilizaría la IP de procedencia de la solicitud SIP o: la IP de la linea o= presente en el paquete SDP será cambiada con la IP publica del servidor
que es también la IP de escucha de RTPProxy Luego se envía la solicitud SIP a la ruta de tipo on_reply con nombre handle_nat. En el segundo bloque si la bandera de mensaje contiene el valor NAT, se añade el parámetro ;nat=yes a la cabecera Record-Route generada por OpenSIPs indicando que procede de un dispositivo que se encuentra detrás de un NAT. Para terminar se procesa la solicitud SIP de manera Satefull. Como en este bloque se llama la ruta de tipo on_reply con nombre handle_nat y como esta ruta ya existe (se ha configurado anteriormente), se modifica: onreply_route[handle_nat] { if(status=="200") && has_body("application/sdp") { if (nat_uac_test("8")) { xlog("Detect NAT on 200 OK $ru\n"); fix_nated_sdp("7"); } } } Para que quede: onreply_route[handle_nat] { if (nat_uac_test("1")) fix_nated_contact(); if ( isflagset(NAT) && has_body("application/sdp")) rtpproxy_answer("ro"); } En esta ruta se averigua si en la cabecera Contact: está presente una IP privada; si así fuera se modifica utilizando la IP publica de donde procede la solicitud SIP. Luego si la bandera de tipo mensaje contiene el valor NAT y en la solicitud SIP está presente el anexo SDP, se utiliza nuevamente la función rtpproxy_answer para enviar el flujo media hacia el Proxy RTP. Para terminar, como la captura del “NAT” se ejecuta en la ruta RELAY2, se vuelve a modificar la ruta RELAY: route[RELAY] { if (is_method("INVITE")) { t_on_reply("handle_nat"); } if (!t_relay()) { sl_reply_error(); }; 263
exit; } para que quede: route[RELAY] { if (!t_relay()) { sl_reply_error(); }; exit; } Se guardan los cambios y se averigua que la configuración de OpenSIPs esté bien: opensips -c /etc/opensips/opensips.cfg Si todo está bien se reinicia OpenSIPs: service opensips restart En el LOG de OpenSIPs aparecerán las siguientes lineas: INFO:rtpproxy:rtpp_test: rtp proxy found, support for it enabled INFO:rtpproxy:rtpp_test: rtp proxy found, support for it enabled INFO:rtpproxy:rtpp_test: rtp proxy found, support for it enabled INFO:rtpproxy:rtpp_test: rtp proxy found, support for it enabled INFO:rtpproxy:rtpp_test: rtp proxy found, support for it enabled INFO:rtpproxy:rtpp_test: rtp proxy found, support for it enabled INFO:rtpproxy:rtpp_test: rtp proxy found, support for it enabled que indican que la conexión entre OpenSIPs y RTPProxy está funcionando correctamente. Ya se puede realizar una nueva prueba de llamadas entre extensiones. Se registran X-Lite y Jitsi a OpenSIPs y una vez que estén registrados, se realiza una llamada de X-Lite a la extensión configurada en Jitsi: El audio debería funcionar correctamente. En el LOG de RTPProxy: INFO:handle_command: new session M2VkMDcyNzRlMmFkZGQyZmQ4NjUzYjA4OWI2MmY1ZmE., tag 7515df51;1 requested, type strong linea que indica que se ha creado una nueva sesión en RTPProxy. Cuando la llamada termine: INFO:remove_session: session on ports 31052/31606 is cleaned up INFO:handle_delete: forcefully deleting session 2 on ports 30602/37932 31052 y 31606 son los dos puertos utilizados para el flujo media entre las dos extensiones y 264
efectivamente están dentro del rango definido en la configuración de RTPProxy (de 30000 a 40000). 6.7 OpenSIPs Presencia y Mensajes Instantáneos En esta parte se verá como implementar la presencia y los mensajes instantáneos (MI) entre extensiones. Hay que destacar que no todos los SoftPhone, teléfonos SIP soportan los dos protocolos involucrados. Para las pruebas se utilizará Jitsi que soporta correctamente presencia y MI, y X-Lite que soporta MI. La configuración de la presencia en OpenSIPs se basa en la RFC6665 que ha vuelto obsoleta la RFC3265. El sistema utiliza dos métodos SIP: • •
SUBSCRIBE para subscribirse al estado de una extensión/dispositivo SIP NOTIFY para notificar el cambio de estado de una extensión/dispositivo SIP
Para la configuración hay que tener en cuenta que los únicos dos métodos que crean un dialogo SIP son INVITE y SUBSCRIBE. Además de estos dos métodos, se utiliza el método PUBLISH (RFC3903) que los Softphone/dispositivos que lo soportan, utilizan para “publicar” su estado una vez que se registren al servidor Proxy. De los Softphone que hemos utilizado hasta el momento, solamente Jitsi soporta este estándar. De los Softphone de pago, Bria soporta este método. Se inicia este párrafo configurando la parte relacionada con la presencia para luego pasar a la configuración de los MI. 6.7.1 Presencia Los módulos involucrados para la implementación de la presencia en OpenSIPs son: • • •
Xcap Presence Presence XML
El primer modulo es requerido por el modulo Presence XML y sin su presencia todo el sistema no funcionaría. El modulo Presence es el más importante porque permite configurar todas una series de parámetros y activa las funciones que luego se utilizarán en el script de OpenSIPs: • •
handle_publish handle_subscribe
El modulo Presence XML permite la gestión de paquetes SIP de tipo NOTIFY y SUBSCRIBE utilizando anexos en formato XML. Complementa el modulo Presence. 265
Se abre el archivo de configuración de OpenSIPs: oscfg y después de este bloque: #### RTP Proxy loadmodule "rtpproxy.so" modparam("rtpproxy", "rtpproxy_sock", "udp:localhost:12221")) se añade: #### PRESENCE modules loadmodule "xcap.so" loadmodule "presence.so" loadmodule "presence_xml.so" modparam("xcap|presence", "db_url","mysql://opensips:opensipsrw@localhost/opensips") modparam("presence_xml", "force_active", 1) modparam("presence", "server_address", "sip:dominio.org:5060") • • • • •
•
•
En la primera linea una descripción del bloque En la segunda linea se carga el modulo Xcap en la tercera linea se carga el modulo presence en la cuarta linea se carga el modulo presence XML en la quinta linea como el sistema de presencia utilizará tres tablas de la base de datos OpenSIPs, para el modulo Xcap y Presence se indican los datos de conexión a la base de datos. Las tres tablas son: ◦ presentity: donde se guardarán los datos de las extensiones que han publicado su estado (Método PUBLISH) ◦ active_watchers: donde se guardarán los datos de las extensiones que están monitoreando el estado de otras ◦ watchers: donde se guardarán todas las suscripciones procesadas por OpenSIPs. En la sexta linea para el modulo Presence XML se configura el parámetro force_active en 1. Esto tiene que ser siempre así si no se utiliza un servidor Xcap. Un servidor Xcap permite gestionar todo el escenario de presencia de forma externa. Si se utilizara, OpenSIPs no tendría esta función. En la séptima linea se configura la SIP URI que estará presente en la cabecera Contact, en 200OK enviados por OpenSIPs para SUBSCRIBE y PUBLISH: también en NOTIFY generados por el Proxy SIP. Modificar dominio.org con el nombre de dominio de su servidor
Ahora se pasa a la configuración del script. Como el método SUBSCRIBE puede crear diálogos y como los diálogos se identifican por los tag presentes en la cabeceras to y from, y por la cabecera CallID, en el bloque que inicia con: if (has_totag()) {
266
después de estas linea: route(RELAY); } else { se añade: if (is_method("SUBSCRIBE") && $rd == "li926-75.members.linode.com:5060") { xlog("L_NOTICE", "Recibido un SUBSCRIBE dentro de un dialogo"); route(handle_presence); exit; } De esta forma se capturarán los SUBSCRIBE recibidos dentro de un dialogo y se enviarán a la subrutina handle_presence donde se procesarán. Modificar dominio.org con el nombre de dominio del servidor. Ahora hay que tomar una decisión; solicitar o no la autenticación para todos los mensajes SUBSCRIBE y PUBLISH Claramente por temas de seguridad es la mejor opción aunque no sea indispensable. Se modifica este bloque: if(is_method("SUBSCRIBE")) && (avp_check("$hdr(Event)", "eq/message-summary/i")) { xlog("L_NOTICE","cabecera Event: $hdr(Event)"); rewritehostport("IPPrivada:5090"); lb_count_call("$rd","$rp","1","channel"); if (!t_relay()) { t_reply("500", "Server internal error"); } exit; } Para que quede: if (is_method("SUBSCRIBE|PUBLISH")) { route(autent); if(is_method("SUBSCRIBE")) && (avp_check("$hdr(Event)", "eq/message-summary/i")) {
rewritehostport("IPPrivada:5090"); if (!t_relay()) { t_reply("500", "Server internal error"); } exit; } if (is_method("SUBSCRIBE|PUBLISH")) { route(handle_presence); exit; 267
} } Modificar IPPrivada con la IP Privada del servidor. Que se lee: si el método SIP es uno de los dos indicados se envía la solicitud a la subrutina autent donde se autentica utilizando el mismo procedimiento que se ha utilizado para los INVITE. Una vez realizada la autenticación, la subrutina autent devolverá la solicitud a este bloque donde: • •
si el método SIP es SUBSCRIBE y contiene en la cabecera Event: el valor message-summary, se envía a Asterisk para la gestión de las suscripciones relacionada con el buzón de voz si el método SIP es SUBSCRIBE o PUBLISH se enviará a la subrutina handle_presence que se ocupará de procesar la solicitud.
Para terminar faltan las dos subrutinas llamadas por los bloques que se acaban de configurar. Antes de este bloque: route[RELAY] { if (!t_relay()) { sl_reply_error(); }; exit; } se añade: route[autent] { if (!proxy_authorize("", "subscriber_v1")) { proxy_challenge("", "0"); exit; } xlog("L_NOTICE","$rm del Usuario $fU Autenticado"); consume_credentials(); return; } Que es el bloque que se utilizará para autenticar SUBSCRIBE, PUBLISH y MESSAGE. Después del bloque de arriba, se añade: route[handle_presence] { if (!t_newtran()) { sl_reply_error(); exit; } if(is_method("PUBLISH")) { handle_publish(); } 268
else if( is_method("SUBSCRIBE")) { handle_subscribe(); } exit; } Donde se procesarán SUBSCRIBE y PUBLISH. Las dos funciones activadas por el modulo Presence tienen la siguiente tarea: •
•
handle_publish: gestiona todos los paquetes SIP PUBLISH recibidos, crea y actualiza la información acerca del estado de un dispositivo en la base de datos OpenSIPs y genera mensajes SIP NOTIFY para notificar el cambio de estado del dispositivo a todos los dispositivos que se han subscrito para conocer el estado de esa extensión. handle_subscribe: tiene las mismas funcionalidades de la función anterior pero para todas las solicitudes SIP de tipo SUBSCRIBE.
Se guardan los cambios y se controla que el archivo de configuración esté correcto: opensips -c /etc/opensips/opensips.cfg Mar 12 08:57:26 [9349] WARNING:core:warn: warning in config file //etc/opensips/opensips.cfg, line 13, column 13-16: tls support not compiled in Listening on udp: 45.56.76.75 [45.56.76.75]:5060 Aliases: *: li926-75.members.linode.com:5060 Mar 12 08:57:26 [9349] NOTICE:core:main: config file ok, exiting... Se reinicia OpenSIPs: service opensips restart Para probar la nueva configuración, primero se abre Jitsi configurado con una extensión creada en A2Billing. Una vez realizado el registro, el Softphone enviará un PUBLISH “publicando” su estado en OpenSIPs. Esto se reflejará en la tabla presentity de OpenSIPs: mysql -u root -psesamo mysql> use opensips mysql> select * from presentity; que contendrá una entrada relacionada con el estado de Jitsi (en la columna body): opensip:
[email protected] Luego se abre el X-Lite. Se selecciona el siguiente icono:
luego se selecciona el icono de la imagen que sigue:
En la pagina que aparece:
Se pone en Softphone el numero de la extensión configurada en Jitsi y luego se presiona el botón “Add”. Para terminar se presiona el botón “Ok” que aparece en la parte baja a la derecha de la ventana. El resultado será:
Como Jitsi publica correctamente su estado, aparecerá en linea. En la tabla active_watchers: mysql> select * from active_watchers; aparecerá la entrada de la subscripción de X-Lite hacia Jitsi. 270
Si en Jitsi se selecciona el estado "Do not disturb".
En X-Lite:
Se vuelve a poner Jitsi en linea. 6.7.2 Mensajes Instantáneos (MI) Para configurar el envío y recepción de los mensajes instantáneos se utiliza, como se ha dicho, el método SIP MESSAGE que hay que configurar en OpenSIPs. Se abre el archivo de configuración: oscfg y después del bloque: if (is_method("SUBSCRIBE|PUBLISH")) { route(autent); if(is_method("SUBSCRIBE")) && (avp_check("$hdr(Event)", "eq/message-summary/i")) {
rewritehostport("IPPrivada:5090"); if (!t_relay()) { t_reply("500", "Server internal error"); } exit; } if (is_method("SUBSCRIBE|PUBLISH")) { route(handle_presence); exit; } } 271
Se añade: if (is_method("MESSAGE") && db_does_uri_exist()) { #if (db_does_uri_exist()) { xlog("L_NOTICE","El usuario $tU existe código: $retcode"); if (lookup("location","m")) { xlog("L_NOTICE","El usuario $tU existe y está conectado código: $retcode");
} else { xlog("L_NOTICE","El usuario $tU existe pero no está conectado código: $retcode");
sl_send_reply("402","No en linea"); exit; } route(RELAY); } que es parecido al bloque utilizado para las llamadas entre extensiones pero como algunos datos cambian es mejor tener uno separado. Para enviar un MESSAGE hay que conocer si la extensión existe y si está conectada. Si así es, el MESSAGE se procesa sino se contesta con un 402 “Usuario no en linea” y el mensaje instantáneo se descarta. En el caso en que el usuario no exista, se sale del bloque y se descarta la solicitud. Se guardan los cambios y se reinicia OpenSIPs: service opensips restart Ahora si se posiciona el ratón encima de la linea del contacto presente en X-Lite, aparecerán dos iconos; se selecciona el globo para enviar un mensaje instantáneo a la extensión configurada en Jitsi:
272
En Jitsi:
Si desde Jitsi se contesta:
En X-Lite:
Si se cierra el X-Lite y se envía un nuevo mensaje desde Jitsi:
Que es el error que se ha configurado en el archivo de configuración de OpenSIPs para comunicar que el usuario no se encuentra conectado: if (is_method("MESSAGE") && db_does_uri_exist()) { #if (db_does_uri_exist()) { xlog("L_NOTICE","El usuario $tU existe código: $retcode"); if (lookup("location","m")) { xlog("L_NOTICE","El usuario $tU existe y está conectado código: $retcode");
} else { xlog("L_NOTICE","El usuario $tU existe pero no está conectado código: $retcode");
sl_send_reply("402","No en linea"); 273
exit; } route(RELAY); } En estos casos hay la posibilidad de guardar el mensaje en una tabla de la base de datos de opensips y entregarlo cuando la extensión vuelva a registrarse. Para este tipo de escenario, se utiliza el modulo MSILO. MSILO depende de un modulo Database (en este caso MySQL que ya está configurado) y el modulo TM que también está configurado. Se abre la configuración de OpenSIPs: oscfg y después de este bloque: #### PRESENCE modules loadmodule "xcap.so" loadmodule "presence.so" loadmodule "presence_xml.so" modparam("xcap|presence", "db_url","mysql://opensips:opensipsrw@localhost/opensips") modparam("presence_xml", "force_active", 1) modparam("presence", "server_address", "sip:dominio.org:5060") se añade: #### MSILO module loadmodule "msilo.so" modparam("msilo", "db_url","mysql://opensips:opensipsrw@localhost/opensips") modparam("msilo", "content_type_hdr", "Content-Type: text/plain\r\n") modparam("msilo", "from_address", "sip:
[email protected]") modparam("msilo", "offline_message", "*** El usuario $rU no se encuentra en linea ***") • • • • • •
274
la primera linea es un comentario en la segunda linea se carga el modulo en la tercera linea se configura la conexión a la base de datos opensips ya que los mensajes no enviados se guardarán en la tabla silo en la cuarta linea se indica que el mensaje instantáneo que se enviará a la extensión que está enviando el MI sin éxito, notificando que el usuario no se encuentra en linea, será en texto plano en la quinta linea se configura una dirección SIP que notificará al usuario que está intentando enviar el MI, que el destinatario no se encuentra en linea. Modificar dominio.org con el nombre de dominio del servidor en la sexta linea el mensaje que recibirá el usuario que está intentando enviar el mensaje a un usuario que no se encuentra en linea. La pseudo variable $rU contendrá el valor de la extensión
de destino sin la parte después de la arroba. Con este modulo se activan dos funciones: • •
m_store: se utiliza para guardar el MI en la tabla silo cuando el usuario destinatario del mensaje no se encuentra en linea m_dump: para entregar el mensaje guardado en la tabla silo al usuario que no se encontraba en linea y ha vuelto a registrarse.
La primera función se añade al siguiente bloque: if (is_method("MESSAGE") && db_does_uri_exist()) { #if (db_does_uri_exist()) { xlog("L_NOTICE","El usuario $tU existe código: $retcode"); if (lookup("location","m")) { xlog("L_NOTICE","El usuario $tU existe y está conectado código: $retcode"); } else { xlog("L_NOTICE","El usuario $tU existe pero no está conectado código: $retcode");
sl_send_reply("402","No en linea"); exit; } route(RELAY); } para que quede: if (is_method("MESSAGE") && db_does_uri_exist()) { #if (db_does_uri_exist()) { xlog("L_NOTICE","El usuario $tU existe código: $retcode"); if (lookup("location","m")) { xlog("L_NOTICE","El usuario $tU existe y está conectado código: $retcode"); } else { xlog("L_NOTICE","El usuario $tU existe pero no está conectado código: $retcode");
sl_send_reply("402","No en linea"); if (m_store("$ru")) { xlog("L_NOTICE","BM Mensaje fuera de linea almacenato"); if (!t_reply("202", "Accepted")) { sl_reply_error(); } } else { xlog("L_NOTICE","BM Mensaje fuera de linea no almacenato"); if (!t_reply("503", "Service Unavailable")) { sl_reply_error(); } } exit; } 275
t_on_failure("msilo"); route(RELAY); } Como se puede notar al final del bloque se añade la ruta t_on_failure("msilo") que se utiliza en el caso en que el usuario se registre desde un dispositivo que no soporta el método SIP MESSAGE. La segunda función se añade al siguiente bloque: if (is_method("REGISTER")) { $var(autent_cod) = www_authorize("", "subscriber_v1"); if ( $var(autent_cod) == -1 || $var(autent_cod) == -2 ) { xlog("L_NOTICE","error de autent para $fU@$fd desde $si causa $var(autent_cod)"); sl_send_reply("403","Te he pillado"); exit; } if ( $var(autent_cod) < 0 ) { www_challenge("", "0"); exit; } save("location"); consume_credentials(); xlog("L_NOTICE","Usuario $fU Registrado"); t_replicate("sip:IPPrivada:5090"); exit; } para que quede: if (is_method("REGISTER")) { $var(autent_cod) = www_authorize("", "subscriber_v1"); if ( $var(autent_cod) == -1 || $var(autent_cod) == -2 ) { xlog("L_NOTICE","error de autent para $fU@$fd desde $si causa $var(autent_cod)"); sl_send_reply("403","Te he pillado"); exit; } if ( $var(autent_cod) < 0 ) { www_challenge("", "0"); exit; } save("location"); consume_credentials(); m_dump(); xlog("L_NOTICE","Usuario $fU Registrado"); 276
t_replicate("sip:IPPrivada:5090"); exit; } Modificar IPPrivada con la IP privada del servidor. Por ultimo se añade la ruta de failure. Después de este bloque: failure_route[GW_FAILOVER] { if (t_was_cancelled()) { exit; } # failure detection with redirect to next available trunk if (t_check_status("(408)|([56][0-9][0-9])")) { xlog("Failed trunk $rd/$du detected \n"); if ( load_balance("1","channel") ) { t_on_failure("GW_FAILOVER"); t_relay(); exit; } xlog("L_ERROR", "Recurso $du no disponible"); send_reply("500","All GW are down"); } } Se añade: failure_route[msilo] { if (m_store()) { xlog("L_NOTICE","Mensaje fuera de linea almacenato"); t_reply("202", "Accepted"); } else { xlog("L_NOTICE","Mensaje fuera de linea no almacenato"); t_reply("503", "Service Unavailable"); } } Que sería: si el mensaje instantáneo no se ha podido entregar porque el dispositivo no soporta el método SIP MESSAGE pero ha sido marcado por el sistema como entregado, se vuelve a guardar en la tabla silo de la base de datos opensips. Se guardan los cambios y se averigua que la configuración esté correcta: opensips -c /etc/opensips/opensips.cfg Mar 12 11:31:24 [25842] WARNING:core:warn: warning in config file //etc/opensips/opensips.cfg, 277
line 13, column 13-16: tls support not compiled in Listening on udp: 45.56.76.75 [45.56.76.75]:5060 Aliases: *: li926-75.members.linode.com:5060 Mar 12 11:31:24 [25842] NOTICE:core:main: config file ok, exiting... Se cierran todos los softphone abiertos y se reinicia OpenSIPs: service opensips restart Se abre nuevamente X-Lite y desde este ultimo se envía un MI a la extensión configurada en Jitsi que claramente no aparece en linea. Se verá:
y llegará el MI desde OpenSIPs como configurado en el modulo de MSILO:
Se abre Jitsi y después de unos cuantos segundos que esté conectado:
278
6.8 OpenSIPs Autenticación sobre IP Hay clientes que se autentican con usuario y contraseña y hay clientes que prefieren la autenticación sobre IP. Esto porque se mejora el nivel de seguridad y al mismo tiempo se evitan contestaciones de los reportes de las llamadas ya que se pueden generar solamente desde la IP del cliente mismo. En esta parte se verá como autenticar un cliente sobre IP y como configurar A2Billing y OpenSIPs para este tipo de escenario. Esta solución se puede implementar de dos formas distintas: 1. Modificando la configuración de la extensión directamente desde la pagina de administración de A2Billing y creando una nueva vista en la base de datos opensips que lea esos datos y los guarde en una nueva tabla. 2. Eliminado la configuración de la extensión desde la pagina de administración de A2Billing y añadiendo la IP y el ACCOUNTCODE del cliente en una tabla de OpenSIPs. Esta segunda opción tiene la ventaja que si un cliente quiere autenticar más de una IP o se quieren añadir las IPs de donde llegarán las llamadas a los números geográficos, se puede realizar sin problemas. Además el limite de una vista en general es que no se pueden añadir nuevas entradas con el comando INSERT de MySQL. Si no se tiene planeado vender números geográfico, esta primera opción el viable ya que, como se verá más adelante, se podrán crear distintas extensiones con distintas IP para el mismo cliente. IMPORTANTE: si se configura el procedimiento que se describe a seguir no va configurado el que se explicará más adelante. En este libro se utilizará la segunda forma En el caso de la primera forma se entra en la pagina de administración de A2Billing. En el menú CUSTOMERS → VoIP Settings, se modifica una de las extensiones presentes:
En SECRET se quita la contraseña:
En HOST se pone la IP asignada por el proveedor de Internet; esto para realizar la prueba (la IP a autenticar para el cliente):
En TYPE se pone peer:
279
En USERNAME se quita el valor presente. Se guardan los cambios presionando el botón CONFIRM DATA. La nueva configuración debería reflejarse en seguida en la tabla subscriber_v1 de opensips. mysql -u root -psesamo mysql> use opensips mysql> select * from subscriber_v1;
Aparecerá la linea de la extensión que se acaba de modificar sin la contraseña. Como los valores de las columnas ha1 y ha1b se calculan sobre el valor del parámetro USERNAME de la configuración de la extensión y se utilizan para la autenticación de la extensión en OpenSIPs, si se intenta sacar una llamada con un softphone configurado con esa extensión, fallará. De esta forma ha la certeza que esa extensión pueda sacar las llamadas solamente autenticándose en OpenSIPs con la IP. En OpenSIPs para autenticar los INVITEs que llegan desde unas determinadas IPs, existe el modulo PERMISSIONS. La configuración de las IP se puede realizar en una archivo de texto o, como en este caso, en la tabla address de la base de datos opensips. Los datos de la tabla: mysql> desc address;
• 280
id: numero progresivo creado automáticamente por MySQL
• • •
• • • •
grp: las IPs se pueden asignar a grupos ip: la IP a la que se permite el acceso. Se puede indicar la IP completa o un rango de IP configurando este parámetro en asociación con el que sigue mask: en el caso que la IP se indique de forma completa, este parámetro tendrá que ser 32 sino se indica el rango de IP que se quiere incluir. Ejemplo: 190.67.244.0/24. El parámetro 190.67.244.0 se configurará en ip y mask será 24. Esto quiere decir que serán admitidas todas las IP que van de 190.67.244.0 a 190.67.244.255 port: además de la IP se puede indicar también el puerto. Si se pone 0, podrá ser cualquiera. proto: se indica el protocolo que tendrá que utilizar la IP para ser autenticada. Si se pone any, podrá ser cualquier protocolo (UDP, TCP, TLS) pattern: en este campo se indica la expresión regular que luego se podrá utilizar con las funciones check_address o check_source_address activadas por este modulo context_info: es una entrada donde se asigna un valor que luego se podrá utilizar como pseudo variable en las funciones check_address o check_source_address activadas por este modulo. En este caso se ingresará el ACCOUNTCODE de la extensión para el tema de la facturación de las llamadas
De esa tabla se crea un VIEW (vista) tomando los datos más importantes de la tabla cc_sip_buddies de la base de datos de A2Billing. Primero se seca una copia de la estructura de la tabla: mysql> quit cd /tmp mysqldump -u root -psesamo opensips address > address.sql Se accede nuevamente a MySQL: mysql -u root -psesamo se borra la tabla: mysql> drop table address; luego se crea el VIEW (la vista) mysql> CREATE VIEW opensips.address AS SELECT id AS id, cast(0 as DECIMAL) AS grp, host AS ip, cast(32 as DECIMAL) AS mask, cast(port as DECIMAL) AS port, 'UDP' AS proto, '' AS pattern, accountcode AS context_info from a2billing.cc_sip_buddies WHERE host != 'dynamic'; Query OK, 0 rows affected (0.01 sec)
281
de esta forma se creará la vista que contendrá solamente las extensiones configuradas con una IP estática. De hecho: mysql> select * from address;
Se sale del cliente MySQL: mysql> quit Más adelante se explicará como sacar las llamadas autenticando el cliente sobre IP. IMPORTANTE: a partir de este punto se aplica la segunda forma que es la configuración escogida en este libro para la configuración de la autenticación de los clientes sobre IP. En este caso se entra en la pagina de administración de A2Billing, menú CUSTOMERS → VoIP Settings y se escoge la extensión que se quiere configurar para que se autentifique sobre IP. De esa extensión se anota el valor del parámetro ACCOUNTCODE. Para realizar la prueba, se mira la IP publica asignada al momento por parte del proveedor Internet. Esa IP se añadirá junto al ACCOUNTCODE que se anotó para crear una nueva entrada en la tabla address de la base de datos opensips. Si por error o por realizar pruebas, se ha borrado la tabla address y creado la vista, para volver a la tabla normal: mysql -u root -psesamo mysql> use opensips mysql> drop view address; Se sale del cliente y se carga nuevamente la tabla: mysql> quit mysql -u root -psesamo opensips < /tmp/address.sql Se vuelve a entrar en el cliente MySQL: mysql -u root -psesamo
282
mysql> use opensips Se añade una nueva entrada en la tabla address: mysql> insert into address (ip,context_info) values ('IPPublicaCL','38967'); Se cambia IPPublicaCL con la IP publica que asignada al momento por el proveedor de Internet y 38967 con el ACCOUNTCODE de la cuenta de A2Billing que se va a autenticar sobre IP. Se mira el resultado: mysql> select * from address;
No hace falta indicar más datos porque para los demás se tomarán los predefinidos en la tabla. Una vez añadida la entrada en la tabla, se borra la configuración de la extensión en CUSTOMERS → VoIP Settings de la pagina de administración de A2Billing. Ahora hay que modificar el archivo de configuración de OpenSIPs para añadir el nuevo modulo y modificar el script de procesamiento de las peticiones SIP. Se sale del cliente MySQL: mysql> quit Primero se crea una copia del archivo hasta ahora utilizado: cp /etc/opensips/opensips.cfg /etc/opensips/opensips.cfg.4 El nuevo modulo no depende de otros módulos pues se puede configurar en cualquier punto del bloque de los módulos. Se abre el archivo de configuración de OpenSIPs: oscfg y después de este bloque: #### REGISTRAR module loadmodule "registrar.so" modparam("registrar", "max_contacts", 5) modparam("registrar", "received_avp", "$avp(received_nh)") se añade:
283
#### PERMISSIONS module loadmodule "permissions.so" modparam("permissions", "db_url","mysql://opensips:opensipsrw@localhost/opensips") Se modifica este bloque: if (is_method("INVITE")) { $var(invite_cod) = proxy_authorize("", "subscriber_v1"); if ( $var(invite_cod) == -1 || $var(invite_cod) == -2 ) { xlog("L_NOTICE","error de autent para $fU@$fd desde $si causa $var(invite_cod)");
sl_send_reply("403","Te he pillado"); exit; } if ( $var(invite_cod) < 0 ) { proxy_challenge("", "0"); exit; } xlog("L_NOTICE","INVITE del Usuario $fU Autenticado"); consume_credentials(); } para que quede: if (is_method("INVITE")) { if (check_source_address("0","$avp(accountcode)")) { xlog("L_NOTICE","La IP $si es una dirección autorizada"); append_hf("P-Accountcode: $avp(accountcode)\r\n"); } else { $var(invite_cod) = proxy_authorize("", "subscriber_v1"); if ( $var(invite_cod) == -1 || $var(invite_cod) == -2 ) { xlog("L_NOTICE","error de autent para $fU@$fd desde $si causa $var(invite_cod)") ;
sl_send_reply("403","Te he pillado"); exit; } if ( $var(invite_cod) < 0 ) { proxy_challenge("", "0"); exit; } xlog("L_NOTICE","INVITE del Usuario $fU Autenticado"); consume_credentials(); } } Las tres lineas que se añadieron: •
284
en la segunda linea se utiliza la función check_source_address activada por el modulo PERMISSION que permite realizar una búsqueda de la IP de donde ha llegado la petición SIP INVITE. Si la IP existe en la tabla address de la base de datos opensips, se continua con la
• •
tercera linea. Los dos valores indicados en la función son respectivamente el grupo al que pertenece la IP en la tabla address y la variable donde se guardará el valor contenido en el campo context info de la entrada en la tabla de la IP que está enviando la petición SIP en la tercera linea se envía al LOG de OpenSIPs una entrada donde se comenta que la IP es una dirección autorizada. La variable $si contiene la IP de origen en la cuarta linea se añade al INVITE autenticado sobre IP una cabecera P-Accountcode que contiene el ACCOUNTCODE de la extensión que se está autenticando sobre IP (columna context_info de la tabla address)
Se guardan los datos y se controla que el archivo de configuración esté correcto: opensips -c /etc/opensips/opensips.cfg se reinicia OpenSIPs: service opensips restart Ahora en X-Lite se configura la extensión que se autentica sobre IP de la siguiente forma:
Modificar dominio.org con el nombre de dominio del servidor. Se cierran todos los demás Softphone abiertos y se intenta sacar una llamada desde el X-Lite. Se recibirá un error porque Asterisk no acepta la llamada. En la consola: chan_sip.c:25666 handle_request_invite: Failed to authenticate device "38967";tag=a3732d67 Esto porque Asterisk recibe la llamada directamente desde la IP de OpenSIPs y no puede autenticarla. Con las extensiones configuradas con usuario y contraseña, esto no pasaba porque Asterisk autenticaba las llamadas basándose en esos datos y no en la IP de donde llegaban las llamadas. Es por eso que hay que realizar algunos cambios. Se abre la configuración del archivo sip.conf: 285
nano /etc/asterisk/sip.conf antes de esta linea: #include additional_a2billing_sip.conf se añade la troncal hacia OpenSIPs: [opensip] type=peer context=opensip host=IPPublica disallow=all allow=alaw allow=alaw allow=g729 language=es dtmfmode = rfc2833 nat=no qualify=yes en el parámetro host, se cambia IPPublica con la IP publica del servidor. Se guardan los datos y se recarga la configuración sip: aste CLI> sip reload CLI> sip show peers aparecerá la nueva troncal activa. Ahora en el dialplan hay que configurar el nuevo contexto opensip (como configurado en la troncal) donde se interceptarán todas las llamadas procedentes de OpenSIPs de las extensiones que se están autenticando sobre IP: nano /etc/asterisk/extensions.conf al final del archivo se añade el siguiente bloque: [opensip] exten => _X.,1,NoOp(Llamadas autenticadas sobre IP) same => n,Set(CDR(accountcode)=${SIP_HEADER(P-Accountcode)}) same => n,Goto(a2billing2,${EXTEN},1) same => n,hangup
286
En la segunda linea se asocia a la variable CDR(accountcode) el contenido de la cabecera PAccountcode contenida en el INVITE. Como se ha explicado esa cabecera contiene el ACCOUNTCODE de la extensión que el dato imprescindible para la facturación de la llamada. y después del contexto [a2billing]: [a2billing2] exten => _X.,1,NoOp(A2Billing Start) same => n,Agi(a2billing.php,1) same => n,Hangup exten => h,1,Hangup De esta forma la extensión que se autentica sobre IP no tendrá acceso al buzón de voz (lógico) y, en general, a todo el bloque de dialplan configurado en el contexto [a2billing]. Se guardan los cambios y se recarga el dialplan: aste CLI> dialplan reload Se realiza una nueva llamada desde la misma extensión que esta vez tendrá éxito. En la consola de Asterisk: Executing [5753850962@opensip:1] NoOp("SIP/opensip-0000000e", "Llamadas autenticadas sobre IP") in new stack -- Executing [5753850962@opensip:2] Set("SIP/opensip-0000000e", "CDR(accountcode)=03568") in new stack -- Executing [5753850962@opensip:3] Goto("SIP/opensip-0000000e", "a2billing2,5753850962,1") in new stack -- Goto (a2billing2,5753850962,1) -- Executing [5753850962@a2billing2:1] NoOp("SIP/opensip-0000000e", "A2Billing Start") in new stack -- Executing [5753850962@a2billing2:2] AGI("SIP/opensip-0000000e", "a2billing.php,1") in new stack
y en el invite recibido desde OpenSIPs: INVITE sip:
[email protected] SIP/2.0 Record-Route: Via: SIP/2.0/UDP 45.56.76.75:5060;branch=z9hG4bKb556.67ca915.0 Via: SIP/2.0/UDP 192.168.1.106:63298;received=82.49.11.235;branch=z9hG4bK-d8754z33a08765c51ac846-1---d8754z-;rport=63298 Max-Forwards: 69 Contact: To: From: "38967";tag=1400644f Call-ID: N2Q0Y2E5NDVmNTVmYzVhNWU1YWFjN2U2OTM2NzMwZTk CSeq: 1 INVITE Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO Content-Type: application/sdp Supported: replaces User-Agent: X-Lite 4.7.1 74247-ddd1fa7b-W6.1 Content-Length: 303 287
P-Accountcode: 38967 En negrita la cabecera añadida por OpenSIPs que contiene el ACCOUNTCODE de la extensión. Para tener la certeza de que todo esté funcionando correctamente, se pueden realizar pruebas de llamadas de extensiones que todavía se autentican con usuario y contraseña, llamadas entre extensiones, llamadas al buzón de voz. 6.9 Números Geográficos A2Billing puede ser utilizado también para la ventas de números geográficos. La única desventaja es que para volver disponibles los números a los clientes, en la mayoría de los casos hay que comprarlos anticipadamente. La plataforma integra las API de didx.net, es decir que si se tiene una cuenta con ese proveedor de DID, es posible adquirirlos directamente desde la pagina de administración de A2Billing. En el párrafo que sigue se ilustrará como integrar OpenSIPs y A2Billing para la gestión de los números geográficos. 6.9.1 Integración DIDs entre A2Billing y OpenSIPs El primer paso es configurar dos números geográficos (inventados) de prueba. Unos se desviará a un numero fijo/celular y otro a la extensión del cliente que lo adquirió. Se accede a la pagina de administración de A2Billing y se entra en el menú INBOUND DID → Groups → ADD DID GROUP:
Se crea un grupo para los DID. Se presiona el botón CONFIRM DATA. Se continua con el menú INBOUND DID → Add :: Search donde se va a crear el primer numero DID utilizando el enlace Add DID:
288
• • • • • • • •
DID: el numero geográfico BILLING: se cobrará un fijo mensual para el alquiler y las llamadas salientes si el desvío es hacia un numero fijo/celular START DATE: fecha en que se ha creado el nuevo numero EXPIRY DATE: fecha en que se vencerá el numero DIDGROUP: el grupo al que pertenece el numero (se ha creado solamente Colombia) COUNTRY: el país del numero ACTIVATED: Yes El numero está activado MONTHLY RATE: el costo mensual (1 dólar)
Los demás parámetros se pueden dejar vacíos. Se confirma la creación con el botón CONFIRM DATA y se crea un segundo numero:
289
Se guardan los cambios con CONFIRM DATA. Ahora se entra en el menú INBOUND DID → Destination y se asocian los DID a los clientes con el enlace Add DESTINATION. Para el primer numero:
• • • • • • •
DESTINATION: el desvío en este caso será hacia un numero de celular de Colombia (personalizar) CUSTOMER ID: el id del cliente al que se asociará el destino que se está creando y de esta forma también el numero DID: el numero geográfico asignado al cliente (el primero creado) ACTIVATED: Yes desvío activado VALIDATED: Validated desvío validado PRIORITY: la prioridad del desvío si se configuran más de uno VOIP_CALL: No ya que el desvío es hacia un numero celular y no una SIP URI
Se termina presionando el botón CONFIRM DATA. A partir de este momento el numero geográfico se cobrará al cliente con ID 1 y el desvío será activo. En la cuenta de cliente, menú INVOICES → Preview Next Billing, aparecerá el cobro. Se continua con el segundo:
En este caso para el segundo DID se configura el desvío hacia la extensión del cliente con ID2 (claramente puede ser cualquiera. Lo importante es que tenga crédito suficiente para pagar el DID) y la 290
IP publica del servidor. En el ultimo parámetro se indica que la llamada será de tipo VOIP_CALL. Se guardan los cambios y se pasa a la configuración de OpenSIPs. Se accede al cliente MySQL: mysql -u root -psesamo base de datos a2billing: mysql> use a2billing; La tabla que contiene la configuración de los DID es cc_did: mysql> select id,iduser,did from cc_did; aparecerá:
La tabla donde se guardan los desvíos configurados es cc_did_destination: mysql> select id,destination from cc_did_destination;
Se sale del cliente MySQL: mysql> quit ¿Cual es la idea detrás de esta configuración? Que si la llamada que llega a OpenSIPs procede desde uno de los números geográficos configurados como DID en A2Billing y el desvío es hacia el servidor OpenSIPs, la llamada se procesará directamente en OpenSIPs Si el numero es uno de los configurados como DID en A2Billing y el desvío es hacia un numero fijo, celular o otra SIP URI que no sea OpenSIPs, la llamada se enviará a Asterisk. Una particularidad de A2billing es que si una extensión llama un numero geográfico configurado en A2Billing, el sistema sacará la llamada “internamente”, es decir que la extensión llamante no estará pagando esa llamada (si no se configura A2Billing 291
diversamente). Hay que tener en cuenta que si el desvío es hacia la extensión, como la llamada se gestiona directamente desde OpenSIPs, este tipo de llamadas no se podrán facturar. Se tendrán dos escenarios distintos: 1. Si la llamada al numero geográfico se realiza desde una extensión configurada en A2Billing con usuario y contraseña, la llamada llegará al contexto [a2billing] 2. Si la llamada al numero geográfico se realiza desde una extensión configurada en A2Billing con autenticación sobre IP o desde una linea fija o celular, la llamada llegará al contexto [opensip] La llamada que llegará a Asterisk, se procesará en uno de los dos contextos y luego se enviará a un nuevo contexto creado especialmente para el procesamiento de las llamadas hacia números geográficos configurados en A2Billing. Se crea una copia del archivo de configuración de OpenSIPs: cp /etc/opensips/opensips.cfg /etc/opensips/opensips.cfg.5 Se abre el archivo de configuración: oscfg Como se utilizará el modulo AVPOPS para realizar la consulta en las dos tablas de la base de datos a2billing, hay que modificar este bloque: #### AVPOPS module loadmodule "avpops.so" Para quede: #### AVPOPS module loadmodule "avpops.so" modparam("avpops", "db_url", "mysql://a2user:sesamo@localhost/a2billing") En este modulo se pueden crear diferentes conexiones a distintas base de datos que se diferencian con un ID. De esta forma desde el script se podrán realizar consultas a cualquiera de las base de datos configuradas indicando el id de la conexión. En este caso, como la base de datos es una, no hace falta indicar el id. Si se quisiera crear una segunda conexión, por ejemplo a la base de datos opensips, se añadiría la siguiente linea: modparam("avpops", "db_url", "1 mysql://opensips:opensipsrw@localhost/opensips") El 1 antes del enlace indica el ID de esta conexión. Después de este bloque: if (is_method("INVITE")) { if (check_source_address("0","$avp(accountcode)")) { xlog("L_NOTICE","La IP $si es una dirección autorizada"); 292
append_hf("P-Accountcode: $avp(accountcode)\r\n"); } else { $var(invite_cod) = proxy_authorize("", "subscriber_v1"); if ( $var(invite_cod) == -1 || $var(invite_cod) == -2 ) { xlog("L_NOTICE","error de autent para $fU@$fd desde $si causa $var(invite_cod)");
sl_send_reply("403","Te he pillado"); exit; } if ( $var(invite_cod) < 0 ) { proxy_challenge("", "0"); exit; } xlog("L_NOTICE","INVITE del Usuario $fU Autenticado"); consume_credentials(); } } Se añade: if (avp_db_query("select did,destination from cc_did,cc_did_destination where cc_did.id=cc_did_destination.id_cc_did and did='$rU'","$avp(numerodid);;$avp(destino)")) { xlog("L_NOTICE","DID = $avp(numerodid) Destino = $avp(destino) retcode=$retcode");
if ($rU = $avp(numerodid) && $avp(destino)!~"^.*@1\.2\.3\.4") { append_hf("P-didnumber: $avp(numerodid)\r\n"); prefix("DID"); rewritehostport("IPPrivada:5090"); lb_count_call("$rd","$rp","1","channel"); record_route(); route(RELAY); } $avp(destino)=$(avp(destino){s.substr,4,0}); xlog("L_NOTICE","la nueva AVP Destino es $avp(destino)"); $ru="sip:" + $avp(destino); xlog("L_NOTICE","la nueva Request URI es $ru"); } La lineas que se han añadido: •
• 293
avp_db_query: esta función permite realizar una consulta en una base de datos. En este caso la base de datos es a2billing y la consulta es: busca el numero llamado en la tabla cc_did de a2billing. Si está presente, devuelve el mismo numero y el destino configurado en la tabla cc_did_destiantion de A2Billing. Los dos valores devueltos se asignarán a dos variables: • $avp(numerodid) contendrá el numero geográfico • $avp(destino) contendrá el destino Si la consulta tiene éxito se siguen con las demás lineas sino se salta al bloque que inicia con if (db_does_uri_exist()) { en la segunda linea se devuelven los valores de las dos variables más de la variable $retcode al
•
• • • • • •
LOG de OpenSIPs en la tercera linea se realiza la siguiente operación: si la parte usuario de la Request URI es igual al valor contenido en la variable $avp(numerodid) pero la variable $avp(destino) no contiene la IP se OpenSIPs, se continua con la linea que sigue sino se salta a la primera linea fuera del bloque que sería: $avp(destino)=$(avp(destino){s.substr,4,0}) en la cuarta linea se añade la cabecera P-didnumber al INVITE que será generado por OpenSIPs hacia Asterisk. Esa cabecera contendrá el numero DID en la quinta linea se añade el prefijo DID a la parte usuario de la Request URI en la sexta linea se reescribe la parte después de la @ de la Request URI indicando la IP privada del servidor Asterisk en la séptima linea se cuenta la llamada en el sistema del balanceamineto de carga y se asigna al recurso channel en la octava linea se añade la función record_route para que OpenSIPs se mantenga en el medio de la señalización SIP por ultimo se envía la transacción a la ruta route(RELAY) donde se procesará de manera Statefull.
En el caso en que la consulta: if ($rU = $avp(numerodid) && $avp(destino)!~"^.*@1\.2\.3\.4") devuelva un valor negativo se ejecuta el siguiente bloque: $avp(destino)=$(avp(destino){s.substr,4,0}); xlog("L_NOTICE","la nueva AVP Destino es $avp(destino)"); $ru="sip:" + $avp(destino); xlog("L_NOTICE","la nueva Request URI es $ru"); • • • •
En la primera linea se quitan los primeros 4 caracteres a la variable $avp(destino), es decir SIP/ y se asigna el nuevo valor nuevamente a la variable $avp(destino) en la segunda linea se envía al LOG de OpenSIPs el nuevo valor de la variable $avp(destino) en la tercera linea se cambia la Request URI (pseudo variable $ru) asignándole el valor modificado de la variable $avp(destino) (la pseudo variable $ru es de lectura/escritura) en la cuarta linea se envía el nuevo valor de Request URI al LOG de OpenSIPs. Luego se procede con los bloques que siguen.
Antes de guardar los cambios, se modifica IPPrivada con la IP privada del servidor y 1\.2\.3\.4 con la IP publica del servidor, ejemplo: 107\.170\.186\.192. Se guardan los cambios y se averigua que la configuración esté correcta: opensips -c /etc/opensips/opensips.cfg si todo está bien, se reinicia OpenSIPs: service opensips restart Ahora se abre el X-Lite configurado con los datos de una extensión presente en A2Billing que se 294
autentica con usuario y contraseña y se marca el primer numero geográfico configurado:
La llamada llegará a Asterisk pero aparecerá este error: NOTICE[2814][C-00000010]: chan_sip.c:25759 handle_request_invite: Call from '09148' (45.56.76.75:5060) to extension 'DID5712345678' rejected because extension not found in context 'a2billing'. Si la llamada se realiza en X-Lite configurado con la extensión que se autentica sobre IP el resultado será: Call from 'opensip' (45.56.76.75:5060) to extension 'DID5712345678' rejected because extension not found in context 'opensip'. Es por eso que se modifica el dialplan: nano /etc/asterisk/extensions.conf En el contexto [a2billing] después de este bloque: exten => 97,1,NoOp(Buzón de voz) same => n,VoicemailMain(${CALLERID(num)}@default) same => n,Hangup Se añade: exten => _DID.,1,NoOp(Llamadas a números geográficos) same => n,Goto(a2billing3,${EXTEN:3},1) same => n,Hangup y al final del contexto [opensip] se añade nuevamente el mismo bloque: exten => _DID.,1,NoOp(Llamadas a números geográficos) same => n,Goto(a2billing3,${EXTEN:3},1) same => n,Hangup Como el numero que llega a Asterisk inicia con DID (el prefijo añadido desde OpenSIPs), la llamada se envía al contexto a2billing3 a la extensión se quita DID, prioridad 1. Como ese contesto todavía no existe se crea. Después de este bloque: [a2billing2] 295
exten => _X.,1,NoOp(A2Billing Start) same => n,Agi(a2billing.php,1) same => n,Hangup exten => h,1,Hangup se añade: [a2billing3] exten => _X.,1,NoOp(A2Billing DID Start) same => n,Agi(a2billing.php,1,did) same => n,Hangup exten => h,1,Hangup En la aplicación Agi (segunda linea) se añade al final did que significa que aquí se procesarán los números geográficos configurados en A2Billing. Se guardan los cambios y se recarga el dialplan: aste CLI> dialplan reload Se realiza nuevamente la llamada desde el X-Lite configurado con la dos extensiones (la que se autentica con usuario y contraseña y la que se autentica sobre IP). El resultado en la consola de Asterisk para ambas pruebas será: (SIP/voztovoice1/00573163435746,60,rL(7889000:61000:30000)) El sistema llamará el numero 573163435746 que es el configurado como desvío para el DID 5712345678 Ahora se configura un segundo dispositivo con la extensión que debería recibir la llamada cuando se marque el segundo numero geográfico. Una vez registrada en OpenSIPs, desde X-Lite se marca el segundo DID:
La llamada debería llegar correctamente a la extensión configurada para el desvío. Hasta ahora se han realizado las pruebas en local, es decir sin un numero geográfico real configurado con un proveedor de DID. En el caso en que se quiera realizar la prueba con DIDWW, como se sabe, la llamada puede llegar desde distintas IPs y esas IPs hay que autorizarlas en OpenSIPs. Se accede a MySQL: mysql -u root -psesamo 296
mysql> use opensips se añaden todas las IP de DIDWW: mysql> insert into address (grp,ip) values ('0','46.19.209.10'),('0','46.19.209.11'), ('0','46.19.209.12'),('0','46.19.209.13'),('0','46.19.209.14'),('0','46.19.209.15'),('0','46.19.209.75'), ('0','46.19.209.76'),('0','46.19.209.77'),('0','46.19.209.78'),('0','46.19.209.79'),('0','46.19.209.80'), ('0','46.19.210.10'),('0','46.19.210.11'),('0','46.19.210.12'),('0','46.19.210.13'),('0','46.19.210.14'), ('0','46.19.210.15'),('0','46.19.210.75'),('0','46.19.210.76'),('0','46.19.210.77'),('0','46.19.210.78'), ('0','46.19.210.79'),('0','46.19.210.80'); mysql> quit En DIDWW se configura el DID para que apunte al mismo numero asignado por DIDWW y la IP publica de OpenSIPs. Se configura el numero geográfico en A2Billling en el mismo modo visto anteriormente y luego se asigna a un cliente configurando en INBOUND DID → Destination una nueva entrada y decidiendo si enviar la llamada un numero fijo/celular o a la misma extensión del cliente. Para recargar los valores de la tabla address en la memoria cache sin reiniciar OpenSIPs: opensipsctl fifo address_reload Luego se llama el numero desde un teléfono fijo/celular o desde una extensión de su PBX personal (si disponible). Esto para que la prueba sea totalmente confiable. 6.10 A2Billing como sistema de tarjetas telefónicas Hasta ahora se ha presentado la configuración de A2Biling como sistema de venta al detalle. En este párrafo se ilustrará como configurar el programa como sistema de tarjetas telefónicas. A2Billing brinda la posibilidad de activar dos o más configuraciones y utilizarlas a la vez. Esto se realiza creando distintos agi-conf en el menú SYSTEM SETTINGS → Add agi-conf. Se entra en ese menú y en la pagina que aparece:
297
Se presiona el botón “Create AGI-CONF2” (ya que es el segundo agi-conf que se está creando). En la pagina que aparece:
Se presiona el Botón “Search” y se inicia la configuración para un sistema de tarjetas telefónicas. Se activarán casi todas las opciones disponibles en modo de poder probar el sistema en toda su totalidad. Luego se irán quitando algunas para realizar distintas pruebas. En negrita aparecen los parámetros que hay que modificar: Titulo Call to free DID Dial Command Params
Valor
Descripción
,60,L(%timeout %:61000:30000)
Opciones para el comando Dial de Asterisk para llamadas a DID gratuitos.
Description
tarjetas-telefónicas
Un nombre para este perfil
Asterisk Version
1_11
Versión de Asterisk utilizada
Answer Call
Yes
El Agi contestará la llamada
Play Audio
Yes
Se habilita el utilizo de las locuciones audio
Say GoodBye
Yes
Se utilizará la locución Goodbye al terminar una llamada
Play Language Menu
Yes
Se presentará el IVR para escoger el idioma
Force Language
Fuerza el uso de un idioma para las locuciones. No aplica para esta configuración
Intro Prompt
Locución de introducción personalizada
298
Min Call Credit
0.5
Crédito mínimo para que un cliente pueda realizar una llamada. Ayuda a no tener saldos negativos
Min Bill Duration
0
Duración mínima para que la llamada sea cobrada. 0 = se cobra a partir del momento en que es contestada.
Not Enough Credit
No
Con yes; si el cliente no tiene suficiente crédito en la tarjeta que está utilizando, se le permitirá seleccionar otra
New Caller ID
No
Si el parámetro anterior es Yes, este parámetro en Yes asocia el CallerID del cliente a la nueva tarjeta
Use DNID
No
Con No: no se utiliza el contenido de la variable DNID para realizar la llamada que contiene el numero marcado y de esta forma al cliente no se le pide que ingrese el numero a marcar
Not Use DNID
Try Count
Lista de números que si marcados enviarán la llamada al sistema de tarjetas telefonicas aunque el parámetro anterior esté configurado con Yes. 3
Numero de intentos permitidos al cliente para marcar un numero
Force CallPlan
Para forzar el utilizo de determinado (no se utiliza)
Say Balance After Auth Yes
Anuncia al cliente el crédito disponible después de la autenticación
Say Balance After Call
Yes
Anuncia el crédito disponible al terminar la llamada
Say Rate
Yes
Anuncia el costo de la llamada
Say Duration
Yes
Anuncia la duración de la llamada en base al crédito disponible
Auto Set CLID
No
Permite al cliente de escoger un CallerID para la llamada
Force CLID
CLID Sanitize
299
un
Callplan
Si el parámetro anterior está en yes y este contiene un numero, ese numero se utiliza como identificativo de llamada para las llamadas salientes. CID
Si el parámetro anterior no está configurado, en este parámetro se configura cual numero se
utilizará para el identificativo de las llamadas salientes del cliente: • NO: desactivado • CID: uno de los números configurados por el cliente como identificativo de llamada • DID: uno de los números geográficos adquiridos por el cliente • BOTH: el identificativo de llamada puede ser o un DID del cliente o uno de los números configurados por el cliente. CLID Enable
Yes
Se autentica el cliente con el CallerID
Ask PIN
Yes
Si no se identifica el callerid del llamante, se le pedirá el PIN
FailOver Prefix
LCR/LCD No
Si en un CallPlan están presentes dos tarifas distintas para terminar la llamada (ejemplo prefijos 573 y 57) y se llama a un celular de Colombia, el sistema intentará sacar la llamada con la primera tarifa (573). Si no tiene éxito, se intentará utilizar la segunda tarifa (57). Con No se desactiva esta funcionalidad
Auto CLID
No
Si el cliente no se puede autenticar con el CallerID se le pedirá su numero de tarjeta e automáticamente se asociará al numero de tarjeta al CallerId del teléfono de donde está llamando
Auto CLID Security
No
Con yes se controla que el CallerID del cliente esté asociado con la tarjeta que está utilizando para la llamada
SIP Call
No
Se habilita para permitir llamadas gratuitas entre las extensiones SIP/IAX
SIP Call Prefix
555
Prefijo que hay que anteponer al numero de extensión SIP/IAX que se quiere llamar (funciona si SIP CALL = Yes)
Direct Call
No
Si se deja deshabilitada se presentará una locución para marcar un numero. Si este numero empieza por 555 la llamada sera cursada hacia la extensión SIP/IAX marcada; de otra forma se cursará normalmente
IVR Voucher Refill
Yes
Si está en Yes permite recargar las tarjetas utilizando un voucher
IVR Voucher Prefix
8
Dígito a marcar desde el menú de tarjetas
300
telefónicas para recargar la cuenta con un voucher IVR Low Credit
Yes
Dial Command Params ,60,rL(%timeout %:61000:30000)
Si está en Yes y el crédito disponible del cliente es menor que el valor definido en el parámetro “Min Call Credit”, se presentará en automático el IVR para recargar la tarjeta utilizando un voucher Opciones para el comando Dial de Asterisk. La opción r que aparece en la linea genera un timbrado falso. En algunos dispositivos este timbrado puede generar problemas de facturación de la llamada. En esos casos, se quita la r de la linea .
SIP/IAX Dial , Opciones para el comando Dial para llamadas Command Params 60,rL(3600000:61000:3000 entre extensiones. Duración máxima de la 0) llamada 3600000 mili segundos = 1 hora Outbound Call
No
Forma de marcar el numero: No SIP/Proveedor/numero – Yes SIP/numero@IPProveedor
Failover Retry Limit
1
Numero de intentos de cursar la llamada utilizando las troncales de respaldo
Max Time
3600
Numero máximo, en segundos, de duración de una llamada cuya tarifa es igual o inferior a 0
Send Reminder
Yes
Yes = se envía un correo electrónico al cliente cuando su crédito es inferior al valor del parámetro “ Min Call Credit”
Record Call
No
Yes = se grabará el audio de las llamadas
Monitor File Format
gsm
Formato audio utilizado para grabar las llamadas
AGI Force Currency
Currency Associated Default Accountcode
301
= =
Indicando una moneda el crédito disponible se anunciará en la moneda indicada en lugar de la moneda configurada por el cliente en su pagina personal usd:dollars,mxn:pesos,eur:e Locuciones para las monedas configuradas uros,cop:pesos,all:credit Si en este parmentro se indica el numero de un cliente, o ACCOUNTCODE, todas las llamadas que utilizarán este agi-conf se cobrarán a ese cliente. Esto dependiendo de la configuración del parámetro “Default Accountcode Behaviour” que aparece más
adelante. Se deja vacío Option Local Dialing
No
No añadir el prefijo internacional del cliente si el numero marcado contiene solamente un 0 inicial
Max time to Call a DID 3600 no billed
Numero máximo de segundos que se puede llamar un DID del sistema y por el cual no se cobra la llamada
File Enter Destination
prepaid-enter-dest
Locución utilizada para pedir al cliente el numero a marcar
Menu Language Order
es:en:fr
Lista de idiomas disponibles en el IVR que permite escoger un idioma para las locuciones
Bill Callback
Yes
Se cobrará la llamada de Callback del primer canal aunque el segundo canal no ha contestado o no se ha podido establecer la llamada
International prefixes
011,00,09
Prefijos internacionales que se quitarán al numero marcado si el CallPlan lo prevea
Extra charge DIDs
1800,1900
Cargos adicionales para DID que empiecen con 1800 0 1900 (por minuto)
Extra charge DID fees
0,0
Se indican los costos, por minuto, de llamadas a los números que empiecen con el prefijo indicado en el parámetro anterior.
Extra charge DID buy 0,0 fees
Se indican los costos adicionales para la compra de números cuyo prefijo está presente en el parámetro “Extra charge DIDs”
Max Time Unlimited Calls
For 7200
Tiempo máximo de duración de una llamada incluida en un paquete de minutos gratuitos cuyo paquete tiene configurado en el parámetro PACKAGE TYPE el valor “Unlimited calls”
Max Time For Free 3600 Calls
Tiempo máximo de duración de una llamada incluida en un paquete de minutos gratuitos cuyo paquete tiene configurado en el parámetro PACKAGE TYPE el valor “Number of Free calls”.
CallPlan threshold Deck switch
Este parámetro se utiliza para pasar un cliente de un Call Plan cuando haya utilizado n segundos de llamadas del primero. Los valores se indican de la siguiente forma: ID Call Plan : segundos (coma) ID segundo Call Plan : segundos. Ejemplo: 1:3600,2:7200
Disable
Yes = no anuncia el numero de segundos si el
302
annoucement Yes
the second of the times that the card can call
cliente para la llamada tiene disponible más de un minuto
Currency Association
Como se anunciará los centavos del crédito disponible.
Cents usd:prepaidcents,eur:prepaidcents,gbp:prepaidpence,all:credit
Verbosity
3
Configura el nivel de detalle de los registros de A2Billling 3 = INFO
Logging
3
Lo mismo para lo registros
Dial reservation
Balance 0.25
Crédito que se reserva por cada llamada en el caso de clientes que pueden utilizar más de una canal a la vez. Ayuda a prevenir la presencia de saldos negativos
Option CallerID update Yes
Permitir al cliente de actualizar su CallerID antes de la llamada
Auto Create Card
No
Si está en yes y el CallerID del cliente se captura, se generará una nueva tarjeta de llamadas asociadas a ese CallerID
Card 10
Longitud del numero de tarjeta generado automáticamente
Auto Create Length
Auto Create Card Type PREPAID
Tipo de tarjeta generada (PREPAID = prepago; POSTPAID = postpago)
Auto Credit
Crédito disponible en la tarjeta creada
Create
Card 0
Auto Create Card Limit 0
Si es una tarjeta de postpago, aquí se fija el limite de crédito para la tarjeta
Auto Create TariffGroup
Card 1
Grupo de tarifas que se utilizará para la tarjeta (véase el menú Callplan)
3
Tiempo en segundos de la duración del tono de ocupado
Reduce 1
Monto que se quitará al crédito disponible del cliente para asegurarse que la llamada de callback tenga crédito suficiente.
Busy Timeout Callback Balance
IVR Locking option IVR Information IVR Speed Dial
303
Yes
Si está en Yes permite al cliente configurar un segundo código para acceder a su cuenta
Account Yes
Si está en Yes permite al cliente consultar una serie de datos relacionados con su cuenta
Yes
Si está en Yes permite al cliente configurar los números de marcación rápida
Play rate lower one Callback Beep Destination
0
Si está en Yes anuncia el valor de la llamada aunque el costo sea menor de un centavo
for No
= Yes, a lo largo de una llamada de callback, el cliente escuchará un beep cuando la llamada se establece.
Callback CID Prompt No Confirm PhoneNumber
Si está en Yes a quien inicia una llamada de callback se le pedirá de confirmar su numero
LCR Mode
Este parámetro ha sido añadido con la versión 2.0 de A2Billing. Si el valor es 0 A2billing busca el prefijo que más se acerca al numero marcado en todas las RateCard presentes en un CallPlan y escoge la ruta más barata. Si el valor es 1 A2Billing busca en cada RateCard presente en un CallPlan el prefijo que más se acerca al numero marcado y entre todos los encontradas, escoge la ruta más barata. Más adelante se mostrará como se utiliza esta nueva funcionalidad.
1
Default Accountcode No Behaviour
Si está en Yes utiliza el ACCOUNTCODE definido en el parámetro “Default Accountcode” aunque la llamada tenga asociado un ACCOUNTCODE. Si está en no aplicará este ACCOUNTCODE solamente para las llamadas que no tengan uno.
Normalmente un sistema de tarjetas telefónicas se apoya a números de acceso telefónicos que los clientes llaman para efectuar sus llamadas utilizando este sistema. Estos números telefónicos pueden ser lineas telefónicas configuradas en Asterisk a través de una tarjeta telefónica o ATA, o números geográficos. En el primer caso la llamada llega directamente a Asterisk, en el segundo se puede decidir si inviar la llamada a OpenSIPs o Asterisk: • •
Si se envía a OpenSIPs, habrá que configurar el numero geográfico en A2Billing y desviar las llamadas entrantes al contexto donde se configura el dialplan para las tarjetas telefónicas Si se envía la llamada a Asterisk, hay que abrir el puerto 5090 (donde escucha Asterisk) para todas la IP indicadas por el proveedor del numero geográfico. Luego añadir las mismas IP como troncales en el archivo sip.conf.
Seguramente la segunda opción es la mejor pero en este caso se utilizará la primera ya que OpenSIPs está configurado para recibir las llamadas de números geográficos configurados en A2Billing. En la pagina de administración, se entra en el menú INBOUND DID → Add :: Search y se añade un nuevo numero con Add DID:
304
No se cobrará por el numero. Se continua con INBOUND DID → Destination, Add DESTINATION:
La idea es asociar el DID a una cuenta utilizada solamente por temas de administración. En el parámetro DESTINATION se pone local/5719999999@tartel. Esto significa que la llamada será local y entrará al contexto [tartel], prioridad 57199999999 de Asterisk. Ese contexto hay que crearlo: nano /etc/asterisk/extensions.conf al final del archivo se añaden las siguientes lineas: [tartel] exten => 5719999999,1,NoOp(A2Billing tarjetas telefónicas) same => n,Agi(a2billing.php,2) 305
exten => h,1,Hangup la parte importante de este bloque de dialplan es la segunda linea: cuando entre una llamada a este bloque se ejecutará el AGI a2billing.php. El numero 2 que aparece después de la coma indica que se utilizará el segundo agi-conf creado, es decir, él que se acaba de configurar en la pagina de administración de A2Billing. Se guardan los cambios y se entra en la consola de Asterisk: asterisk -rvvvvvvvvvvvvv se recarga el dialplan: CLI> dialplan reload Para conocer la sintaxis de una aplicación de Asterisk el comando que hay que escribir es: CLI> core show application nombreaplicacion ejemplo: CLI> core show application NoOp -= Info about application 'NoOp' =[Synopsis] Do Nothing (No Operation). [Description] This application does nothing. However, it is useful for debugging purposes. This method can be used to see the evaluations of variables or functions without having any effect. [Syntax] NoOp([text]) [Arguments] text Any text provided can be viewed at the Asterisk CLI. [See Also] Verbose(), Log() Para probar el sistema de tarjetas telefónicas, desde el X-lite conectado a OpenSIPs, se marca el numero 5719999999. Se escuchará primero el IVR que permite seleccionar el idioma. Se presentan tres idiomas: ingles, francés, español. Esto se puede modificar en la pagina de administración de A2Biling menú SYSTEM SETTINGS → Global List → agi-conf2, parámetro “Menu Language Order “. 306
Luego el sistema pedirá el código PIN (numero de tarjeta). Introducido el código PIN se escuchará el crédito disponible en la cuenta. La siguiente locución anuncia que digitando la tecla 4 se puede entrar en un menú para recibir distintas informaciones acerca de la cuenta. Se continua con un anuncio que permite, digitando la tecla 5, configurar un segundo PIN para la cuenta. Si este PIN se configura, para poder efectuar una llamada habrá que digitar ambos (el numero de la tarjeta y el segundo PIN de seguridad). La siguiente locución anuncia que digitando la tecla 8 se puede recargar la cuenta con un voucher. Más adelantes se efectuará una prueba para realizar este tipo de operación. El sucesivo anuncio permite configurar teclas para las llamadas rápidas, es decir asociar a un numero (de 0 a 9) un numero de teléfono. De esta forma marcando ese numero seguido de la tecla numero, se llamará el numero de teléfono asociado. Por ultimo, después de todos estos menú, la ultima locución pedirá de introducir el numero a llamar seguido de la tecla numero (almohadilla). Introducido el numero se escuchará el costo de la llamada por minuto y los minutos disponibles. Como se puede ver, las opciones son muchas. Algunas son útiles y otras menos. Se puede ir depurando la configuración empezando con el IVR de los idiomas. Si este IVR se quita, el idioma predefinido será aquel configurado en el siguiente parámetro presente en la lista agi-conf2: Force Language
ES
Fuerza el uso de un idioma para las locuciones.
En la lista de parámetros de agi-conf2 se modifica también: Play Language Menu
Yes
Se presentará el IVR para escoger el idioma
Poniéndolo en no. Hecho el cambio se vuelve a marcar el numero. Ya no se escuchará el IVR de los idiomas y la locución que pedirá de introducir el código PIN será en español. Una vez introducido el código PIN, el idioma predefinido para las locuciones a seguir, será el configurado por el cliente al momento de registrarse al sistema. Para simplificar las llamadas se pueden quitar el IVR para obtener informaciones acerca de la cuenta y el IVR para configura las teclas de llamadas rápidas. Esto porque el cliente puede ver esos datos en la pagina de su cuenta y de todas formas no son configuraciones importantes. Para ese efecto se modifican los dos siguientes parámetros:
IVR Account Information
307
Yes
Si está en Yes permite al
cliente consultar una serie de datos relacionados con su cuenta IVR Speed Dial
Yes
Si está en Yes permite al cliente configurar los números de marcación rapida
y se ponen en no. Se marca el numero 5719999999 otra vez. Quedarán disponibles dos opciones: la posibilidad de configurar un PIN de seguridad y la posibilidad de recargar la cuenta con un voucher. Para recargar la cuenta con un voucher, primero hay que crear uno. Se entra en la pagina de administración de A2Billling y luego en el menú BILLING → Vouchers. Se escoge la opción Add Voucher y en la nueva pagina se crea uno:
Se toma nota del numero del voucher y desde el X-Lite se marca otra vez el numero de acceso telefónico Cuando se escucha la locución de la recarga con voucher (desafortunadamente la hay solo en ingles), se digita el numero 8 y luego el numero del voucher.. Ahora en en menú Billings → Vouchers aparecerá:
El voucher ha sido usado por el cliente cuyo numero de tarjeta es 09148 Si se entra en el pagina personal de ese cliente bajo el menú Vouchers:
aparecerá el voucher que el cliente acaba de utilizar como recarga. Todos los menú y las locuciones son completamente configurables según las exigencias del 308
administrador de A2Billing y/o de los clientes. El cliente, desde su pagina personal, tiene la posibilidad de configurar hasta 5 distintos CallerID. Si realiza la llamada desde uno de estos 5 teléfonos, el sistema no le pedirá de introducir el numero de la tarjeta porque lo autenticará utilizando el CalleID. Otra opción que se puede configurar es la posibilidad de añadir en automático el CallerID del cliente una vez que se haya autenticado con su numero de tarjeta. De esta forma cuando el cliente vuelva a marcar desde el mismo teléfono, no se le pedirá más el numero de su tarjeta. Esta escenario se crea modificando este parámetro del agi-conf2: Auto CLID
No
Si el cliente no se puede autenticar con el CallerID se le pedirá su numero de tarjeta e automáticamente se asociará al numero de tarjeta al CallerId de teléfono de donde está llamando
Poniéndolo en Yes. Se marca el numero de acceso telefónico y si introduce el numero de tarjeta. Se cuelga la llamada y se entra en la pagina de administración de a2billing. En los parámetros del cliente cuya tarjeta se ha utilizado para autenticarse, aparecerá el nuevo CallerID (en este caso el numero de la extensión ):
Si se vuelve a marcar el numero de acceso, el sistema ya no pedirá el numero de tarjeta. Si a lo largo de una llamada se deja que el llamante cuelgue primero, el sistema anunciará nuevamente el crédito disponible y permitirá efectuar una nueva llamada. 6.11 CallBack (Rellamada) En A2Billing la funcionalidad de Callback o rellamada se puede utilizar de dos formas: desde la pagina personal de los clientes (si activada) o marcando un numero de acceso telefónico configurado en la centralita Asterisk. Normalmente ese numero es un numero geográfico o un numero de teléfono tradicional conectado a Asterisk a través de una gateway PSTN o Tarjeta telefónica instalada en el servidor Linux. En el primer caso la rellamada funciona de la siguiente manera. El sistema llama el primer numero indicado en la pagina y cuando este conteste llama el segundo. En este caso el costo de la llamada será 309
la suma del costo de la llamada hacia el primer numero y el costo de la llamada hacia el segundo numero. Con la configuración predefinida, A2billing cobra la primera llamada aunque la segunda no sea contestada. Si se quiere modificar este comportamiento, en el menú SYSTEM SETTINGS → Global List → Select Gruop → agi-conf1, se modifica la siguiente linea cambiando el parámetro de yes a no:
Bill Callback
Yes
Se cobrará la llamada de Callback del primer canal aunque el segundo canal no ha contestado o no se ha podido establecer la llamada
En el segundo caso, el cliente marca un numero de acceso telefónico determinado donde se configura el sistema con el tipo de callback que se quiera utilizar. Los distintos tipos son: • •
•
cid-callback: el sistema lee el CALLERID del llamante y cuelga. Si el numero está presente en la configuración de algún cliente devuelve la llamada a ese numero. Cuando el cliente conteste, se le pedirá de marcar el numero de destino. cid-prompt-callback: el sistema lee el CALLERID del llamante y le pide que introduzca el numero de destino. Cuelga la llamada y si el CALLERID está presente en la configuración de algún cliente devuelve la llamada a ese numero. Cuando el cliente conteste, marca directamente el segundo numero escogido por el cliente. all-callback: el sistema lee el CALLERID del llamante y cuelga. Luego devuelve la llamada al numero del llamante y cuando este conteste, le solicita el código PIN que sería el ACCOUNT NUMBER de su cuenta. Una vez digitado el PIN, el sistema pedirá al cliente de marcar el numero de destino.
La configuración del CallBack en A2Billing se realiza en el menú CALLBACK. En este menú es posible definir los grupos de servidores utilizados y dentro de cada grupo, los servidores que se utilizarán para las llamadas de Callback. Entrando en el menú CALLBACK → Server Group se verá que hay solamente un grupo configurado. Entrando en el menú CALLBACK → Server se verá que hay solamente un servidor configurado. Como en la configuración de A2Billing se ha modificado el nombre de usuario y la contraseña para conectarse a la AMI de Asterisk (véase /etc/asterisk/manager.conf), hay que modificar la entrada:
310
Los dos parámetros son lo mismos que aparecen en el menú SYSTEM SETTINGS → Global List → Global:
Con esto ya se tiene configurado el servidor Asterisk y A2Billing para las llamadas de Callback. En la primera prueba se verá como un cliente puede solicitar una llamada de Callback desde su pagina personal y en la segunda como funciona la rellamada utilizando un numero de acceso telefónico. 6.11.1. Rellamada desde la pagina del cliente Para realizar una prueba de rellamada desde la pagina web del cliente se entra en el menú CALLBACK desde la pagina del cliente. En la pagina que aparece hay que indicar los dos números a marcar. En la primera linea se indica el propio numero y en la segunda el numero de la persona que se quiere llamar:
Los números que aparecen en la imagen no son reales. Lo importante es que la sintaxis de los números a marcar sea: código país + numero de teléfono. Antes de iniciar la llamada se entra en el servidor Linux y se modifica el dialplan: nano /etc/asterisk/extensions.conf al final del archivo se añaden las siguientes lineas: [a2billing-callback] exten => _X.,1,Agi(a2billing.php,1,callback) same => n,Hangup exten => h,1,Hangup El contexto [a2billing-callback] es el que se ha configurado en el menú SYSTEM SETTINGS → Global List → callback.
311
Se guardan los cambios y se recarga el dialplan: aste CLI> dialplan reload CLI> quit Luego se escribe el siguiente comando: tail -f /var/log/a2billing/a2b-callback-daemon.log de esta forma se verá como el servicio de callback enviará la llamada al AMI de Asterisk. Se vuelve a la pagina del cliente y se presiona el botón “Click here to Place de Call”. El sistema llamará el primer numero y cuando este conteste llamará el segundo. En la ventana terminal aparecerá:
Volviendo a la pagina de administración de A2billing y entrando en el menú CALLBACK → Add se encontrará la llamada de Callback efectuada:
En STATUS aparece el estado de la llamada de Callback (en este caso SENT, enviada), en AR el resultado generado por el AMI de Asterisk, en este caso Success, que significa que la llamada se ha realizado con éxito. Para terminar se entra en el menú CALL REPORTS → CDRs y se verá como el sistema ha facturado las dos llamadas:
312
El la segunda linea, bajo la columna CallType, se puede ver que el tipo de llamada es CALLBACK. 6.11.2 Rellamada con numero de acceso Como se ha dicho, en el segundo caso normalmente se utiliza un numero de acceso telefónico. Para que se pueda realizar la prueba se simulará su funcionamiento configurando un nuevo numero geográfico. Se entra en el menú INBOUND DID → Add :: Search, luego Add DID:
Luego in INBOUND DID → Destination → Add DESTINATION:
313
Se abre el archivo del dialplan: nano /etc/asterisk/extensions.conf y al final del archivo se añaden las siguientes lineas: [callback] exten => 5718888888,1,Set(CALLERID(num)=189445322) same => n,Agi(a2billing.php,1,cid-callback,57) same => n,hangup Una pequeña explicación. Se define un contexto con nombre “callback” que es el mismo configurado en el desvío del numero geográfico configurado. El callback que se está configurando utiliza la autenticación basada sobre el CallerID del llamante. Esto significa que el sistema permitirá rellamadas solamente a números de teléfonos asociados a los clientes. Como en este caso la llamada no se realiza a un numero de acceso real, en la primera linea se asigna un CallerID a la extensión que está llamando. Para que la prueba funcione, hay que configurar en la primera linea un numero real al que se quiere que el sistema llame (sin el prefijo del país). En la segunda linea se ejecuta el AGI de A2Billing especificando que es una llamada de callback con autenticación del CallerID del llamante. Los últimos dos números son el código del país que hay que añadir al CallerID del llamante para devolverle la llamada (en este caso Colombia). Ejemplo: si el numero de teléfono es el celular 3121234567 en la primera linea se pone ese numero. Como es un numero de celular de Colombia, en la segunda linea se pone el prefijo del país (57) Se guardan los cambios y se entra en la pagina de administración de A2Billing, en el menú CUSTOMERS → Caller-ID y se añade un nuevo CallerID con Add CallerID. En esta pagina:
hay que asignar el CallerID configurado en el dialplan de Asterisk y seleccionar el cliente para el cual será valido. Se confirma la creación con el botón CONFIRM DATA. Se guardan los cambios y se entra en la consola de Asterisk: asterisk -rvvvvvvvvvvvvvv se recarga la configuración del dialplan: 314
CLI> dialplan reload Desde el X-Lite configurado con el numero de extensión a la que se acaba de añadir el CALLERID, se marca el numero 5718888888. El sistema leerá el CallerID del llamante y colgará la llamada. Después de 10 segundos llamará ese numero y una vez que se conteste la llamada se escuchará una locución que invitará a marcar el numero de destino seguido por la tecla numero (#). El el menu Call Reports → CDRs estará el registro de la llamada:
Se puede modificar el bloque: [callback] exten => 5718888888,1,Set(CALLERID(num)=3182409064) same => n,Agi(a2billing.php,1,cid-callback,57) same => n,hangup Para probar los distintos tipos de callback. Para all-callback: exten => 5718888888,1,Set(CALLERID(num)=189445322) same => n,Agi(a2billing.php,1,all-callback,57) same => n,hangup Para cid-prompt-callback: exten => 5718888888,1,Set(CALLERID(num)=189445322) same => n,Agi(a2billing.php,1,cid-prompt-callback,57) same => n,hangup De esta forma se tendrá la certeza que el sistema de CallBack de A2Billing esté funcionando correctamente. 6.12 Añadir extensiones a un cliente En algunas ocasiones, por ejemplo pequeñas oficinas o residencias, los clientes necesitan más de una extensión ya que quieren realizar las llamadas desde distintos dispositivos y al mismo tiempo llamarse entre los dispositivos configurados. Otro ejemplo es si se ha optado por la primera opción para la autenticación de los clientes sobre IP; puede suceder que haya clientes que necesiten autenticar más de 315
una IP. En estos casos existe en A2Billing la posibilidad de crear nuevas extensiones y asociarlas a un cliente que ya existe en el sistema. Se entra en el menú CUSTOMERS → VOIP Settings y luego Add SIP Config. Como se puede ver, los datos predefinidos de algunos parámetros no son los mismos que crea el sistema cuando la extensión SIP se genera junto a la creación del cliente. Para modificar los datos predefinidos, se abre el siguiente archivo a la linea 115: nano +115 /usr/local/src/a2billing/admin/Public/form_data/FG_var_friend.inc se modifica este bloque: if ($form_action=="ask-add" || $form_action == "add_sip" || $form_action == "add_iax") { $AMAFLAGS_default= "value='".$A2B->config["peer_friend"]['amaflag']."'"; $TYPE_default= "value='friend'"; $NAT_default= "value='yes'"; $DTMFMODE_default= "value='RFC2833'"; $CANREINVITE_default= "value='yes'"; $DISALLOW_default= "value='all'"; $ALLOW_default= "value='ulaw,alaw,gsm,g729'"; $HOST_default= "value='dynamic'"; $CONTEXT_default= "value='".$A2B->config["peer_friend"]['context']."'"; $REGSECONDS_default= "value='0'"; $CANCALLFORWARD_default= "value='yes'"; $TRUNK_default= "value='yes'"; para que quede: if ($form_action=="ask-add" || $form_action == "add_sip" || $form_action == "add_iax") { $AMAFLAGS_default= "value='".$A2B->config["peer_friend"]['amaflag']."'"; $TYPE_default= "value='friend'"; $NAT_default= "value='force_rport,comedia'"; $DTMFMODE_default= "value='RFC2833'"; $CANREINVITE_default= "value='no'"; $DISALLOW_default= "value='all'"; $ALLOW_default= "value='ulaw,alaw'"; $HOST_default= "value='dynamic'"; $CONTEXT_default= "value='".$A2B->config["peer_friend"]['context']."'"; $REGSECONDS_default= "value='0'"; $CANCALLFORWARD_default= "value='no'"; $TRUNK_default= "value='yes'"; Se guardan los cambios y se selecciona nuevamente Add SIP Config:
316
En ID CARD se selecciona el icono evidenciado y en la nueva ventana el cliente al que se quiere asociar la nueva extensión:
Automáticamente el parámetro ACCOUNTCODE tendrá como valor el numero de la tarjeta del cliente seleccionado. Esto porque este parámetro es el que permite al sistema saber a que cliente facturar las llamadas salientes. Se modifica solamente el siguiente parámetro que tiene que quedar en no:
Se confirma la creación de la nueva extensión con el botón CONFIRM DATA. En la lista de las extensiones aparecerá una nueva entrada:
La segunda extensión del cliente aparecerá con un grosor distinto a indicar que no es la principal. Se configura el X-Lite con los datos de usuario y contraseña de la nueva extensión creada y se realiza una llamada.
En el campo CallerID aparecerá el numero de la extensión y en la columna Account el numero de la cuenta a la que será facturada la llamada. De esta forma el cliente, en su reporte de llamadas, podrá diferenciar las llamadas según la extensión de donde se realizaron. En el caso en que la nueva extensión se crea para añadir una nueva IP del cliente a autenticar, antes de guardar los cambios: • • • •
se borra el contenido del parámetro SECRET se modifica el contenido del parámetro HOST con la nueva IP que se quiere autenticar se modifica el contenido del parámetro TYPE de friend a peer se borra el contenido del parámetro USERNAME
Se guardan los cambios. 317
6.13 Conteo de canales Cuando se configura un nuevo cliente (párrafo 4.7) entre los distintos parámetros que se pueden configurar hay:
Como se puede leer en la descripción, la funcionalidad no está implementada. En teoría su tarea sería la de limitar el numero de canales que un cliente puede utilizar siempre y cuando en la configuración de su cuenta se ha configurado el parámetro:
Para poder implementar esta funcionalidad, se podría utilizar MySQL realizando una consulta a la tabla cc_card de a2billing y de ahí sacar el valor del parámetro MAX CONCURRENT CALLS y compararlo con los canales que efectivamente está utilizando el cliente. El problema con este tipo de solución es que si el sistema procesa muchas llamadas concurrentes y/o se está utilizando un sistema de balanceo de carga entre distintos servidores Asterisk, no se puede tener cuenta de todas las llamadas realizadas en todos los servidores. Afortunadamente hay una solución alternativa que se basa en un sistema de base de datos NoSQL: Redis. En general los sistemas NoSQL, a pesar de que no permiten consultas SQL, no utilizan tablas para guardar los datos y escalan mucho mejor horizontalmente; esto quiere decir que son más rápidos en elaborar las entradas y pueden almacenar una cantidad considerable de datos y acceder a ellos en tiempos breves. Para implementar esta solución, los pasos a seguir son: 1. 2. 3. 4. 5.
crear la consulta en la tabla cc_card de la base de datos A2Billing instalar el servidor Redis y la relativa librería Perl para interaccionar con Asterisk Configurar el servidor Redis Crear el script que se encargará de la cuenta de los canales modificar el dialplan de Asterisk
Para crear la consulta en la tabla cc_card se utilizará el modulo func_odbc de Asterisk. Los pasos a seguir serían: • • •
Configurar ODBC para la conexión a la base de datos a2billing Configurar el archivo res_odbc.conf para conectarse a la base de datos a2billing utilizando el conector ODBC configurar el archivo func_odbc.conf
Como los primeros dos pasos ya se realizaron en el párrafo 3.3.3 (Asterisk Realtime), lo único que hace 318
falta es configurar el archivo func_odbc.conf. Se renombra el predefinido: mv /etc/asterisk/func_odbc.conf /etc/asterisk/func_odbc.conf.old se crea uno nuevo: nano /etc/asterisk/func_odbc.conf y se copian la lineas que siguen: [canales] dsn=a2b readsql=select max_concurrent from cc_card where username='${SQL_ESC(${ARG1})}' Lo datos: • • •
[canales]: el nombre de la función que se va a crear: dsn=a2b: parámetro para la conexión a la base de datos. Este parámetro tiene que corresponder a la etiqueta que da inicio al bloque configurado en el archivo res_odbc.conf en la tercera linea aparece la consulta SQL que sería: selecciona el campo max_concurrent desde la tabla cc_card donde el valor username corresponde a la variable que te voy a pasar a través del diaplan.
Se guardan los cambios y se entra en la consola de Asterisk: aste Se recarga el modulo func_odbc CLI> module reload func_odbc.so y se mira si efectivamente la nueva función existe: CLI> core show function ODBC_canales -= Info about function 'ODBC_canales' =[Synopsis] Runs the referenced query with the specified arguments [Description] Runs the following query, as defined in func_odbc.conf, performing substitution of the arguments into the query as specified by ${ARG1}, ${ARG2}, ... ${ARGn}. This function may only be read, not set. SQL: select max_concurrent from cc_card where username='${SQL_ESC(${ARG1})}'
319
[Syntax] ODBC_canales([...[,]]) Perfecto! Ya se puede salir de la consola de Asterisk: CLI> quit El segundo paso es instalar el servidor Redis y la relativa librería perl: yum --enablerepo=epel install redis perl-Redis -y Se configura el servidor Redis: se renombra el archivo de configuración predefinido: mv /etc/redis.conf /etc/redis.conf.old se crea uno nuevo: nano /etc/redis.conf se copian las lineas que siguen: daemonize yes pidfile /var/run/redis/redis.pid port 6379 timeout 0 loglevel notice logfile /var/log/redis/redis.log databases 16 save 900 1 save 300 10 save 60 10000 rdbcompression yes dbfilename dump.rdb dir /var/lib/redis/ appendonly no appendfsync everysec no-appendfsync-on-rewrite no auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb slowlog-log-slower-than 10000 slowlog-max-len 1024 vm-enabled no vm-max-memory 0 vm-page-size 32 vm-pages 134217728 320
vm-max-threads 4 hash-max-zipmap-entries 512 hash-max-zipmap-value 64 list-max-ziplist-entries 512 list-max-ziplist-value 64 set-max-intset-entries 512 zset-max-ziplist-entries 128 zset-max-ziplist-value 64 activerehashing yes Con esta configuración, Redis escuchará sobre el puerto 6379 de todas las direcciones IP configuradas en el servidor. Se guardan los cambios y se configura para que se inicie al Boot del sistema: chkconfig redis on Ya se puede iniciar: service redis start Se averigua si hay errores y/o advertencias en los registros del programa: nano /var/log/redis/redis.log Debería aparecer este WARNING: WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect. Se soluciona como se dice en la linea: nano /etc/sysctl.conf al final del archivo se añade: vm.overcommit_memory = 1 Se guardan los cambios y se ejecuta el comando: sysctl vm.overcommit_memory=1 Se reinicia el servidor Redis: service redis restart Ya no debería aparecer más la advertencia.
321
Para acceder a la consola del servidor Redis: redis-cli Para ver los datos presentes: redis 127.0.0.1:6379> keys * (empty list or set) Para salir: redis 127.0.0.1:6379> quit El cuarto paso es crear el script para contar el números de canales y guardarlos en Redis. Se entra en la siguiente carpeta: cd /usr/local/bin se crea un nuevo archivo: nano canales.pl se copian las siguientes lineas: #!/usr/bin/perl my $redis_db = $ARGV[0]; my $command = $ARGV[1]; my $keyname = $ARGV[2]; my $value = $ARGV[3]; require Redis; my $redis = Redis->new(server => '127.0.0.1:6379'); if($redis_db > 0 && $redis_db < 16){ $redis->select("$redis_db"); } else { print "using Default Redis DB\n"; } if($command eq "GET"){ $val=$redis->get("$keyname"); print "$val"; } if($command eq "SET" && $value != ""){ $redis->set("$keyname" => "$value"); } if($command eq "INCR"){ 322
$redis->incr("$keyname"); } if($command eq "DECR"){ $redis->decr("$keyname"); } $redis->quit; En el primer bloque se asignan 4 variables que el script recibirá desde Asterisk. Luego se configura la conexión al servidor Redis sobre la IP 127.0.0.1 y puerto 6379 (el predefinido). En el caso en que el servidor Redis se encuentre en otro servidor, habría que indicar la IP publica de ese servidor y el puerto; luego en el servidor remoto abrir en el cortafuego el puerto 6379 para la IP del servidor donde está configurado el script. Se guardan los cambios y se vuelve el archivo ejecutable: chmod +x canales.pl Luego se prueba la conexión del script con el servidor Redis: ./canales.pl using Default Redis DB Si no aparecen errores, significa que la conexión funciona correctamente. El ultimo paso es modificar el dialplan: ext se modifica este bloque: [a2billing] exten => _X.,1,NoOp(A2Billing Start) same => n,Agi(a2billing.php,1) same => n,Hangup exten => h,1,Hangup para que quede: [a2billing] exten => _X.,1,NoOp(A2Billing Start) same => n,System(/usr/local/bin/canales.pl 1 INCR ${CDR(accountcode)}) same => n,Set(CALLS=${SHELL(/usr/local/bin/canales.pl 1 GET ${CDR(accountcode)})}) same => n,GotoIf($[${CALLS} > ${ODBC_canales(${CDR(accountcode)})}]?cong) same => n,NoOp(El cliente: ${CDR(accountcode)} tiene ${CALLS} llamadas activas) same => n,Agi(a2billing.php,1) same => n,Hangup 323
same => n(cong),Congestion(3) same => n,hangup exten => h,1,System(/usr/local/bin/canales.pl 1 DECR ${CDR(accountcode)}) exten => h,n,Hangup y modificar este bloque (donde llegan las llamadas autenticadas sobre IP): [a2billing2] exten => _X.,1,NoOp(A2Billing Start) same => n,Agi(a2billing.php,1) same => n,Hangup exten => h,1,Hangup para que quede: [a2billing2] exten => _X.,1,NoOp(A2Billing Start) same => n,System(/usr/local/bin/canales.pl 1 INCR ${CDR(accountcode)}) same => n,Set(CALLS=${SHELL(/usr/local/bin/canales.pl 1 GET ${CDR(accountcode)})}) same => n,GotoIf($[${CALLS} > ${ODBC_canales(${CDR(accountcode)})}]?cong) same => n,NoOp(El cliente: ${CDR(accountcode)} tiene ${CALLS} llamadas activas) same => n,Agi(a2billing.php,1) same => n,Hangup same => n(cong),Congestion(3) same => n,hangup exten => h,1,System(/usr/local/bin/canales.pl 1 DECR ${CDR(accountcode)}) exten => h,n,Hangup La cuenta de los canales se basará en el ACCOUNTCODE del cliente. Esto porque, como se dijo en el párrafo 5.7, es posible asociar más de una extensión a un cliente y el único parámetro común es propio el ACCOUNTCODE. En la segunda linea se ejecuta el script canales.pl pasando las siguientes variables: • • •
1: se utilizará la base de datos numero 1 de Redis (hay 16 disponibles) INCR: es el comando que se utiliza para aumentar de 1 unidad el valor de una variable. Si la variable no existe se creará y se le asociará el valor 1 ${CDR(accountcode)}: es la variable que contiene el ACOOUNTCODE de quien está llamando y será la variable que se creará en el servidor Redis
En la tercera linea se asocia a la variable CALLS el numero de canales en uso por el cliente. Valor que se obtiene consultando nuevamente la base de datos de Redis En la cuarta linea se compara el valor de la variable CALLS con el valor del parámetro MAX CONCURRENT CALLS configurado en la cuenta del cliente. Si la variable CALLS es mayor a ese valor se envía la llamada a la etiquete cong donde se reproduce una señal de congestión y se cuelga la llamada. Si es inferior se continua con la siguiente linea del dialplan. 324
Por ultimo en la extensión h,1 se utiliza el comando DECR para disminuir de una unidad en el servidor Redis el numero de canales utilizados por el cliente. Se guardan los cambios y se entra en la consola de Asterisk: aste Se actualiza el dialplan: CLI> dialplan reload y desde un cliente se realiza una llamada. El resultado en la consola de Asterisk: NoOp("SIP/0132102681-00000004", "A2Billing Start") in new stack System("SIP/0132102681-00000004", "/usr/local/bin/canales.pl 1 INCR 0132102681") in new stack Set("SIP/0132102681-00000004", "CALLS=1") in new stack GotoIf("SIP/0132102681-00000004", "0?cong") in new stack NoOp("SIP/0132102681-00000004", "El cliente: 09148 tiene 1 llamadas activas") in new stack AGI("SIP/0132102681-00000004", "a2billing.php,1") in new stack Cuando la llamada termine: System("SIP/0132102681-00000004", "/usr/local/bin/canales.pl 1 DECR 09148") Hangup("SIP/0132102681-00000004", "") En el servidor Redis debería estar la nueva variable con valor 0: redis-cli se selecciona la base de datos 1 redis 127.0.0.1:6379> select 1 OK Se saca la lista de variables presentes redis 127.0.0.1:6379[1]> keys * 1) "0132102681" Se mira el valor de la variable 1 redis 127.0.0.1:6379[1]> get "09148" "0" En el caso de muchos trafico y/o una caída del servidor es posible reajustar la base de datos borrando todas las variables presentes: 325
redis 127.0.0.1:6379[1]> FLUSHDB Ya se puede salir de cliente: redis 127.0.0.1:6379[1]> quit
326
Capitulo VII Seguridad del servidor La seguridad del servidor es la parte más delicada de toda la puesta en marcha del sistema de facturación A2Billing. Si alguien lograra acceder al servidor mismo, tendría acceso a cualquier tipo de información (datos de los clientes, troncales, etc). Es por eso que se necesita asegurar el sistema en su totalidad. Esto quiere decir que hay que hacerlo desde el protocolo SSH hasta el servidor Web pasando por el servidor Asterisk y el servidor MySQL. En el párrafo 1.2 ya se ha presentado la forma de asegurar los accesos SSH a través de la clave RSA. Con esta configuración es imposible para cualquier atacante poder acceder a la consola del servidor Linux. Lo importante es que nadie logre acceder a la clave RSA privada guardada en el computador local. En el párrafo 3.4 se ha visto como configurar el Firewall (cortafuegos) para dejar abiertos solamente algunos puertos bien definidos del servidor. La segunda fase es mejorar la seguridad del servidor Web que será el tema del próximo párrafo. 7.1 Poner en seguridad el servidor WEB Si se entra en la pagina principal del servidor Web: http://IPservidor aparece esta pagina:
Se ha dejado esta pagina disponible porque normalmente el sistema de facturación A2Billing es asociado con el sitio web de la empresa que está ofreciendo el servicio. En el caso que no se quiera o no se necesite configurar un sitio web, es mejor modificar esta pagina para que no sea la predefinida. Una posible solución es redireccionar el trafico que llega a esta pagina, a la pagina segura de los clientes. Esto se realiza copiando un pequeño archivo de texto en la carpeta raíz del servidor Web. cd /var/www/html nano index.html se copian estas lineas:
En lugar de ipservidor se pone la IP del servidor Linode o, mejor aun, el nombre de dominio. Se guardan los cambios y se recarga la pagina. Después de unos segundos, aparecerá la pagina de acceso de los clientes. Si se entra en la siguiente pagina: http:://ipservidor/common las carpetas serán visibles:
esto no es una buena cosa porque puede permitir accesos no deseados. Para que esto no suceda hay que modificar un parámetro en el archivo de configuración del servidor Web: nano +331 /etc/httpd/conf/httpd.conf y modificar la linea: Options Indexes FollowSymLinks para que quede: Options -Indexes FollowSymLinks
329
De esta forma ya no se podrán ver las carpetas presentes en el servidor. Se guardan los cambios y se reinicia el servidor Web: /etc/init.d/httpd restart Si se vuelve a entra a la misma pagina, se recibirá el siguiente mensaje:
A pesar de que las carpetas ya no son visibles, se están entregando bastantes datos sensibles (versión del servidor Web, distribución Linux y IP/Dominio del servidor. Para reducir al mínimo la visibilidad de estos datos, se abre nuevamente el archivo de configuración de Apache: nano /etc/httpd/conf/httpd.conf y se modifica estas dos lineas: ServerSignature On ServerTokens OS para que queden: ServerSignature Off ServerTokens PROD Se guardan los cambios y se reinicia el servidor Web. Otra forma de reiniciarlo es utilizando el comando service: service httpd restart visitando la misma pagina se notará el cambio:
Mucho mejor. Si cualquier persona pone la dirección Web de la pagina de administración de A2Billing puede ver la 330
pagina y intentar acceder al sistema. Para evitar que se pueda acceder directamente, se configura el servidor Web para que pida un usuario y una clave de acceso. Esto se realiza siguiendo el procedimiento que se describe. Se abre el archivo de configuración del servidor Web: nano +338 /etc/httpd/conf/httpd.conf y se modifica este parámetro (en la linea 338 del archivo): AllowOverride None para que quede: AllowOverride All de esta forma el servidor Web leerá, si presentes, los archivos .htaccess en las carpetas del servidor web. Se reinicia el servidor: service httpd restart Se entra en la carpeta de la pagina de administración de A2Billing: cd /var/www/html/admin/Public y se crea el archivo .htaccess: nano .htaccess copiando estas lineas: order allow,deny deny from all order allow,deny deny from all AuthUserFile /etc/httpd/htpasswd AuthName "Administration" AuthType Basic require valid-user En el primer bloque se niega el acceso a la carpeta a todos los usuarios. En el segundo bloque se niega 331
el acceso al archivo .htaccess a todos los usuarios. En las ultimas cuatro lineas se define que tendrán acceso a la pagina solamente los usuarios que podrán validarse con una contraseña. Se guardan los cambios y se crea un usuario con su respectiva contraseña. El comando que permite este tipo de operación es htpasswd: htpasswd -c /etc/httpd/htpasswd admin New password: Re-type new password: Adding password for user admin se teclea dos veces la contraseña para el usuario admin y de esta forma se habrá configurado el primer usuario. Ahora si se intenta acceder a la pagina de administración de A2Billing: http://IPservidor/admin aparecerá la ventana:
Se ponen los datos de usuario y contraseña y se presiona el botón Aceptar. Ya se puede acceder a la pagina de administración de A2Billing. De esta forma, los eventuales visitantes de la pagina no tendrán la menor idea de lo que hay detrás de la ventana de autorización. 7.2 Seguridad en OpenSIPs En OpenSIPs, a nivel de script, se han implementado toda una serie de controles para garantizar la integridad de las solicitudes SIP recibidas. Esto debería garantizar que solamente se procesen determinadas solicitudes SIP y se descarten las demás. Ahora, para aumentar la seguridad, se instalará Fail2ban. 7.2.1 Fail2Ban Se descarga:
332
cd /usr/src wget https://github.com/fail2ban/fail2ban/archive/0.8.14.tar.gz
se descomprime: tar -xf 0.8.14.tar.gz se entra en la carpeta creada: cd fail2ban-0.8.14 y se instala: python setup.py install Se activa el script para iniciarlo como servicio: cp /usr/src/fail2ban-0.8.14/files/redhat-initd /etc/init.d/fail2ban chkconfig --add fail2ban chkconfig fail2ban on En el archivo de configuración de OpenSIPs se pusieron dos lineas que envían al LOG de OpenSIPs una frase en el caso en que el usuario no pueda autenticar su REGISTER o no pueda autenticar su INVITE, más precisamente son: xlog("L_NOTICE","error de autent para $fU@$fd desde $si causa $var(autent_cod)"); xlog("L_NOTICE","error de autent para $fU@$fd desde $si causa $var(invite_cod)"); Con esas dos frases (que son iguales) se configura el archivo opensips para Fail2ban: cd /etc/fail2ban/filter.d nano opensips.conf se copian las siguientes lineas: [INCLUDES] # Read common prefixes. If any customizations available -- read them from # common.local #before = common.conf [Definition]
333
#_daemon = opensips # 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 "" can # be used for standard IP/hostname matching and is only an alias for # (?:::f{4,6}:)?(?P\S+) # Values: TEXT # failregex = error de autent para .* desde causa -[1-2] # Option: ignoreregex # Notes.: regex to ignore. If this regex matches, the line is ignored. # Values: TEXT # ignoreregex = La parte importante es la linea que inicia con failregex. Ahí con las expresiones regulare se captura en el LOG de OpenSIPs la frase que interesa. Se guardan los cambios y se termina modificando el archivo de configuración general de fail2ban: cd /etc/fail2ban nano jail.conf al final del archivo se añaden las lineas que siguen: [opensips-iptables] enabled = true filter = opensips action = iptables-allports[name=opensips, protocol=all] sendmail-whois[name=opensip, dest=root@localhost,
[email protected]]
logpath = /var/log/opensips.log maxretry = 3 bantime = 1800 En la línea logpath aparece el archivo de LOG que fail2ban leerá para localizar intentos frustrados de ataques a OpenSIPs. En lugar de root@localhost se pone la dirección de correo electrónico donde se quiere recibir las notificaciones. En sender, en lugar de
[email protected] se pone el dominio asociado a su servidor. Para enviar los correos, fail2ban está configurado con Sendmail. Con esta configuración cuando se verifiquen 3 ataques procedentes de la misma IP, Fail2ban bloqueará la IP insertando una nueva regla en la configuración de Iptables y mantendrá bloqueada la IP por 1800 segundos. Se guardan los cambios y se inicia fail2ban: 334
/etc/init.d/fail2ban start Iniciando fail2ban:
[ OK ]
Se averigua que no haya errores en el log de fail2ban: tail -f /var/log/fail2ban.log Para realizar una prueba se configura X-Lite con una extensión configurada en A2Billing usando una contraseña incorrecta. Después de 3 intentos de registros sin éxito, Fai2Ban bloqueará la IP de donde está intentando registrarse X-Lite y no habrá más acceso al VPS. Si se puede acceder desde otra IP, se escribe el comando: iptables -L -v Debe aparecer:
y se debe recibir un correo electrónico de notifica del bloqueo:
Ahora para desbloquear la IP, se reinicia iptables: service iptables restart 335
y luego fail2ban: service fail2ban restart 7.2.2 Bloquear IP por países Normalmente los clientes de una empresa que vende terminación SIP son casi siempre de una determinada aérea geográfica o, de todas formas, siempre habrán países donde no se vende trafico. En estos caso, para mejorar la seguridad de la PBX, es posible bloquear todas la IP de un determinado país y de esta forma evitar que se presenten ataques procedentes del país mismo. Este tipo de solución se apoya a una base de datos que contiene todas las IP del mundo, divididas por países, y Xtables-addons que contiene una serie de módulos adicionales para IPtables entre los cuales se encuentra él que permite interactuar con la base de datos. Los requerimientos para este tipo de instalación son: • • •
iptables >= 1.4.3 kernel-source >= 2.6.29 Perl
Primero se instalan algunos paquetes necesarios para la compilación de Xtables-addons: yum install xz iptables-devel zip unzip -y yum --enablerepo=epel install perl-Text-CSV_XS -y Luego se descargan las fuentes de Xtables-addons: cd /usr/src wget http://downloads.sourceforge.net/project/xtables-addons/Xtables-addons/1.47/xtables-addons-1.47.1.tar.xz
Se descomprime: tar -xf xtables-addons-1.47.1.tar.xz Se entra en la carpeta creada, se compila e instala: cd xtables-addons-1.47.1 ./configure --prefix=/usr --libdir=/usr/lib64 make si a lo largo del make aparece este error:
336
/usr/src/xtables-addons-1.47.1/extensions/compat_xtables.c: En la función 'xtnu_ipv6_find_hdr': /usr/src/xtables-addons-1.47.1/extensions/compat_xtables.c:633: error: faltan argumentos para la función 'ipv6_find_hdr' make[4]: *** [/usr/src/xtables-addons-1.47.1/extensions/compat_xtables.o] Error 1 make[3]: *** [_module_/usr/src/xtables-addons-1.47.1/extensions] Error 2 make[3]: se sale del directorio `/usr/src/kernels/2.6.32-431.11.2.el6.x86_64' make[2]: *** [modules] Error 2 make[2]: se sale del directorio `/usr/src/xtables-addons-1.47.1/extensions' make[1]: *** [all-recursive] Error 1 make[1]: se sale del directorio `/usr/src/xtables-addons-1.47.1' make: *** [all] Error 2 se corrige: nano /lib/modules/2.6.32-504.12.2.el6.x86_64/build/include/linux/autoconf.h se modifica esta linea: #define CONFIG_IP6_NF_IPTABLES_MODULE 1 para dejarla comentada: /* #define CONFIG_IP6_NF_IPTABLES_MODULE 1 */ Se guardan los cambios y se compila nuevamente: ./configure --prefix=/usr --libdir=/usr/lib64 make make install Se entra en la carpeta donde están presentes los script que permiten descargar la base de datos de GeoIP: cd geoip Se descarga la base de datos en formato CSV: ./xt_geoip_dl Desde la base de datos se crean los archivos de las IP por países: ./xt_geoip_build GeoIPCountryWhois.csv El resultado será la creación de dos carpetas que contienen las IP por países en el formato que IPtables puede leer. Se crea la carpeta predefinida donde IPtables buscará las IP: mkdir -p /usr/share/xt_geoip/ 337
y se copian las dos carpetas: cp -r {BE,LE} /usr/share/xt_geoip/ Para bloquear las direcciones IP de un determinado país en IPtables, la sintaxis es: -A INPUT -m geoip --src-cc CN -j DROP CN es la sigla del país (en este caso China) Se puede realizar una prueba bloqueando todas las IP de su proprio País (en este caso Colombia) para el puerto 5060. Se abre el archivo de configuración de IPtables: nano /etc/sysconfig/iptables antes de esta linea: -A INPUT -p udp -m udp --dport 5060 -j ACCEPT se pone: -A INPUT -p udp --dport 5060 -m geoip --src-cc CO -j DROP Se guardan las modificaciones y se reinicia Iptables y Fail2ban: service iptables restart service fail2ban restart Ahora se intenta conectarse a Asterisk con las credenciales de unos de los clientes configurados en A2Billing. El registro no funcionará y en IPtables se verá, en la linea que se acaba de crear, que todos los paquetes han sidos rechazados iptables -L -v
Si se quiere invertir la configuración, es decir aceptar conexiones solamente desde Colombia, la linea 338
cambiaría de: -A INPUT -p udp --dport 5060 -m geoip --src-cc CO -j DROP a -A INPUT -p udp --dport 5060 -m geoip --src-cc CO -j ACCEPT Claramente esto si los clientes y los proveedores VoIP son solamente de Colombia. En el caso que el proveedor VoIP sea de otro país (ejemplo Estados Unidos) habría que añadir otra linea después de la de Colombia: -A INPUT -p udp --dport 5060 -m geoip --src-cc US -j ACCEPT Si se quiere actualizar la lista de las IP de GeoIP de forma automática cada inicio mes se crea un script en bash: nano /usr/local/bin/geoip.sh se copian las siguientes lineas: #!/bin/bash /usr/src/xtables-addons-1.47.1/geoip/xt_geoip_dl /usr/src/xtables-addons-1.47.1/geoip/xt_geoip_build GeoIPCountryWhois.csv \cp -rf {BE,LE} /usr/share/xt_geoip/ /etc/init.d/iptables restart /etc/init.d/fail2ban restart Se guardan los cambios y se vuelve ejecutable el archivo creado: chmod +x /usr/local/bin/geoip.sh Se configura un cronjob para que ejecute el script cada primer día del mes: crontab -e al final del archivo se añaden las siguientes lineas: # GeoIP 0 0 1 * * /usr/local/bin/geoip.sh Se guardan los cambios. Si se quiere realizar una prueba para ver si todo funciona como esperado:
339
/usr/local/bin/geoip.sh 7.2.3 SIP OPTIONS Accediendo nuevamente al VPS y revisando el LOG del programa, veremos muchas lineas de este tipo: Solicitud recibida OPTIONS no es un INVITE Esto porque el servidor Asterisk donde está configurada la troncal hacia OpenSIPs, como tiene el parametro qualify=yes, alrededor de cada 30 segundos, enviará un paquete OPTIONS para averiguar si el servidor OpenSIPs está activo y alcanzable. Si se quiere evitar de llenar el LOG de mensajes de este tipo, cosa que vuelve más complicada la consulta de este archivo, se configura el modulo OPTIONS de OpenSIPs para que el Proxy acepte los OPTIONS que recibe. Se abre el archivo de configuración: oscfg y después de este bloque: #### PERMISSIONS module loadmodule "permissions.so" modparam("permissions", "db_url","mysql://opensips:opensipsrw@localhost/opensips") se añade: #### LOAD OPTIONS module loadmodule "options.so" En la configuración del script, antes de este bloque: # CANCEL processing if (is_method("CANCEL")) { if (t_check_trans()) t_relay(); xlog("L_NOTICE", "Recibido un CANCEL relacionado con una transacción valida");
exit; } Se añade: if ((method==OPTIONS) && (! uri=~"sip:.*[@]+.*")) { options_reply(); exit; 340
} De esta forma OpenSIPs contestará todos los mensajes SIP de tipo OPTIONS recibidos. Se guardan los cambios y se averigua que la configuración de esté correcta: opensips -c /etc/opensips/opensips.cfg Si así es, se reinicia OpenSIPS: service opensips restart Se inicia la captura de los paquetes SIP en el puerto 5060: ngrep -W byline port 5060 Aparecerán los paquete OPTIONS enviados desde Asterisk hacia OpenSIPs: U 107.170.186.192:5090 -> 50.116.23.240:5060 OPTIONS sip:sip1.voztovoice.eu SIP/2.0. Via: SIP/2.0/UDP 107.170.186.192:5090;branch=z9hG4bK67d1bbc7. Max-Forwards: 70. From: "asterisk" ;tag=as781962d1. To: . Contact: . Call-ID:
[email protected]:5090. CSeq: 102 OPTIONS. User-Agent: VozToVoice 2.0. Date: Wed, 25 Feb 2015 21:26:50 GMT. Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH, MESSAGE. Supported: replaces, timer. Content-Length: 0. Que OpenSIPs contestará: U 50.116.23.240:5060 -> 107.170.186.192:5090 SIP/2.0 200 OK. Via: SIP/2.0/UDP 107.170.186.192:5090;received=107.170.186.192;rport=5090;branch=z9hG4bK67d1bbc7. From: "asterisk" ;tag=as781962d1. To: ;tag=e88370f58093333468932cf5ec0aa990.8ddb. Call-ID:
[email protected]:5090. CSeq: 102 OPTIONS. Accept: */*. Accept-Encoding: . Accept-Language: en. Supported: . 341
Server: VozToVoice Proxy Server2. Content-Length: 0. Con esto termina la aparte dedicada a la seguridad del servidor.
342
Capitulo VIII Monitoreo del sistema Monitorear el sistema es una parte muy importante de la configuración de A2Billing. Es necesario conocer si las troncales están activas, si las llamadas se completan y si el sistema está padeciendo algún tipo de mal funcionamiento. Si se ha testado el sistema y se sabe que puede soportar, por ejemplo, 40 llamadas simultaneas, es importante conocer en cada momento cuantas son las llamadas que efectivamente el sistema está cursando. En esta parte se verá como monitorear algunos parámetros del sistema a través de algunas funcionalidades presentes en A2BIlling. 8.1 Monitoreo desde A2Billing El pagina de administración de A2Billing tenemos dos sistemas de monitoreo: • •
uno para la calidad de las llamadas uno para el sistema en general
8.1.1 Monitoreo calidad llamadas En la pagina de administración de A2Billing, se entra en el menú MAINTENANCE → Alarms. Una pequeña premisa: en este menú es posible configurar tres tipos de alarmas: 1. Alarma basada en el ALOC (average length of call). El ALOC permite monitorear la duración media de las llamadas y si este valor es más alto o más bajo del umbral definido, el sistema enviará un correo electrónico de notificación a la dirección configurada; 2. Alarma basada en el ASR (answer seize ratio). El ASR mide la relación entre las llamadas realizadas y las llamadas atendidas. Si este valor es muy bajo significa que la calidad de la ruta no es buena, si este valor es alto significa que casi todas las llamadas realizadas han sido atendidas. 3. Alarma basada en el CIC (Consecutive Incomplete Calls). Se las llamadas consecutivas que no se completan superan el numero indicado, se activará el alarma y puede ser la síntoma que algo con nuestro proveedor no está funcionando. Una vez en la pagina del menú se selecciona Add Alarm y se configura la primera alarma basada en el ALOC:
El alarma queda así configurada: NAME: nombre del alarma PERIOD: cada cuanto ejecutar el control (cada hora) TYPE: el tipo de alarma. En este caso ALOC MAX VALUE: valor máximo. En este caso si el promedio de duración de las llamadas es mayor a 3600 segundos (una hora) el alarma se activará MIN VALUE: valor mínimo. 60 segundos TRUNK: si no se especifica una troncal, el alarma quedará activada para todas las troncales configuradas en A2Billing STATUS: indica si el alarma está activada o no EMAIL TO SEND ALARM: una dirección de correo electrónico donde enviar el mensaje de alarma Se guardan los cambios con el botón Confirm Data y se crean dos alarmas más, una para el ASR:
345
y una para el CIC:
El resultado final será:
346
Presionando el botón VIEW DETAILS de cada alarma se abrirá una nueva ventana con todas las estadísticas relacionadas con el alarma misma. Claramente la configuración se puede personalizar según las troncales. Una cosa que hay que tener en cuenta es que el trafico generado por Call Center es basado en muchas llamadas cuya mayoría son muy breves. Solamente un poco de practica puede ayudar a calibrar los distintos parámetros. 8.1.2 Monitoreo con script y un sistema de TTS (Text to Speech) El segundo tipo de monitoreo que se puede configurar en A2Billing está basado en script que se pueden crear y utilizar en el sistema. Cada script creado hay que copiarlo en la carpeta /var/lib/a2billing/script. Se copia el único script presente en el paquete de A2Billing: cp /usr/local/src/a2billing/addons/script/check_connectivity.sh /var/lib/a2billing/script/ Se modifica para adaptarlo al idioma español: nano /var/lib/a2billing/script/check_connectivity.sh y se modifican estás dos lineas: echo "down" echo "good" para que queden: echo "inactiva" echo "activa" El AGI para monitorear el sistema (a2billing_monitoring.php) utiliza como sistema predefinido para el texto tu voz espeak. Para poderlo utilizar se instalan los paquetes relacionados: yum --enablerepo=epel install espeak espeak-devel -y y algunas dependencias:
347
yum install libsamplerate libsamplerate-devel libsndfile-devel libsndfile -y Luego se instala el modulo de espeak para Asterisk: cd /usr/src Se descarga:
git clone git://github.com/zaf/Asterisk-eSpeak Se entra en la carpeta creada: cd Asterisk-eSpeak Se compila y se instala: make make install make samples Se reinicia Asterisk: /etc/init.d/asterisk restart service a2b-callback-daemon restart y se averigua que el modulo esté cargado: asterisk -rvvvvvvvvvvv CLI> module show like app_espeak.so Module Description app_espeak.so eSpeak TTS Interface 1 modules loaded
Use Count 0
La sinopsis del comando CLI> core show application espeak -= Info about application 'eSpeak' =[Synopsis] Say text to the user, using eSpeak speech synthesizer. [Description] eSpeak(text[,intkeys,language]): This will invoke the eSpeak TTS engine, send a text string, get back the resulting waveform and play it to the user, allowing any given interrupt keys to immediately terminate 348
and return. [Syntax] Not available [Arguments] Not available [See Also] Not available Se sale de la consola de Asterisk: CLI> quit En la carpeta donde están los archivos de configuración de Asterisk se habrá creado un nuevo archivo: espeak.conf. La prueba se realiza con los valores predefinidos. Para probar la instalación, hay que crear algunas lineas en en el dialplan, contexto a2billing: nano /etc/asterisk/extensions.conf al final del contexto phones se añaden las siguientes lineas: exten => 660,1,Answer() same => n,espeak("Bienvenido en el centro de comunicaciones de VoztoVoice",any,es) same => n,Wait(2) same => n,Hangup Se guardan los cambios y se actualiza el dialplan: asterisk -rvvvvvvvv CLI> dialplan reload Desde el X-Lite configurado con una extensión presente en la configuración de A2Billing, se marca el numero 660 y se averigua que la instalación de espeak funcione. Si todo salió bien se puede pasar a la configuración de A2Billing. Se entra en la pagina de administración y luego en el menú MAINTENANCE → Monitoring. En esa pagina se encontrarán tres ejemplos para monitorear el sistema:
349
El primero es para probar la conexión a Internet. El segundo para conocer la fecha y hora exacta del servidor y el tercero para conocer el numero total de llamadas cursadas hasta el momento. Como los textos están en inglés hay que pasarlos al español. Se modifica la primera linea de la siguiente forma:
LABEL: el nombre que se quiere asignar. DIAL CODE: el numero que hay que digitar desde el IVR para utilizar este tipo de monitoreo. DESCRIPTION: una descripción TEXT INTRO: el texto en español que leerá eSpeak QUERY TYPE: El tipo de consulta (en este caso una consulta basada en uno script) QUERY / SHELL SCRIPT: el nombre del script que se utilizará SAY RESULT AS: come va anunciado el resultado (en este caso con el TTS eSpeak) ENABLE: yes = activo 350
Se presiona el botón “Confirm Data” y se procede con la segunda linea:
En este caso el numero que hay que digitar para activar el monitoreo es el 1 y el tipo de consulta es SQL (es decir en una base de datos). La QUERY es el comando que permite realizar la consulta especifica en la base de datos. El resultado se anunciará como UNIXTIME es decir la hora del sistema Linux. Se guardan los cambios y se pasa a la tercera linea:
351
Para utilizar se digita el numero 2, la consulta en la base de datos a2billing busca el numero total de llamadas cursadas por el sistema y lo anuncia como un numero. Se guardan los datos y se modifica el plan de llamadas para poder acceder al IVR de monitoreo de A2BIlling: nano /etc/asterisk/extensions.conf al final del contexto a2billing se añaden las siguientes lineas: exten => 670,1,NoOP same => n,Answer same => n,Agi(a2billing_monitoring.php) same => n,Hangup Se guardan los cambios y se recarga el dialplan: asterisk -rvvvvvvvvvvvvv CLI> dialplan reload Ahora desde el X-Lite conectado se marca el numero 670 y cuando el sistema lo pide se marca el 1 más numeral, el 2 o el 3 más numeral. En el menú MAINTENANCE → Monitoring se puede añadir cualquier tipo de consulta. Otro menú que puede resultar muy útil es MAINTENANCE → Asterisk info. En este menú es posible monitorear el estado de Asterisk, los canales (llamadas) activos y un largo etcétera. Los comandos son enviados directamente a la AMI de Asterisk pero como algunos hacen referencia a versiones anteriores 352
de Asterisk, hay que modificar el siguiente archivo: nano +141 /var/www/html/admin/Public/A2B_asteriskinfo.php Se modifica la linea: if (ASTERISK_VERSION == '1_4'|| ASTERISK_VERSION == '1_6') { para que quede: if (ASTERISK_VERSION == '1_8'|| ASTERISK_VERSION == '1_11') { La misma operación se ejecuta en la linea 364 del archivo. Se guardan los cambios y se vuelve a la pagina de administración de A2Billing, menú MAINTENANCE → Asterisk Info → Summary:
Menú Channels:
353
Menú Peers:
8.2 Monitoreo con Nagios y SNMP En este segundo párrafo del capitulo se ilustrará como monitorear el servidor Linux y Asterisk con Nagios y el protocolo SNMP. De esta forma se podrá tener bajo control el funcionamiento del Servidor Linux, las troncales SIP, los canales SIP activos y recibir por correo o GoogleTalk notificaciones si acontece algún problema en el sistema. Se ilustrará también como guardar los datos de configuración de Nagios y todos los eventos/notificaciones en una base de datos MySQL utilizando NDOutils. Se terminará con la instalación y configuración de PNP4NAGIOS que añade gráficos a la plataforma de Nagios. Para iniciar, lo primero que hay que hacer, es configurar el protocolo SNMP en Asterisk. 8.2.1 Asterisk y SNMP Una definición del protocolo SNMP tomada de Wikipedia: “El Protocolo Simple de Administración de Red o SNMP es un protocolo de la capa de aplicación que facilita el intercambio de información de administración entre dispositivos de red. Es parte de la familia de protocolos TCP/IP. SNMP permite a los administradores supervisar el funcionamiento de la red, buscar y resolver sus problemas, y planear su crecimiento.” De hecho a través de este protocolo se monitorean servidores, router, switch y casi cualquier tipo de dispositivo conectado a la red (local o remota). Asterisk implementa el protocolo SNMP y es posible monitorear muchos parámetros de la PBX. Para empezar se averigua que el modulo res_snmp está instalado y cargado en Asterisk: asterisk -rvvvvvvvvvvvvvvv CLI> module show like snmp
354
Significa que el modulo está instalado. Se sale de la consola de Asterisk: CLI> quit Se configura el modulo: mv /etc/asterisk/res_snmp.conf /etc/asterisk/res_snmp.conf.old nano /etc/asterisk/res_snmp.conf Se añaden las siguientes lineas: [general] subagent = yes enabled = yes Se guardan los cambios y se copian 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 univoca un objeto que en el caso del protocolo SNMP representa un determinado parámetro del dispositivo que se quiere monitorear. Ejemplo: se puede conocer el numero de llamadas totales cursadas por la centralita desde su ultimo arranque. cd /usr/share/snmp/mibs wget http://www.voztovoice.org/tmp/asterisk-mib.txt wget http://www.voztovoice.org/tmp/digium-mib.txt Ahora se configura SNMP de modo que pueda 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 agentx agentXPerms 0660 0550 root root
355
com2sec local localhost public com2sec remote XXX.XXX.XXX.XXX public group asterisk v1 local group asterisk v2c local group NetWork v1 remote group NetWork v2c remote view all included .1 access asterisk "" any noauth exact all none none access NetWork "" any noauth exact all none none 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 realizar 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 efectuar (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 service a2b-callback-daemon restart se inicia snmp: /etc/init.d/snmpd start se vuelve el arranque automático: chkconfig snmpd on Para ver los resultados con una descripción de cada OID en lugar de su su versión numérica: export MIBS=all Ahora ya se puede realizar una consulta utilizando el OID raíz de Asterisk: snmpwalk -OT -c public -v 2c localhost .1.3.6.1.4.1.22736 De todas las lineas que aparecen, las que interesan son estas tres: ASTERISK-MIB::astChanTypeName.6 = STRING: SIP ASTERISK-MIB::astChanTypeName.7 = STRING: IAX2 ASTERISK-MIB::astChanTypeName.9 = STRING: DAHDI Se anotan los valores que aparecen en negrita y el tipo de canal asociado, es decir: 356
SIP 6 IAX2 7 DAHDI 9 IMPORTANTE: los tres valores pueden cambiar según el tipo de instalación y la configuración de Asterisk Se pasa a la instalación y configuración de Nagios. 8.2.2 Nagios Para la instalación de Nagios desde los paquetes pre compilados se activa el repositorio epel y se controlan los paquetes disponibles para Nagios: yum --enablerepo=epel search nagios Se instalan los siguientes paquetes (el programa, los plugins, una utilidad para guardar los registros de Nagios en una base de datos, unas librerías en Perl para utilizar el protocolo XMPP, una aplicación para el envío de los correo electrónicos desde Nagios utilizando una linea de comando): yum --enablerepo=epel install nagios nagios-plugins-all perl-Net-Jabber \ perl-IO-Socket-SSL ndoutils mailx ndoutils-mysql -y CentOS se hará cargo de instalar también todas las dependencias necesarias. Se creará el grupo y usuario nagios, unas carpetas donde se guardarán los registros y los archivo necesarios para que Nagios funcione, y un archivo para la integración con el servidor Web (apache). Una vez terminada la instalación, se empieza con la configuración de Nagios. El archivo principal donde se definen los parámetros para el programa es nagios.cfg y se encuentra en la carpeta /etc/nagios. Para la configuración inicial no hace falta realizar algún tipo de modifica. 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
357
En este archivo se cambian estas líneas: define contact{ contact_name nagiosadmin use generic-contact alias Nagios Admin email nagios@localhost } para que queden: define contact{ contact_name nagiosadmin use generic-contact alias Nagios Administrador email
[email protected] address1 fulano }
[email protected] es la dirección de correo electrónico donde Nagios enviará las notificaciones (personalizar). Address1 es el usuario GoogleTalk donde Nagios enviará las notificaciones vía mensaje instantáneo. Nagiosadmin es el nombre del administrador predefinido en Nagios. Cada vez que aparece una línea que empieza con “use”, hace referencia a un template definido en el archivo templates.cfg. Se guardan los cambios y se abre el archivo templates.cfg. En este archivo el bloque del genericcontact es: nano /etc/nagios/objects/templates.cfg define contact{ name generic-contact service_notification_period 24x7 host_notification_period 24x7 service_notification_options w,u,c,r,f,s host_notification_options d,u,r,f,s service_notification_commands notify-service-by-email,notify-service-jabber host_notification_commands notify-host-by-email,notify-host-jabber can_submit_commands 1 register 0 } En este bloque se añaden las dos partes en negrita. Esto para enviar las notificaciones también vía GoogleTalk. Hay una explicación de estos parámetros en la documentación oficial de Nagios 3.0 En el servidor hay servicios que no son críticos y que se pueden monitorear cada 5 minutos (el tiempo 358
predefinido en Nagios). Para Asterisk, a veces, estos cinco minutos pueden ser demasiados. Por eso al final del archivo se añade el siguiente bloque que define que para todos los servicios de Asterisk el control se efectuará cada minuto (se puede personalizar): define service{ name asterisk use generic-service max_check_attempts 4 normal_check_interval 1 retry_check_interval 1 register 0 } Ahora se modifica el tercer archivo (commands.cfg) donde se definen los comandos que luego se utilizarán para la configuración del monitoreo del servidor local. Los plugins de Nagios se instalan en /usr/lib64/nagios/plugins. Para monitorear Asterisk, se usará el plugin check_snmp y otro que se descargará. Para monitorear las troncales, se descargará un plugin del repositorio de Nagios y por ultimo, para enviar las notificaciones via GoogleTalk se descargará otro plugin. Se entra en la carpeta /usr/lib64/nagios/plugins y se descargan los plugins que hacen falta: cd /usr/lib64/nagios/plugins wget http://www.voztovoice.org/campus/a2b/check_asterisk_peers wget http://www.voztovoice.org/campus/a2b/notify_via_jabber.pl wget http://www.voztovoice.org/campus/a2b/check_asterisk.pl Se cambian los permisos para que se pueda ejecutar: chmod +x check_asterisk_peers chmod +x notify_via_jabber.pl chmod +x check_asterisk.pl Notify_via_jabber.pl es el único que tiene que ser modificado. Se abre: nano notify_via_jabber.pl se modifican estas dos lineas: my $username = "usuarioGoogleTalk"; my $password = "password"; para que queden: my $username = "sutano"; my $password = "password";
359
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 modifica el archivo commands.cfg nano /etc/nagios/objects/commands.cfg Primero se configura el comando para enviar las notificaciones vía mensaje instantáneo. Esto se realiza para los servidores (en este caso uno) y los servicios. Después del bloque notify-service-by-email se añade: # 'host-notify-by-jabber' command definition define command{ command_name notify-host-jabber command_line /usr/lib64/nagios/plugins/notify_via_jabber.pl $CONTACTADDRESS1$ "Host '$HOSTALIAS$' is $HOSTSTATE$ - Info: $HOSTOUTPUT$" } # 'service-notify-by-jabber' command definition define command { command_name notify-service-jabber command_line /usr/lib64/nagios/plugins/notify_via_jabber.pl $CONTACTADDRESS1$ "$NOTIFICATIONTYPE$ $HOSTNAME$ $SERVICEDESC$ $SERVICESTATE$ $SERVICEOUTPUT$ $LONGDATETIME$" } IMPORTANTE: todo lo que aparece en la linea command-line debe estar en el mismo renglón Se continua con el plugin check_snmp para monitorear Asterisk a través del protocolo SMNP. Se buscan estas lineas: # 'check_snmp' command definition define command{ command_name check_snmp command_line $USER1$/check_snmp -H $HOSTADDRESS$ $ARG1$ 360
} y se modifican para que queden: # 'check_snmp' command definition define command{ command_name check_snmp command_line $USER1$/check_snmp -H $HOSTADDRESS$ -C public -o $ARG1$ -P 2c -l $ARG2$ -w $ARG3$ -c $ARG4$
} Command name: nombre del comando Command line: los parámetros que se pasarán al comando: • La macro (variable) $USER1$ contiene el valor /usr/lib64/nagios/plugins como especificado en el archivo /etc/nagios/resource.cfg • check_snmp – Nombre del plugin • -H $HOSTADDRESS$ – la opción -H define el servidor que se va a consultar y $HOSTADDRESS$ es una macro (variable) predefinida que contiene el nombre del servidor como se definirá luego en localhost.cfg • -C public – es la comunidad que se va a utilizar para la conexión al agente como definido en el archivo /etc/snmp/snmp.conf • -o – la OID que se consultará • -P 2c – versión de SNMP utilizada para la consulta • -l la etiqueta que luego se definirá • -w – está por Warning • -c – está por Critical • $ARG1$ $ARG2$ $ARG3$ ARG4$ son las macros (variables) cuyo valor será asignado desde la configuración de localhost.cfg Al verificarse el evento Warning y/o Critical, Nagios enviará una notificación por correo electrónico y vía mensaje instantáneo. El segundo plugin se define de la siguiente forma (añadir las lineas después del bloque anterior): define command{ command_name check_asterisk command_line $USER1$/check_asterisk.pl -h $HOSTADDRESS$ -m mgr -u nagios -p sesamo
} nagios y sesamo indican respectivamente el usuario y la contraseña para conectarse a la AMI de Asterisk. Para definirlos, luego hay que modificar el manager.conf de Asterisk: El ultimo plugin que se define en el archivo command.cfg, es el que permite monitorear las troncales: define command{ command_name check_voztovoice 361
command_line sudo /usr/lib64/nagios/plugins/check_asterisk_peers -t sip -p $ARG1$ } Para terminar como el protocolo SSH se utiliza sobre el puerto 15000, hay que cambiar este bloque: # 'check_ssh' command definition define command{ command_name check_ssh command_line $USER1$/check_ssh $ARG1$ $HOSTADDRESS$ } para que quede: # 'check_ssh' command definition define command{ command_name check_ssh command_line $USER1$/check_ssh -p $ARG1$ $HOSTADDRESS$ } Se guardan los cambios. El plugin check_asterisk_peers 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. Se modifica el archivo sudousers con el comando: visudo primero se modifica esta linea: Defaults
requiretty
para que quede: # Defaults
requiretty
luego al final del archivo se añade: nagios ALL=(ALL) NOPASSWD: /usr/lib64/nagios/plugins/check_asterisk_peers Se guardan los cambios. Como se había dicho el plugin check_asterisk.pl funciona conectándose a la AMI de Asterisk. Para que funcione hay que modifica el archivo manager.conf de Asterisk: nano /etc/asterisk/manager.conf 362
Al final del archivo se añade: [nagios] secret = sesamo deny=0.0.0.0/0.0.0.0 permit=127.0.0.1/255.255.255.255 read = system,call,log,verbose,agent,user,config,dtmf,reporting,cdr,dialplan write = system,call,agent,user,config,command,reporting,originate Se guardan los cambios y se 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: mv /etc/nagios/objects/localhost.cfg /etc/nagios/objects/localhost.cfg.old se crea uno nuevo: nano /etc/nagios/objects/localhost.cfg Se añaden las siguientes lineas: define host{ use linux-server host_name LibroA2BSIP alias A2Billing address 127.0.0.1 } define service{ use asterisk host_name LibroA2BSIP service_description SIP check_command check_snmp!ASTERISK-MIB::astChanTypeChannels.6!"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 LibroA2BSIP service_description IAX2 check_command check_snmp!ASTERISK-MIB::astChanTypeChannels.7!"Canales IAX2 Activos"!4!8
} 363
define service{ use asterisk host_name LibroA2BSIP service_description DAHDI check_command check_snmp!ASTERISK-MIB::astChanTypeChannels.9!"Canales DAHDI Activos"!4!8
} define service{ use asterisk host_name LibroA2BSIP service_description Asterisk_check check_command check_asterisk } define service{ use asterisk host_name LibroA2BSIP service_description Troncal_Voztovoice1 check_command check_voztovoice!voztovoice1 } define service{ use asterisk host_name LibroA2BSIP service_description Troncal_Voztovoice2 check_command check_voztovoice!voztovoice2 } 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 vía SNMP como se ha 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. Los últimos dos bloques se utilizan para monitorear las dos troncales SIP de Asterisk. 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…), 364
se añaden estas líneas: define service{ use local-service host_name LibroA2BSIP service_description PING check_command check_ping!100.0,20%!500.0,60% } define service{ use local-service host_name LibroA2BSIP service_description Current Users check_command check_local_users!20!50 } define service{ use local-service host_name LibroA2BSIP service_description Total Processes check_command check_local_procs!250!400!RSZDT } define service{ use local-service host_name LibroA2BSIP service_description Current Load check_command check_local_load!5.0,4.0,3.0!10.0,6.0,4.0 } define service{ use local-service host_name LibroA2BSIP service_description SSH check_command check_ssh!15000 } Se guardan los cambios. Antes de iniciar Nagios hay una forma para controlar que todos los archivos de configuración estén exentes de errores: nagios -v /etc/nagios/nagios.cfg Si la respuesta termina con: Total Warnings: 0 365
Total Errors: 0 Things look okay - No serious problems were detected during the pre-flight check Significa que la configuración está bien. En caso contrario Nagios indicará el archivo y la línea donde se encuentra el error. El acceso a la pagina de Nagios está protegido y para poder acceder hay que configurar la contraseña del usuario predefinido, nagiosadmin, de la siguiente forma: htpasswd -bc /etc/nagios/passwd nagiosadmin sesamo Adding password for user nagiosadmin Este comando creará una archivo passwd que contendrá los datos de acceso para el usuario predefinido nagiosadmin (en este caso la contraseña es sesamo) Se configura Nagios para que arranque en automático: chkconfig nagios on Se reinicia apache y luego se inicia Nagios: /etc/init.d/httpd restart /etc/init.d/nagios start Para entrar en la pagina de Nagios: http://IPLinode/nagios Aparecerá una ventana donde habrá que insertar las credenciales de acceso es decir usuario: nagiosadmin y contraseña: sesamo
Se presiona el botón Aceptar. Aparece la pagina inicial de Nagios:
366
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. Una prueba. Se entra en el sip.conf y se modifica el dominio de la troncal voztovoice1: nano /etc/asterisk/sip.conf en lugar de sip.voztovoice.eu se pone voip.voztovoice.eu Se guardan los cambios y se recarga la configuración SIP: 367
asterisk -rvvvvvvvvvvvvvvv CLI> sip reload CLI> sip show peers
La conexión con la troncal no está activa. En la pagina de Nagios (después de unos minutos):
El mensaje instantáneo recibido:
y el correo electrónico:
368
Ahora se restablece la IP correcta y se averigua lo que pasa en la pagina de Nagios:
Se recibirá un nuevo mensaje instantaneo:
y un nuevo correo electrónico:
Todo ha vuelto a la normalidad. 8.2.3 NDOutils Para utilizar NDOutils y 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; 369
se asigna al usuario nagios los permisos para la base de datos creada: mysql> GRANT ALL PRIVILEGES ON nagios.* TO 'nagios'@'localhost' IDENTIFIED BY 'sesamo'; mysql> flush privileges; mysql> quit Se crean las tablas en la base de datos nagios desde un archivo instalado con el paquete NDOutils: mysql -u root -psesamo nagios < /usr/share/doc/ndoutils-mysql-1.5.2/db/mysql.sql Ahora falta modificar dos archivos de configuración: nagios.cfg y ndo2db.cfg. Primero se modifica nagios.cfg nano /etc/nagios/nagios.cfg al final del archivo se añaden las siguientes lineas: event_broker_options=-1 broker_module=/usr/lib64/nagios/brokers/ndomod.so config_file=/etc/nagios/ndomod.cfg que permiten a Nagios de conectarse a la librería de NDOutils para enviar todos los datos de configuración y los eventos. Se guardan los cambios y se continua con el ndo2db.cfg: nano /etc/nagios/ndo2db.cfg Después de estas dos lineas: ndo2db_user=nagios ndo2db_group=nagios se añade: lock_file=/var/log/nagios/ndo2db.lock en db_user y db_password se pone: db_user=nagios db_pass=sesamo se guardan los cambios y se inicia NDOutils:
370
/etc/init.d/ndo2db start Se configura para que arranque en automático: chkconfig ndo2db on y se reinicia Nagios: /etc/init.d/nagios restart se averigua que en el log de Nagios haya conexión con la librería NDOutils: nano /var/log/nagios/nagios.log Las lineas que interesan son:
Después de unos minutos, se puede corroborar que efectivamente los datos de Nagios se están guardando en la base de datos creada: mysql -u root -psesamo mysql> use nagios mysq> select command_id,instance_id,config_type,object_id from nagios_commands;
371
Todo está funcionando como debería. Se encuentran distintos tipos de consultas de las tablas en la carpeta /usr/share/doc/ndoutils-mysql-1.5.2/db/queries/ 7.2.4 PNP4NAGIOS Seguramente Nagios es un optimo programa para el monitoreo de servidores, switch y dispositivos, pero le hace falta algo que la mayoría de los programas de monitoreo tienen: los gráficos. Pasa suplir esta falta existe el programa PNP4Nagios. En este párrafo se verá como instalarlo y complementarlo con Nagios. Requisitos previos: • • • •
Perl >= 5.x y los paquetes perl-Time-HiRes rrdtool-perl RRDtool >= 1.x, mejor 1.2 pero no obligatorio PHP >= 5.1.6 para el frontal web basado en Kohana Nagios >= 2.x o Icinga
Kohana necesita que el módulo de Apache “mod_rewrite” esté habilitado. Se instala el paquete perl-Time-HiRes: yum install perl-Time-HiRes rrdtool-perl perl-ExtUtils-MakeMaker -y RRDtool se instala desde las fuentes: cd /usr/src 372
wget http://oss.oetiker.ch/rrdtool/pub/rrdtool-1.4.9.tar.gz tar -xf rrdtool-1.4.9.tar.gz cd rrdtool-1.4.9 ./configure --prefix=/usr --libdir=/usr/llib64 make make install Terminada la instalación de RRDTool ya se puede instalar PNP4Nagios: cd /usr/src wget http://downloads.sourceforge.net/project/pnp4nagios/PNP-0.6/pnp4nagios-0.6.25.tar.gz tar -xf pnp4nagios-0.6.25.tar.gz cd pnp4nagios-0.6.25 ./configure Aparecerá:
PNP4Nagios detectará de forma automática RRDTool y estará listo para la instalación. Se continua con: make all make fullinstall Terminada la instalación los pasos a seguir son: • 373
Modificar el templates.cfg de Nagios
• • • • •
Modificar el commands.cfg de Nagios Modificar la configuración general de Nagios Modificar la configuración del servidor localhost y los servicios monitoreados Reiniciar Nagios Reiniciar el Servidor Web
Se inicia modificando el archivo templates.cfg: nano /etc/nagios/objects/templates.cfg al final del archivo se añade: define host { name host-pnp action_url /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=_HOST_ register 0 } define service { name srv-pnp action_url /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=$SERVICEDESC$ register 0 } Se guardan los cambios y se continua con el archivo commands.cfg nano /etc/nagios/objects/commands.cfg Después de este bloque de comentario: ################################################################################ # # SAMPLE PERFORMANCE DATA COMMANDS # # These are sample performance data commands that can be used to send performance # data output to two text files (one for hosts, another for services). If you # plan on simply writing performance data out to a file, consider using the # host_perfdata_file and service_perfdata_file options in the main config file. ################################################################################# se borran los dos bloques que siguen y se sustituyen con los siguientes: define command { command_name process-service-perfdata command_line /usr/bin/perl /usr/local/pnp4nagios/libexec/process_perfdata.pl }
374
define command { command_name process-host-perfdata command_line /usr/bin/perl /usr/local/pnp4nagios/libexec/process_perfdata.pl -d HOSTPERFDATA
} Estos dos comandos son los que se encargan de recolectar los datos para luego crear los gráficos. Se guardan los cambios y se pasa al archivo nagios.cfg: nano /etc/nagios/nagios.cfg Se buscan estas lineas: process_performance_data=0 #host_perfdata_command=process-host-perfdata #service_perfdata_command=process-service-perfdata y se modifican para que queden: process_performance_data=1 host_perfdata_command=process-host-perfdata service_perfdata_command=process-service-perfdata Al final del archivo se añade la siguiente linea: broker_module=/usr/local/pnp4nagios/lib/npcdmod.o config_file=/usr/local/pnp4nagios/etc/npcd.cfg Se guardan los cambios. El modulo npcdmod.o es el que se encarga de pasar los datos de Nagios a PNP4NAGIOS; para activar el servicio: chkconfig --add npcd chkconfig npcd on Se inicia: /etc/init.d/npcd start Para activar PNP4NAGIOS para cada host, servicio monitoreado, se abre el archivo localhost.cfg: nano /etc/nagios/objects/localhost.cfg se modifica el primer bloque: define host{ use linux-server host_name LibroA2BSIP 375
alias A2Billing address 127.0.0.1 } para que quede: define host{ use linux-server,host-pnp host_name LibroA2BSIP alias A2Billing address 127.0.0.1 } Para todos los demás bloques al final de la linea use se añade una coma y srv-pnp. Ejemplo: define service{ use asterisk,srv-pnp host_name LibroA2BSIP service_description SIP check_command check_snmp!ASTERISK-MIB::astChanTypeChannels.13!"Canales SIP Activos"! 8!16 } Una vez modificado todo el archivo, se guardan los cambios y se reinicia Nagios: service nagios restart Antes de reiniciar el servidor web, se modifica el archivo de configuración de PNP4NAGIOS para el servidor web: nano /etc/httpd/conf.d/pnp4nagios.conf Se cambia esta linea: AuthUserFile /usr/local/nagios/etc/htpasswd.users para que quede: AuthUserFile /etc/nagios/passwd Se guardan los cambios y se reinicia el servidor web: service httpd restart Si se vuelve a entrar en la pagina de administración de Nagios → Services:
376
A lado de cada servicio aparecerá un icono de un gráfico. Si se presiona el icono de la linea PING se abrirá otra pestaña en el navegador donde PNP4NAGIOS averiguará que la configuración esté sin errores. Si todo está bien, al final de la pagina aparecerá:
Como indicado se borra el archivo: rm /usr/local/pnp4nagios/share/install.php Se recarga la pagina:
Se verá el gráfico (después de algunos minutos) del servicio PING. Si se quiere personalizar la configuración de PNP4Nagios hay que modificar el siguiente archivo: 377
nano /usr/local/pnp4nagios/etc/config.php 8.3 Monitoreo OpenSIPs Para el monitoreo de OpesSIPs se pueden adoptar distintas soluciones; el mismo protocolo SNMP que se ha visto para Asterisk, el panel de control de OpenSIPs y, como se verá a continuación, MONIT. Primero una dependencia: yum install pam-devel -y Luego se descarga la ultima versión disponible: cd /usr/src wget http://mmonit.com/monit/dist/monit-5.12.tar.gz se descomprime: tar -xf monit-5.12.tar.gz cd monit-5.12 Se compila y se instala: ./configure --prefix=/usr --libdir=/usr/lib64 make make install Se termina la instalación con la copia y activación del script de inicio de monit: cd system/startup/ cp rc.monit /etc/init.d/monit chmod +x /etc/init.d/monit chkconfig --add monit chkconfig monit on Ahora se modifica el archivo de configuración para monitorear los siguientes programas: • 378
Servidor Linux
• • •
MySQL Asterisk OpenSIPs
El archivo de configuración de Monit se divide en tres bloques: • • •
Global Section; aquí se pone la configuración general del programa Services; donde se configuran los servicios Includes: permite incluir a la configuración de Monit otros archivo que contienen a su vez la configuración de otros procesos.
nano /etc/monitrc set daemon 60 # Indica cada cuantos segundos Monit controla los servicios (en este caso cada 60) with start delay 30 # Al iniciar el programa el primer ciclo de control se ejecutará después de 30 segundos set logfile /var/log/monit.log # Nombre del archivo donde se guardarán todos los registros de Monit set pidfile /var/run/monit.pid # Carpeta y nombre del del archivo del proceso de Monit cuando se inicia set idfile /var/.monit.id # Nombre de la carpeta y archivo donde se guardará el numero único del proceso de Monit set statefile /var/.monit.state # Carpeta y nombre del archivo donde Monit guardará el estado de cada ciclo de monitoreo set mailserver localhost # nombre del host del servidor de correo electrónico que Monit utilizará para enviar las alertas set eventqueue basedir /var/monit slots 100 # Si por alguna razón el servidor de correo electrónico no esté funcionando se puede indicar a Monit de # guardar todas las alerta en una determinada carpeta. Cuando el servidor vuelva a funcionar, todas las # alertas serán enviadas siguiendo el orden cronológico en que se guardaron set mail-format { From:
[email protected] Subject: monit alerta -- $EVENT $SERVICE Message: $EVENT Servicio $SERVICE Fecha: $DATE Accion: $ACTION Host: $HOST 379
Descripcion: $DESCRIPTION Tu devoto empleado, Monit } # Con el bloque de arriba, se define como tiene que ser enviado el correo electrónico de alerta # Personalizar el parámetro from con el nombre de su dominio set alert
[email protected] # Con esta línea se define el correo electrónico que recibirá todas las alertas (personalizar) set httpd port 2812 allow admin:sesamo # Monit viene con un servidor Web embebido. En las dos lineas de arriba se activa en el puerto 2812 # (que hay que abrir en el cortafuegos) y se define nombre de usuario y contraseña para ingresar a la # pagina # Monitoreo Servidor Linux check system cursoA2BSIP if loadavg (1min) > 4 then alert if loadavg (5min) > 2 then alert if memory usage > 75% then alert if cpu usage (user) > 70% then alert if cpu usage (system) > 30% then alert if cpu usage (wait) > 20% then alert # Monitoreo Asterisk check process asterisk with pidfile /var/run/asterisk/asterisk.pid start program = "/etc/init.d/asterisk start" with timeout 60 seconds stop program = "/etc/init.d/asterisk stop" with timeout 60 seconds if failed host 127.0.0.1 port 5038 then restart if 5 restarts within 5 cycles then timeout # Monitoreo MySQL check process mysql with pidfile /var/run/mysqld/mysqld.pid group database start program = "/etc/init.d/mysqld start" stop program = "/etc/init.d/mysqld stop" if failed port 3306 protocol mysql then restart if 5 restarts within 5 cycles then timeout # Monitoreo OpenSIPs check process opensips with pidfile /var/run/opensips.pid start program = "/etc/init.d/opensips start" stop program = "/etc/init.d/opensips stop" if 5 restarts within 5 cycles then timeout
380
Personalizar estás dos lineas: • •
From:
[email protected] – Poner el nombre de dominio del servidores set alert
[email protected] – Poner una dirección de correo electrónico personalizada
Una explicación. Monit averiguará cada 60 segundos que los tres servicios estén corriendo. Si por alguna razón unos de los servicios se cae, Monit intentará iniciarlo nuevamente por 5 veces. Si no lo lograra, dejará de monitorear el servicio. Se guardan los cambios y se cambian los permisos del archivo de configuración: chmod 700 /etc/monitrc Se inicia Monit: /etc/init.d/monit start En el cortafuegos, hay que abrir el puerto 2812 TCP para tener acceso al servidor Web interno de Monit: nano /etc/sysconfig/iptables Después de esta linea: -A INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT se añade: # Monit -A INPUT -p tcp -m state --state NEW -m tcp --dport 2812 -j ACCEPT Se guardan los cambios y se reinicia iptables y fail2ban: service iptables restart service fail2ban restart Después de unos minutos se puede acceder a la pagina de administración de Monit: http://IPservidor:2812 aparecerá:
381
Nombre de usuario: admin Contraseña: sesamo Veremos:
Más en detalle los tres procesos monitoreados:
En el caso de OpenSIPs:
382
Si se para OpenSIPs: service opensips stop Después de unos segundos:
Correo recibido: Cuando Monit intenta reiniciar el servicio, si lo logra:
383
El nuevo correo:
8.4 Monitoreo calidad de las llamadas con pre-dial handlers y hangup-handlers Con la versión 11 de Asterisk se ha introducido una funcionalidad que permite ejecutar una subrutina antes que la llamada empiece pero después que los dos canales, llamante y llamado, se han credo. Esta funcionalidad se llama pre-dial handlers. En la subrutina se puede indicar otra subrutina que se ejecutará cuando la llamada termine; esta subrutina, también introducida con la versión 11 de Asterisk, se llama hangup-handlers. Aprovechando estas dos funcionalidades es posible, con un mínimo de 384
configuración, guardar en una tabla de una base de datos, todas las estadísticas de una llamada. Para empezar hay que crear los pre-dial handlers que se utilizarán solamente para las llamadas salientes. La sintaxis para el canal del llamante es: B([[context^]exten^]priority[(arg1[^...][^argN])]) para el canal de llamado es: b([[context^]exten^]priority[(arg1[^...][^argN])]) Las dos subrutinas van configuradas en la linea del Dial. Se entra en la pagina de administración de A2Billing, menú SYSTEM SETTINGS → Global List → agi-conf1 y se modifica este parámetro:
Para que quede:
es decir que se añade este bloque: B(predial^caller_handler^1)b(predial^callee_handler^1) Luego se modifica el dialplan: nano /etc/asterisk/extensions.conf Al final del archivo se crean el contexto y las dos extensiones que se acaban de configurar en A2Billing: [predial] exten => caller_handler,1,NoOp(Caller_Handler) same => n,Set(CHANNEL(hangup_handler_push)=caller,s,1); same => n,Return exten => callee_handler,1,NoOp(Callee_Handler) same => n,Set(CHANNEL(hangup_handler_push)=callee,s,1); same => n,Return En el bloque del llamante se indica que cuando termine la llamada se ejecutará la subrutina presente en el contexto caller, extensión s, prioridad 1. Para el llamado la subrutina será presente en el contexto 385
callee, extensión s, prioridad 1. El paso a seguir es crear las dos subrutinas (al final del archivo). Para el llamante: [caller] exten => s,1,NoOp(${CHANNEL(rtpqos,audio,all)}) same => n,set(hangupcause=${HANGUPCAUSE}) same => n,set(accountcode=${CDR(accountcode)}) same => n,set(peerip=${CHANNEL(peerip)}) same => n,set(recvip=${CHANNEL(recvip)}) same => n,set(useragent=${CHANNEL(useragent)}) same => n,set(codecr=${CHANNEL(audioreadformat)}) same => n,set(codecw=${CHANNEL(audiowriteformat)}) same => n,set(codecn=${CHANNEL(audionativeformat)}) same => n,set(tlp=${CHANNEL(rtpqos,audio,txcount)}) same => n,set(llp=${CHANNEL(rtpqos,audio,txploss)}) same => n,set(porlp=$[{CHANNEL(rtpqos,audio,txploss)} / ${CHANNEL(rtpqos,audio,txcount)} * 100])
same => n,set(trp=${CHANNEL(rtpqos,audio,rxcount)}) same => n,set(rlp=${CHANNEL(rtpqos,audio,rxploss)}) same => n,set(porrp=$[{CHANNEL(rtpqos,audio,rxploss)} / ${CHANNEL(rtpqos,audio,rxcount)} * 100])
same => n,set(ljitter=${CHANNEL(rtpqos,audio,local_maxjitter)}) same => n,set(rjitter=${CHANNEL(rtpqos,audio,remote_maxjitter)}) same => n,Set(ODBC_cdr2()=${STRFTIME(${EPOCH},,%y%m%d%H%M%S)},${hangupcause},$ {accountcode},${peerip},${recvip},${useragent},${codecr},${codecw},${codecn},${tlp},${llp},${porlp}, ${trp},${rlp},${porrp},${ljitter},${rjitter}) same => n,Return Para el llamado: [callee] exten => s,1,NoOp(${CHANNEL(rtpqos,audio,all)}) same => n,set(hangupcause=${HANGUPCAUSE}) same => n,set(accountcode=${CDR(accountcode)}) same => n,set(peerip=${CHANNEL(peerip)}) same => n,set(recvip=${CHANNEL(recvip)}) same => n,set(useragent=${CHANNEL(useragent)}) same => n,set(codecr=${CHANNEL(audioreadformat)}) same => n,set(codecw=${CHANNEL(audiowriteformat)}) same => n,set(codecn=${CHANNEL(audionativeformat)}) same => n,set(tlp=${CHANNEL(rtpqos,audio,txcount)}) same => n,set(llp=${CHANNEL(rtpqos,audio,txploss)}) same => n,set(porlp=$[{CHANNEL(rtpqos,audio,txploss)} / ${CHANNEL(rtpqos,audio,txcount)} * 100])
same => n,set(trp=${CHANNEL(rtpqos,audio,rxcount)}) same => n,set(rlp=${CHANNEL(rtpqos,audio,rxploss)}) same => n,set(porrp=$[{CHANNEL(rtpqos,audio,rxploss)} / ${CHANNEL(rtpqos,audio,rxcount)} * 100])
same => n,set(ljitter=${CHANNEL(rtpqos,audio,local_maxjitter)}) same => n,set(rjitter=${CHANNEL(rtpqos,audio,remote_maxjitter)}) 386
same => n,Set(ODBC_cdr2()=${STRFTIME(${EPOCH},,%y%m%d%H%M%S)},${hangupcause},$ {accountcode},${peerip},${recvip},${useragent},${codecr},${codecw},${codecn},${tlp},${llp},${porlp}, ${trp},${rlp},${porrp},${ljitter},${rjitter}) same => n,Return Los datos que se guardarán son (para cada canal): • • • • • • • • • • • • • • • •
Hangupcause: el código relacionado con el colgado de la llamada accountcode: la cuenta utilizada para realizar la llamada peerip: la dirección IP de donde se ha originado la llamada recvip: la dirección IP recibida por Asterisk para la llamada useragent: el dispositivo utilizado para realizar la llamada codecr: el codec audio “leído” por Asterisk sobre el canal codecw: el codec audio “escrito” por Asterisk sobre el canal codecn: el codec nativo utilizado por Asterisk para el canal tlp: el total de paquetes audio trasmitidos desde el dispositivo hacia Asterisk llp: el total de paquetes audio perdidos desde el dispositivo hacia Asterisk porlp: el porcentaje de paquetes audio perdidos desde el dispositivo hacia Asterisk trp: el total de paquetes audio trasmitidos desde Asterisk hacia el dispositivo rlp: el total de paquetes audio perdidos desde Asterisk hacia el dispositivo porrp: el porcentaje de paquetes audio perdidos desde Asterisk hacia el dispositivo ljitter: el Jitter de la llamada desde el dispositivo hacia Asterisk rjitter: el Jitter de la llamada desde Asterisk hacia el dispositivo
Ahora todos los datos presentes en los dos hangup-handlers se guardan en una tabla de la base de datos asteriskcdr. Se entra en mysql: mysql -u root -psesamo se selecciona la base de datos asteriskcdr: mysql> use asteriskcdr y se crea la nueva tabla: mysql> CREATE TABLE `cdr2` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `calldate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `hangupcause` int(2) NOT NULL DEFAULT '0', `accountcode` varchar(20) DEFAULT NULL, `peerip` varchar(20) DEFAULT NULL, `recvip` varchar(20) DEFAULT NULL, `useragent` varchar(30) DEFAULT NULL, `codecr` varchar(10) DEFAULT NULL, `codecw` varchar(10) DEFAULT NULL, `codecn` varchar(10) DEFAULT NULL, `tlp` int(15) NOT NULL DEFAULT '0', 387
`llp` int(15) NOT NULL DEFAULT '0', `porlp` decimal(6,3) unsigned zerofill NOT NULL DEFAULT '000.000', `trp` int(15) NOT NULL DEFAULT '0', `rlp` int(15) NOT NULL DEFAULT '0', `porrp` decimal(6,3) unsigned zerofill NOT NULL DEFAULT '000.000', `ljitter` decimal(7,6) unsigned zerofill NOT NULL DEFAULT '0.000000', `rjitter` decimal(7,6) unsigned zerofill NOT NULL DEFAULT '0.000000', PRIMARY KEY (`id`) ); mysql> quit Para que los datos se guarden en la tabla se recurre nuevamente al archivo func_odbc. Como no hay una conexión ODBC hacia la base de datos asteriskcdr, hay que crearla: nano /etc/odbc.ini [asteriskcdr] Description = MySQL asteriskcdr Driver = MySQL Database = asteriskcdr Server = localhost User = asterisk Password = sesamo Port = 3306 Option = 3 Se guardan los cambios y se prueba la conexión: isql asteriskcdr asterisk sesamo +---------------------------------------+ | Connected! | | | | sql-statement | | help [tablename] | | quit | | | +---------------------------------------+ SQL> Perfecto! Se sale del programa: SQL> quit 388
Luego para que func_odbc funcione, hay que crear un nuevo bloque en el archivo res_odbc.conf que es donde se conectará unc_odbc: nano /etc/asterisk/res_odbc.conf al final del archivo se pone: [cdr] enabled => yes dsn => asteriskcdr username => asterisk password => sesamo pre-connect => yes sanitysql => select 1 idlecheck => 3600 connect_timeout => 10 Se guardan los cambios y se configura func_odbc: nano /etc/asterisk/func_odbc.conf al final del archivo se añade: [cdr2] dsn=cdr writesql=insert into cdr2 (calldate,hangupcause,accountcode,peerip,recvip,useragent,codecr,codecw,codecn,tlp,llp,porlp,trp,rl p,porrp,ljitter,rjitter) values ("${SQL_ESC(${VAL1})}","${SQL_ESC(${VAL2})}","${SQL_ESC(${VAL3})}","${SQL_ESC($ {VAL4})}","${SQL_ESC(${VAL5})}","${SQL_ESC(${VAL6})}","${SQL_ESC(${VAL7})}", "${SQL_ESC(${VAL8})}","${SQL_ESC(${VAL9})}","${SQL_ESC(${VAL10})}","${SQL_ESC($ {VAL11})}","${SQL_ESC(${VAL12})}","${SQL_ESC(${VAL13})}","${SQL_ESC(${VAL14})}", "${SQL_ESC(${VAL15})}","${SQL_ESC(${VAL16})}","${SQL_ESC(${VAL17})}") Todos los datos presentes en la linea writesql tienen que estar en el mismo renglón. Se guardan las modificaciones y se entra en la consola de Asterisk: asterisk -rvvvvvvvvvvvvvvvvvvvv se recarga el modulo res_odbc y luego el modulo func_odbc CLI> module reload res_odbc.so CLI> module reload func_odbc.so se recarga el dialplan: 389
CLI> dialplan reload y se realiza una prueba llamando un numero fijo/celular. Una vez terminada la llamada se entra nuevamente en la consola de MySQL: mysql -u root -psesamo se selecciona la base de datos asteriskcdr: mysql> use asteriskcdr y se revisa que se ha guardado en la tabla cdr2: mysql> select id,calldate,hangupcause,accountcode,peerip,recvip,tlp,llp,porlp,trp,rlp,porrp from cdr2;
8.5 Monitoreo calidad de las llamadas con VoIPMonitor VoIPmonitor es un programa que permite guardar todos los datos relacionados con la calidad de las llamadas en una base de datos. De este programa existen dos versiones: una Open Source sin la GUI (Interfaz gráfica); una comercial que incluye la GUI que es la que permite ver todas las estadísticas desde un navegador 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: • • • • • • 390
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: • •
Versión de Libpcap >= 1.0 Librería MySQL++
Primero se instalan los paquetes de libpcap: yum install libpcap libpcap-devel -y Luego se averigua la versión instalada: rpm -q libpcap libpcap-1.4.0-1.20130826git2dbcaa1.el6.x86_64 Se instalan algunas dependencias: yum --enablerepo=epel install snappy* libssh-devel json-c-devel -y Instalados los pre requisitos se decarga VoIPMonitor ya compilado. cd /usr/src wget http://downloads.sourceforge.net/project/voipmonitor/10.0/voipmonitor-amd64-10.0.35-static.tar.gz
Se descomprime: tar -xf voipmonitor-amd64-10.0.35-static.tar.gz Se entra en la carpeta creada: cd voipmonitor-amd64-10.0.35-static Se ejecuta el script de instalación: ./install-script.sh Se crea la base de datos donde se guardarán los datos de las llamadas: mysql -u root -psesamo 391
mysql> create database voipmonitor; mysql> quit Se modifica el archivo de configuración: nano /etc/voipmonitor.conf Se modifican las siguientes lineas: #id_sensor = 1 mysqlhost = 127.0.0.1 mysqlport = 3306 mysqlusername = root mysqlpassword = #interface = eth0,eth1 #sipport = 5061 #jitterbuffer_f1 = no #jitterbuffer_f2 = yes #jitterbuffer_adapt = no para que queden: id_sensor = 1 mysqlhost = 127.0.0.1 mysqlport = 3306 mysqlusername = root mysqlpassword = sesamo interface = eth0,eth0:1 sipport = 5061 jitterbuffer_f1 = yes jitterbuffer_f2 = yes jitterbuffer_adapt = yes Se guardan las modificaciones y se inicia el servicio: service voipmonitor start Starting voipmonitor: voipmonitor version 10.0.35 Loading configuration from file /etc/voipmonitor.conf OK SQL DRIVER: mysql voipmonitor[31391]: connect - db version 5.1 voipmonitor[31391]: mysql use voipmonitor mysql> select ID,calldate,called,duration,connect_duration,a_received,b_received,a_lost,b_lost from cdr;
8.6 CDR-STATS El programa CDR-STATS permite analizar todas las entradas presentes en la tabla CDR (Call Detail Records), que se ha creado en el párrafo 2.4 de este libro, y con los datos presentes crear reportes más detallados de los de A2Billing. Implementa también un sistema de análisis de las llamadas que permite crear alarmas con relativas notificaciones en el caso el sistema detecte trafico anómalo hacia determinatos destinos. La instalación se basa en un script que se encarga de instalar todos los paquetes y dependencias necesarias para la instalación y configuración del programa. Para empezar, se descarga el archivo: cd /usr/src wget --no-check-certificate https://raw.github.com/Star2Billing/cdr-stats/master/install/installcdr-stats-asterisk.sh -O install-cdr-stats-asterisk.sh Se vuelve ejecutable: chmod +x install-cdr-stats-asterisk.sh y se inicia: ./install-cdr-stats-asterisk.sh
393
Se presiona la tecla Enter/Envío. Aparecerá: This script is only intended to run on Ubuntu LTS 10.04 / 12.04 or CentOS 6.X Como CentOS 6.6 no está incluido, primero de modifica: nano install-cdr-stats-asterisk.sh Cambiando estás dos lineas: wget --no-check-certificate https://raw.github.com/Star2Billing/cdr-stats/$BRANCH/install/bashcommon-functions.sh -O bash-common-functions.sh wget --no-check-certificate https://raw.github.com/Star2Billing/cdr-stats/$BRANCH/install/cdrstats-functions.sh -O cdr-stats-functions.sh Para que queden (comentadas): # wget --no-check-certificate https://raw.github.com/Star2Billing/cdr-stats/$BRANCH/install/bashcommon-functions.sh -O bash-common-functions.sh # wget --no-check-certificate https://raw.github.com/Star2Billing/cdr-stats/$BRANCH/install/cdrstats-functions.sh -O cdr-stats-functions.sh Luego se modifica: nano +31 bash-common-functions.sh en esa linea se cambia 6.2 con 6.6. Se guardan los cambios y se ejecuta nuevamente el script de instalación: ./install-cdr-stats-asterisk.sh
Se presiona la tecla Enter/Envío. Aparecerá:
394
Se escribe YES y se presiona la tecla Enter:
En un sistema con bastante carga es recomendable instalar el programa directamente en el servidor Web. En este caso se escribe 1 (Installa All) y se presiona la tecla Enter. Empezará la instalación del programa y de todas las dependencias:
Se presiona la tecla Enter:
Cuando el programa de instalación lo solicite, se ingresan todos los datos de configuración de la base de datos donde se ha creado la tabla CDR y se sigue presionando la tecla Enter:
Cuando el programa de instalación lo solicite, se escoge un nombre de usuario, un correo electrónico y una contraseña para acceder a la pagina de administración de CDR-STATS:
395
Terminada la instalación aparecerá la imagen de arriba indicando que el proceso ha tenido éxito. Se presiona la tecla Enter:
cuando se vuelve a este menú se digita 0 y la tecla Enter. Se volverá al prompt de la consola de Linux. Como hay que personalizar la configuración, se para el proceso de cdr-stats: /etc/init.d/cdr-stats-celeryd stop y se abre el archivo de configuración y se modifica esta linea: nano /usr/share/cdr_stats/settings_local.py TIME_ZONE = 'Etc/UTC' para que quede (para Colombia): TIME_ZONE = 'America/Bogota' se continua con este bloque: DEFAULT_FROM_EMAIL = 'CDR-Stats ' 396
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' EMAIL_USE_TLS = True EMAIL_HOST = 'smtp.gmail.com' EMAIL_PORT = 587 EMAIL_HOST_USER = '
[email protected]' EMAIL_HOST_PASSWORD = 'password' EMAIL_SUBJECT_PREFIX = '[CDR-Stats] ' Se personalizan los datos con su nombre de dominio, cuenta Gmail y contraseña de la cuenta. Se modifica: LOCAL_DIALCODE = 1 Con el prefijo de su país: LOCAL_DIALCODE = 57 En: PREFIX_TO_IGNORE = "+,0,00,000,0000,00000,011,55555,99999" Se añaden los prefijos de SipTraffic para que la linea quede: PREFIX_TO_IGNORE = "+,0,00,000,0000,00000,00001,011,55555,99999" Se modifica la linea: LOCAL_SWITCH_IP = 'IPServidor' Para que quede: LOCAL_SWITCH_IP = 'localhost' Estas tres lineas: ASTERISK_MANAGER_HOST = 'localhost' ASTERISK_MANAGER_USER = 'cdrstats_user' ASTERISK_MANAGER_SECRET = 'cdrstats_secret' Permiten a CDR-STATS de conectaste a la AMI de Asterisk con nombre de usuario y contraseña que aparecen respectivamente en la segunda y tercera linea. Se guardan las modificaciones y se modifica el archivo manager.conf de Asterisk: nano /etc/asterisk/manager.conf y al final se añade el siguiente bloques:
397
[cdrstats_user] secret=cdrstats_secret deny=0.0.0.0/0.0.0.0 permit=127.0.0.1/255.255.255.255 displayconnects = no read = system,call,log,verbose,agent,user,config,dtmf,reporting,cdr,dialplan write = system,call,agent,user,config,command,reporting,originate Se guardan los cambios y se recarga la configuración de Asterisk: service asterisk reload Ahora se puede iniciar nuevamente el programa: /etc/init.d/cdr-stats-celeryd start Antes de acceder a la pagina de administración de CDR-STATS hay que abrir los puertos 8008 y 9000 tcp en el Firewall: nano /etc/sysconfig/iptables después de esta linea: -A INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT se añade: # CDR-STATS -A INPUT -p tcp -m state --state NEW -m tcp --dport 8008 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 9000 -j ACCEPT Se guardan los cambios y se reinicia iptables y fail2ban: service iptables restart service fail2ban restart ya se puede acceder a la pagina de administración con nombre de usuario y contraseña definidos a lo largo de la instalación: http://IPservidor:8008
Se presiona el botón Login y se entrará en la pagina de los reportes de CDR-STATS. Para asegurarse que el sistema esté funcionando sin problemas, en el menú Admin: 398
En la nueva pagina debe aparecer:
Las zonas evidenciadas son las que indican que el programa está funcionando bien. Para profundizar algunos temas de la configuración de CDR-STATS, se aconseja consultar el manual en linea del programa.
399
Capitulo VIII Trucos y consejos En este capitulo del libro, se ilustrarán algunas soluciones que han nacido como inquietudes a lo largo de los cursos a distancia de A2Billing dictados por VozToVoice. 9.1 Cambiar la moneda predefinida En el libro se ha asumido que la moneda predefinida para las tarifas, los clientes y las recargas, fuera el dólar. Esto no significa que no se pueda cambiar. Para hacerlo se entra en el Menú SYSTEM SETTINGS → Global y se modifica este parámetro (para el peso colombiano): Base Currency
cop
Moneda predefinida
Para aceptar pagos en pesos colombianos en SYSTEM SETTINGS → epayment_method se modifica: Currency Code
COP
Moneda utilizada para los pagos (se puede personalizar)
Para configurar como moneda predefinida el peso colombiano. Luego hay que decirle a A2Billing que todas las tasas de cambio tienen que calcularse a partir de esta moneda, se entra en el menú BILLING → Currencies List y se presiona el botón que aparece en la imagen que sigue:
El resultado será:
En la lista de las monedas si se busca el peso colombiano el cambio tienes que estar en 1:
Esto permite resolver un problema muy sencillo. Si se utiliza como moneda predefinida el dólar y el cliente al momento de registrarse escoge como moneda el peso colombiano, su crédito cambiará cada día ya que el sistema actualiza las tasas de cambio cada 24 horas. Esto significa que el cliente encontrará variaciones en su crédito (más bajo o más alto) a pesar que no haya realizado llamadas. 9.2 Rellamada sin cobrar en ningún caso la primera llamada Como se ha visto en el párrafo 5.3 dedicado a la rellamada, hay un parámetro que se puede modificar para decidir si cobrar o no la primera llamada: Bill Callback
Yes
Se cobrará la llamada de Callback del primer canal aunque el segundo canal no ha contestado o no se ha podido establecer la llamada
Este parámetro permite definir si en una rellamada la primera “pata” se cobre o no en base a si la segunda llamada sea contestada o no. Si estás en Yes se cobrará la primera llamada aunque la segunda no sea contestada; si está en No se cobrará la primera llamada solamente si la segunda conteste. Desafortunadamente no hay un sistema para decirle a A2Billing que no cobre en ningún caso la primera llamada. Para solucionar este problema se puede adoptar el siguiente truco; primero se crea un nuevo paquete de llamadas gratuitas. Se entra en el menú Package Offer → Add:
Y se escoge el enlace “Add Package”. Se configura un paquete de la siguiente forma:
402
El paquete configurado permite cursar 10000 llamadas gratuitas. Se guardan los cambios presionando el botón “Confirm Data”. Se selecciona el botón “Add rates” del paquete que se acaba de crear y se seleccionan todos los prefijos presentes en la Rate Card Base1:
Ahora se entra en el menu RATES→ CallPlan y se crea un nuevo plan de llamadas:
Como se puede ver en la imagen a este nuevo CallPlan se asocia el paquete de llamadas gratuitas que se acaba de crear. Se guardan los cambios presionando el botón “Confirm Data” y se vuelve a entrar al 403
callplan creado para asignarle una RateCard (en este caso Base1):
El nuevo CallPlan creado tendrá un numero ID:
en este caso el numero es 4. Este numero es el que hay que utilizar para configurar la linea del AGI del Callback. Se retoma la configuración del dialplan vista en el párrafo 6.10.2: nano /etc/asterisk/extensions.conf exten => 5718888888,1,Set(CALLERID(num)=189445322) same => n,Agi(a2billing.php,1,cid-callback,57,,4) same => n,hangup y se modifica para que quede: exten => 5001,1,Set(CALLERID(num)=189445322) same => n,Agi(a2billing.php,1,cid-callback,57,,4) same => n,hangup La linea que se ha cambiado es: same => n,Agi(a2billing.php,1,cid-callback,57,,4) 1 2 345 En la posición 5 es posible indicar que CallPlan se utilizará para devolver la llamada a quien ha solicitado el callback. En este caso el CallPlan será el numero de ID 4 que es él que se ha configurado en A2Billing. De esta forma la primera llamada de callback no será cobrada bajo ninguna circunstancia. Una vez hecha la prueba en CALL Reports → CDRs aparecerá:
La llamada de callback que realiza el sistema no se ha cobrado (columna Sell de la segunda linea). 404
9.3 Nginx en lugar de Apache En lugar de utilizar el servidor Web Apache, otra posibilidad es sostituirlo con otro servidor Web: Nginx. Nginx (pronunciado en inglés “engine X”) es un servidor web/proxy inverso ligero, de alto rendimiento y también un proxy para protocolos de correo electrónico (IMAP/POP3) (Wikipedia). Siendo mucho más liviano que Apache, permite una convivencia mucho más funcional entre el servidor Web y la PBX. En este párrafo se verá como instalar y configurar Nginx en CentOS 6.6 para trabajar con la parte Web de A2Billing. Se instala el paquete junto a Fast-CGI desde los repositorios epel: yum --enablerepo=epel install nginx spawn-fcgi fcgi -y Se modifica el archivo de configuración principal: nano /etc/nginx/nginx.conf cambiando esta linea: user
nginx;
para que quede: user
apache apache;
De esta forma se inicia el servidor Nginx con usuario apache y grupo apache. Los mismos datos del servidor Apache. Esto para no tener que modificar los permisos de todos los archivos que se han modificado a lo largo de la instalación de A2Billing. Se sigue añadiendo después de esta linea: default_type application/octet-stream; la siguiente linea: client_max_body_size 8m; Esta linea permite cargar en A2Billing archivos de hasta 8 Megabyte (las tarifas). Se guardan los cambios y se configura el archivo para el servidor Web. Se renombra el predefinido: mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.old y se crea uno nuevo: nano /etc/nginx/conf.d/default.conf Se copian las siguientes lineas: server { 405
listen 80; server_name _; root /var/www/html; index index.html index.htm index.php; server_tokens off; location ~ \.php$ { try_files $uri =404; fastcgi_pass 127.0.0.1:9010; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name; include /etc/nginx/fastcgi_params; } location /admin { auth_basic "Administration"; auth_basic_user_file /etc/httpd/htpasswd; } location /admin/Public { auth_basic "Administration"; auth_basic_user_file /etc/httpd/htpasswd; } location ~ /\.ht { deny all; } } Se guardan los cambios y se crea la configuración para las conexiones seguras. Se renombra el archivo predefinido: mv /etc/nginx/conf.d/ssl.conf /etc/nginx/conf.d/ssl.conf.old se crea uno nuevo nano /etc/nginx/conf.d/ssl.conf se copian las lineas que siguen: server { listen 443; server_name _; root /var/www/html; index index.html index.htm index.php; server_tokens off; ssl on; 406
ssl_certificate /etc/pki/tls/certs/localhost.crt; ssl_certificate_key /etc/pki/tls/private/localhost.key; ssl_session_timeout 5m; ssl_protocols SSLv2 SSLv3 TLSv1; ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP; ssl_prefer_server_ciphers on; location ~ \.php$ { try_files $uri =404; fastcgi_pass 127.0.0.1:9010; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name; include /etc/nginx/fastcgi_params; } location /admin { auth_basic "Administration"; auth_basic_user_file /etc/httpd/htpasswd; } location /admin/Public { auth_basic "Administration"; auth_basic_user_file /etc/httpd/htpasswd; } location ~ /\.ht { deny all; } } En este archivo se utilizan los certificados que venían por defecto con la instalación de Apache. Para averiguar que la configuración de Nginx esté sin errores: nginx -t La respuesta tiene que ser: nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful Se pasa a la configuración de Fast-CGI: nano /etc/sysconfig/spawn-fcgi
407
Se modifican estas lineas: #SOCKET=/var/run/php-fcgi.sock #OPTIONS="-u apache -g apache -s $SOCKET -S -M 0600 -C 32 -F 1 -P /var/run/spawn-fcgi.pid -- /usr/bin/php-cgi"
para que queden: SOCKET=/var/run/php-fcgi.sock OPTIONS="-u apache -g apache -p 9010 -S -M 0600 -C 6 -F 1 -P /var/run/spawn-fcgi.pid -- /usr/bin/php-cgi"
Para conocer el significado de cada opción presente: man spawn-fcgi El bloque de la configuración de Nginx que permite conectarse al servicio spawn-fcgi, y de esta forma procesar cada archivo PHP, es: location ~ \.php$ { try_files $uri =404; fastcgi_pass 127.0.0.1:9010; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name; include /etc/nginx/fastcgi_params; } Se guardan los cambios y se para el servidor Apache: /etc/init.d/httpd stop Luego se inicia primero Fast-CGI seguido por Nginx: /etc/init.d/spawn-fcgi start /etc/init.d/nginx start Se hace una primera prueba entrando con el nombre de dominio o la dirección IP del servidor: http://IPservidor Después de algunos segundo se entrará a la pagina de los clientes de forma segura (de la misma forma en que se había configurado en Apache). Si se entra en la siguiente pagina: http://IPservidor/common Aparecerá:
408
Normalmente junto a “nginx” aparece el numero de versión. Se ha quitado con la sentencia: server_tokens off; presente en la configuración de Nginx. Si se entra en la pagina: http://IPservidor/admin Aparecerá:
De la misma forma en que aparecía con el servidor Apache. Esto se debe a estos dos bloques presentes en la configuración de Nginx: location /admin { auth_basic "Administration"; auth_basic_user_file /etc/httpd/htpasswd; } location /admin/Public { auth_basic "Administration"; auth_basic_user_file /etc/httpd/htpasswd; } Cuyo significado es: para la carpeta /admin y /admin/Public se requiere una autenticación (auth_basic) y los datos de usuarios y contraseñas se encuentran en el archivo /etc/httpd/htpasswd (el mismo creado para Apache). Una vez ingresados los datos de usuario (admin) y contraseña (sesamo) se entrará en la pagina de 409
administración de A2Billing donde hay que ingresar los datos de acceso. Una vez probado el sistema , si se quiere utilizar Nginx en lugar de Apache, hay que terminar con la configuración: chkconfig httpd off chkconfig spawn-fcgi on chkconfig nginx on chown -Rf apache:apache /var/lib/nginx/ De esta forma iniciando el servidor nuevamente, se iniciarán en automático spawn-fcgi y Nginx. Apache estará desactivado. Para averiguarlo: reboot 9.4 Guardar la IP del llamante en el CDR En algunas ocasiones puede ser útil guardar la dirección IP utilizada para cada llamada. En la tabla CDR , donde se guardan todos los registros de las llamadas, hay un campo (userfield) que está disponible para cualquier tipo de uso. En este caso se utilizará para guardar las direcciones IP de los llamantes. El procedimiento es bastante sencillo. Se modifica el dialplan de a2billing modificando una linea: nano /etc/asterisk/extensions.conf se modifica este bloque: [a2billing] exten => _X.,1,NoOp(A2Billing Start) same => n,System(/usr/local/bin/canales.pl 1 INCR ${CDR(accountcode)}) same => n,Set(CALLS=${SHELL(/usr/local/bin/canales.pl 1 GET ${CDR(accountcode)})}) same => n,GotoIf($[${CALLS} > ${ODBC_canales(${CDR(accountcode)})}]?cong) same => n,NoOp(El cliente: ${CDR(accountcode)} tiene ${CALLS} llamadas activas) same => n,Agi(a2billing.php,1) same => n,Hangup same => n(cong),Congestion(3) same => n,hangup exten => h,1,System(/usr/local/bin/canales.pl 1 DECR ${CDR(accountcode)}) exten => h,n,Hangup para que quede: [a2billing] exten => _X.,1,NoOp(A2Billing Start) same => n,set(CDR(userfield)=${CHANNEL(peerip)}) same => n,System(/usr/local/bin/canales.pl 1 INCR ${CDR(accountcode)}) same => n,Set(CALLS=${SHELL(/usr/local/bin/canales.pl 1 GET ${CDR(accountcode)})}) 410
same => n,GotoIf($[${CALLS} > ${ODBC_canales(${CDR(accountcode)})}]?cong) same => n,NoOp(El cliente: ${CDR(accountcode)} tiene ${CALLS} llamadas activas) same => n,Agi(a2billing.php,1) same => n,Hangup same => n(cong),Congestion(3) same => n,hangup exten => h,1,System(/usr/local/bin/canales.pl 1 DECR ${CDR(accountcode)}) exten => h,n,Hangup De esta forma, en cada entrada de la tabla CDR, bajo el campo userfield, estará la dirección IP de donde se ha originado la llamada. Para más información acerca de la función CHANNEL: asterisk -rvvvvvvvvvvvvvvv CLI> core show function CHANNEL 9.5 Cambiar el numero de las tarjetas Normalmente el ACCOUNT NUMBER del cliente es generado automáticamente por el sistema y no se puede modificar. Esto porque en la configuración de A2BIlling el campo está configurado como de sola lectura. Es posible modificar la configuración de A2Billing para que el campo sea de lectura/escritura. Se abre el archivo que sigue: nano +329 /var/www/html/admin/Public/form_data/FG_var_card.inc y se modifica la siguiente linea: "size=30 $maxi readonly maxlength=40", Para que quede: "size=30 $maxi maxlength=40", Se guardan los cambios Se entra en el menú CUSTOMERS → Add Search y luego se escoge la opción “Add Customer”. El campo ACCOUNT NUMBER ya se debería poder modificar sin problema:
411
La longitud del campo no puede ser inferior al valor indicado en el siguiente parámetro (SYSTEM SETTINGS → Global List → Global): Card Number length
5-20
Longitud llamada
numérica.
Tarjeta
porque en ese caso el sistema de tarjetas prepago no funcionaria ya que el sistema espera recibir un numero de tarjeta entre 5 y 20 cifras. 9.6 Añadir nuevas troncales desde la pagina de administración de A2Billing Puede ser bastante cómodo poder añadir troncales al archivo sip.conf sin tener que acceder a la consola de Linux. Para hacerlo primero se cambian los permisos del archivo de forma que el usuario apache (el servidor Web) pueda acceder: chown apache:apache /etc/asterisk/sip.conf El segundo paso es modificar una linea en este archivo: nano +67 /usr/local/src/a2billing/admin/Public/phpconfig_init.php $fakeuser = "myasterisk"; para que quede: $fakeuser = "asterisk"; asterisk es el nombre que se ha configurado en el manager.conf para dar acceso a A2Billing al AMI. Luego se accede a la pagina de administración de A2Billing y se entra en el menú SYSTEM SETTINGS → Config Editor:
412
Se selecciona el archivo sip.conf:
Se añade un nueva troncal y para terminar se presiona el botón Update: Aparecerá un mensaje que confirmará el éxito de la operación:
Para recargar la configuración de Asterisk desde A2BIlling se selecciona el siguiente enlace:
Aparecerá:
Para averiguar que efectivamente la nueva configuración sea efectiva, se entra en la consola de Asterisk: 413
asterisk -rvvvvvvvvvvvv y se escribe: CLI> sip show peers Aparecerá:
El mismo procedimiento se puede utilizar para modificar el dialplan desde la pagina de administración de A2Billing. Nada más cambiar los permisos del archivo extensions.conf: chown apache:apache /etc/asterisk/extensions.conf IMPORTANTE: a partir de la versión 2.0.16 de A2Billing cuando se intenta actualizar la configuración con el botón UPDATE, el sistema no funciona 9.7 Modificar el tamaño del campo destination en distintos reportes En algunos casos, en los reportes de llamadas presentes en la pagina de administración de A2Billing, no es posible identificar de forma clara el destino de las llamadas realizadas. Esto se debe al tamaño reservado por A2Billing a ese tipo de información. En el caso que se quiera aumentar el tamaño de ese campo en el reporte de las llamadas del la pagina de administración: nano +116 /var/www/html/admin/Public/call-log-customers.php Se modifica esta linea: $FG_TABLE_COL [] = array (gettext ( "Destination" ), "dest","10%", "center", "SORT", "15", "lie", "cc_prefix", "destination,prefix", "prefix='%id'", "%1" ); para que quede: $FG_TABLE_COL [] = array (gettext ( "Destination" ), "dest","10%", "center", "SORT", "30", "lie", "cc_prefix", "destination,prefix", "prefix='%id'", "%1" ); El parámetro que se modifica es SORT y se cambia su valor de 15 a 30. Se guardan los cambios. La misma cosa, aunque normalmente no se necesita, se puede hacer para los reportes de llamadas de la 414
pagina de los clientes. Se abre el siguiente archivo: nano +102 /var/www/html/customer/call-history.php y se modifica la siguiente linea: $FG_TABLE_COL[]=array (gettext("Destination"), "destination", "14%", "center", "SORT", "30", "lie", "cc_prefix", "destination", "prefix='%id'", "%1" ); Modificando el parámetro SORT de 30 a 40: $FG_TABLE_COL[]=array (gettext("Destination"), "destination", "14%", "center", "SORT", "40", "lie", "cc_prefix", "destination", "prefix='%id'", "%1" ); El mismo procedimiento se puede utilizar también para la pagina de las tarifas, menú RATES → Rates: nano +118 /usr/local/src/a2billing/admin/Public/form_data/FG_var_def_ratecard.inc se modifica la linea: $HD_Form -> AddViewElement(gettext("DESTINATION"), "destination", "17%", "center", "", "15");
para que quede: $HD_Form -> AddViewElement(gettext("DESTINATION"), "destination", "20%", "center", "", "30");
9.8 Campo destination en la tabla cc_call El campo destination de la tabla donde se guardan los reportes de las llamadas, cc_call, contiene un numero que representa el prefijo utilizado para escoger la ruta en la RateCards. Solamente al momento de visualizar el reporte de las llamadas, este numero se sustituye con el nombre del destino que el sistema saca de la tabla cc_prefix (véase el menú PROVIDERS → Prefixes). Mientras el campo prefix de la tabla cc_prefix está configurado como bigint(20), el campo destination de la tabla cc_call está configurado como Int(11). Problema: si en el campo prefix de la tabla cc_prefix está presente un valor con una longitud mayor de 11, como el valor del campo destination de la tabla cc_call no acepta valores con una longitud mayor de 11, no se visualizará correctamente el nombre del destino y en su lugar aparecerá el siguiente numero: 2147483647 Solución: modificar el campo destination de la tabla cc_call para que quede bigint(20): mysql -u root -psesamo mysql> use a2billing 415
mysql> ALTER TABLE cc_call CHANGE destination destination BIGINT( 20 ) NULL DEFAULT '0'; 9.9 Registros de Asterisk Como y donde se guardan los registros de Asterisk, se define en el archivo logger.conf. Para tener registros más detallados y distribuidos de forma más ordenada, se modifica dicho archivo: mv /etc/asterisk/logger.conf /etc/asterisk/logger.conf.old nano /etc/asterisk/logger.conf Se copian las lineas que siguen: [general] dateformat=%F %T ; ISO 8601 date format ;dateformat=%F %T.%3q ; with milliseconds ;appendhostname = yes queue_log = yes queue_log_name = queue_log rotatestrategy = rotate event_log = yes [logfiles] ; ; Format is "filename" and then "levels" of debugging to be included: ; debug ; notice ; warning ; error ; verbose ; dtmf debug => debug console => notice,warning,error,dtmf,debug security => security,notice messages => notice,warning full => error verbose => verbose,fax Se guarda los cambios y se recarga la configuración de ese archivo desde la consola: aste CLI> logger reload
416
CLI> logger show channels
Para que no se creen archivos muy pesados, se aplican unas cuantas reglas de rotación. Para Asterisk: nano /etc/logrotate.d/asterisk Se copian las lineas que siguen: /var/log/asterisk/messages /var/log/asterisk/debug /var/log/asterisk/verbose /var/log/asterisk/security /var/log/a2billing/a2billing_agi.log{
missingok rotate 7 daily postrotate /usr/sbin/asterisk -rx 'logger reload' > /dev/null 2> /dev/null endscript } /var/log/asterisk/queue_log { missingok rotate 5 size=1000k postrotate /usr/sbin/asterisk -rx 'logger reload'> /dev/null 2> /dev/null endscript } Para OpenSIPs: nano /etc/logrotate.d/opensips /var/log/opensips.log{ missingok rotate 7 daily postrotate /bin/kill -HUP `cat /var/run/syslogd.pid 2>/dev/null` 2>/dev/null || true endscript }
417
9.10 Cambio nombre pestaña Navegador Cada vez que se entra a cualquier pagina de A2Billing, en la pestaña del navegador aparecerá el siguiente nombre:
Si se quiere modificar este nombre, se abre el siguiente archivo: nano +125 /var/www/html/common/lib/common.defines.php se modifica la linea: define ("CCMAINTITLE", gettext("A2Billing Portal")); Para que quede (personalizar): define ("CCMAINTITLE", gettext("VozToVoice")); El resultado:
9.11 Aumentar el numero de decimales en los reportes de llamadas Por defecto, los números de decimales que aparecen en los reportes de llamadas son 3:
Esto a pesar que en la base de datos, los datos se guarden con 5 decimales. Si se quiere modificar el numero de decimales, se abre el siguiente archivo: nano +512 /var/www/html/common/lib/Misc.php se modifica la linea: echo number_format($var, 3) . ' ' . strtoupper($currency); Para que quede (para 4 decimales):
418
echo number_format($var, 4) . ' ' . strtoupper($currency); Se guardan los cambios. El resultado:
9.12 Actualizar A2Billing a una nueva versión Para actualizar una versión “vieja” de A2Billing, a la ultima disponible, los pasos a seguir son: 1. 2. 3. 4. 5. 6. 7.
Parar Asterisk y Apache o Nginx Sacar una copia de la base de datos a2billing Descargar la ultima versión Actualizar los permisos de los archivos Actualizar la base de datos Modificar nuevamente todos los archivos que se han cambiado en la vieja versión Iniciar nuevamente Asterisk
En este caso se actualizará la versión 2.0.11 a la versión 2.1.0. Primero se para Asterisk: service asterisk stop Se para Apache o Nginx según el que se utilice: service httpd stop service nginx stop Se entra en la siguiente carpeta: cd /usr/local/src Se realiza una copia de la base de datos a2billing (por seguridad): mysqldump -u root -psesamo a2billing > a2billing.sql se descarga la versión 2.1.0 de A2Billing: wget https://github.com/Star2Billing/a2billing/archive/v2.1.0.tar.gz se descomprime: tar -xf v2.1.0.tar.gz 419
Se renombra la carpeta que contiene la versión 2.0.11 de A2Billing: mv a2billing a2billing.2.0.11 Se renombra la carpeta que contiene A2Billing 2.1.0: mv a2billing-2.1.0 a2billing Se cambian los permisos en estas tres carpetas donde se guardarán los archivos temporales para cada tipo de usuario: chmod 755 /usr/local/src/a2billing/admin/templates_c chmod 755 /usr/local/src/a2billing/customer/templates_c chmod 755 /usr/local/src/a2billing/agent/templates_c Se cambian nuevamente los permisos en las carpetas visibles en el servidor web: chown -Rf apache:apache /var/www/html/admin/ chown -Rf apache:apache /var/www/html/agent/ chown -Rf apache:apache /var/www/html/customer/ chown -Rf apache:apache /var/www/html/common/ Se continua con la actualización de la base de datos: cd /usr/local/src/a2billing/DataBase/mysql-5.x/ se envía a MySQL los archivos desde la versión 2.0.11 hasta la versión 2.1.0 de la siguiente forma: mysql -u root -psesamo a2billing < UPDATE-a2billing-v2.0.11-to-v2.0.12.sql mysql -u root -psesamo a2billing < UPDATE-a2billing-v2.0.12-to-v2.0.13.sql mysql -u root -psesamo a2billing < UPDATE-a2billing-v2.0.13-to-v2.0.14.sql mysql -u root -psesamo a2billing < UPDATE-a2billing-v2.0.14-to-v2.0.15.sql mysql -u root -psesamo a2billing < UPDATE-a2billing-v2.0.15-to-v2.0.16.sql mysql -u root -psesamo a2billing < UPDATE-a2billing-v2.0.16-to-v2.0.17.sql mysql -u root -psesamo a2billing < UPDATE-a2billing-v2.0.17-to-v2.1.0.sql Terminada la actualización de la base de datos, se modifican los archivos que se habían cambiado en la versión anterior: nano /var/www/html/admin/Public/A2B_invoice_view.php para e logo de las facturas lado administrador. nano /var/www/html/customer/A2B_invoice_view.php Para el logo de las facturas lado cliente. 420
nano +776 /usr/local/src/a2billing/admin/Public/form_data/FG_var_card.inc Para que por defecto no se cree una extensión IAX cuando un administrador crea un nuevo cliente. nano +147 /var/www/html/customer/A2B_entity_sipiax_info.php Para modificar la salida del menú SIP/IAX INFO de la pagina del cliente. nano /usr/local/src/a2billing/customer/templates/default/index.tpl Para traducir la pagina de acceso del cliente al español. nano /usr/local/src/a2billing/agent/Public/templates/default/index.tpl Para traducir la pagina de acceso del revenedor al español. nano +758 /usr/local/src/a2billing/agent/Public/form_data/FG_var_card.inc Para que por defecto no se cree una extensión IAX cuando un revendedor crea un nuevo cliente. nano +115 /usr/local/src/a2billing/admin/Public/form_data/FG_var_friend.inc Para modificar los parametros predefinidos cuando se añade una nueva extensión a un cliente. nano +141 /var/www/html/admin/Public/A2B_asteriskinfo.php Para modificar la versión de Asterisk en el menú MAINTENANCE → Asterisk Info nano +329 /var/www/html/admin/Public/form_data/FG_var_card.inc Para volver el parámetro ACCOUNT NUMBER del cliente modificable desde la pagina de administración nano +67 /usr/local/src/a2billing/admin/Public/phpconfig_init.php Para modificar el usuario como indicado en el archivo manager.conf nano +116 /var/www/html/admin/Public/call-log-customers.php Para agrandar el tamaño del campo DESTINATION en los reportes de la pagina de administración nano +102 /var/www/html/customer/call-history.php Para agrandar el tamaño del campo DESTINATION en los reportes de la pagina del cliente nano +118 /usr/local/src/a2billing/admin/Public/form_data/FG_var_def_ratecard.inc 421
Para agrandar el tamaño del campo DESTINATION en la pagina de las tarifas nano +125 /var/www/html/common/lib/common.defines.php Para modificar el nombre que aparece en la pestaña del navegaor. nano +512 /var/www/html/common/lib/Misc.php Para aumentar el numero de decimales en los reportes de las llamadas. Ahora que se han modificado todos los archivos y supuestamente el sistema está configurado con la nueva versión, se inicia nuevamente Asterisk, Apache o Nginx: service asterisk start service httpd start service nginx start Se accede a la pagina de administración de A2Billing y se averigua que efectivamente la versión de la interfaz y de la base de datos sea la 2.1.0. Menú DASHBOARD:
422
Capitulo X Resolución de problemas Este capitulo está dedicado a la resolución de problemas que puedan ocurrir a lo largo de la configuración y implementación de A2BIlling. 10.1 Pagina Web en blanco Si al momento de entrar en la pagina de administración de A2BIlling, aparece una pagina totalmente blanca, significa que hay algún tipo de error en la configuración del sistema o en el código PHP del sistema de facturación. El tipo de error no aparece porque por seguridad en la configuración predefinida del php.ini este parámetro está deshabilitado. Para habilitarlo se abre el archivo: nano /etc/php.ini y se modifica este parámetro: display_errors = Off para que quede: display_errors = On se reinicia el servidor Web: service httpd restart Se vuelve a entrar en la pagina que quedaba en blanco. Ya aparecerá el tipo de error. Una vez que se tenga esta referencia ya se puede solucionar el problema y una vez solucionado se vuelve a poner el parámetro como estaba: nano /etc/php.ini de: display_errors = On a:
display_errors = Off service httpd restart 10.2 Recuperar password administrador A2billing Si por cualquier motivo se olvida la contraseña de administrador de A2BIlling hay una forma para volver a configurar la predefinida. Suponiendo que el usuario que se está utilizando es admin, los pasos a seguir son: entrar en la consola de MySQL mysql -u root -psesamo utilizar la base de datos a2billing: mysql> use a2billing se escribe este comando: mysql> update cc_ui_authen set pwd_encoded = '410fc6268dd3332226de95e42d9efa4046c5463769d7493b85e65cfa5c26362dc2455cc23c0bc5831de b008def4ab11a9eaa9b76ba3f377da134f39ec60dd758' where login='admin'; Este comando no hace nada más que volver a poner como password predefinida changepassword. Todos los numeros y las letras que aparecen son la versión cifrada de esa password. Se sale del cliente mysql: mysql> quit y se vuelve a entrar en la pagina de administración de A2Billing utilizando estos datos: Usuario: admin Password: changepassword 9.3 Tarificación errada de las llamadas En algunos ATA la llamada se empieza a cobrar desde que se termina de marcar el numero. Para solucionar el problema en la linea en el menú SYSTEM SETTINGS → Globa List, se selecciona el agi-conf que se está utilizando para las llamadas y se modifica el siguiente parámetro:
425
Dial Command Params
,60,rL(%timeout%:61000:30000)
Opciones para el comando Dial de Asterisk.
quitando la r de la linea del Dial para que quede: Dial Command Params
,60,L(%timeout%:61000:30000)
Opciones para el comando Dial de Asterisk.
Esta es también la configuración indicada para evitar que se cobre la llamadas a celulares cuando vaya al buzón de voz.
426
Apéndice A Archivo de Configuración de OpenSIPs A seguir el archivo de configuración de OpenSIPs como quedaría al terminar este libro. Modificar IPPublica con la IP publica del servidor, IPPrivada con la IP privada del servidor, 1.2.3.4 con la IP publica del servidor, dominio.org con el nombre de dominio asociado al servidor, los datos de conexión a la base de datos opensips en el caso en que no se utilicen los predefinidos. ####### Global Parameters ######### debug=3 log_stderror=no log_facility=LOG_LOCAL0 fork=yes children=4 auto_aliases=no listen=udp:IPPublica:5060 alias="dominio.org":5060 disable_tcp=yes disable_tls=yes user_agent_header="User-Agent: VozToVoice Proxy Agent" server_header="Server: VozToVoice Proxy Server" ####### Modules Section ######## #set module path mpath="/lib64/opensips/modules/" #### SIGNALING module loadmodule "signaling.so" #### StateLess module loadmodule "sl.so" #### Transaction Module loadmodule "tm.so" modparam("tm", "fr_timeout", 5) modparam("tm", "fr_inv_timeout", 60) modparam("tm", "restart_fr_on_each_reply", 0) modparam("tm", "onreply_avp_mode", 1) #### Record Route Module loadmodule "rr.so"
modparam("rr", "append_fromtag", 0) #### MAX ForWarD module loadmodule "maxfwd.so" #### SIP MSG OPerationS module loadmodule "sipmsgops.so" #### FIFO Management Interface loadmodule "mi_fifo.so" modparam("mi_fifo", "fifo_name", "/tmp/opensips_fifo") modparam("mi_fifo", "fifo_mode", 0666) #### URI module loadmodule "uri.so" modparam("uri", "db_url", "mysql://opensips:opensipsrw@localhost/opensips") modparam("uri", "db_table", "subscriber_v1") modparam("uri", "use_uri_table", 0) #### MYSQL module loadmodule "db_mysql.so" #### AUTH module loadmodule "auth.so" ##### AUTH_DB module loadmodule "auth_db.so" modparam("auth_db", "db_url", "mysql://opensips:opensipsrw@localhost/opensips") #### AVPOPS module loadmodule "avpops.so" modparam("avpops", "db_url", "mysql://a2user:sesamo@localhost/a2billing") #### ACCounting module loadmodule "acc.so" modparam("acc", "early_media", 0) modparam("acc", "report_cancels", 0) modparam("acc", "detect_direction", 0) modparam("acc", "failed_transaction_flag", "ACC_FAILED") modparam("acc", "db_flag", "ACC_DO") modparam("acc", "db_missed_flag", "ACC_MISSED") modparam("acc", "cdr_flag", "CDR_FLAG") modparam("acc", "db_extra", "Llamante=$fU;Llamado=$tU") modparam("acc", "db_url", "mysql://opensips:opensipsrw@localhost/opensips") #### DIALOG module loadmodule "dialog.so" modparam("dialog", "dlg_match_mode", 1) modparam("dialog", "default_timeout", 21600) modparam("dialog", "db_mode", 2)
429
modparam("dialog", "db_url","mysql://opensips:opensipsrw@localhost/opensips") #### LOAD BALANCER module loadmodule "load_balancer.so" modparam("load_balancer","db_url","mysql://opensips:opensipsrw@localhost/opensips") modparam("load_balancer", "probing_method", "OPTIONS") modparam("load_balancer", "probing_interval", 30) modparam("load_balancer", "probing_reply_codes", "404") #### LOCATION module loadmodule "usrloc.so" modparam("usrloc", "nat_bflag", "NAT_BFLAG") modparam("usrloc", "db_url","mysql://opensips:opensipsrw@localhost/opensips") modparam("usrloc", "db_mode", 3) #### REGISTRAR module loadmodule "registrar.so" modparam("registrar", "max_contacts", 5) modparam("registrar", "received_avp", "$avp(received_nh)") #### PERMISSIONS module loadmodule "permissions.so" modparam("permissions", "db_url","mysql://opensips:opensipsrw@localhost/opensips") #### LOAD OPTIONS module loadmodule "options.so" #### NATHELPER modules loadmodule "nathelper.so" modparam("nathelper", "natping_interval", 10) modparam("nathelper", "ping_nated_only", 0) modparam("nathelper", "received_avp", "$avp(received_nh)") #### RTP Proxy loadmodule "rtpproxy.so" modparam("rtpproxy", "rtpproxy_sock", "udp:localhost:12221") #### PRESENCE modules loadmodule "xcap.so" loadmodule "presence.so" loadmodule "presence_xml.so" modparam("xcap|presence", "db_url","mysql://opensips:opensipsrw@localhost/opensips") modparam("presence_xml", "force_active", 1) modparam("presence", "server_address", "sip:dominio.org:5060") #### MSILO module loadmodule "msilo.so" modparam("msilo", "db_url","mysql://opensips:opensipsrw@localhost/opensips") modparam("msilo", "content_type_hdr", "Content-Type: text/plain\r\n") modparam("msilo", "from_address", "sip:
[email protected]")
430
modparam("msilo", "offline_message", "*** El usuario $rU no se encuentra en linea ***") ####### Routing Logic ######## route{ force_rport(); if (nat_uac_test("31")) { if (is_method("REGISTER")) { fix_nated_register(); setbflag(NAT); } else { fix_nated_contact(); setflag(NAT); } } if (!mf_process_maxfwd_header("10")) { xlog("L_ERROR","Superado el numero máximo de FORWARD Permitidos"); sl_send_reply("483","Too Many Hops"); exit; } if (has_totag()) { xlog("L_NOTICE", "La transacción tiene un tag en la cabecera To:"); if (loose_route()) { if ( $DLG_status!=NULL && !validate_dialog() ) { xlog("L_ERROR", "El Dialogo $rm de $si (CALLERID=$ci) no es valido"); ## exit; } if (is_method("BYE")) { setflag(ACC_DO); setflag(ACC_FAILED); xlog("L_NOTICE", "Recibido un BYE dentro de un dialogo"); } else if (is_method("INVITE")) { xlog("L_NOTICE", "Recibido un re-INVITE dentro de un dialogo"); record_route(); } route(RELAY); } else { if (is_method("SUBSCRIBE") && $rd == "IPPublica:5060") { xlog("L_NOTICE", "Recibido un SUBSCRIBE dentro de un dialogo"); route(handle_presence); exit; } if ( is_method("ACK") ) { if ( t_check_trans() ) { xlog("L_NOTICE", "Recibido un ACK dentro de un dialogo");
431
t_relay(); exit; } else { exit; } } sl_send_reply("404","Not here"); xlog("L_ERROR", "Recibida una petición sin Dialogo asociado"); } exit; } #### INITIAL REQUESTS if ((method==OPTIONS) && (! uri=~"sip:.*[@]+.*")) { options_reply(); exit; } if (is_method("CANCEL")) { if (t_check_trans()) t_relay(); xlog("L_NOTICE", "Recibido un CANCEL relacionado con una transacción valida"); exit; } if (is_method("SUBSCRIBE|PUBLISH")) { route(autent); if(is_method("SUBSCRIBE")) && (avp_check("$hdr(Event)", "eq/message-summary/i")) { rewritehostport("IPPrivada:5090"); if (!t_relay()) { t_reply("500", "Server internal error"); } exit; } if (is_method("SUBSCRIBE|PUBLISH")) { route(handle_presence); exit; } } if (is_method("MESSAGE") && db_does_uri_exist()) { #if (db_does_uri_exist()) { xlog("L_NOTICE","El usuario $tU existe código: $retcode"); if (lookup("location","m")) { xlog("L_NOTICE","El usuario $tU existe y está conectado código: $retcode"); } else { xlog("L_NOTICE","El usuario $tU existe pero no está conectado código: $retcode"); sl_send_reply("402","No en linea"); if (m_store("$ru")) {
432
xlog("L_NOTICE","BM Mensaje fuera de linea almacenato"); if (!t_reply("202", "Accepted")) { sl_reply_error(); } } else { xlog("L_NOTICE","BM Mensaje fuera de linea no almacenato"); if (!t_reply("503", "Service Unavailable")) { sl_reply_error(); } } exit; } t_on_failure("msilo"); route(RELAY); } if (is_method("REGISTER")) { $var(autent_cod) = www_authorize("", "subscriber_v1"); if ( $var(autent_cod) == -1 || $var(autent_cod) == -2 ) { xlog("L_NOTICE","error de autent para $fU@$fd desde $si causa $var(autent_cod)"); sl_send_reply("403","Te he pillado"); exit; } if ( $var(autent_cod) < 0 ) { www_challenge("", "0"); exit; } save("location"); consume_credentials(); m_dump(); xlog("L_NOTICE","Usuario $fU Registrado"); t_replicate("sip:IPPrivada:5090"); exit; } if (!is_method("INVITE")) { send_reply("405","Method Not Allowed"); xlog("L_ERROR", "Solicitud recibida $rm no es un INVITE"); exit; } if ($rU==NULL) { sl_send_reply("484","Address Incomplete"); xlog("L_ERROR", "El usuario $rU no es valido"); exit; } t_check_trans();
433
# preloaded route checking if (loose_route()) { xlog("L_ERR","Attempt to route with preloaded Route's [$fu/$tu/$ru/$ci]"); if (!is_method("ACK")) sl_send_reply("403","Preload Route denied"); sl_send_reply("403","Preload Route denied"); exit; } if(!uri==myself) { xlog("La solicitud no es local. Descartada"); sl_send_reply("404","Not Here"); exit; } if (is_method("INVITE")) { if (check_source_address("0","$avp(accountcode)")) { xlog("L_NOTICE","La IP $si es una dirección autorizada"); append_hf("P-Accountcode: $avp(accountcode)\r\n"); } else { $var(invite_cod) = proxy_authorize("", "subscriber_v1"); if ( $var(invite_cod) == -1 || $var(invite_cod) == -2 ) { xlog("L_NOTICE","error de autent para $fU@$fd desde $si causa $var(invite_cod)"); sl_send_reply("403","Te he pillado"); exit; } if ( $var(invite_cod) < 0 ) { proxy_challenge("", "0"); exit; } xlog("L_NOTICE","INVITE del Usuario $fU Autenticado"); consume_credentials(); } } if (avp_db_query("select did,destination from cc_did,cc_did_destination where cc_did.id=cc_did_destination.id_cc_did and did='$rU'","$avp(numerodid);;$avp(dest$ xlog("L_NOTICE","DID = $avp(numerodid) Destino = $avp(destino) retcode=$retcode"); if ($rU = $avp(numerodid) && $avp(destino)!~"^.*@1\.2\.3\.4") { append_hf("P-didnumber: $avp(numerodid)\r\n"); prefix("DID"); rewritehostport("IPPrivada:5090"); lb_count_call("$rd","$rp","1","channel"); record_route(); route(RELAY); } $avp(destino)=$(avp(destino){s.substr,4,0}); xlog("L_NOTICE","la nueva AVP Destino es $avp(destino)"); $ru="sip:" + $avp(destino); xlog("L_NOTICE","la nueva Request URI es $ru"); }
434
if (db_does_uri_exist()) { xlog("L_NOTICE","El usuario $tU existe código: $retcode"); if (lookup("location","m")) { xlog("L_NOTICE","El usuario $tU existe y está conectado código: $retcode"); } else { xlog("L_NOTICE","El usuario $tU existe pero no está conectado código: $retcode"); prefix("EU"); rewritehostport("IPPrivada:5090"); lb_count_call("$rd","$rp","1","channel"); } record_route(); setflag(ACC_DO); setflag(CDR_FLAG); setflag(ACC_MISSED); t_on_failure("timeout"); if (isbflagset(NAT)) setflag(NAT); route(RELAY2); } # record routing record_route(); setflag(ACC_DO); setflag(CDR_FLAG); setflag(ACC_MISSED); if ($rU=="97") { rewritehostport("IPPrivada:5090"); lb_count_call("$rd","$rp","1","channel"); route(RELAY); exit; } if ( !load_balance("1","channel")) { send_reply("500","No Destination available"); exit; } xlog("L_NOTICE", "Llamada de $fu IP $si $sp a $tu para $du"); t_on_failure("GW_FAILOVER"); route(RELAY); } route[RELAY] { if (!t_relay()) { sl_reply_error(); }; exit; }
435
route[autent] { if (!proxy_authorize("", "subscriber_v1")) { proxy_challenge("", "0"); exit; } xlog("L_NOTICE","$rm del Usuario $fU Autenticado"); consume_credentials(); return; } route[handle_presence] { if (!t_newtran()) { sl_reply_error(); exit; } if(is_method("PUBLISH")) { handle_publish(); } else if( is_method("SUBSCRIBE")) { handle_subscribe(); } exit; } route[RELAY2] { if (is_method("INVITE")) { if (isflagset(NAT)) { rtpproxy_offer("ro"); } t_on_reply("handle_nat"); } if (isflagset(NAT)) { add_rr_param(";nat=yes"); } if (!t_relay()) { sl_reply_error(); }; exit; } onreply_route[handle_nat] { if (nat_uac_test("1")) fix_nated_contact(); if ( isflagset(NAT) && has_body("application/sdp")) rtpproxy_answer("ro"); }
436
failure_route[timeout] { if (t_was_cancelled()) { xlog("L_NOTICE", "La transacción ha sido anulada"); exit; } if (t_check_status("408")) { prefix("EU"); } else if (t_check_status("486")) { prefix("EO"); } rewritehostport("IPPrivada:5090"); lb_count_call("$rd","$rp","1","channel"); record_route(); t_relay(); exit; } failure_route[GW_FAILOVER] { if (t_was_cancelled()) { exit; } # failure detection with redirect to next available trunk if (t_check_status("(408)|([56][0-9][0-9])")) { xlog("Failed trunk $rd/$du detected \n"); if ( load_balance("1","channel") ) { t_on_failure("GW_FAILOVER"); t_relay(); exit; } xlog("L_ERROR", "Recurso $du no disponible"); send_reply("500","All GW are down"); } } failure_route[msilo] { if (m_store()) { xlog("L_NOTICE","Mensaje fuera de linea almacenato"); t_reply("202", "Accepted"); } else { xlog("L_NOTICE","Mensaje fuera de linea no almacenato"); t_reply("503", "Service Unavailable"); } } local_route { if (is_method("BYE") && $DLG_dir=="UPSTREAM") {
437
acc_db_request("200 Dialog Timeout", "acc"); } }
438
Apéndice B Arquitectura de cuatro Servidores En esta apéndice se verá como configurar una arquitectura de cuatro servidores. Un servidor con la parte Web de A2Billing, un servidor con OpenSIPs y dos servidores con Asterisk. Aunque este tipo de escenario no garantice la alta disponibilidad (si se cae el servidor OpenSIPs se caen las llamadas), permite escalar horizontalmente (añadir servidores Asterisk) y al mismo tiempo realizar rutinas de mantenimiento de los mismos servidores Asterisk sin parar el servicio. Para esta configuración se utilizará 4 servidores del proveedor DigitalOcean, pero aplica a prácticamente cualquier tipo de proveedor de VPS. Al finalizar la configuración los clientes se registrarán y realizarán las llamadas utilizando OpenSIPs. Podrán autenticarse con usuario y contraseña o sobre IP. Se ha eliminado la llamada entre extensiones, el buzón de voz y la gestión de los números geográficos. Este tipo de arquitectura es pensada solamente para la venta de trafico VoIP sin servicios de valor añadido. Los Datos: Servidor 1 – Parte WEB - sip21 IPPublica: 45.55.177.251 IPPrivada: 10.132.111.9 Servidor 2 – OpenSIPs - sip20 IPPublica: 104.131.181.192 IPPrivada: 10.132.111.14 Servidor 3 – Asterisk1 - sip22 IPPublica: 104.131.3.193 IPPrivada: 10.132.111.10 Servidor 4 – Asterisk2 - sip23 IPPublica: 45.55.178.7 IPPrivada: 10.132.111.13 En todos los servidores: se actualiza el sistema: yum update -y se instala el editor de texto nano: yum install nano wget -y
se instalan los reposistorios EPEL: rpm -Uvh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm se modifica la zona horaria del servidor: rm /etc/localtime ln -s /usr/share/zoneinfo/America/Bogota /etc/localtime se modifica el idioma del servidor: nano /etc/sysconfig/i18n se modifica esta linea: LANG="en_US.UTF-8" para que quede (para Colombia): LANG="es_CO.iso88591" Se guardan los cambios. Se instala el servidor para la sincronización de la hora: yum install ntp -y chkconfig ntpd on service ntpd start Se instala el paquete de desarrollo del Kernel: yum install -y kernel-devel-$(uname -r) Se configuran algunos parámetros y alias para los comandos que más se utilizarán a lo largo del curso: nano .bash_profile al final del archivo se pegan las lineas que siguen: export EDITOR=/usr/bin/nano export PS1='\[\033[0;35m\]\H\[\033[0;33m\] \w\[\033[00m\]: ' alias free="free -m" Se recarga la configuración de la consola Linux: source .bash_profile Ya se puede reiniciar los servidores:
441
reboot B.1 Servidor WEB En el servidor Web se instalará la parte web de A2Billing y el servidor MySQL para gestionar la base de datos a2billing. Luego se configurará una replicación Maestro-Maestro de las base de datos con el servidor OpenSIPs. Se instala el servidor MySQL: yum install mysql mysql-server -y Se instala PHP y se modifican algunos parámetros de la configuración: yum install php php-gd php-mysql php-process httpd mod_ssl php-cli php-soap php-mcrypt -y nano +946 /etc/php.ini Se modifica la linea para que quede (personalizar con su zona horaria): date.timezone = America/Bogota En el mismo archivo se busca esta linea: upload_max_filesize = 2M y se modifica para que quede: upload_max_filesize = 8M De esta forma se podrán cargar los archivos de tarifas que tengan un tamaño de hasta de 8 MegaBytes. Siempre en el mismo archivo, se busca esta linea: error_reporting = E_ALL & ~E_DEPRECATED y se modifica para que quede: error_reporting = E_ALL & ~E_NOTICE Se guardan los cambios y se descarga la ultima versión disponible de A2Billing: cd /usr/local/src wget https://github.com/Star2Billing/a2billing/archive/v2.1.0.tar.gz
442
Se descomprime: tar -xf v2.1.0.tar.gz se renombra la carpeta creada: mv a2billing-2.1.0 a2billing Se procede con la configuración de MySQL para crear la base de datos a2billing: /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 poner en seguridad el servidor MySQL se ejecuta el programa: mysql_secure_installation Se contestan las preguntas somo sigue: Enter current password for root (enter for none): sesamo OK, successfully used password, moving on... Change the root password? [Y/n] n ... skipping. Remove anonymous users? [Y/n] y ... Success! Disallow root login remotely? [Y/n] y ... Success! Remove test database and access to it? [Y/n] y - Dropping test database... Reload privilege tables now? [Y/n] y ... Success! 443
Cleaning up... All done! If you've completed all of the above steps, your MySQL installation should now be secure. Thanks for using MySQL! Se configura la zona horaria en MySQL: mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -psesamo mysql Warning: Unable to load '/usr/share/zoneinfo/iso3166.tab' as time zone. Skipping it. Warning: Unable to load '/usr/share/zoneinfo/zone.tab' as time zone. Skipping it. nano /etc/my.cnf Bajo la etiqueta [mysqld] se añade (personalizar con su zona horaria): default-time-zone = America/Bogota Se reinicia el servidor MySQL: service mysqld restart se crea la base de datos a2billing: mysql> create database a2billing; Query OK, 1 row affected (0.00 sec) se otorgan los permisos de acceso a la base de datos creada al usuario a2user identificado con la contraseña sesamo (desde local): mysql> GRANT ALL PRIVILEGES ON a2billing.* TO 'a2user'@'localhost' IDENTIFIED BY 'sesamo'; Query OK, 0 rows affected (0.00 sec) se actualizan los permisos: mysql> flush privileges; Query OK, 0 rows affected (0.00 sec) se sale del cliente MySQL: mysql> quit Bye Se crean las tablas en la base de datos a2billing utilizando el script presente en la siguiente carpeta: 444
cd a2billing/DataBase/mysql-5.x/ se ejecuta: ./install-db.sh Se insertan los datos como mostrado en la imagen que sigue:
Para resumir: Database Name: a2billing Hostname: localhost Username: root Password: sesamo Se continua con la instalación copiando el archivo de configuración de a2billing en la carpeta /etc: cp /usr/local/src/a2billing/a2billing.conf /etc/ se abre con el editor: nano /etc/a2billing.conf se modifican estas lineas: [database] hostname = localhost port = user = a2billing_dbuser password = a2billing_dbpassword dbname = a2billing_dbname 445
dbtype = mysql para que queden: [database] hostname = 127.0.0.1 port = 3306 user = a2user password = sesamo dbname = a2billing dbtype = mysql Se guardan los cambios. Una vez terminada esta parte se crean una series de carpetas. La primera es donde se instalará la parte web de A2Billing: mkdir /var/www/html/a2billing La segunda donde se guardarán los archivos temporales y los script de A2Billing: mkdir -p /var/lib/a2billing/script la tercera donde se guardará el proceso de los script PHP que utilizar A2Billling para algunas tareas de mantenimiento y facturación: mkdir -p /var/run/a2billing Ahora ya se puede crear un enlace simbólico a las carpetas que se necesitan para la parte Web de A2billing que son: • • • •
admin (para la conexión de los administradores) customer (para la conexión de los clientes) agent (para la conexión de los agentes/revendedores) common (compartida por las demás tres)
ln -s /usr/local/src/a2billing/admin/ /var/www/html/a2billing/admin ln -s /usr/local/src/a2billing/agent/ /var/www/html/a2billing/agent ln -s /usr/local/src/a2billing/customer/ /var/www/html/a2billing/customer ln -s /usr/local/src/a2billing/common/ /var/www/html/a2billing/common Se cambian los permisos en estas tres carpetas donde se guardarán los archivos temporales para cada tipo de usuario: chmod 755 /usr/local/src/a2billing/admin/templates_c chmod 755 /usr/local/src/a2billing/customer/templates_c chmod 755 /usr/local/src/a2billing/agent/templates_c Se cambia el usuario y grupo que tiene acceso a todas las carpetas creadas (el servidor Web Apache): 446
chown -Rf apache:apache /var/www/html chown -Rf apache:apache /var/www/html/a2billing/admin/ chown -Rf apache:apache /var/www/html/a2billing/agent/ chown -Rf apache:apache /var/www/html/a2billing/customer/ chown -Rf apache:apache /var/www/html/a2billing/common/ Los registros de las actividades de A2Billing se guardan en una serie de archivos que hay que crear antes de acceder por primera vez a la pagina de administración. Primero se crea la carpeta: mkdir /var/log/a2billing se entra en la carpeta creada: cd /var/log/a2billing se crean los archivos: touch cront_a2b_alarm.log cront_a2b_autorefill.log cront_a2b_batch_process.log cront_a2b_archive_data.log cront_a2b_bill_diduse.log cront_a2b_subscription_fee.log cront_a2b_currency_update.log cront_a2b_invoice.log cront_a2b_check_account.log a2billing_paypal.log a2billing_epayment.log a2billing_api_ecommerce_request.log a2billing_api_callback_request.log a2billing_api_card.log a2billing_agi.log A2biblling necesita que se ejecuten una serie de script para monitorear el sistema y para elaborar algunas funciones (ejemplo: pagos, facturas, etc.). Estos script se añaden al cron del sistema: crontab -e Se pega el siguiente bloque de lineas: # A2Billing # Para actualizar la tasa de cambio de las monedas 0 6 * * * php /usr/local/src/a2billing/Cronjobs/currencies_update_yahoo.php # Para el pago se servicios subscritos 0 6 1 * * php /usr/local/src/a2billing/Cronjobs/a2billing_subscription_fee.php # Para notificaciones cuando el credito del cliente es más bajo de lo indicado 0 * * * * php /usr/local/src/a2billing/Cronjobs/a2billing_notify_account.php # Para el pago de los numeros geograficos asociados a los clientes 0 2 * * * php /usr/local/src/a2billing/Cronjobs/a2billing_bill_diduse.php # Para el pago de servicios periodicos 0 12 * * * php /usr/local/src/a2billing/Cronjobs/a2billing_batch_process.php # Para la generación de las facturas de los clientes 0 6 * * * php /usr/local/src/a2billing/Cronjobs/a2billing_batch_billing.php # Para la generación de llamadas automaticas utilizadas en las campañas # */5 * * * * php /usr/local/src/a2billing/Cronjobs/a2billing_batch_autodialer.php # Para la gestión de las alarmas que se pueden configurar en A2Billing 447
0 * * * * php /usr/local/src/a2billing/Cronjobs/a2billing_alarm.php # Para archivar los datos de las llamadas más viejos de lo indicado en la configuración de A2Billing 0 12 * * * php /usr/local/src/a2billing/Cronjobs/a2billing_archive_data_cront.php # Para recargar el crédito de un cliente en automatico 0 6 1 * * php /usr/local/src/a2billing/Cronjobs/a2billing_autorefill.php Se deja comentada la linea 8 del archivo ya que no se van a utilizar las campañas de llamadas. Se guardan las modificaciones e se reinicia Cron: /etc/init.d/crond restart Se continua con la instalación de un servidor de correo electrónico, SENDMAIL, que se utilizará para el envío de los correos electrónicos a los clientes de A2Billing y otras tareas: yum install sendmail sendmail-devel sendmail-cf -y Se configura para que arranque en automático: chkconfig sendmail on Por defecto el servidor de correo electrónico escucha solamente en la puerto TCP 25 local. Si se necesita que sea alcanzable desde remoto (para recibir correos electrónicos) hay que abrir el archivo de configuración de Sendmail: nano /etc/mail/sendmail.mc buscar esta linea (para buscar un texto con el editor Nano hay que presionar la combinación de teclas CTRL-W): DAEMON_OPTIONS(`Port=smtp,Addr=127.0.0.1, Name=MTA')dnl y modificar como sigue: DAEMON_OPTIONS(`Port=smtp,, Name=MTA')dnl se guardan los cambios y se vuelve a compilar la configuración de Sendmail: make -C /etc/mail se inicia el servidor de correo: /etc/init.d/sendmail start Se remueve el servidor de correo POSTFIX que viene por defecto: service postfix stop yum remove postfix -y 448
Se inicia el servidor Web y se configura para se inicie en automatico: service httpd start chkconfig httpd on B.1.1 Servidor Web Cortafuegos Para proteger el servidor Web de accesos no autorizados hay que instalar un firewall (cortafuegos) y abrir los puertos que la parte WEB necesita para aceptar conexiones externas. Para instalar iptables: yum install iptables -y Se acepta todo el trafico en entrada con destino la interfaz lookpack iptables -A INPUT -i lo -j ACCEPT Se rechaza (REJECT) todo el trafico entrante con destino 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 deja pasar todos los paquetes salientes. iptables -A OUTPUT -j ACCEPT Se deja pasar todo el trafico en entrada para el protocolo SSH (puerto 22 tcp) iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT Se deja pasar todo el trafico en entrada para el protocolo SMTP (puerto 25 tcp) SOLAMENTE si se necesita utilizar el servidor de correo electrónico SENDMAIL para correos entrantes: iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 25 -j ACCEPT Se deja pasar todo el trafico en entrada para el protocolo HTTP (puerto 80 tcp) iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT Se deja pasar todo el trafico en entrada para el protocolo HTTPs (puerto 443 tcp)
449
iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT Se deja abierto el puerto 3306 (servidor MySQL) para la IPPrivada del servidor OpenSIPs para cuando se configurará la replicación Maestro-Maestro: iptables -A INPUT -p tcp -m state -m tcp --dport 3306 --state NEW -s 10.132.111.14 -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 REJECT iptables -A FORWARD -j REJECT Se averigua el estado de las reglas definidas con el comando: iptables -L Chain INPUT (policy ACCEPT) target prot opt source destination ACCEPT all -- anywhere anywhere REJECT all -- anywhere loopback/8 ACCEPT all -- anywhere anywhere ACCEPT tcp -- anywhere anywhere ACCEPT tcp -- anywhere anywhere ACCEPT tcp -- anywhere anywhere ACCEPT tcp -- anywhere anywhere ACCEPT tcp -- 10.132.111.9 anywhere ACCEPT icmp -- anywhere anywhere REJECT all -- anywhere anywhere
reject-with icmp-port-unreachable state RELATED,ESTABLISHED state NEW tcp dpt:ssh state NEW tcp dpt:smtp state NEW tcp dpt:http state NEW tcp dpt:https state NEW tcp dpt:mysql icmp echo-request reject-with icmp-port-unreachable
Chain FORWARD (policy ACCEPT) target prot opt source destination REJECT all -- anywhere anywhere
reject-with icmp-port-unreachable
Chain OUTPUT (policy ACCEPT) target prot opt source destination ACCEPT all -- anywhere anywhere Para guardar los cambios: service iptables save iptables: Guardando las reglas del cortafuegos en /etc/sysconfig/iptables [ OK ]
450
Se inicia el servicio: service iptables start Se intenta acceder a la pagina de administración de A2Billing utilizando la IPPublica del servidor: http://IPPublica/a2billing/admin Si todo se ha instalado correctamente debería aparecer la pagina de administración de A2Billing. Ahora se configura A2Billing a partir del SYSTEM SETTINGS y continuando hasta llegar a la creación de los clientes. B.2 Servidor OpenSIPs En el servidor OpenSIPs se instalan las dependencias para la instalación de OpenSIPs y la base de datos de OpenSIPs, Asterisk y A2Billing. Esta ultima se configurará luego con la replicación MaestroMaestro con el servidor Web: yum install gcc ncurses-devel make gcc-c++ compat-libtermcap zlib-devel libtool bison \ bison-devel openssl-devel bzip2-devel wget newt-devel subversion flex gtk2-devel expat-devel -y yum install mysql mysql-devel mysql-server -y yum install unixODBC unixODBC-devel mysql-connector-odbc libtool-ltdl-devel -y yum install xmlrpc-c-devel lynx pcre pcre-devel gdb libxml2 libxml2-devel -y yum install net-snmp net-snmp-devel net-snmp-libs net-snmp-utils -y yum install git -y Se descarga la ultima versión disponible de OpenSIPs de la rama 1.11: cd /usr/src git clone https://github.com/OpenSIPS/opensips.git -b 1.11 opensips_1_11 Se entra en la carpeta creada: cd opensips_1_11 Se ejecuta el comando que permite la configuración e instalación a través de un menú gráfico: make menuconfig en el menú que aparece: 451
se escoge la opción “Configure Compile Options”:
en el siguiente menú se selecciona “Configure Excluded Modules”:
452
Se seleccionan los módulos que aparecen en las dos imágenes. Se vuelve al menú anterior con la tecla ←
Se selecciona el menú “Configure Install Prefix”:
y se pone la / come carpeta de instalación. Se presiona la tecla Enter dos veces y se selecciona la opción “Save Changes”:
453
Se presiona la tecla Enter hasta que no aparezcan más notificaciones en la linea de comando. Se vuelve al menú anterior con la tecla ←
En el menú principal se selecciona “Compile And Install OpensSIPs”. Empezará la compilación e instalación de Opensips. Terminada la operación aparecerá el siguiente mensaje:
Se presiona la tecla Enter y se volverá el menú Principal:
Para salir del menuconfig se selecciona la opción “Exit & Save Changes” y se presiona la tecla Enter hasta volver al prompt de Linux. Se instala el script de arranque para Opensips: cd packaging/fedora nano opensips.init Se modifica esta línea: opensips=/usr/sbin/$prog para que quede: opensips=/sbin/$prog Se guardan los cambios y se continua con la configuración: 454
chmod 755 opensips.init cp opensips.init /etc/init.d/opensips chkconfig --add opensips chkconfig opensips on Se crean usuario y grupo “opensips” requeridos por el script de arranque: groupadd opensips mkdir /var/run/opensips useradd -d /var/run/opensips/ -s /bin/false -g opensips opensips useradd: aviso: el directorio personal ya existe. No se copia ningún fichero del directorio skel en él. chown -R opensips.opensips /var/run/opensips Se renombra el archivo de configuración predefinido: mv /etc/opensips/opensips.cfg /etc/opensips/opensips.cfg.old Se crea uno nuevo: nano /etc/opensips/opensips.cfg ####### Global Parameters ######### debug=3 log_stderror=no log_facility=LOG_LOCAL0 fork=yes children=4 auto_aliases=no listen=udp:IPPublica:5060 disable_tcp=yes disable_tls=yes user_agent_header="User-Agent: VozToVoice Proxy Agent" server_header="Server: VozToVoice Proxy Server" ####### Modules Section ########
455
#set module path mpath="/lib64/opensips/modules/" #### SIGNALING module loadmodule "signaling.so" #### StateLess module loadmodule "sl.so" #### Transaction Module loadmodule "tm.so" modparam("tm", "fr_timeout", 5) modparam("tm", "fr_inv_timeout", 60) modparam("tm", "restart_fr_on_each_reply", 0) modparam("tm", "onreply_avp_mode", 1) #### Record Route Module loadmodule "rr.so" modparam("rr", "append_fromtag", 0) #### MAX ForWarD module loadmodule "maxfwd.so" #### SIP MSG OPerationS module loadmodule "sipmsgops.so" #### FIFO Management Interface loadmodule "mi_fifo.so" modparam("mi_fifo", "fifo_name", "/tmp/opensips_fifo") modparam("mi_fifo", "fifo_mode", 0666) #### URI module loadmodule "uri.so" modparam("uri", "db_url", "mysql://opensips:opensipsrw@localhost/opensips") modparam("uri", "use_uri_table", 0) #### MYSQL module loadmodule "db_mysql.so" #### AUTH module loadmodule "auth.so" ##### AUTH_DB module loadmodule "auth_db.so" modparam("auth_db", "db_url", "mysql://opensips:opensipsrw@localhost/opensips")
456
#### AVPOPS module loadmodule "avpops.so" #### ACCounting module loadmodule "acc.so" modparam("acc", "early_media", 0) modparam("acc", "report_cancels", 0) modparam("acc", "detect_direction", 0) modparam("acc", "failed_transaction_flag", "ACC_FAILED") modparam("acc", "db_flag", "ACC_DO") modparam("acc", "db_missed_flag", "ACC_MISSED") modparam("acc", "cdr_flag", "CDR_FLAG") modparam("acc", "db_url", "mysql://opensips:opensipsrw@localhost/opensips") #### DIALOG module loadmodule "dialog.so" modparam("dialog", "dlg_match_mode", 1) modparam("dialog", "default_timeout", 21600) modparam("dialog", "db_mode", 2) modparam("dialog", "db_url","mysql://opensips:opensipsrw@localhost/opensips") #### LOAD BALANCER module loadmodule "load_balancer.so" modparam("load_balancer","db_url","mysql://opensips:opensipsrw@localhost/opensips") modparam("load_balancer", "probing_method", "OPTIONS") modparam("load_balancer", "probing_interval", 30) modparam("load_balancer", "probing_reply_codes", "404") #### LOCATION module loadmodule "usrloc.so" modparam("usrloc", "nat_bflag", "NAT_BFLAG") modparam("usrloc", "db_url","mysql://opensips:opensipsrw@localhost/opensips") modparam("usrloc", "db_mode", 3) #### REGISTRAR module loadmodule "registrar.so" modparam("registrar", "max_contacts", 5) modparam("registrar", "received_avp", "$avp(received_nh)") #### PERMISSIONS module loadmodule "permissions.so" modparam("permissions", "db_url","mysql://opensips:opensipsrw@localhost/opensips") #### LOAD OPTIONS module loadmodule "options.so" 457
#### NATHELPER modules loadmodule "nathelper.so" modparam("nathelper", "natping_interval", 10) modparam("nathelper", "ping_nated_only", 0) modparam("nathelper", "received_avp", "$avp(received_nh)") ####### Routing Logic ######## route{ force_rport(); if (nat_uac_test("31")) { if (is_method("REGISTER")) { fix_nated_register(); setbflag(NAT); } else { fix_nated_contact(); setflag(NAT); } } if (!mf_process_maxfwd_header("10")) { xlog("L_ERROR","Superado el numero máximo de FORWARD Permitidos"); sl_send_reply("483","Too Many Hops"); exit; } if (has_totag()) { xlog("L_NOTICE", "La transacción tiene un tag en la cabecera To:"); if (loose_route()) { if ( $DLG_status!=NULL && !validate_dialog() ) { xlog("L_ERROR", "El Dialogo $rm de $si (CALLERID=$ci) no es valido"); ## exit; } if (is_method("BYE")) { setflag(ACC_DO); setflag(ACC_FAILED); xlog("L_NOTICE", "Recibido un BYE dentro de un dialogo"); } else if (is_method("INVITE")) { xlog("L_NOTICE", "Recibido un re-INVITE dentro de un dialogo"); record_route(); }
458
route(RELAY); } else { if ( is_method("ACK") ) { if ( t_check_trans() ) { xlog("L_NOTICE", "Recibido un ACK dentro de un dialogo"); t_relay(); exit; } else { exit; } } sl_send_reply("404","Not here"); xlog("L_ERROR", "Recibida una petición sin Dialogo asociado"); } exit; } #### INITIAL REQUESTS if ((method==OPTIONS) && (! uri=~"sip:.*[@]+.*")) { options_reply(); exit; } if (is_method("CANCEL")) { if (t_check_trans()) t_relay(); xlog("L_NOTICE", "Recibido un CANCEL relacionado con una transacción valida"); exit; } if (is_method("REGISTER")) { $var(autent_cod) = www_authorize("", "subscriber"); if ( $var(autent_cod) == -1 || $var(autent_cod) == -2 ) { xlog("L_NOTICE","error de autent para $fU@$fd desde $si causa $var(autent_cod)"); sl_send_reply("403","Te he pillado"); exit; } if ( $var(autent_cod) < 0 ) { www_challenge("", "0"); exit; } save("location"); consume_credentials(); xlog("L_NOTICE","Usuario $fU Registrado"); 459
exit; } if (!is_method("INVITE")) { send_reply("405","Method Not Allowed"); xlog("L_ERROR", "Solicitud recibida $rm no es un INVITE"); exit; } if ($rU==NULL) { sl_send_reply("484","Address Incomplete"); xlog("L_ERROR", "El usuario $rU no es valido"); exit; } t_check_trans(); # preloaded route checking if (loose_route()) { xlog("L_ERR","Attempt to route with preloaded Route's [$fu/$tu/$ru/$ci]"); if (!is_method("ACK")) sl_send_reply("403","Preload Route denied"); sl_send_reply("403","Preload Route denied"); exit; } if(!uri==myself) { xlog("La solicitud no es local. Descartada"); sl_send_reply("404","Not Here"); exit; } if (is_method("INVITE")) { if (check_source_address("0","$avp(accountcode)")) { xlog("L_NOTICE","La IP $si es una dirección autorizada"); append_hf("P-Accountcode: $avp(accountcode)\r\n"); } else { $var(invite_cod) = proxy_authorize("", "subscriber"); if ( $var(invite_cod) == -1 || $var(invite_cod) == -2 ) { xlog("L_NOTICE","error de autent para $fU@$fd desde $si causa $var(invite_cod)");
sl_send_reply("403","Te he pillado"); exit; } if ( $var(invite_cod) < 0 ) { proxy_challenge("", "0"); exit; } xlog("L_NOTICE","INVITE del Usuario $fU Autenticado"); 460
consume_credentials(); } } # record routing record_route(); setflag(ACC_DO); setflag(CDR_FLAG); setflag(ACC_MISSED); if ( !load_balance("1","channel")) { send_reply("500","No Destination available"); exit; } xlog("L_NOTICE", "Llamada de $fu IP $si $sp a $tu para $du"); t_on_failure("GW_FAILOVER"); route(RELAY); } route[RELAY] { if (!t_relay()) { sl_reply_error(); }; exit; } failure_route[GW_FAILOVER] { if (t_was_cancelled()) { exit; } # failure detection with redirect to next available trunk if (t_check_status("(408)|([56][0-9][0-9])")) { xlog("Failed trunk $rd/$du detected \n"); if ( load_balance("1","channel") ) { t_on_failure("GW_FAILOVER"); t_relay(); exit; } xlog("L_ERROR", "Recurso $du no disponible"); send_reply("500","All GW are down"); 461
} } local_route { if (is_method("BYE") && $DLG_dir=="UPSTREAM") { acc_db_request("200 Dialog Timeout", "acc"); } } Antes de guardar los cambios, modificar esta linea: listen=udp:IPPublica:5060 Cambiando IPPublica con la IPPublica del servidor. Personalizar estás dos lineas: user_agent_header="User-Agent: VozToVoice Proxy Agent" server_header="Server: VozToVoice Proxy Server" Luego se configura RSYSLOG para guardar el LOG de OpenSIPs en un archivo separado: nano /etc/rsyslog.conf antes de esta linea: local7.*
/var/log/boot.log
ponemos: local0.*
-/var/log/opensips.log
Se guardan los cambios y se crea el archivo opensips.log: touch /var/log/opensips.log se reinicia rsyslog: /etc/init.d/rsyslog restart Se inicia el servidor MySQL: service mysqld start se configura para que arranque en automático: chkconfig mysqld on 462
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 poner en seguridad el servidor MySQL se ejecuta el programa: mysql_secure_installation Se contestan las preguntas somo sigue: Enter current password for root (enter for none): sesamo OK, successfully used password, moving on... Change the root password? [Y/n] n ... skipping. Remove anonymous users? [Y/n] y ... Success! Disallow root login remotely? [Y/n] y ... Success! Remove test database and access to it? [Y/n] y - Dropping test database... Reload privilege tables now? [Y/n] y ... Success! Cleaning up... All done! If you've completed all of the above steps, your MySQL installation should now be secure. Thanks for using MySQL! Se configura la zona horaria en MySQL: mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -psesamo mysql Warning: Unable to load '/usr/share/zoneinfo/iso3166.tab' as time zone. Skipping it. Warning: Unable to load '/usr/share/zoneinfo/zone.tab' as time zone. Skipping it. nano /etc/my.cnf 463
Bajo la etiqueta [mysqld] se añade (personalizar con su zona horaria): default-time-zone = America/Bogota Se reinicia el servidor MySQL: service mysqld restart Se crea la base de datos para guardar los registros de las llamadas de Asterisk. Se entra en el cliente de MySQL: mysql -u root -psesamo se crea la base de datos asterisk: mysql> create database asterisk; se selecciona: mysql> use asterisk 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) ); 464
Se otorgan los permisos para acceder a la base de datos Asterisk al usuario asterisk desde la IPPrivada del servidor Asterisk1 y la IPPrivada del servidor Asterisk2: mysql> GRANT ALL PRIVILEGES ON asterisk.* TO 'asterisk'@'10.132.111.10' IDENTIFIED BY 'sesamo'; Query OK, 0 rows affected (0.00 sec) mysql> GRANT ALL PRIVILEGES ON asterisk.* TO 'asterisk'@'10.132.111.13' IDENTIFIED BY 'sesamo'; Query OK, 0 rows affected (0.00 sec) Se sale del cliente MySQL: mysql> quit Se continua con la preparación de la creación de la base de datos opensisp. Se renombra el archivo a partir del cual se crea la base de datos opensips: mv /etc/opensips/opensipsctlrc /etc/opensips/opensipsctlrc.old Se crea uno nuevo: nano /etc/opensips/opensipsctlrc se copian las lineas que siguen: SIP_DOMAIN=IPPublica DBENGINE=MYSQL DBHOST=localhost DBNAME=opensips DBRWUSER=opensips DBRWPW="opensipsrw" DBROOTUSER="root" INSTALL_EXTRA_TABLES=ask INSTALL_PRESENCE_TABLES=ask ALIASES_TYPE="DB" OSIPS_FIFO="/tmp/opensips_fifo" VERIFY_ACL=1 PID_FILE=/var/run/opensips.pid Antes de guardar los cambios hay que modificar la primera linea y en lugar de IPPublica poner la IP Publica del servidor. Se guardan los cambios. La aplicación para crear la base de datos es opensipsdbctl. Ejecutando el comando sin opciones aparecerán todas las posibilidades disponibles. En nuestro caso se utiliza create: opensipsdbctl create MySQL password for root: INFO: test server charset 465
INFO: creating database opensips ... INFO: Core OpenSIPS tables succesfully created. Install presence related tables? (y/n): y INFO: creating presence tables into opensips ... INFO: Presence tables succesfully created. Install tables for imc cpl siptrace domainpolicy carrierroute userblacklist b2b registrant call_center? (y/n): y INFO: creating extra tables into opensips ... INFO: Extra tables succesfully created. Primero preguntará por la contraseña de root (sesamo) y luego si se quieren crear también las tablas para el modulo de presencia y para otros módulos disponibles en OpenSIPs. Se contesta con yes a las dos preguntas. Ahora que la base de datos está creada, el paso a seguir es averiguar que la configuración de OpenSIPs esté sin errores. El comando para realizar esta operación es: opensips -c /etc/opensips/opensips.cfg El resultado será: Apr 2 12:57:16 [652] WARNING:core:warn: warning in config file //etc/opensips/opensips.cfg, line 12, column 13-16: tls support not compiled in Listening on udp: 104.131.181.192 [104.131.181.192]:5060 Aliases: Apr 2 12:57:16 [652] NOTICE:core:main: config file ok, exiting... Ya se puede iniciar OpenSIPs: service opensips start Starting opensips:
[ OK ]
Si no aparecen errores significa que el programa se ha iniciado con éxito. Se puede revisar el archivo de log para ver si hay algún problema: nano /var/log/opensips.log Se entra nuevamente en el cliente MySQL: mysql -u root -p sesamo base de datos OpenSIPs: mysql> use opensips
466
y se añaden los dos servidores Asterisk a la tabla load_balancer: mysql> insert into load_balancer (group_id,dst_uri,resources,probe_mode,description) values ('1','sip:IPAsterisk1','channel=40','2','Asterisk1'); antes de presionar la tecla Envío, cambiar IPAsterisk1 con la IP publica del servidor Asterisk1 mysql> insert into load_balancer (group_id,dst_uri,resources,probe_mode,description) values ('1','sip:IPAsterisk2','channel=40','2','Asterisk2'); antes de presionar la tecla Envío, cambiar IPAsterisk2 con la IP publica del servidor Asterisk2. Se sale del cliente MySQL: mysql> quit se recarga el modulo load_balancer en OpenSIPs: opensipsctl fifo lb_reload y se mira el resultado: opensipsctl fifo lb_list Destination:: sip:104.131.3.193 id=1 group=1 enabled=no auto-re=on Resources:: Resource:: channel max=40 load=0 Destination:: sip:45.55.178.7 id=2 group=1 enabled=no auto-re=on Resources:: Resource:: channel max=40 load=0 Después de unos segundos los dos recursos aparecerán no disponibles (enabled=no) ya que todavía no se han instalados y configurados los servidores Asterisk. B.2.1 Servidor OpenSIPs cortafuegos Para proteger el servidor OpenSIPs de accesos no autorizados hay que instalar un firewall (cortafuegos) y abrir los puertos que OpenSIPs necesita para aceptar conexiones externas. Para instalar iptables: yum install iptables -y Se acepta todo el trafico en entrada con destino la interfaz lookpack iptables -A INPUT -i lo -j ACCEPT Se rechaza (REJECT) todo el trafico entrante con destino las IP 127.0.0.0/127.255.255.255 menos los paquetes para la interfaz -lo
467
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 deja pasar todos los paquetes salientes. iptables -A OUTPUT -j ACCEPT Se deja pasar todo el trafico en entrada para el protocolo SSH (puerto 22 tcp) iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT Se deja abierto el puerto 3306 (servidor MySQL) para la IPPrivada del servidor Web, para la configuración de la replicación Maestro-Maestro, y para las IPs privadas de los dos servidores Asterisk para la conexión a la base de datos a2billing y asterisk: iptables -A INPUT -p tcp -m state -m tcp --dport 3306 --state NEW -s 10.132.111.9 -j ACCEPT iptables -A INPUT -p tcp -m state -m tcp --dport 3306 --state NEW -s 10.132.111.10 -j ACCEPT iptables -A INPUT -p tcp -m state -m tcp --dport 3306 --state NEW -s 10.132.111.13 -j ACCEPT Se bloquea el trafico sobre el puerto 5060 para los más conocidos programas de escaneo de servidores SIP utilizado para ataques y fraudes de llamadas: iptables -A INPUT -p udp -m udp --dport 5060 -m string --string "friendly-scanner" --algo bm -j DROP
iptables -A INPUT -p udp -m udp --dport 5060 -m string --string "sipcli" --algo bm -j DROP iptables -A INPUT -p udp -m udp --dport 5060 -m string --string "VaxSIPUserAgent/3.0" --algo bm -j DROP
iptables -A INPUT -p udp -m udp --dport 5060 -m string --string "sipvicious" --algo bm -j DROP Solamente ahora 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 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.
468
iptables -A INPUT -j REJECT iptables -A FORWARD -j REJECT Se averigua el estado de las reglas definidas con el comando: iptables -L Chain INPUT (policy ACCEPT) target prot opt source destination ACCEPT all -- anywhere anywhere REJECT all -- anywhere loopback/8 reject-with icmp-port-unreachable ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED ACCEPT tcp -- anywhere anywhere state NEW tcp dpt:ssh ACCEPT tcp -- 10.132.111.9 anywhere state NEW tcp dpt:mysql ACCEPT tcp -- 10.132.111.10 anywhere state NEW tcp dpt:mysql ACCEPT tcp -- 10.132.111.13 anywhere state NEW tcp dpt:mysql DROP udp -- anywhere anywhere udp dpt:sip STRING match "friendly-scanner" ALGO name bm TO 65535 DROP udp -- anywhere anywhere udp dpt:sip STRING match "sipcli" ALGO name bm TO 65535 DROP udp -- anywhere anywhere udp dpt:sip STRING match "VaxSIPUserAgent/3.0" ALGO name bm TO 65535 DROP udp -- anywhere anywhere udp dpt:sip STRING match "sipvicious" ALGO name bm TO 65535 ACCEPT udp -- anywhere anywhere udp dpt:sip ACCEPT icmp -- anywhere anywhere icmp echo-request REJECT all -- anywhere anywhere reject-with icmp-port-unreachable Chain FORWARD (policy ACCEPT) target prot opt source destination REJECT all -- anywhere anywhere
reject-with icmp-port-unreachable
Chain OUTPUT (policy ACCEPT) target prot opt source destination ACCEPT all -- anywhere anywhere Para guardar los cambios: service iptables save iptables: Guardando las reglas del cortafuegos en /etc/sysconfig/iptables [ OK ] Se inicia el servicio: service iptables start Para iniciar iptables automáticamente:
469
chkconfig iptables on Se continua con la replicación Maestro-Maestro de la base de datos a2billing entre el servidor Web y el servidor OpenSIPs. B.3 Replicación Maestro-Maestro A2Bbilling La bases de datos a2billing ya existe y está configurada en el Servidor Web. Partiendo de este hecho se inicia la configuración de la replicación. B.3.1 Servidor Web Se crea una carpeta donde guardar los Binary log de MySQL. Los Binary log son los archivos donde el servidor MySQL guarda los cambios realizados en la base de datos a2billing: mkdir /var/log/mysql se cambia usuario y grupo que tiene los permisos en la carpeta creada: chown mysql:mysql /var/log/mysql Se entra en el cliente MySQL y se crean los privilegios de replicación para un nuevo usuario: mysql -u root -psesamo mysql> GRANT REPLICATION SLAVE ON *.* TO 'masteros'@'IPPrivadaOS' IDENTIFIED BY 'sesamo'; antes de ejecutar el comando, se modifica IPPrivadaOS con la IP privada del VPS OpenSIPS. Se actualizan los privilegios: mysql> flush privileges; se sale del cliente MySQL mysql> quit Se modifica el archivo de configuración de MySQL: nano /etc/my.cnf bajo la etiqueta [mysqld] se pone: server-id = 10 auto_increment_increment = 10 470
auto_increment_offset = 1 log_bin = /var/log/mysql/mysql-bin.log expire_logs_days = 10 max_binlog_size = 10M replicate-do-db =a2billing sync_binlog =1 Los parámetros: • • •
• • • • •
server-id: identifica de manera univoca el servidor MySQL Con auto_increment_increment en 10 cada entrada en la base de datos a2billing tendrá un ID progresivo que irá de 10 en 10. Con auto_increment_offset en 1 cada entrada usará el entero 1. En el caso de tres entradas el resultado será: • ID 11 • ID 21 • ID 31 log_bin: nombre del archivo donde se guardará el Binary log expire_log_days: especifica el numero de días que se guardarán los Binary log (10) antes de borrarlos max_binlog_size: el tamaño máximo de un Binary log (10 MegaByte) binlog_do_db: el nombre de las base de datos que se va a replicar (a2billing) sync_binlog: cada evento generado en el Master será escrito inmediatamente en el Binary log. Aumenta la carga del Master a cambio de una replicación más precisa. IMPORTANTE: en el caso de sistemas con muchas llamadas por segundo, es mejor deshabilitar esta opción (poner 0)
Se guardan los cambios y se reinicia mysql: /etc/init.d/mysqld restart Considerando que la base de datos A2Billing ya contiene bastantes datos, hay que crear una copia para luego importarla en el Servidor OpenSIPs: mysql -u root -psesamo Se bloquea la escritura en todas las tablas de las base de datos: mysql> FLUSH TABLES WITH READ LOCK; Por ultimo se mira el estado del Maestro: mysql> SHOW MASTER STATUS; Aparecerá algo por el estilo:
471
Se anotan los datos que aparecen en la columna File (mysql-bin.000001) y en la columna Position (106); sin cerrar esta ventana, se abre otra ventana terminal o otra conexión al Servidor Web y se crea una copia de la bases de datos: cd /tmp mysqldump -u root -psesamo a2billing > a2billing.sql se copia el archivo en la carpeta tmp del Servidor OpenSIPs: scp a2billing.sql root@IPPublicaOS:/tmp Se modifica IPPublicaOS con la dirección IP publica del servidor OpenSIPs. Terminada la operación se cierra esta ventana terminal y se regresa a la primera donde se desbloquean las tablas: mysql> UNLOCK TABLES; y se sale del cliente MySQL: mysql> quit B.3.2 Servidor OpenSIPs 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 a2billing: mysql -u root -psesamo mysql> create database a2billing; Se sale del cliente MySQL: mysql> quit
472
Se importa la base de datos: cd /tmp mysql -u root -psesamo a2billing < a2billing.sql Se averigua que efectivamente las tabla y los datos presentes se han guardado: mysql -u root -psesamo mysql> use a2billing mysql> select * from cc_sip_buddies; Aparecerán las mismas entradas del Servidor Web. Se crea un nuevo usuario con los permisos de replicación: mysql> GRANT REPLICATION IDENTIFIED BY 'sesamo';
SLAVE
ON
*.*
TO
'masterweb'@'IPPrivadaWeb'
cambiar IPPrivadaWeb con la IP privada del Servidor Web. Se actualizan los permisos y se sale del cliente MySQL: mysql> flush privileges; mysql> quit Ahora se modifica el archivo de configuración de MySQL: nano /etc/my.cnf bajo la etiqueta [mysqld] se pone: server-id = 20 auto_increment_increment = 10 auto_increment_offset = 2 log_bin = /var/log/mysql/mysql-bin.log expire_logs_days = 10 max_binlog_size = 10M replicate-do-db =a2billing sync_binlog =1 El auto_increment_offset es igual a 2. En el caso de tres entradas el ID será: ID 12 ID 22 ID 32 473
Como se puede ver, de esta forma no se presentarán conflictos en las entradas de cualquier tabla de la base de datos A2Billing. Se reinicia Mysql: /etc/init.d/mysqld restart Ahora como para el Servidor Web, se mira el Binary log y se anotan los datos: mysql -u root -psesamo mysql> FLUSH TABLES WITH READ LOCK; mysql> SHOW MASTER STATUS;
mysql> UNLOCK TABLES; mysql> quit Ahora se conecta el Servidor OpenSIPs al Servidor Web: mysql -u root -psesamo Se cambia IPPrivadaWeb con la IP privada del Servidor Web, MASTER_LOG_FILE y MASTER_LOG_POS con los datos devueltos por el comando SHOW MASTER STATUS en el Servidor Web mysql> CHANGE MASTER TO MASTER_HOST='IPPrivadaWeb', MASTER_USER='masteros', MASTER_PASSWORD='sesamo', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=106; 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: 474
mysql> SHOW SLAVE STATUS\G
Se sigue el mismo procedimiento en el Servidor Web: Se entra en cliente MySQL: mysql -u root -psesamo Se cambia IPPrivadaOS con la IP privada del Servidor OpenSIPs, MASTER_LOG_FILE y MASTER_LOG_POS con los datos devueltos por el comando SHOW MASTER STATUS en el 475
Servidor OpenSIPs mysql> CHANGE MASTER TO MASTER_HOST='IPPrivadaOS', MASTER_USER='masterweb', MASTER_PASSWORD='sesamo', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=269; Query OK, 0 rows affected (0.10 sec) mysql> START SLAVE; Query OK, 0 rows affected (0.00 sec) mysql> SHOW SLAVE STATUS\G
476
¿Cómo hay la certeza que la replicación está funcionando correctamente? Con los valores de estos dos parámetros: • •
Slave_IO_Running: Yes Slave_SQL_Running: Yes
Se crean también los permisos para que los dos servidores Asterisk se puedan conectar a la base de datos a2billing presente en el servidor OpenSIPs: mysql> GRANT ALL PRIVILEGES ON a2billing.* TO 'a2user'@'10.132.111.10' IDENTIFIED BY 'sesamo'; Query OK, 0 rows affected (0.00 sec) 477
mysql> GRANT ALL PRIVILEGES ON a2billing.* TO 'a2user'@'10.132.111.13' IDENTIFIED BY 'sesamo'; Query OK, 0 rows affected (0.00 sec) Se sale del cliente MYSQL: mysql> quit B.3.3 Tabla subscriber_v1 Ahora que la replicación está configurada, se puede pasar a la creación de la vista de la tabla cc_sip_buddies de A2Billing en una nueva tabla en OpenSIPs. La nueva tabla es la que OpenSIPs utilizará para buscar las credenciales de cada extensión. El esquema es igual a la tabla predefinida de opensips que es subscriber. En el servidor OpenSIPs: mysql -u root -psesamo mysql> use opensips mysql> desc subscriber;
Se crea la vista (modificar IPPublicaOS con la IP publica de su Servidor OpenSIPs): mysql> CREATE VIEW opensips.subscriber_v1 AS SELECT id AS id, name AS username, 'IPPublicaOS' AS domain, secret AS password, md5(concat(username, ':', 'IPPublicaOS', ':', secret)) AS ha1, md5(concat(username, '@', 'IPPublicaOS', ':', 'IPPublicaOS', ':', secret)) AS ha1b, name AS rpid from a2billing.cc_sip_buddies; La nueva tabla contendrá todos valore de las extensiones SIP configuradas en A2Billing. Se puede comprobar con el comando:
478
mysql> select * from subscriber_v1; Cada tabla en OpenSIPs tiene un valor de versión que OpenSIPs utiliza para su validación. En el caso de la tabla subscriber este valor es: mysql> select * from version where table_name='subscriber';
Se asigna el mismo valor a la nueva tabla subscriber_v1: mysql> INSERT INTO version (table_name,table_version) VALUES ('subscriber_v1','7'); El resultado: mysql> select * from version where table_name='subscriber_v1';
Ya se puede salir del cliente MySQL: mysql> quit Ahora falta modificar el archivo de configuración de OpenSIPs para que utilice esa tabla para autenticar los REGISTER y los INVITES recibidos. Se abre el archivo de configuración: nano /etc/opensips/opensips.cfg se modifica las dos lineas que siguen: $var(autent_cod) = www_authorize("", "subscriber"); } else { $var(invite_cod) = proxy_authorize("", "subscriber"); para que queden: $var(autent_cod) = www_authorize("", "subscriber_v1"); } else { $var(invite_cod) = proxy_authorize("", "subscriber_v1");
479
Se guardan los cambios y se reinicia OpenSIPs: service opensips restart A partir de este momento las extensiones configuradas en A2Billing se registrarán y sacarán las llamadas pasando por el servidor OpenSIPs. Lo podrán hacer solamente utilizando la IPPublica del servidor OpenSIPs y no el nombre de dominio ya que la vista se ha creado utilizando la IPPublica. Se termina con las instalación y configuración de los dos servidores Asterisk. B.4 Servidores Asterisk1 y Asterisk2 En los dos servidores Asterisk se instalan las dependencias para la instalación de Asterisk PBX, A2Billing para los AGI (sin el callback) y la configuración del cortafuegos. B.4.1 Asterisk PBX yum install libvorbis libvorbis-devel vorbis-tools libogg libogg-devel -y yum install gsm gsm-devel gsm-tools -y yum install curl curl-devel libidn-devel -y yum install gcc ncurses-devel make gcc-c++ compat-libtermcap zlib-devel libtool bison \ bison-devel openssl-devel bzip2-devel wget newt-devel subversion flex gtk2-devel -y yum install mysql mysql-devel -y yum install unixODBC unixODBC-devel mysql-connector-odbc libtool-ltdl-devel -y yum install sqlite sqlite-devel -y yum install festival festival-devel hispavoces-pal-diphone hispavoces-sfl-diphone -y yum install libuuid libuuid-devel uuid uuid-devel -y yum install speex speex-devel wavpack wavpack-devel -y cd /usr/src wget http://downloads.sourceforge.net/project/sox/sox/14.4.1/sox-14.4.1.tar.gz tar -xf sox-14.4.1.tar.gz cd sox-14.4.1 ./configure --prefix=/usr --libdir=/usr/lib64 make make install 480
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.10.0.1 make make install cd /usr/src wget http://downloads.asterisk.org/pub/telephony/dahdi-tools/dahdi-tools-current.tar.gz tar -xf dahdi-tools-current.tar.gz cd dahdi-tools-2.10.0.1 ./configure make make install make config /etc/init.d/dahdi start yum install libtiff libtiff-devel libxml2 libxml2-devel -y yum install spandsp spandsp-apidoc spandsp-devel -y yum install gnutls gnutls-devel gnutls-utils -y yum install iksemel iksemel-devel iksemel-utils -y yum install compat-openldap openldap openldap-clients openldap-devel openldap-servers -y yum install net-snmp net-snmp-devel net-snmp-libs net-snmp-utils -y yum install radiusclient-ng radiusclient-ng-devel radiusclient-ng-utils -y yum install lua lua-devel -y yum install libical libical-devel neon neon-devel -y yum install git words -y cd /usr/src git clone https://github.com/cisco/libsrtp libsrtp cd libsrtp ./configure --prefix=/usr CFLAGS=-fPIC --libdir=/usr/lib64 make make runtest make install
481
cd /usr/src wget http://downloads.asterisk.org/pub/telephony/asterisk/releases/asterisk-11.17.0.tar.gz tar -xf asterisk-11.17.0.tar.gz cd asterisk-11.17.0 ./configure --libdir=/usr/lib64 make menuconfig En el menú Add-ons se seleccionan los módulos a seguir:
En el menú Compiler Flags, se de selecciona la opción indicada:
En “Core Sound Packages”, “Music On Hold File Packages” y “Extras Sound Packages” se seleccionan todos los modulos presentes. Se sale del menú de configuración con “Save and Exit” y se continua con la compilación: contrib/scripts/get_mp3_source.sh make make install make samples make config Se continua con la instalación de los AGI de A2Billing: yum install php php-gd php-mysql php-process httpd mod_ssl php-cli php-soap php-mcrypt -y nano +946 /etc/php.ini
482
date.timezone = America/Bogota cd /usr/local/src wget https://github.com/Star2Billing/a2billing/archive/v2.1.0.tar.gz Se descomprime: tar -xf v2.1.0.tar.gz se renombra la carpeta creada: mv a2billing-2.1.0 a2billing Se instalan las locuciones distribuidas con el programa (ingles, francés, español, portugués y ruso): cd /usr/local/src/a2billing/addons/sounds/ utilizando el siguiente script: ./install_a2b_sounds.sh Se continua con la instalación copiando el archivo de configuración de a2billing en la carpeta /etc: cp /usr/local/src/a2billing/a2billing.conf /etc/ se abre con el editor: nano /etc/a2billing.conf se modifican estas lineas: [database] hostname = localhost port = user = a2billing_dbuser password = a2billing_dbpassword dbname = a2billing_dbname dbtype = mysql para que queden: [database] hostname = IPPrivadaOS port = 3306 user = a2user password = sesamo 483
dbname = a2billing dbtype = mysql Antes de guardar los cambios se modifica IPPrivadaOS con la IP Privada del servidor OpensSIPs. Se continua con los script AGI presentes en el paquete de A2Billing. Uno se utiliza para realizar las llamadas (a2billing.php) y el segundo para monitorear el servidor (a2billing_monitoring.php). Se entra en la carpeta que contiene los AGI: cd /usr/local/src/a2billing/AGI se crean dos enlaces simbólicos de los dos AGI en la carpeta /var/lib/asterisk/agi-bin donde Asterisk busca los AGI que se ejecuten: ln -s /usr/local/src/a2billing/AGI/a2billing.php /var/lib/asterisk/agi-bin/a2billing.php ln -s /usr/local/src/a2billing/AGI/a2billing_monitoring.php /var/lib/asterisk/agi-bin/a2billing_monitoring.php
Como los AGI se apoyan en una serie de librerías contenidas en la carpeta /lib, se crea un enlace simbólico también a esta carpeta: ln -s /usr/local/src/a2billing/AGI/lib /var/lib/asterisk/agi-bin/lib Se vuelven ejecutables los dos archivos: chmod +x /var/lib/asterisk/agi-bin/a2billing.php chmod +x /var/lib/asterisk/agi-bin/a2billing_monitoring.php mkdir /var/log/a2billing se entra en la carpeta creada: cd /var/log/a2billing se crea el archivo: touch a2billing_agi.log mv /etc/asterisk/sip.conf /etc/asterisk/sip.conf.old se crea uno nuevo: nano /etc/asterisk/sip.conf se pegan las siguientes lineas: [general] context=default allowguest=no 484
allowtransfer=no realm=asterisk udpbindaddr=0.0.0.0:5060 tcpenable=no tcpbindaddr=0.0.0.0:5060 tcpauthtimeout=30 tcpauthlimit=100 transport=udp srvlookup=yes pedantic=yes maxexpiry=3600 minexpiry=60 defaultexpiry=120 mwiexpiry=3600 maxforwards=70 qualifyfreq=120 qualifygap=200 keepalive=yes disallow=all allow=ulaw allow=alaw mohinterpret=default mohsuggest=default language=es relaxdtmf=no sendrpid = yes prematuremedia=no progressinband=no useragent=VozToVoice 2.0 promiscredir=no dtmfmode = rfc2833 videosupport=yes maxcallbitrate=384 callevents=yes alwaysauthreject=yes rtptimeout=60 rtpholdtimeout=300 allowsubscribe=yes subscribecontext=subscribe notifyringing=yes notifyhold=yes callcounter = yes t38pt_udptl = yes,fec,maxdatagram=400 faxdetect=yes directmedia=no sdpsession=A2Billing sdpowner=a2billing 485
externaddr=IPPublica localnet=10.132.111.0/255.255.255.0 en la penúltima linea se pone la IP publica del servidor y en la ultima la ip privada utilizando la misma sintaxis indicada en el parámetro de ejemplo. Siempre en el mismo archivo se añaden los datos para configurar las troncales. En este caso se crean dos de ejemplo con el mismo proveedor, utilizando la autenticación con usuario y contraseña; la segunda troncal se utilizará como respaldo de la primera: [voztovoice1] type=peer port=5060 host=sip.voztovoice.eu defaultuser=usuario fromuser=usuario secret=contraseña dtmfmode=rfc2833 disallow=all context=from-trunk canreinvite=no allow=ulaw allow=alaw qualify=yes [voztovoice2] type=peer port=5060 host=sip1.voztovoice.eu defaultuser=usuario fromuser=usuario secret=contraseña dtmfmode=rfc2833 disallow=all context=from-trunk canreinvite=no allow=ulaw allow=alaw qualify=yes Modificar los campos defaultuser y fromuser de las dos troncales con el usuario de su cuenta VoIP Modificar el campo secret de las dos troncales con la contraseña de su cuenta VoIP. Por ultimo se añade la troncal de OpenSIPs en el caso se utilice también la autenticación sobre IP de los clientes:
486
[opensip] type=peer context=opensip host=IPPublicaOS disallow=all allow=alaw allow=alaw allow=g729 language=es dtmfmode = rfc2833 nat=no qualify=yes Se modifica IPPublicaOS con la IP publica del servidor OpenSIPs. Se guardan los cambios y se sigue con el dialplan. Se renombra el archivo extensions.conf predefinido: mv /etc/asterisk/extensions.conf /etc/asterisk/extensions.conf.old Se crea uno nuevo: nano /etc/asterisk/extensions.conf se pegan la lineas que siguen: [general] static = yes writeprotect = no autofallthrough = yes extenpatternmatchnew = true clearglobalvars = no userscontext=default [globals] ; Variables globales y se incluye el contexto para las llamadas con el AGI de a2billing: [a2billing] exten => _X.,1,NoOp(A2Billing Start) same => n,Agi(a2billing.php,1) same => n,Hangup exten => h,1,Hangup [a2billing2] exten => _X.,1,NoOp(A2Billing Start) same => n,Agi(a2billing.php,1) 487
same => n,Hangup exten => h,1,Hangup [opensip] exten => _X.,1,NoOp(Llamadas autenticadas sobre IP) same => n,Set(CDR(accountcode)=${SIP_HEADER(P-Accountcode)}) same => n,Goto(a2billing2,${EXTEN},1) same => n,hangup B.4.2 Asterisk Realtime Las extensiones SIP/IAX creadas a través del sistema de facturación se guardarán en la base de datos de A2Billing. Para que Asterisk las pueda leer y actualizar, hay que configurar Asterisk utilizando su funcionalidad, llamada Realtime, que le permite interaccionar con base de datos para la configuración, en este caso, de las extensiones SIP e IAX En este caso la configuración se implementará con ODBC en lugar de utilizar directamente MySQL. El primer paso es configurar Asterisk para que cargue los módulos ODBC antes de todos los demás. Esto cambio se efectúa modificando el archivo /etc/asterisk/modules.conf. Se abre: nano /etc/asterisk/modules.conf Se modifican estas dos lineas: ;preload => res_odbc.so ;preload => res_config_odbc.so para que queden: preload => res_odbc.so preload => res_config_odbc.so Luego se configura ODBC para la conexión a MySQL: mv /etc/odbcinst.ini /etc/odbcinst.old nano /etc/odbcinst.ini se añaden las siguientes lineas: [MySQL] Description = ODBC for MySQL Driver = /usr/lib64/libmyodbc5.so Setup = /usr/lib64/libodbcmyS.so FileUsage = 1
488
Se guardan los cambios y se continua con la conexión a la base de datos a2billing: nano /etc/odbc.ini se añaden las siguientes lineas: [a2billing] Description = MySQL a2billing Driver = MySQL Database = a2billing Server = IPPrivadaOS User = a2user Password = sesamo Port = 3306 Option = 3 Antes de guardar los cambios se modifica IPPrivadaOS con la IP Privada del servidor OpenSIPs. Se controla que la conexión esté funcionando correctamente: isql a2billing a2user sesamo El resultado:
Se puede salir del programa: SQL> quit Se pasa a Asterisk. En la PBX la configuración Realtime con ODBC se realiza en dos archivos: • •
extconfig.conf res_odbc.conf
En el primero se define que las extensiones SIP e IAX deberán ser configuradas en Realtime utilizando ODBC y la base de datos a2billing: nano /etc/asterisk/extconfig.conf se modifican estas lineas:
489
;iaxusers => odbc,asterisk ;iaxpeers => odbc,asterisk ;sippeers => odbc,asterisk para que queden: iaxusers => odbc,a2b,cc_iax_buddies iaxpeers => odbc,a2b,cc_iax_buddies sippeers => odbc,a2b,cc_sip_buddies_empty Se guardan los cambios. cc_iax_buddies y cc_sip_buddies_empty son las tablas de la base de datos a2billing donde están guardadas las extensiones creadas por el sistema de facturación. a2b es el nombre de la etiqueta que se configurará en el archivo res_odbc.conf. Para terminar se configura el archivo res_odbc.conf: nano /etc/asterisk/res_odbc.conf al final del archivo se añaden las siguientes lineas: [a2b] enabled => yes dsn => a2billing username => a2user password => sesamo pre-connect => yes sanitysql => select 1 idlecheck => 3600 connect_timeout => 10 La conexión funciona de la siguiente manera. En el archivo extconfig.conf se define la conexión a la base de datos utilizando el nombre que aparece como etiqueta del bloque presente en el archivo res_odbc.onf (en este caso el nombre es a2b). En el archivo res_odbc.conf en el parámetro dsn se define el nombre de la etiqueta del bloque configurado en el archivo odbc.ini (a2billing). En el archivo odbc.ini se define la conexión a la base de datos MySQL (en este caso la base de datos se llama a2billing). Por ultimo se crea la conexión a la base de datos asterisk para que los dos servidores puedan guardar los registros de las llamadas en la tabla CDR: 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:
490
[global] hostname=IPPrivadaOS dbname=asterisk table=cdr password=sesamo user=asterisk port=3306 sock=/var/lib/mysql/mysql.sock Modificar IPPrivadaOS con la IP Privada del servidor OpenSIPs. Los datos: 1. [global] – etiqueta inicial del bloque 2. hostname - nombre de dominio o IP del servidor MySQL 3. dbname - nombre de la base de datos 4. table - nombre de la tabla 5. password - contraseña del usuario que tiene los permisos para acceder a la base de datos 6. user - nombre del usuario que tiene los permisos para acceder a la base de datos 7. port – puerto donde MySQL recibirá las conexiones (predefinido 3306) 8. sock – archivo que se crea 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 status asterisk (pid 2403) is running... se entra en la consola: asterisk -rvvvvvvvvvvvvvvvv se controla que la conexión a la base de datos asterisk esté activa: CLI> cdr mysql status Connected to
[email protected], port 3306 using table cdr for 5 seconds. Wrote 0 records since last restart. se averigua también la conexión a la base de datos a2billing: CLI> odbc show la respuesta debe ser: ODBC DSN Settings ----------------491
Name: a2b DSN: a2billing Last connection attempt: 1969-12-31 19:00:00 Pooled: No Connected: Yes Se sale de la consola de Asterisk: CLI> quit B.4.3 Asterisk Cortafuegos Para proteger los servidores Asterisk de accesos no autorizados hay que instalar un firewall (cortafuegos) y abrir los puertos que se necesita para aceptar conexiones externas. Para instalar iptables: yum install iptables -y Se acepta todo el trafico en entrada con destino la interfaz lookpack iptables -A INPUT -i lo -j ACCEPT Se rechaza (REJECT) todo el trafico entrante con destino 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 deja pasar todos los paquetes salientes. iptables -A OUTPUT -j ACCEPT Se deja pasar todo el trafico en entrada para el protocolo SSH (puerto 22 tcp) iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT Se deja pasar todo el trafico en entrada destinado al puerto udp 5060 (protocolo SIP) solamente si procedente del servidor OpenSIPs y de los proveedores VoIP: iptables -A INPUT -p udp --dport 5060 -s 104.131.181.192 -j ACCEPT
492
iptables -A INPUT -p udp --dport 5060 -s sip.voztovoice.eu -j ACCEPT iptables -A INPUT -p udp --dport 5060 -s sip1.voztovoice.eu -j ACCEPT Se deja pasar el trafico para los puertos desde 10000 a 20000 UDP utilizados por el servidor Asterisk para el protocolo RTP (Flujo media): 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 REJECT iptables -A FORWARD -j REJECT Se averigua el estado de las reglas definidas con el comando: iptables -L Chain INPUT (policy ACCEPT) target prot opt source destination ACCEPT all -- anywhere anywhere REJECT all -- anywhere loopback/8 reject-with icmp-port-unreachable ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED ACCEPT tcp -- anywhere anywhere state NEW tcp dpt:ssh ACCEPT udp -- sip20.voztovoice.net anywhere udp dpt:sip ACCEPT udp -- voztovoice.eu anywhere udp dpt:sip ACCEPT udp -- sip1.voztovoice.eu anywhere udp dpt:sip ACCEPT udp -- anywhere anywhere udp dpts:ndmp:dnp ACCEPT icmp -- anywhere anywhere icmp echo-request REJECT all -- anywhere anywhere reject-with icmp-port-unreachable Chain FORWARD (policy ACCEPT) target prot opt source destination REJECT all -- anywhere anywhere Chain OUTPUT (policy ACCEPT) target prot opt source destination ACCEPT all -- anywhere anywhere Para guardar los cambios: service iptables save 493
reject-with icmp-port-unreachable
iptables: Guardando las reglas del cortafuegos en /etc/sysconfig/iptables [ OK ] Se inicia el servicio: service iptables start Para iniciar iptables automáticamente: chkconfig iptables on Ya se puede empezar a realizar pruebas de llamadas y de registro para comprobar que el sistema esté funcionando correctamente. IMPORTANTE: Poner en seguridad el servidor OpenSIPs y el servidor WEB consultando los relativos párrafos presentes en este libro.
494
Apéndice C GNU Free Documentation License Version 1.3, 3 November 2008
Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. 0. PREAMBLE The purpose of this License is to make a manual, textbook, or other functional and useful document "free" in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others. This License is a kind of "copyleft", which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software. We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference. 1. APPLICABILITY AND DEFINITIONS This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The "Document", below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as "you". You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law. A "Modified Version" of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language. A "Secondary Section" is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document's overall
subject (or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them. The "Invariant Sections" are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none. The "Cover Texts" are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words. A "Transparent" copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount of text. A copy that is not "Transparent" is called "Opaque". Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, and standard-conforming simple HTML, PostScript or PDF designed for human modification. Examples of transparent image formats include PNG, XCF and JPG. Opaque formats include proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML, PostScript or PDF produced by some word processors for output purposes only. The "Title Page" means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, "Title Page" means the text near the most prominent appearance of the work's title, preceding the beginning of the body of the text. The "publisher" means any person or entity that distributes copies of 497
the Document to the public. A section "Entitled XYZ" means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a specific section name mentioned below, such as "Acknowledgements", "Dedications", "Endorsements", or "History".) To "Preserve the Title" of such a section when you modify the Document means that it remains a section "Entitled XYZ" according to this definition. The Document may include Warranty Disclaimers next to the notice which states that this License applies to the Document. These Warranty Disclaimers are considered to be included by reference in this License, but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is void and has no effect on the meaning of this License. 2. VERBATIM COPYING You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3. You may also lend copies, under the same conditions stated above, and you may publicly display copies. 3. COPYING IN QUANTITY If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the Document's license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects. If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages. If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent 498
copy along with each Opaque copy, or state in or with each Opaque copy a computer-network location from which the general network-using public has access to download using public-standard network protocols a complete Transparent copy of the Document, free of added material. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public. It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document. 4. MODIFICATIONS You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version: A. Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission. B. List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has fewer than five), unless they release you from this requirement. C. State on the Title page the name of the publisher of the Modified Version, as the publisher. D. Preserve all the copyright notices of the Document. E. Add an appropriate copyright notice for your modifications adjacent to the other copyright notices. F. Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below. G. Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document's license notice. H. Include an unaltered copy of this License. I. Preserve the section Entitled "History", Preserve its Title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section Entitled "History" in the Document, create one 499
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 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 or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version's license notice. These titles must be distinct from any other section titles. You may add a section Entitled "Endorsements", provided it contains nothing but endorsements of your Modified Version by various parties--for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard. You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one. The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version. 5. COMBINING DOCUMENTS 500
You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice, and that you preserve all their Warranty Disclaimers. The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work. In the combination, you must combine any sections Entitled "History" in the various original documents, forming one section Entitled "History"; likewise combine any sections Entitled "Acknowledgements", and any sections Entitled "Dedications". You must delete all sections Entitled "Endorsements". 6. COLLECTIONS OF DOCUMENTS You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects. You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document. 7. AGGREGATION WITH INDEPENDENT WORKS A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, is called an "aggregate" if the copyright resulting from the compilation is not used to limit the legal rights of the compilation's users beyond what the individual works permit. When the Document is included in an aggregate, this License does not apply to the other works in the aggregate which are not themselves derivative works of the Document. If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one half of the entire aggregate, the Document's Cover Texts may be placed on covers that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is in electronic form. 501
Otherwise they must appear on printed covers that bracket the whole aggregate. 8. TRANSLATION Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License, and all the license notices in the Document, and any Warranty Disclaimers, provided that you also include the original English version of this License and the original versions of those notices and disclaimers. In case of a disagreement between the translation and the original version of this License or a notice or disclaimer, the original version will prevail. If a section in the Document is Entitled "Acknowledgements", "Dedications", or "History", the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual title. 9. TERMINATION You may not copy, modify, sublicense, or distribute the Document except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, or distribute it is void, and will automatically terminate your rights under this License. However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, receipt of a copy of some or all of the same material does not give you any rights to use it. 10. FUTURE REVISIONS OF THIS LICENSE The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in 502
detail to address new problems or concerns. See http://www.gnu.org/copyleft/. Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License "or any later version" applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation. If the Document specifies that a proxy can decide which future versions of this License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Document. 11. RELICENSING "Massive Multiauthor Collaboration Site" (or "MMC Site") means any World Wide Web server that publishes copyrightable works and also provides prominent facilities for anybody to edit those works. A public wiki that anybody can edit is an example of such a server. A "Massive Multiauthor Collaboration" (or "MMC") contained in the site means any set of copyrightable works thus published on the MMC site. "CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0 license published by Creative Commons Corporation, a not-for-profit corporation with a principal place of business in San Francisco, California, as well as future copyleft versions of that license published by that same organization. "Incorporate" means to publish or republish a Document, in whole or in part, as part of another Document. An MMC is "eligible for relicensing" if it is licensed under this License, and if all works that were first published under this License somewhere other than this MMC, and subsequently incorporated in whole or in part into the MMC, (1) had no cover texts or invariant sections, and (2) were thus incorporated prior to November 1, 2008. The operator of an MMC Site may republish an MMC contained in the site under CC-BY-SA on the same site at any time before August 1, 2009, provided the MMC is eligible for relicensing. ADDENDUM: How to use this License for your documents To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page: Copyright (c) YEAR YOUR NAME. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU 503
Free Documentation License". If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, replace the "with...Texts." line with this: with the Invariant Sections being LIST THEIR TITLES, with the Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. If you have Invariant Sections without Cover Texts, or some other combination of the three, merge those two alternatives to suit the situation. If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software license, such as the GNU General Public License, to permit their use in free software.
504
Apéndice D POODLE y el protocolo SSLv3 El reciente Bug (error de programación) del protocolo de cifrado SSL v3 permite descifrar en tiempo real una comunicación entre un cliente y un servidor Web que utilice este sistema de cifrado. Si se piensa utilizar el cifrado disponible en el servidor Web, en apache se soluciona desactivando por completo el protocolo: nano +93 /etc/httpd/conf.d/ssl.conf se modifica la linea: SSLProtocol all -SSLv2 para que quede: SSLProtocol all -SSLv2 -SSLv3 Se guardan los cambios y se reinicia el servidor Web: service httpd restart Para averiguar que efectivamente el protocolo se ha desactivado, se puede entrar a esta pagina: https://www.tinfoilsecurity.com/poodle Ingresar el nombre del dominio:
El resultado:
507