Curso Asterisk (IV): El Dialplan

En la anterior entrada vimos cómo dar de alta algunas extensiones internas, y trabajamos muy por encima con el Dialplan para poder llamar de una extensión a otra.

El Dialplan es el verdadero corazón de Asterisk y de cualquier sistema VoIP. El Dialplan, o plan de marcado, es una colección ordenada de acciones que se ejecutan cuando alguien marca un número dentro de nuestro Asterisk. El ejemplo más trivial sería que cuando alguien marca la extensión de otra persona, por ejemplo “3001”, suene el teléfono de ese usuario. Sin embargo, se pueden hacer cosas mucho más avanzadas, como por ejemplo gestionar las llamadas en función de un horario, crear una centralita automática de recepción de llamadas, grabar conversaciones, poner música en espera, etc.

Antes de entrar en lo que se puede hacer con el Dialplan, vamos a definir algunos conceptos básicos.

CONCEPTOS BÁSICOS

Extensiones

Definición: Una extensión es una marcación en el teclado de un teléfono.

Por ejemplo, un usuario podría marcar “3001” en su teléfono, y eso sería una extensión. También podría marcar un número de teléfono nacional, como por ejemplo “915881000”, y también sería una extensión.

Aunque lo normal es que las extensiones sean numéricas, no debemos pensar sólo en números, ya que en Asterisk también se pueden definir extensiones como texto. Por ejemplo, “pizza” sería una extensión válida.

Un plan de marcado empieza con una colección de extensiones a las que se puede llamar. Esta definición de extensiones puede ser literal, o puede ser una expresión. Por ejemplo, si hemos definido las extensiones desde la 3001 hasta la 3009, podemos definirlas en nuestro dialplan enumerándolas una detrás de otra, de forma literal:

  • 3001
  • 3002
  • 3003
  • 3004
  • 3005
  • 3006
  • 3007
  • 3008
  • 3009

Sin embargo, si todas ellas van a tener la misma colección de acciones (en general, pasar la llamada a la extensión marcada), sería mucho más cómodo definirlas todas a la vez con una expresión:

  • _300X

Las expresiones van precedidas de guión bajo “_”, que indica que lo que viene a continuación es una expresión que puede cuadrar con más de una extensión. Para definir expresiones en Asterisk disponemos del siguiente lenguaje:

Símbolo Significado
X Cualquier cifra de 0 a 9
Z Cualquier cifra de 1 a 9
N Cualquier cifra de 2 a 9
[x-y] Cualquier cifra de "x" a "y"
[xyz] Las cifras "x", "y" o "z"
. Una o más repeticiones del símbolo anterior
! Cero o más repeticiones del símbolo anterior

En general necesitaremos hacer uso de expresiones para definir las extensiones de nuestro sistema, ya que hay cosas que no se pueden hacer de forma literal. Por ejemplo, no podemos definir uno a uno todos los números de teléfono posibles de España. Lo lógico es decir “los teléfonos móviles en España empiezan por “6” y tienen 9 dígitos en total”, y no empezar a enumerar las 1.000.000.000 (mil millones) de posibilidades existentes. Veamos algunos ejemplos:

Significado Expresión
Todas las extensiones de 4 cifras _XXXX
Todas las extensiones de 4 cifras que empiecen por 3 _3XXX
Móviles de España que empiecen por 6 _6XXXXXXXX
Móviles de España que empiecen por 7 _7[1-4]XXXXXXX
Fijos de España que empiezan por 9 _9[1-8]XXXXXXX
Todos los fijos de España _[8-9][1-8]XXXXXXX

A continuación veremos cómo se relacionan las extensiones con las acciones, llamadas “aplicaciones” en Asterisk.

 

Aplicaciones (acciones)

Definición: Las aplicaciones son el conjunto de acciones a ejecutar cuando un usuario inicia una llamada.

Por ejemplo, supongamos que cuando alguien marque “3001”, queremos que suene el teléfono de esa persona. Sería algo así:

También podríamos querer darle un mensaje a la persona que llama antes de pasar la llamada a destino. Por ejemplo:

O pasar la llamada sólo entre las 10h de la mañana y las 20h de la tarde:

Las aplicaciones más utilizadas son las siguientes:

Aplicación Ficha Descripción
Answer URL Descuelga la llamada entrante
Dial URL Realiza una llamada saliente
Hangup URL Termina la llamada en curso
Wait URL Espera X segundos antes de continuar con la siguiente acción
Festival URL Utiliza el sintetizador Festival para emitir mensajes de voz
Playback URL Reproduce un archivo de sonido o vídeo
SayUnixTime URL Dice la fecha y hora actual a la persona llamante
Background URL Reproduce música en espera
NoOp URL No realiza ninguna operación, pero imprime el mensaje indicado en la consola de Asterisk
ExecIf URL Ejecutar la aplicación indicada si se cumple la condición dada
ExecIfTime URL Ejecutar la aplicación indicada si se cumple el requisito de fecha y hora indicados

En esta página web se puede ver un listado completo de aplicaciones de Asterisk junto con la descripción y sintaxis de cada una de ellas:

Asterisk Applications

 

Prioridades

En un lenguaje de scripting, las acciones se van ejecutando de arriba a abajo, en orden. En cambio, en Asterisk, el orden en el que se ejecutan las acciones debe ser explícitamente indicado mediante números. Así, primero se ejecutará la acción 1, después la acción 2, y así sucesivamente.

Es decir, en los ejemplos anteriores no basta con poner las aplicaciones (acciones) una debajo de la otra. Hay que indicar numéricamente el orden, de forma explícita.

Definición: La prioridad representa el orden en el que se ejecutarán las acciones del dialplan.

La sintaxis para indicar el orden la veremos a continuación.

 

PONIENDO TODO JUNTO

Hemos visto cómo se definen las extensiones mediante expresiones, qué aplicaciones (acciones) podemos utilizar, y también que es necesario especificar de forma explícita el orden de éstas. ¿Cuál es la sintaxis de Asterisk para poner todo esto junto?

Por ejemplo, supongamos que cuando alguien marque la extensión 3001, se pase la llamada sólo entre las 10h de la mañana y las 20h de la tarde:

Generalizando el ejemplo anterior, supongamos que queremos el mismo comportamiento cuando alguien marque cualquier extensión desde la 3001 hasta la 3009. Para esto, lo más cómodo es utilizar expresiones:

Fijaos que en este caso hemos utilizado la variable ${EXTEN} dentro de la llamada a Dial() para que se lance la llamada a quien corresponda. La variable ${EXTEN} es una de las variables básicas que utilizaremos, y que contiene la extensión marcada por la persona llamante.

 

PONIENDO TODO JUNTO: VARIANTES

En “Poniendo todo junto” hemos visto la sintaxis básica del dialplan de Asterisk. Sin embargo, a la larga es una sintaxis muy engorrosa de mantener. El problema es que hay que repetir la expresión en cada línea, y hay que indicar la prioridad de ejecución cuando lo normal es que las acciones se ejecuten de arriba a abajo.

Supongamos este dialplan de ejemplo, donde la expresión cuadra con todos los fijos nacionales de España en formato internacional:

Si quisiéramos introducir una nueva aplicación entre Wait() y Dial(), nos obligaría a actualizar los números de prioridad de todas las aplicaciones que vienen debajo. Si el dialplan fuese mucho más largo, digamos 50 acciones en lugar de 5, imaginaos el engorro que puede suponer esto.

Una solución mejor es indicar que las aplicaciones se ejecuten de forma consecutiva, de arriba a abajo. Para esto, podemos utilizar la prioridad “n”, que indica “next”. De esta forma, podemos introducir nuevas aplicaciones en mitad de un dialplan sin tener que actualizar los números de prioridad. Sólo tenemos que indicar cuál es la prioridad “1”, y utilizar prioridad “n” para el resto:

Por otro lado, cambiar la expresión de las extensiones a las que se hacen referencia también resulta un engorro, ya que la expresión aparece en cada una de las líneas del dialplan. Si quisieramos que el segundo dígito admitiera “cero” para poder llamar a números “902 XXX XXX”, tendríamos que modificar cada una de las líneas de este dialplan. Sin embargo, hay otra sintaxis que permite definir la expresión sólo una vez, e indicar en las siguientes líneas que se trata de la misma extensión:

Esta última sintaxis es la que utilizaremos en el presente curso a partir de ahora, ya que es la más cómoda y compacta de todas las posibles.

 

CONTEXTOS

Ya hemos visto cómo se definen las extensiones de marcación y las acciones asociadas a ellas. Según lo estudiado hasta ahora, todos los usuarios tienen las mismas libertades. Ya que no todos los usuarios son iguales, necesitamos algún mecanismo que nos permita variar el comportamiento del sistema en función del mismo. Eso son los contextos.

Cuando definimos un usuario en sip.conf le asignamos un contexto. Cuando ese usuario inicia una llamada, se utiliza ese contexto del dialplan para ver qué extensiones tiene accesibles y qué acciones debe realizar el sistema.

Definición: Los contextos representan la unidad de organización más básica del dialplan de Asterisk. Un contexto engloba extensiones y acciones. Se utiliza para aumentar la seguridad del sistema, y para ofrecer servicios diferenciados en función del usuario.

Un contexto se define de la siguiente manera:

 

EJEMPLO COMPLETO

Supongamos un hotel con una recepción y tres habitaciones que cumple lo siguiente:

  • Para llamar a la recepción hay que marcar “0”
  • Para llamar a las habitaciones hay que marcar el número de habitación: “101”, “102” o “103”
  • La recepcionista puede llamar a cualquier habitación
  • Los huéspedes sólo pueden llamar a recepción (no pueden llamar a otras habitaciones)

Índice del Curso Asterisk:

17 pensamientos en “Curso Asterisk (IV): El Dialplan

  1. He llegado a tu blog buscando información acerca de como montar un asterisk. Quiero felicitarte por los 4 artículos porque son excelentes, muy bien explicados y muy instructivos. Me ha asustado la idea de que asterisk pueda ser vulnerable a ataques desde el exterior. ¿Tienes pensado hacer algún artículo relativo a la seguridad con asterisk?

    Un saludo.

  2. Hola Joaquín.

    Muchas gracias por tus comentarios. Me alegro mucho de que el curso te esté resultando de ayuda.

    Sobre lo que preguntas de la seguridad, te diré que Asterisk es MUY INSEGURO en su configuración por defecto. Tengo programado un capítulo del curso dedicado exclusivamente a seguridad que publicaré un poco más adelante, pero primero quiero hablar de conexiones con proveedores VoIP, y de los problemas que causa el NAT.

    No obstante, si sigues mi curso, los ejemplos que pongo ya tienen en cuenta la mayoría de elementos de seguridad necesarios para un entorno de uso real, solo que aun no los estoy explicando. En el capítulo de seguridad, que calculo que será la 7º entrada, explicaré esos detalles junto con algunas técnicas “para nota”, como es el uso de fail2ban + iptables para detectar y detener ataques de fuerza bruta. Mientras tanto, puedes basarte en los ejemplos del curso para montar un servidor Asterisk con confianza.

    Un saludo.

  3. Hola oye una pregunta estoy haciendo un portero con un teléfono SIP ya funciona cuando marco la extensión activa un relevador, tome 3volts del display le metí una fase de aplificación para mantener los 5volts del relevador y funciona bien lo que quiero ahora es que esa extensión solo la puedan marcar determinadas extensiones ose si yo tengo no se 20 extensiones por decir de la 101 a la 120 quiero que la 109 y 110 puedan marcar esa extensión los demás no, ya que no están autorizados para abrir slaudos

  4. La mejor forma es redirigir las extensiones 101-108 y 111-120 hacia un contexto “context-no-puede-abrir”, y las extensiones 109-110 hacia otro contexto diferente “context-puede-abrir” donde ejecutes la acción de abrir la puerta.

  5. hola me puedes ayudar tengo un problema quiero hacer que mis extensiones no puedan llamar al exterior, pero si puedan llamarse entre ellas, hasta aquí lo logre. cada extensión solicita a la operadora una llamada y la operadora le concede la llamada transfiriéndole. PERO aquí es el relajo la llamada solo tiene que durar 3 MIN he echo mil Contextos con TimeOUT y todos funcionan bien si la llamada sale desde la extensión. pero si es transferida salta todo..

    [Extension-Bloqueada]
    include => ext-local
    exten => _X.,1,Set(LIMIT TIMEOUT FILE=goodbye)
    exten => _X.,n,Set(LIMIT WARNING FILE=beep)
    exten => _X.,n,Dial(DAHDI/8/${EXTEN:1},40,TtL(60000:40000:20000))
    exten => _X.,n,Macro(outisbusy)

  6. Una pregunta, ¿quieres que las llamadas pasen obligatoriamente por operadora, o es simplemente la forma que has encontrado para impedir que llamen al exterior? Lo pregunto porque, con un dialplan apropiado, puedes permitir llamadas entre extensiones sin tener que pasar por operadora, e impedir que puedan llamar al exterior. Si lo haces así, el parámetro “L” de Dial(), que ya estás usando, te funcionará perfecto para lo que buscas.

    Crea un contexto “extensiones-internas” que sólo permita llamar a las extensiones internas, y asígnaselo a tus cuentas de usuario para impedir que puedan llamar al exterior.

  7. hola gracias por Responder

    te cuento bien cual es el requerimiento

    1° todas las extensiones pueden llamarse entre si y a los app de la central (Reloj,VoiceMail,Call Parking.etc)
    2° Dos Extensiones el jefe y la operadora no tienen restricción de tiempo estan con el contexto from-internal
    3° solo la operadora puede llamar y transferir la llamada a los usuarios, estas llamadas tienen que durar 3 min

    te cuento las pruebas que echo

    1° en GENERAL SETINGS/Asterisk Outbound Dial command options: puse la opción L(60000:40000:20000) con esto logro que todas las extensiones logren solo una llamada de 1min pero al momento de transferir la llamada deja sin efecto la restricción

    2° cree un contexto el cual le pongo a las extensiones para que puedan llamar pero con la restricción de tiempo
    [Extension-Bloqueada]
    exten => _X.,1,Set(LIMIT TIMEOUT FILE=goodbye)
    exten => _X.,n,Set(LIMIT WARNING FILE=beep)
    exten => _X.,n,Dial(DAHDI/8/${EXTEN:1},40,TtL(60000:40000:20000))
    exten => _X.,n,Macro(outisbusy)

    pero esto no es lo que necesito si no que la operadora transfiera la llamada y dure 3min échame una manito que ya acabe con todo jajaja

  8. Hola;

    Felicidades por al artículo, he llegado a él porque tengo un problema con la configuración de los softphone…..

    Resulta que quiero analizar los tráficos con ellos y veo que un está transmitiendo en RTP y el otro en NBNS y no sé porque….

  9. Hola me gustaría saber como implementar un dial plan que consulte información a una base de datos externa
    gracias espero me puedan ayudar

  10. hola, muchas gracias por tu excelente blog, estoy siguiendo tu curso al pie de la letra ayer monte mi asterisk el cual tengo funcional.

  11. Buen día

    tengo un inconveniente no se si puedas colaborar me, puesto que he definido el dial plan para una de las extensiones que tengo configuradas, necesitaba realizar una transferencia al IVR principal, eso lo hice definiendo unos parámetros pero en el momento que realizo la transferencia la linea se queda ocupada hasta que la llamada entrante se cuelgue.
    que debo hacer para que me ingresen al IVR las llamas?

    Gracias 😀

  12. Buenos dias amigo.. excelente tu blog… estoy algo trabada con lo de llamar y grabar llamadas… si me pudieras ayudar serias de gran ayuda :).. de antemano espero tu respuesta

  13. Hola, muy bueno el tutorial, los felicito…
    ahora les pregunto:
    Si tengo un conjunto de extensiones, de la 9501 a la 9521 de las cuales son teléfonos IP fijos y quiero que cada extension marque un código de salida antes de tener linea exterior (Para el CDR y posterior facturador) como se configuraría? Son un conjunto de 20 códigos distintos para esa finalidad.
    Ejemplo: desde la extension 9501 quiero hacer una llamada al exterior de la PBX marcando 41360 + numero exterior (donde el 4136 es el código y 0 es salida a linea exterior). Como se configuraría?

    Desde ya muchas gracias, estoy trabado en esa configuración.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *