Montando un Sistema Asterisk Autonomo I

Durante el curso de Asterisk Advanced, una de las cuestiones que surgieron con los compañeros, era el tema de la «practicidad» eventual que podia surgir a la hora de decidir montar una interfaz grafica a pesar de que muchos hayan criticado, es el simple hecho que otorga un «sistema» para que manos inexpertas (bajo nuestra aprobacion y previamente formados), puedan tomar el control de nuestro Asterisk sin nuestra supervision constante.

Evidentemente surgen algunas inconveniencias, que son inevitables en este tipo de situaciones, pero en las manos adecuadas, pueden ser mas pros que contras (por ejemplo explicandole a un equipo tecnico o IT funcionalidades basicas de Asterisk como crear nuevas extensiones para poder cursar llamadas. De esto se trata la idea de montar un sistema Autonomo (al menos autonomamente de nuestra persona).

Un paso mas alla, viendo el sistema RealTime de Asterisk, se me ocurrio la -evidente- idea de crear una micro interfaz grafica (por ejemplo basada en web con PHP como sera el caso que exponga a continuacion), para gestionar esos aspectos de Asterisk especificos, y poder definitivamente, tomando esto como ejemplo generico, poder obviar todas esas interfaces graficas (ejemplo FreePBX) para siempre.

Lo que me planteo de ejemplo ahora: Activar RealTime para los «peers» SIP de nuestro Asterisk y crear la interfaz grafica web en PHP para Crear y Borrar estas extensiones (La funcion de editar seria Borrar y volver a crear para este ejemplo sencillo, aunque realmente no seria nada dificil de implementar)

Como ya comente en su momento en otro mensaje, el montaje de un sistema RealTime es verdaderamente secuencial, es mas ya lo hicimos en las practicas durante Asterisk Advanced en detalle.

En primer lugar, obviamente necesitamos tener instalado un sistema de gestion de bases de datos como MySQL, tambien un servidor web como Apache, y los modulos de PHP para el mismo. En este caso, como ya vimos antes, LAMP es lo ideal. Asi que ejecutamos tasksel y lo instalamos (LAMP Server, Ubuntu/Debian)

Tambien necesitamos las librerias de ODBC puesto que vamos a utilizarlas con Asterisk:

# aptitude install unixodbc libmyodbc

En segundo lugar, configuramos la base de datos y la tabla donde volcar los usuarios SIP:

– Creamos un fichero por ejemplo en /tmp/ llamado por ejemplo sip_buddies.sql con esta informacion (se puede encontrar mas informa acerca de la tabla asociada a los peers SIP  aqui). Atencion al ultimo campo que coloreo en Rojo. Muy importante que lo agreguéis manualmente para lo que vamos a tratar de hacer a continuacion

CREATE TABLE `sip_buddies` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(80) NOT NULL default »,
`host` varchar(31) NOT NULL default »,
`nat` varchar(5) NOT NULL default ‘no’,
`type` enum(‘user’,’peer’,’friend’) NOT NULL default ‘friend’,
`accountcode` varchar(20) default NULL,
`amaflags` varchar(13) default NULL,
`call-limit` smallint(5) unsigned default NULL,
`callgroup` varchar(10) default NULL,
`callerid` varchar(80) default NULL,
`cancallforward` char(3) default ‘yes’,
`canreinvite` char(3) default ‘yes’,
`context` varchar(80) default NULL,
`defaultip` varchar(15) default NULL,
`dtmfmode` varchar(7) default NULL,
`fromuser` varchar(80) default NULL,
`fromdomain` varchar(80) default NULL,
`insecure` varchar(4) default NULL,
`language` char(2) default NULL,
`mailbox` varchar(50) default NULL,
`md5secret` varchar(80) default NULL,
`deny` varchar(95) default NULL,
`permit` varchar(95) default NULL,
`mask` varchar(95) default NULL,
`musiconhold` varchar(100) default NULL,
`pickupgroup` varchar(10) default NULL,
`qualify` char(3) default NULL,
`regexten` varchar(80) default NULL,
`restrictcid` char(3) default NULL,
`rtptimeout` char(3) default NULL,
`rtpholdtimeout` char(3) default NULL,
`secret` varchar(80) default NULL,
`setvar` varchar(100) default NULL,
`disallow` varchar(100) default ‘all’,
`allow` varchar(100) default ‘g729;ilbc;gsm;ulaw;alaw’,
`fullcontact` varchar(80) NOT NULL default »,
`ipaddr` varchar(15) NOT NULL default »,
`port` smallint(5) unsigned NOT NULL default ‘0’,
`regserver` varchar(100) default NULL,
`regseconds` int(11) NOT NULL default ‘0’,
`lastms` int(11) NOT NULL default ‘0’,
`username` varchar(80) NOT NULL default »,
`defaultuser` varchar(80) NOT NULL default »,
`subscribecontext` varchar(80) default NULL,
`useragent` varchar(20) default NULL,
`useradmin`  int(1) NOT NULL DEFAULT ‘0’,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`),
KEY `name_2` (`name`)
) ENGINE=MyISAM ROW_FORMAT=DYNAMIC;

#mysql -p
Entramos con nuestra password
mysql> create database asterisk;
mysql> use asterisk;
mysql> source /tmp/sip_buddies.sql

En tercer lugar vamos a configurar los ficheros basicos de Asterisk para poder trabajar con el conector ODBC

/etc/asterisk/extconfig.conf

[settings]
sippeers => odbc,asterisk ,sip_buddies

/etc/asterisk/res_odbc.conf

[asterisk]
enabled => yes
pre-connect => yes
dsn => asterisk
username => root
password => (el password que le pusimos al usuario de la base de datos mysql root durante la configuracion de LAMP)

/etc/odbc.ini

[asterisk]
Description = ODBC para MySQL
Driver = MySQL
Server = localhost
Database = asterisk
Socket = /var/run/mysqld/mysqld.sock

/etc/odbcinst.ini

[MySQL]
Description = MySQL ODBC MyODBC Driver
Driver = /usr/lib/odbc/libmyodbc.so
Setup = /usr/lib/odbc/libodbcmyS.so

Con esto vamos al CLI de Asterisk
# asterisk -r
CLI> odbc show

Y si vemos «Connected: Yes» entonces ya esta preparado

En cuarto lugar vamos a configurar los usuarios SIP:

Para ello creamos un fichero temporal por ejemplo /tmp/usuarios_sip_buddies.sql con la siguiente info:

INSERT INTO sip_buddies (`name`, `host`, `nat`, `type`, `cancallforward`, `canreinvite`, `context`, `md5secret`, `qualify`, `disallow`, `allow`, `fullcontact`, `ipaddr`, `port`, `regseconds`, `lastms`, `username`, `defaultuser`)
VALUES (‘ext10’, ‘dynamic’, ‘no’, ‘friend’, ‘yes’, ‘yes’, ‘extensiones’, ‘e8a325cb599ad4b6eb95d79aa4506ed2’, ‘yes’, ‘all’, ‘g729;ilbc;gsm;ulaw;alaw’, », », ‘0’,’0′, ‘0’, », »)

Importante, el ultimo valor a 1, y la clave sera 1234 en formato md5 evidentemente se deberia cambiar.

Ahora como antes lo ejecutamos desde el interfaz de comandos de MySQL

#mysql -p
mysql> use asterisk;
mysql> source /etc/usuarios_sip_buddies.sql

Finalmente necesitamos editar el fichero sip.conf con una configuracion minima. Por ejemplo:

/etc/asterisk/sip.conf

[general]
language = es

Desde este mismo momento ya tenemos el usuario sip ext10 con la clave 1234 listo para funcionar. Podemos probarlo con cualquier telefono SIP.

Puede parecer muchisima historia comparado a configurar un fichero sip.conf, pero con la practica y unas plantillas, esta gestion se realiza en 5 minutos y ahora viene la «potencia».

El script PHP:

Voy a crear un solo fichero PHP al estilo monolitico para que funcione y nada mas. Evidentemente sera bastante mejorable y ya esta en nuestras manos con unos conocimientos basicos de programacion PHP (y obviamente adaptable a cualquier otro lenguaje de programacion con el que nos sintamos mas comodos)

Lo primero vamos a crear algunos directorios dentro del lugar donde tengamos publicado el servidor web apache, por defecto /var/www
# cd /var/www
# mkdir asterisk
# cd asterisk
# mkdir sip
# cd sip

Ahora vamos a crear un fichero index.php con el siguiente contenido:

 <?php

// Conexion a la base de Datos

$base = "asterisk";
$host = "localhost";
$user = "root";
$password = "nuestra_contraseña_sql";
$conexion = mysql_connect($host,$user,$password);
$result = mysql_select_db($base,$conexion) or die ("Error en la Conexion a BD");

session_start();

// Si no estamos logeados

if (!$_SESSION['login'])
{
 if(isset($_POST['loginsubmit']))
 {
 $usuario = $_POST['usuario'];
 $password = $_POST['password'];

 if((!$usuario) || (!$password))
 {
 echo "Error 1<br>";
 exit();
 }
 $password = $usuario.":asterisk:".$password;
 $password = md5($password);
 $query = mysql_query("SELECT * FROM sip_buddies WHERE name='$usuario' AND md5secret = '$password' AND useradmin = '1'");
 if (mysql_num_rows($query) > 0)
 {
 session_register('login');
 $_SESSION['login'] = '1';
 }
 else
 echo "Error 2<br><br>";

 echo "<a href='index.php'>Home</a>";
 }
 else
 {
 echo "<form method='post' action='?'>";
 echo "Usuario: <input name='usuario' type='text'><br>";
 echo "Contrase&ntilde;a: <input name='password' type='password'><br>";
 echo "<input type='submit' name='loginsubmit'>";
 echo "</form>";
 }

}
// Si ya estamos logeados

else
{
 // Salida del Sistema
 if(isset($_REQUEST['exit']))
 {
 session_destroy();

 if(!session_is_registered('login'))
 echo "<a href='index.php'>Home</a>";

 }
 // Insercion de un nuevo Registro
 elseif(isset($_POST['insertsubmit']))
 {
 $sipuser = $_POST['sipuser'];
 $sippass = $_POST['sippass'];
 $sippass = $sipuser.":asterisk:".$sippass;
 $sippass = md5($sippass);
 $query = mysql_query("INSERT INTO sip_buddies (`name`, `host`, `nat`, `type`, `cancallforward`, `canreinvite`, `context`, 
 `md5secret`, `qualify`, `disallow`, `allow`, `fullcontact`, `ipaddr`, `port`, `regseconds`, `lastms`, `username`, `defaultuser`) 
 VALUES ('$sipuser', 'dynamic', 'no', 'friend', 'yes', 'yes', 'extensiones', '$sippass', 'yes', 'all', 'g729;ilbc;gsm;ulaw;alaw', '', '', 
 '0','0', '0', '', '')");

 echo "<a href='index.php'>Home</a><br>";
 echo "<a href='index.php?exit'>Exit</a>";
 }
 // Borrado de un Registro
 elseif(isset($_POST['deletesubmit']))
 {
 $sipid = $_POST['sipid'];
 $query = mysql_query("DELETE FROM sip_buddies WHERE id = '$sipid'");

 echo "<a href='index.php'>Home</a><br>";
 echo "<a href='index.php?exit'>Exit</a>";
 }
 // Formularios de Insercion y Borrado
 else
 {
 echo "Insertar Registro:<br>"; 
 echo "<p><form method='post' action='?'>";
 echo "Usuario: <input name='sipuser' type='text'><br>";
 echo "Contrase&ntilde;a: <input name='sippass' type='password'><br>";
 echo "<input type='submit' name='insertsubmit' value='Insertar'>";
 echo "</form></p>";

 echo "<table border='1'>";
 echo "<tr><td colspan ='2' align='center'>SIP Peers Activos</td></tr>";
 echo "<tr><td>Usuario</td><td>Borrar</td></tr>"; 

 $query = mysql_query("SELECT * FROM sip_buddies WHERE type = 'friend'");
 $rows = mysql_num_rows($query);
 for ($i=0;$i<$rows;$i++)
 {
 $sippeersarray = mysql_fetch_array($query);
 $sipuser = $sippeersarray['name'];
 $sipid = $sippeersarray['id'];

 echo "<tr>";
 echo "<td>".$sipuser."</td>";
 echo "<td>";
 echo "<form method='post' action='?'>";
 echo "<input type=hidden name='sipid' value='$sipid'>";
 echo "<input type=submit name='deletesubmit' value='Borrar'>";
 echo "</form>";
 echo "</td>"; 
 echo "</tr>";

 } 
 echo "</table>"; 
 echo "<a href='index.php?exit'>Exit</a>";

 }
}

?>

Y eso es todo, ahora podemos acceder a traves de un navegador a la direccion:

http://ip_nuestro_servidor_asterisk/asterisk/sip/

Y aparecera para introducir un usuario y contraseña. Siguiendo el ejemplo seria Usuario: ext10,  Contraseña: 1234

Asi accederiamos a la micro interfaz para Crear y Borrar extensiones.

Evidentemente este codigo tiene bastantes deficiencias «tecnicas», por ejemplo se podria intentar realizar una tecnica de Inyeccion de Codigo SQL para logearnos como el usuario administrador por las «bravas», y ya conociendo la estructura, hasta darnos de alta un usuario Administrador para acceder siempre. Pero la idea basica era poder ejemplificar lo que queria mostrar con este articulo, que con solo seguir unos pasos de 5 minutos o menos, y tener este script PHP listo para ser «insertado» en el servidor web, tendriamos una interfaz totalmente Autonoma para nuestro cliente, equivalente a la que «instalamos» en mensajes anteriores, para la gestion de salas de conferencias MeetMe.

Ademas esta claro este codigo se podria mejorar para añadir la posibilidad de editar extensiones, o incluso configurar mas parametros de las extensiones (o tener dos interfaces, una de administrador para nosotros mismos, y otra para los usuarios), asi no tendriamos que andar «trasteando» directamente en el interfaz MySQL si modificamos regularmente las extensiones.

Con esto, ya empiezan a haber motivos para poder ir planteandonos dar un primer paso y dar fin a las interfaces graficas de Asterisk!.

Tengo que reconocer que este mensaje me ha llevado componerlo mas tiempo del previsto originalmente. Toda mejora al codigo, o sugerencia como siempre, sera ampliamente agradecida a traves de los comentarios.

3 comentarios en «Montando un Sistema Asterisk Autonomo I»

  1. Hola, me pareció muy bueno este tutorial, ya lo tenia montado de otra forma, sin embargo esta es una buena propuesta. Quisiera consultarte si existe alguna forma de agregar extensiones en diferentes contextos sin necesidad de agregar contextos manualmente en el archivos extensions.conf. Es que queria agregar grupos de extensiones que no se pudiesen llamar entre ellos y se me ocurrió una forma de diferenciarlas y es a través del contexto, sin embargo, cada vez que voy a crear un nuevo grupo, me toca crear un nuevo contexto de forma manual en el archivo extensions.conf. Busque la forma de crear un .php que me modifca el archivo en mención, pero entonces me toca recargar (reload) asterisk, haciendo que se caigan todas las llamadas actuales. Cual crees tu que sea la mejor forma de diferencias grupos de extensiones para que no se puedan llamar entre ellos? Agradezco mucho cualquier idea. 🙂

  2. Hola Pablo. Si te das cuenta en la tabla hay un campo que es «context». Cuando creas una extensión por Asterisk Realtime (en este caso con la pequeña interfaz grafica en PHP que diseñe), tienes la opcion de ademas, ir configurando los contextos a medida. En este caso como puedes ver en la sentencia INSERT INTO sip_buddies estamos metiendo todas las extensiones por defecto en el contexto «extensiones», pero ahi podrias crear otro campo en el formulario y seleccionar el contexto que deseas incorporar la extensión a voluntad.

    Aparte si lo que necesitas es restringir el «campo de vision» de cada extensión entonces ya es un tema de configuracion del Dialplan, que tambien puedes pasarlo a modo Realtime. La verdad es que yo siempre he trabajado a nivel de fichero de configuracion con extensions.conf porque me resulta mas intuitivo (especialmente por lo extenso que puede llegar a ser), pero aqui tienes una referencia al respecto de este tema: http://www.voip-info.org/wiki/view/Asterisk+RealTime+Extensions

    Quiza en un futuro lo trate en este blog

  3. Call to undefined function session_register() in /var/www/html/asterisk/index.php on line 33

Deja un comentario

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.