OpenVPN y el codec g729

Para los que trabajamos con telefonía IP es bien conocido que el codec g729 es uno de los más populares debido principalmente a que comprime el audio a 8 kbps lo cual permite un uso eficiente del ancho de banda disponible.  Aunque existen otros que realizan la misma función y al mismo tiempo son gratis (ej. Speex), con mucha frecuencia la única opción es g729 ya que es el más soportado por los proveedores y es el que viene incluído en la gran mayoría de los equipos de hardware usados en voz sobre IP.

Pues bien, hace unos días le compré a Digium una licencia de g729 para Asterisk, la cual brinda un máximo de dos registros posibles.  La instalación fluyó perfectamente, hice las pruebas pertinentes y efectivamente pude usar el codec satisfactoriamente.  Luego dejé a un lado el asterisk y le apliqué una actualización al sistema CentOS y más adelante comencé a hacer pruebas de enrutamiento con OpenVPN instalado en el mismo servidor, lo cual condujo a varios reinicios del servicio OpenVPN y del propio servidor.  Finalmente, todas las rutas funcionaban como se esperaba, pero … las llamadas ya no funcionaban.

Al revisar las trazas noté un par de aspectos relevantes: primero, la interfaz de red eth0, aparecia renombrada como eth1; segundo, la traza de las llamadas mostraba error de codec y el comando “g729 show licenses” en el CLI de Asterisk informaba que no encontró licencias válidas en el sistema ya que la existente tenía “incorrect host-id”.  Me las agencié para resolver el primer problema de lograr que volviera a nombrar la interfaz como eth0, pero aún así continuó el error.  Luego de contactar al soporte técnico de Digium, me informaron que el host-id de la licencia se calcula basado en:

  • Las direcciones MAC y los nombres de todas las interfaces de red presentes en el sistema (incluídas las virtuales de OpenVPN).

Como ya tenía las interfaces con sus nombres originales, entonces solo quedaba por revisar las MAC, la interfaz física no podía cambiar la suya, asi que solo quedaba la tap0 correspondiente a la VPN.  Luego de repetir un par de veces “service openvpn restart”  e  “ifconfig”  me di cuenta que openvpn asigna una nueva dirección MAC aleatoria a la interfaz virtual cada vez que se levanta el servicio, así que la solución consistía en lograr que siempre asigne la misma MAC.

Revisando un poco la documentación encontré que existe una forma de lograr esto y consiste en incluir en server.conf, client.conf o como se haya nombrado el archivo de configuración la siguiente directiva:

lladdr 56:37:67:A0:47:BC

donde el parámetro es por supuesto la MAC que se desee asignar.  Lo mejor es copiarlo de la última configuración válida generada disponible a través de “ifconfig” (hwaddr).

Aquí se los dejo y creo que pudiera aplicarse en otros casos más generales de servicios dependientes de la dirección MAC donde al mismo tiempo esté involucrada OpenVPN. Importante: según la documentación, este parámetro solo funciona en Linux, pero supongo que en Windows existan otros métodos de fijar la MAC de una interfaz virtual.

Anuncios

Asterisk: integración con mysql

Una de las características más emocionantes de Asterisk es la posibilidad de integrarse con bases de datos externas (ej. mysql, postgreSQL, LDAP).  Los administradores de redes conocemos bien el valor de mantener la independencia entre el almacenamiento de los usuarios y el servicio en si mismo.

La instalación predeterminada de Asterisk no viene con la integración con mysql, sin embargo es muy fácil añadirla. Basta con descargar desde http://www.asterisk.org/downloads los complementos (addons) para la versión de Asterisk que estemos usando.  Para instalarlos:

#tar xzvf  asterisk-addons-1.6.2.2.tar.gz
# ./configure
#make menuselect
#make
#make install

La opción “menuselect” permite seleccionar los componentes de mysql necesarios para la integración con Asterisk. Para completar es necesario adicionar o modificar las siguientes lineas en dos archivos de configuración en /etc/asterisk:

extconfig.conf
——————
sipusers => mysql,general,cc_sip_buddies
sippeers => mysql,general,cc_sip_buddies

res_mysql.conf  (a partir de la version 1.8 de Asterisk este archivo se nombre res_config_mysql.conf)
——————-
[general]
dbhost = 192.168.0.10
dbname = dba2billing
dbuser = a2billinguser
dbpass = a2billinguser_password
dbport = 3306

Algunas aclaraciones:

  • Estas configuraciones son totalmente flexibles, tanto que en ocasiones tienden a confundir dada su generalidad o tienden a ser aplicadas de forma totalmente mecánica.
  • sipusers y sippeers representan las definiciones de las cuentas de asterisk (extensiones), las que de otra forma tendrian que ser definidas en un archivo texto en /etc/asterisk/sip.conf.
  • El primer parámetro (mysql) indica precisamente que estas cuentas se encuentran en una base de datos mysql.
  • El segundo parámetro “general” puede ser cualquier nombre definido por el administrador, la única condición es que debe ser el mismo que da nombre al contexto definido en res_mysql.conf  (  [general]  Es el enlace entre ambos archivos.
  • El tercer parámetro (cc_sip_buddies)  es el nombre de la tabla que contiene las cuentas dentro de la base de datos mysql especificada. Este nombre puede ser también cualquiera que decida el diseñador de la base de datos.  El requisito de esta tabla es que los nombres de los campos deben coincidir con los nombres de los parámetros de configuración de los sip users en sip.conf, mas información en http://www.voip-info.org/wiki/view/Asterisk+RealTime+Sip.
  • La explicación anterior es válida igualmente con las modificaciones obvias para definir clientes IAX.

Listo!  De esta forma tenemos independencia absoluta entre la gestión de telefonía que desempeña Asterisk y la administración de usuarios.  Por ejemplo, el servidor de Asterisk se puede encontrar en mantenimiento y los agentes pueden continuar con sus tareas rutinarias de actualización, facturación, etc.  Siguiendo la línea del mantenimiento, es muy fácil conectar al sistema un Asterisk de respaldo o emergencia sin siquiera tener que hacer una restauración de la base de datos.  Esta separación permite al mismo tiempo el desarrollo en paralelo de un sistema de facturación y contabilidad totalmente independiente de Asterisk con administradores (probablemente diferentes de los de Asterisk), agentes de ventas, etc:  fallas en este sistema de gestión no afectan el funcionamiento de la actividad teléfonica normal, excepto quizás … uhmmm fallas de seguridad … pero eso es tema para otro post o grupo de posts, la vulnerabilidad/seguridad de los sistemas VoIP es uno de los más candentes en la actualidad.

Por último, si no cuenta con el tiempo, los recursos o los conocimientos para desarrollar un sistema de facturación para Asterisk, en la web se encuentran varios muy buenos y gratis.  El nombre “a2billing” usado en el ejemplo no es casual, http://www.asterisk2billing.org es uno de los más maduros, corre sobre plataforma LAMP e instrumenta un sistema de tarjetas telefónicas, permite las modalidades prepago y postpago.   Trae un conjunto de tablas predefinidas en mysql que permiten la integración explicada anteriormente liberándonos al mismo tiempo de tener que crear un diseño nuevo de la base de datos.

En teoría usando Asterisk y a2billing es posible instrumentar cualquier solución imaginable de telefonía. Al ser una plataforma de código abierto, si aparece un requerimiento nuevo no implementado, siempre es posible adicionarlo.  La instalación es relativamente simple para alguien con cierta experiencia con Linux y sus amigos (apache, mysql, etc) … no es una instalación “apunta y click”.  Los autores de a2biling se dedican al mismo tiempo a ofrecer consultoría, asesoramiento e instalación del soft y estoy de acuerdo con el consejo que dan a los clientes: si Ud. va a contratar a alguien para que le instale una solución de telefonía IP, investigue primero, asegúrese que tenga la experiencia necesaria, o de lo contrario serán mayores las pérdidas que el ahorro que va a tener por usar esta novedosa tecnología.

Actualización: lo anterior es válido también para IAX friends, basta adicionar las siguientes líneas a extconfig.conf:

iaxusers => mysql,general,cc_iax_buddies
iaxpeers => mysql,general,cc_iax_buddies

a2billing: interfaz web e idiomas

Resulta frustrante instalar algo que “debe” funcionar pero NO lo hace.  Este es el caso de lograr que funcione el cambio de idioma en la interfaz web de a2billing. Lo peor es que a primera vista la tendencia es culpar al software en si mismo olvidando sus dependencias.  Este problema aparece de forma general en la gran mayoría de aplicaciones LAMP que brindan soporte para varios idiomas; la primera vez que tuve que enfrentarlo fue instalando un correo web con la plataforma Horde/Imp.  No existe una receta única de como solucionarlo debido a las diferencias entre las distribuciones de Linux, pero resulta muy fácil si conocemos las interioridades del proceso y tenemos Google a mano.  Concretamente, casi todas estas aplicaciones utilizan la función de PHP gettext() que se encarga de la “internacionalización“: dada una cadena de caracteres (mensaje) especifica del programa, realizar una búsqueda de ese mensaje en el idioma especificado en el contexto.

Para ello debe estar instalado en nuestro sistema el paquete “locales” que maneja los idiomas soportados, asi como cada “locale” correspondiente a cada idioma que deseamos soportar.  Según http://linux.die.net/man/7/locale ,  un locale es “un conjunto de reglas de idioma y culturales. Cubre aspectos tales como el idioma de los mensajes, diferentes juegos de caracteres, convenciones lexicográficas, etc.  Un programa debe poder determinar su locale y actuar en correspondencia para ser portable a diferentes culturas”.

En Linux el comando:

locale -a

muestra los locales que están instalados en el sistema. Si en la lista no aparece el español (es_ES en alguna de sus variantes), seguramente no podremos dar soporte español en a2billing.  Ahora la parte específica, recuerdo que en Debian el comando:

dpkg-reconfigure locales

mostraba un menú gráfico que permitía seleccionar los locales a instalar.  Sin embargo en Ubuntu, este comando se limita a verificar la actualidad de los que están instalados y buscar si existen actualizaciones.  Para instalar locales en Ubuntu hay que editar el archivo /var/lib/locales/supported.d/local y adicionar los deseados. La lista de locales válidos se puede encontrar en /usr/share/i18n/SUPPORTED. Tras añadir español, el mio quedó asi:

en_US.UTF-8 UTF-8
es_ES.UTF-8 UTF-8

dpkg-reconfigure locales completa la tarea.

Sin embargo, todavía no podia activar el español en la interfaz web de a2billing.  El archivo de a2billing que maneja los cambios de idioma es <directorio de instalación>/common/lib/languageSettings.php a través de la siguiente función:

function SetLocalLanguage(){
  $slectedLanguage = "";
  $languageEncoding = "";
  $charEncoding = "";
  switch (LANGUAGE)	{
    case "arabic":
      $languageEncoding = "en_US.iso88591";
      $slectedLanguage = "en_US";
      $charEncoding = "iso88591";
      break;
...
    case "spanish":
      $languageEncoding = "es_ES.iso88591";
      $slectedLanguage = "es_ES";
      $charEncoding = "UTF-8";
      break;
...
    default:
      $languageEncoding = "en_US.iso88591";
      $slectedLanguage = "en_US";
      $charEncoding = "iso88591";
      break;
  }
...
}

Mi sistema no tiene la codificación “es_ES.iso88591”, por tanto en el case cambié la parte de español de forma que coincida con el locale que instale anteriormente:

  case "spanish":
  $languageEncoding = "es_ES.UTF-8";
  // $languageEncoding = "es_ES.iso88591";
  $slectedLanguage = "es_ES";
  $charEncoding = "UTF-8";
  break;

y voilá !!!