viernes 14 de diciembre de 2007

SIP REGISTER malicioso (engañando al proxy)

He descubierto recientemente el peligro de un REGISTER con una cabecera "Contact" maliciosa y la vulnerabilidad que puede suponer en entornos con gateways.

Pregunté sobre ello en la lista de users-es@mail.openser.org donde obtuve muy buenas y didácticas respuestas de miembros muy experimentados con estos asuntos.

Escenario

Supongamos una infraestructura con los siguientes personajes:

  • Un proxy SIP (OpenSer) con IP 100.100.100.100 donde registramos a los usuarios SIP y les otorgamos permisos en llamadas PSTN.
  • Un gateway SIP_2_PSTN con IP 1.2.3.4 (un Cisco, Nortel, Asterisk o lo que fuere) que recibe llamadas vía SIP y las convierte a la PSTN.

El flujo que realiza una llamada a la PSTN desde un dispositivo SIP es el siguiente:

  • El teléfono SIP envía un INVITE a su proxy (nuestro OpenSer) con esta pinta:
    INVITE sip:0034666555444@dominio.org SIP/2.0
    From: "Iñaki" <sip:ibc@dominio.org>;tag=iesxq
  • OpenSer nos fuerza a autenticarnos (lo que le sirve también para facturar la llamada) y posteriormente ruta el INVITE al gateway (IP 1.2.3.4).

En este punto hay que aclarar que el gateway no va a pedir autenticación "digest" para ese INVITE (el cliente ya se ha autenticado donde corresponde, es decir, en su proxy, y además OpenSer no es un B2BUA).

De hecho la autenticación en la comunicación proxy -> gateway es por IP o TLS. En nuestro caso supongamos autenticación por IP: El gateway sólo admite INVITE desde la IP de nuestro proxy (100.100.100.100) y se supone que toda la seguridad de acceso y permisos está controlada por el proxy (como ha sido en el caso de autenticar al usuario para la llamada PSTN del ejemplo anterior).

Funcionamiento del registro SIP

Cuando un usuario SIP quiere registrarse en su proxy para recibir llamadas envía un REGISTER tal que así:

REGISTER sip:dominio.org SIP/2.0
To: "Iñaki" <sip:ibc@dominio.org>
From: "Iñaki" <sip:ibc@dominio.org>;tag=pxziz
Contact: <sip:ibc@85.95.10.58>;expires=1800

Importante reseñar que:

  • En un REGISTER el campo importante es el To (y no el From) que implica el AoR (Address of Record) que queremos registrar, en nuestro caso sip:ibc@dominio.org.
  • La cabecera "Contact" indica la localización donde está el usuario (suponemos que está tras IP pública y nos olvidamos por hoy de los problemas y trapicheos del NAT).
  • Super-importante destacar que el contenido de la cabecera "Contact" lo escribe la aplicación cliente.

Así pues, tras el proceso de registro el proxy, en su papel de "Location Server", tendrá almacenada la siguiente información en alguna base de datos:

user                 contact
-----------------------------------------
ibc@dominio.org      sip:ibc@85.95.10.58

Ahora cuando otro usuario llame a ibc@dominio.org el INVITE llegará (por resolución DNS de dominio.org) a nuestro proxy. OpenSer buscará entonces en la base de datos la localización de dicho usuario y obtendrá sip:ibc@85.95.10.58.

Así que rutará allí el INVITE, o sea, llegará al teléfono SIP y sonará.

Trampa en el "Contact" del REGISTER

Ahora supongamos que soy un usuario malicioso (ibc@dominio.org) y quiero aprovecharme de mi proxy para hacer llamadas gratuitas.

Con alguna utilidad SIP genero un REGISTER así:

REGISTER sip:dominio.org SIP/2.0
To: "Iñaki" <sip:ibc@dominio.org>
From: "Iñaki" <sip:ibc@dominio.org>;tag=pxziz
Contact: <sip:0034666555444@1.2.3.4>;expires=1800

Lo que genera esta entrada en la base de datos del proxy:

user                 contact
-----------------------------------------
ibc@dominio.org      sip:0034666555444@1.2.3.4

Ahora desde otra cuenta SIP (o desde la mía propia) hago una llamada a ibc@dominio.org. Igual que antes el proxy consultará la base de datos y obtendrá en esta ocasión que debe rutar la llamada a sip:0034666555444@1.2.3.4, es decir, la rutará al gateway.

O sea, una llamada a sip:ibc@dominio.org se ha convertido en una llamada a la PSTN al número 0034666555444. Además el gateway permitirá esa llamada puesto que viene desde el proxy (IP 100.100.100.100).

Así de fácil hemos vulnerado la seguridad de nuestro proxy y obtenido privilegios en llamada gratuita a la PSTN.

Solución a este problema

El problema de raíz viene originado por el hecho de que el "Contact" en el REGISTER es creado por el usuario (o aplicación de usuario).

Una solución que inicialmente nos podría servir es la de prohibir registros en los que el "Contact" contenga alguna IP (en nuestro caso la 1.2.3.4 del gateway).

Para ello OpenSer, dentro del módulo "permissions" incluye el fichero "register.deny" y una función para consultarlo durante el REGISTER. En dicho fichero podemos escribir un listado de expresiones regulares que no permitimos en la URI de la cabecera "Contact" del REGISTER.

En nuestro caso ponemos:

ALL : "^sip:.*1\.2\.3\.4$"

Entonces si ahora mando el REGISTER malicioso anterior será rechazado por la URI del "Contact".

Ojito...

Pero como he vivido cerca de un colegio se me ocurre otra trampa. Envío este REGISTER:

REGISTER sip:dominio.org SIP/2.0
To: "Iñaki" <sip:ibc@dominio.org>
From: "Iñaki" <sip:ibc@dominio.org>;tag=pxziz
Contact: <sip:0034666555444@1.0002.3.4>;expires=1800

(obsérvese el 1.0002.3.4).

Esa IP no es detectada por la anterior expresión regular, sin embargo es válida:

$ ping 1.0002.3.4
PING 1.0002.3.4 (1.2.3.4) 56(84) bytes of data.
64 bytes from 1.2.3.4: icmp_seq=1 ttl=64 time=0.038 ms
64 bytes from 1.2.3.4: icmp_seq=2 ttl=64 time=0.056 ms
64 bytes from 1.2.3.4: icmp_seq=3 ttl=64 time=0.052 ms

Así que se nos colará de nuevo :(

Mejorando la solución

Entonces ponemos:

ALL : "^sip:.*0*1\.0*2\.0*3\.0*4$"

Y de esta forma se detecta la IP 1.0002.3.4 y se prohibe el registro. ¡Bien!

¿Seguro...?

Como atacante me estrujo el cerebro y mejoro mi estrategia:

Registro un dominio hackeando_mi_proxy.com y le asocio la IP 1.2.3.4. Ahora envío el REGISTER:

REGISTER sip:dominio.org SIP/2.0
To: "Iñaki" <sip:ibc@dominio.org>
From: "Iñaki" <sip:ibc@dominio.org>;tag=pxziz
Contact: <sip:0034666555444@hackeando_mi_proxy.com>;expires=1800

Ahora llamo (como antes) a sip:ibc@dominio.org y el proxy SIP obtendrá de su base de datos sip:0034666555444@hackeando_mi_proxy.com. No es una IP, por lo que antes de rutar el paquete tendrá que hacer una resolución DNS siguiendo el estándar "RFC 3263 - Locating SIP Servers".

Dicha resolución acabará devolviendo la IP 1.2.3.4, por lo que nuevamente hemos vulnerado la seguridad de nuestro proxy y obtenido llamadas gratuitas a la PSTN.

¿Entonces qué?

Una solución horrible es la de impedir dominios en el URI del "Contact", con lo que habríamos resulto el problema... a costa de verter heces sobre el RFC 3261, ya que el URI del "Contact" debe permitir hostnames/dominios. :(

Otra solución es permitir dominios en el "Contact" pero establecer que el gateway sólo admita INVITE con IP en el host del RURI (y no dominios o hostnames):

INVITE sip:0034666555444@1.2.3.4 SIP/2.0

y que rechace cosas como:

INVITE sip:0034666555444@hackeando_mi_proxy.com SIP/2.0
  • En el caso de Asterisk esto se consigue añadiendo en "sip.conf":
    allowexternaldomains=no
    domain=1.2.3.4

El resto de soluciones no me apetece explicarlas aquí porque todavía las estoy digeriendo, así que os remito directamente al hilo de la lista.

Especial mención para las respuestas de Klaus y de Juha Heinanen.

miércoles 10 de octubre de 2007

Gtalk2Voip: pasarela SIP-Gtalk-MSN-Yahoo

Gracias al servicio Gtalk2Voip es posible hablar y chatear entre cuentas SIP genéricas, Gtalk, MSN y Yahoo.

Explico a continuación algún ejemplo y posteriormente una pequeña configuración para OpenSer que ofrece algo de transparencia.

Llamada de SIP a Gtalk

Primeramente es necesario que el receptor (en este caso una cuenta de Gtalk user@gmail.com) autorice a un nuevo contacto (la pasarela) en su lista de contactos. Para ello introducir la dirección del receptor (user@gmail.com) en el recuadro "Subscription" de la página www.gtalk2voip.com.

Al usuario user@gmail.com le aparecerá un nuevo contacto service@gtalk2voip.com que tendrá que aceptar para recibir llamadas y mensajes.

A continuación desde nuestra cuenta SIP (genérica, de un proveedor, etc) llamamos o enviamos un mensaje a: sip:user_at_gmail.com@gtalk.gtalk2voip.com.

Y ya está :)

Llamada de SIP a MSN y Yahoo

Idem, pero con una modificación:

  • Llamada o chat a user@hotmail.com:    sip:user_at__at_msn.com@msn.gtalk2voip.com
  • Llamada o chat a user@yahoo.com:    sip:user_at__at_yahoo.com@yahoo.gtalk2voip.com

Llamada desde Gtalk a cuenta SIP

Muy fácil, ya que Gtalk se integra con este servicio y mostrará un usuario SIP en la lista de contactos (si previamente dicho usuario SIP le ha llamado y le hemos aceptado como contacto).

Es decir, Gtalk hace transparente este servicio en su softphone.

Llamada desde MSN o Yahoo a cuenta SIP

No tan bonito, ya que el único contacto que veremos será el de service@gtalk2voip.com y habrá que enviar comandos propios de este servicio.

Iniciamos un "chat" con service@gtalk2voip.com de nuestra lista de contactos (porque se supone que previamente nos hemos subscrito y aceptado a este contacto), y escribimos: IM sipuser@domain.org (para mensajería instantánea) ó CALL sipuser@domain.org (para llamada de voz)

Podemos conocer todas las posibilidades (hay muchas más) abriendo un chat con service@gtalk2voip.com y escribiendo HELP.

Configuración transparente para OpenSer

Sin duda es un poco feo escribir en nuestro softphone user_at_gmail.com@gtalk.gtalk2voip.com, así que en la sección "outbound" de nuestor OpenSer podemos facilitar un poco las cosas traduciendo las direcciones directamente:

# ---------------------------------------
# Outbound Section
# ---------------------------------------
# Mensajes que no van a nuestro servidor.
route[9] {

  xlog("L_INFO", "Outbound\n");

  ### Pasarela SIP to GoogleTalk.
  # usuario@gmail.com --> usuario_at_gmail.com@gtalk.gtalk2voip.com
  if ($rd == "gmail.com") {
   $avp(s:ru) = $ru;
   avp_subst("$avp(s:ru)", "/@gmail.com/_at_gmail.com@gtalk.gtalk2voip.com/g");
   $ru = $avp(s:ru);
   xlog("L_INFO", "$(Cps)Llamada a GoogleTalk$(Cxx) --> nueva RURI = $ru\n");
   sl_send_reply("181", "Llamada a GoogleTalk redirigida a $ru");
  }

  ### Pasarela SIP to Yahoo Messenger.
  # usuario@yahoo.com --> usuario_at_yahoo.com@yahoo.gtalk2voip.com
  else if ($rd == "yahoo.com") {
   $avp(s:ru) = $ru;
   avp_subst("$avp(s:ru)", "/@yahoo.com/_at_yahoo.com@yahoo.gtalk2voip.com/g");
   $ru = $avp(s:ru);
   xlog("L_INFO", "$(Cps)Llamada a Yahoo Messenger$(Cxx) --> nueva RURI = $ru\n");
   sl_send_reply("181", "Llamada a Yahoo Messenger redirigida a $ru");
  }

  ### Pasarela SIP to MSN Messenger.
  # usuario@msn.com --> usuario_at_msn.com@msn.gtalk2voip.com
  else if ($rd == "msn.com") {
   $avp(s:ru) = $ru;
   avp_subst("$avp(s:ru)", "/@msn.com/_at_msn.com@msn.gtalk2voip.com/g");
   $ru = $avp(s:ru);
   xlog("L_INFO", "$(Cps)Llamada a MSN Messenger$(Cxx) --> nueva RURI = $ru\n");
   sl_send_reply("181", "Llamada a MSN Messenger redirigida a $ru");
 }
  else if ($rd == "hotmail.com") {
   $avp(s:ru) = $ru;
   avp_subst("$avp(s:ru)", "/@hotmail.com/_at_hotmail.com@msn.gtalk2voip.com/g");
   $ru = $avp(s:ru);
   xlog("L_INFO", "$(Cps)Llamada a MSN Messenger$(Cxx) --> nueva RURI = $ru\n");
   sl_send_reply("181", "Llamada a MSN Messenger redirigida a $ru");
  }

  if (method=="INVITE") {
   t_on_branch("8");; # Tratamiento NAT por cada branch con RTP-proxy.
  }

  route(1);
  exit;

}

De esta forma podemos, desde nuestro softphone registrado en OpenSer, llamar o chatear directamente con las direcciones reales de los usuarios de Gtalk, MSN y Yahoo sin tener que "traducirlas" a la nomenclatura de la pasarela Gtalk2Voip: user@gmail.com - user@hotmail.com - user@yahoo.com

Problemas

  • Esta comodidad acarrea un problema. Si enviamos un mensaje a user@gmail.com y éste nos responde, su campo "From" no será user@gmail.com, sino user_at_gmail.com@gtalk.gtalk2voip.com, por lo que nos abrirá una ventana nueva e independiente de la que habíamos iniciado nosotros.
  • Según mis pruebas, este servicio de pasarela Gtalk2Voip no respeta la cabecera "Record-Route" que inserta mi OpenSer (cuyo objetivo es el de mantener a OpenSer en el path de toda la comunicación), por lo que si durante una llamada de voz SIP-Gtalk uno de los usuarios cuelga, el BYE no pasa por OpenSer. No obstante tengo que confirmar este bug aún, ya que el autor me contestó en un correo que sí respetaban esa cabecera.

jueves 13 de septiembre de 2007

Códigos SIP de respuesta en "parallel fork"

Tras un larguísimo pero muy didáctico hilo de discusión en la lista de correo de Twinkle he aprendido algo interesante sobre las distintas formas de rechazar un INVITE y las consecuencias que ello tiene en entornos donde se produce un "pararell fork".

Parallel fork

Este término viene a designar un comportamiento del proxy SIP por el cuál una llamada se ramifica en varias "branches" (ramas), bien porque el usuario llamado está registrado en varias localizaciones, bien porque tiene activado un "forwarding" en paralelo, o bien porque se fuerza en el proxy SIP la creación de una nueva "branch" por la razón que fuere. En cualquier caso, el efecto final es que la llamada se ramifica en varias y llega a distintos dispositivos SIP en paralelo, hasta que alguno la acepte, hasta que alguno la rechace con un código 603 (lo explico más adelante) o hasta que en todas las branches se rechace la llamada o expire el temporizador.

Como curiosidad, aquellos que sólo conozcan SIP desde el punto de vista de Asterisk no han podido experimentar este concepto ya que sencillamente la implementación SIP de Asterisk no lo soporta (en Asterisk un mismo usuario SIP no se puede registrar desde varios dispositivos a la vez, ya que el último registro reemplazaría al anterior).

Casos de "parallel fork"

  • Registro en varias localizaciones: Esto sencillamente significa que una misma cuenta SIP esté configurada en varios dispositivos SIP y que todos ellos se registran en el proxy SIP (insisto en que esto no es posible en Asterisk, pero sí en proxy SIP de verdad como SER u OpenSer). Cuando alguien llama a dicho usuario el proxy SIP consulta los registros del mismo y "forkea" el INVITE a todas las localizaciones.
  • Forwarding en paralelo: Supongamos que un usuario tiene configurado en el proxy SIP un desvío en paralelo a otro destino SIP. Esto significa que si recibe una llamada, ésta se rutará a todas las localizaciones de dicho usuario llamado (el primer caso) y también a otro destino en paralelo (que podría ser un móvil a traves de una pasarela SIP_to_PSTN).

Ejemplo de "parallel fork"

Supongamos que un usuario SIP está registrado en OpenSer desde dos softphones (Twinkle y Linphone), y recibe una llamada desde un Minisip. Describiré mínimamente las branches que se crean (una por cada cabecera "Via") así como los conceptos de llamada o diálogo ("from-tag" + "to-tag" + "call-id"):

  • Linphone inicia un INVITE y genera un branch (transacción SIP), una etiqueta "from-tag" y un "call-id" para identificar dicha llamada (diálogo):
    branch=z9hG4bK1306833844 (Minisip-OpenSer)
    From: tag=1436578172 (Minisip)
    To: (vacío, esto lo genera cada llamado en el "180 Ringing")
    Call-id: 1312809482@192.168.1.58
  • El INVITE llega a OpenSer quien localiza al usuario llamado en Twinkle y Linphone y crea un branch para cada uno:
    branch=z9hG4bK035a.0a4552d7.0 (OpenSer-Twinkle)
    branch=z9hG4bK035a.0a4552d7.1 (OpenSer-Linphone)
  • En las respuestas "180 Ringing" en Twinkle y Linphone cada uno de ellos indica un "to-tag":
    To: tag=omjpo (Twinkle)
    To: tag=875927769 (Minisip)
  • En caso de que uno de ellos acepte la llamada (devuelve "200 OK") ya tenemos los campos necesarios que identifican unequívocamente a dicha llamada. Por ejemplo, si responde Twinkle:
    branch=z9hG4bK1306833844 (Minisip-OpenSer)
    branch=z9hG4bK035a.0a4552d7.0 (OpenSer-Twinkle)
    From: tag=1436578172 (Minisip)
    To: tag=omjpo (Twinkle)
    Call-id: 1312809482@192.168.1.58

Códigos SIP de llamada rechazada

Vamos a contemplar sólo los casos donde una llamada es rechazada por decisión "humana". Esto abarca la posibilidad de que el usuario presione el botón "Colgar" o "Rechazar" llamada (el típico teléfono rojo), o bien que tenga activado DND (Don't Disturb) y el teléfono rechace automáticamente la llamada.

480 Temporarily Unavailable

Según el RFC 3261:

The callee's end system was contacted successfully but the callee is currently unavailable (for example, is not logged in, logged in but in a state that precludes communication with the callee, or has activated the "do not disturb" feature). The response MAY indicate a better time to call in the Retry-After header field. The user could also be available elsewhere (unbeknownst to this server). The reason phrase SHOULD indicate a more precise cause as to why the callee is unavailable. This value SHOULD be settable by the UA. Status 486 (Busy Here) MAY be used to more precisely indicate a particular reason for the call failure. This status is also returned by a redirect or proxy server that recognizes the user identified by the Request-URI, but does not currently have a valid forwarding location for that user.

Básicamente significa que el usuario rechaza la llamada "porque no le viene bien aceptarla" o porque ha activado el DND. Pero lo más importante es entender que los códigos 4XX son respuestas que sólo afectan a su propia "branch". Es decir, si se ha producivo "parallel fork" y un dispositivo SIP devuelve un 480 sólo se cancela dicha llamada, pero el resto de "branches" persisten en estado activo, por lo que los restantes teléfonos siguen sonando.

486 Busy Here

Según el RFC 3261:

The callee's end system was contacted successfully, but the callee is currently not willing or able to take additional calls at this end system. The response MAY indicate a better time to all in the Retry-After header field. The user could also be available elsewhere, such as through a voice mail service. Status 600 (Busy Everywhere) SHOULD be used if the client knows that no other end system will be able to accept this call.

Lo que viene a decir algo similar al 480, aunque a efectos prácticos suele haber diferencias ya que muchos dispositivos SIP conciben un 486 como un "ocupado, pero llama de nuevo tan pronto como quieras", lo que provoca que si se rechaza una llamada con un 486 se repita la llamada instantáneamente.

Esto se produce por ejemplo en algunos Nokia al llamar a través de un proveedor SIP_to_GSM que genera un "486 Busy Here" cuando el móvil devuelve un "Busy" (ocupado en ese momento hablando con otra persona). Entonces el Nokia repite acto seguido la llamada, lo cuál puede llegar a ser molesto.

Dejar también claro que éste es un código 4XX que sólo termina su propia branch.

603 Decline

Según el RFC 3261:

The callee's machine was successfully contacted but the user explicitly does not wish to or cannot participate. The response MAY indicate a better time to call in the Retry-After header field. This status response is returned only if the client knows that no other end point will answer the request.

Su significado literal es "rechazar" la llamada. Pero su característica notable es que se trata de un código 6XX, lo que implica la cancelación del resto de branches generadas en el proxy SIP. Es decir, si se produce "parallel fork" y uno de los dispositivos devuelve un 603, el proxy SIP debe cancelar el resto de branches enviándoles un CANCEL.

Distintas implementaciones

Muchos se quejan de que el RFC no deja nada claro qué código usar para rechazar una llamada, ni siquiera queda muy clara la diferencia entre "480 Temporarily Unavailable" y "486 Busy Here" (la diferencia que he explicado viene a ser más fruto de distintas interpretaciones por parte de cada fabricante/proveedor más que algo que realmente figure en el RFC). Así pues la realidad es que cada teléfono SIP envía un código SIP impredecible cuando el usuario presiona el botón de rechazar llamada. Por ejemplo:

  • Twinkle: Responde con un "603 Decline" por lo que el proxy SIP cancela el resto de branches.
  • X-Lite: Reponde con un "486 Busy Here" (el resto de branches continúan).
  • SJphone: Responde con un "480 Temporarily Unavailable" (el resto de branches continúan).

Tal vez haciendo pruebas me encuentre con otro exótico código de respuesta para estos casos, si así fuese actualizaría este post.

jueves 30 de agosto de 2007

Asterisk: Parche chan_sip para permitir espiral SIP

El "chan_sip" versión 1 presente en Asterisk adolece de la posibilidad de recibir de vuelta un INVITE con el URI modificado. Este hecho se hace palpable cuando usamos un proxy SIP en conjunción con Asterisk.

El problema

Supongamos que tenemos nuestros usuarios SIP en OpenSer y que tenemos un Asterisk para ofrecer servicios de media así como pasarela a la PSTN. Imaginemos el siguiente caso (bastante deseable entiendo yo):

  • Asterisk recibe una llamada vía PSTN y la pone en contacto con un usuario SIP de OpenSer haciendo Dial(SIP/200@openser.mydomain.org).
  • El INVITE llega a OpenSer, quien consulta sus tablas de lógica y encuentra un "forwarding" del usuario "sip:200" al número "675123123".
  • Entonces OpenSer reescribe la URI del INVITE dejándola así: sip:675123123@asterisk.mydomain.org.
  • Así pues dicho INVITE llega de vuelta al Asterisk para que éste efectúe una llamada de móvil.
  • Problema: Cuando Asterisk recibe este INVITE de vuelta reconoce que se trata del INVITE que él envió y lo rechaza con "482 Loop Detected".

En fin, una faena que impide una característica tan vistosa y útil. :(

La solución

Por suerte hay más gente consciente de este problema y con capacidad de modificar el código de Asterisk. En concreto, para solucionar el problema existe un parche gestado a partir de un reporte en el tracker de Asterisk:

0007403: [patch] allow SIP Spiral to work instead of causing a '482 Loop Detected' condition

Por desgracia dicho parche está disponible sólo para la versión Asterisk 1.4 SVN 48358 (ahora van por la 81388). Pero no costaría mucho adaptarlo a la versión trunk.

A testearlo pues

Una vez que unos pocos hemos testeado el funcionamiento del parche lo que toca es que más gente lo haga para que los desarrolladores tengan bien claro que funciona y lo integren cuanto antes en la rama oficial. Así pues indico ahora paso a paso como testearlo:

Descargar la versión SVN 48358 de Asterisk:

~# cd /usr/src
~# svn checkout http://svn.digium.com/svn/asterisk/trunk asterisk-svn48358 -r 48358

Descargar el parche del tracker de Asterisk. Abrir ésta URL y descargar el fichero "sip_spiral.patch" disponible en la sección "Attached Files".

Aplicar el parche modificado:

~# mv sip_spiral3.patch /usr/src/asterisk-svn48358
~# cd /usr/src/asterisk-svn48358
~# patch -p0 < sip_spiral3.patch

Si no hay problemas (no debería) sólo queda compilar e instalar Asterisk como siempre:

~# ./configure
~# make menuselect => En "4. Codec Translators" desactivar "codec_zap" (al menos a mí me falla en esta versión)
~# make
~# make install

Nota: Antes del "make install" es recomendable borrar todos los módulos en "/usr/lib/asterisk/modules".

Reiniciamos Asterisk y en principio ya estaría. Ahora sólo falta montar el escenario de prueba:

  • En OpenSer ponemos un alias de "sip:200@openser.mydomain.org" a "sip:675123123@asterisk.mydomain.org".
  • Ponemos Asterisk permitiendo llamadas anónimas desde cualquier sitio (por no complicarnos la vida).
  • Definimos una extensión exten => test,1,Dial(SIP/200@openser.mydomain.org).
  • Definimos una extensión exten => _6XXXXXXXX,1,PlayBack(demo-congrats) (o si podemos que llame vía PSTN o proveedor SIP).

Y lo probamos:

  • Desde un tfno SIP llamamos a "sip:test@asterisk.mydomain.org".
  • La llamada llega a Asterisk quien generará un INVITE a "sip:200@openser.mydomain.org".
  • Ese INVITE llegará a OpenSer quien comprobará el alias y reescribirá la URI enviando de vuelta a Asterisk a la URI "sip:675123123@asterisk.mydomain.org".
  • Asterisk recibirá el mismo INVITE que él generó pero con URI modificada. Ahora gracias al parche no rechazará la llamada y mostrará:
    --- set_address_from_contact host 'XX.XX.XX.XX' -- Playing 'demo-congrats' (language 'en') -- SIP/openser-081c2c18 answered SIP/openser-081c4d18 -- Packet2Packet bridging SIP/openser-081c4d18 and SIP/openser-081c2c18
  • Además tocaría comprobar que todas las respuestas desde Asterisk pasan por OpenSer (se supone que hemos añadido "Record-Route" y tal).

Confirmar si funciona

En caso de que funcione os pido que me lo confirméis o bien lo hagais saber directamente en el tracker de Asterisk para que los desarrolladores tengan cierta garantía y puedan subir el parche al trunk. ;)