SIP Tracing: HEP Routing en arquitecturas multi-tenant

Muy buenas a tod@s!

Un poco más de #voip today, en vísperas del gran VoIP2Day organizado por Avanzada7, donde seguro los asuntos de métricas, testing, manejo de capturas tendrán su huequito habitual… el mismo año pasado Federico Cabiddu ya nos presentaba las novedades desde QXIP y Celeste Mangani en el cocktail-networking nos trasladaba su interés por repetir, esperamos  tenerles de nuevo 😉

En concreto, queremos comentar el tipo de soluciones/arquitecturas que estamos dando para los despliegues de dichas soluciones en entornos multi-tenant, como es el caso de muchos profesionales con producto propio X, Y o Z o con soluciones adquiridas.

Desde la perspectiva del integrador que configura/parametriza como revendedor o técnico/tenant de cliente C, darle acceso a herramientas de debugging es el primer paso de la auto-gestión, al igual que estamos cómodos con gestionar todo en Amazon AWS, X o Y porque tenemos las herramientas, el acceso a las trazas SIP es el concepto de «dar una caña de pescar» y no «el pescado» (no vaya a ser que acabemos con Percas del Nilo por aquí 😉 ).

Sea como fuere, lo que no pretendemos es publicar un tutorial de SIPCAPTURE, existen ya numerosas presentaciones y documentación de calidad  disponible online .

Planteamiento de base

Dicho esto, la solución  SIPCAPTURE es increíble, pero no soporta el concepto de multi-tenancy, con lo que se puede ofrecer es entregar un flujo HEP y que cada integrador grande  que lo necesite tenga su instancia (dónde quiera / proceda / se lo construya).

Cabe destacar, que para poder hacer esto, tiene que haber un atributo diferenciador clave en el paquete SIP para que podamos saber de que brand/company es. Si hemos seguido las siempre bien recibidas recomendaciones de Olle y está todo bien gestionado con SIP Domains diferenciados, estamos ante una búsqueda fácil, en IVOZ Provider al menos cogimos ese camino y nos ha simplificado esto mucho, si no lo tenemos por Domains, tendremos que buscar por DID/CLID? (en la ruri, diversion, pai, rpid, etc …).

Protocolo HEP

Como base, lo importante a tener en cuenta es que es un protocolo que va mucho más allá de SIP, permite encapsular muchos otros tipos de protocolos y aporta información en sus headers del tipo de payload que lleva. Desde la versión 3 se soporta el envío por TCP (con confirmación de entrega por tanto).

Lanzaban el draft de forma muy específica (disponible aquí) , y la última revisión de la versión 3, actualizada hace 1 mes escaso igualmente disponible en Github.

Cogiendo directamente de dicho PDF tan detallado:

Siendo la cabecera:

Y en concreto, lo que nos interesa de los vendors:

(la imagen está cortada).

Como se puede ver, mucho más allá de SIP, aunque sea la parte que mas usamos los que nos dedicamos a este tipo de soluciones de voz, incluyendo RTCP con sus SR’s y RR’s.

¿Captagent?

QXIP tiene desarrollados y aportados módulos para los principales players open source de este tipo de arquitecturas, y cuando no, siempre se puede desplegar con Captagent y que analice los RTCP vistos directamente on the wire.

A modo de ejemplo, la configuración propuesta en los samples oficiales, para el capture plan:

capture[pcap] {

	# here we can check source/destination IP/port, message size
	if(msg_check("size", "30")) {

		if(is_rtcp()) {
			if(is_rtcp_exist()) {

				#Convert to JSON if needed.
				if(parse_rtcp_to_json()) {
					#Can be defined many profiles in transport_hep.xml
					if(!send_hep("hepsocket")) {
						clog("ERROR", "Error sending HEP!!!!");
					}

				} else {
					clog("ERROR", "couldn't parse RTCP to json");
				}

			} else {
				clog("ERROR", "Couldnot find this call");
			}
		} else {
			clog("ERROR", "This is not RTCP");
		}
        }
	drop;
}

En la parte de transport_hep.xml tendríamos que tener el destino final (ip, puerto, protocolo) definido como «hepsocket» en este ejemplo.

HEP Routing?

El concepto que buscamos seria algo así como:

Es decir, actuar como multiplexor inteligente del flujo (es decir un router 😉 ), e igualmente como duplicador (HUB) si lo vemos necesario. Lo interesante es que en todos los casos tendremos acceso al contenido del paquete y podemos «pensar». A bote pronto, se nos puede ocurrir reenviar solo flujos de info RTCP cuando hay un packet loss > A, o cuando los paquetes vienen/van con una ip network que tenemos «en observación», y no sólo a un homer, sino a otro motor si queremos 😉 Es lo bonito y agradecido de que se haya optado desde QXIP por abrir el protocolo y dotar a los profesionales de esta flexibilidad.

Diferencias entre el módulo Kamailio y OpenSIPS

A fecha de hoy, el módulo SIPCAPTURE de Kamailio no dispone de la function «hep_relay» por el momento, con lo que no se puede redistribuir fácilmente. El módulo SIPCAPTURE de OpenSIPS si que dispone de dicha opción, junto con el módulo proto_hep, y nos permite actuar como HEP Router.

 

No sólo SIP ! ¿RTCP?

De una forma generalista, podemos pensar «está todo ok, mira este SDP que bonito es«, y soltar: «la culpa está en tu lado» y fin, estilo bofh 😉 Pero al final, aparte de que el concepto de culpa es difuso y no muy proactivo, lo que se busca es dotar de info para enfocar el problema.

La analogía se puede hacer por ejemplo con los contadores de matching de reglas de firewall, o no  disfrutamos de poder ver como suben para confirmar que está bien metida? Pues mas o menos, ese es el path que se aprecia mucho, se aprecia mucho el poder de ver una gráfica con 0 packets RTP recibidos y poder dirigir la solución (o viceversa), o poder correlacionar X calls en base a source IP y sacar sus medias de Packet Loss / Jitter.

CFG «hello world» ilustrativo

Pongamos que tenemos un captagent enviando el tráfico a la instancia OpenSIPS, puerto 9060, tanto tráfico SIP como RTP.

De base, tenemos que tener cargados los módulos proto_hep y sipcapture:

loadmodule "proto_hep.so"
loadmodule "sipcapture.so"

Hacemos que escuche HEP en el 9060, en este ejemplo con nuestra IP de LAN:

listen = hep_udp:10.10.0.156:9060

y lo que sí es muy importante es asignar una ruta:

modparam("sipcapture", "hep_route", "hep_route")

¿Qué es lo que pasa si no asignamos una ruta de entrada? Que parsea todo como si fuera SIP y los reportes de RTCP.

Con esta configuración lo que sucederá:

  • Entrarán por la ruta «hep_route», cada paquete HEP.
  • Pero no serán «SIP Tratable», es decir, no tenemos $ru ni $rd ni nada.

¿Cómo hacemos para tratar la info recibida de forma diferenciada?

Se puede coger tal que:

route[hep_route] {

hep_get("11", "$var(vendor)", "$var(data)");
xlog("L_DEBUG","HEP PROTO TYPE: $var(data)");

Y con eso ya vemos logs del tipo:

sep 19 12:03:37 zgor-pruebas-opensips01 /usr/sbin/opensips[22924]: HEP PROTO TYPE: RTCP
sep 19 12:03:37 zgor-pruebas-opensips01 /usr/sbin/opensips[22922]: HEP PROTO TYPE: RTCP
sep 19 12:03:37 zgor-pruebas-opensips01 /usr/sbin/opensips[22924]: HEP PROTO TYPE: SIP
sep 19 12:03:37 zgor-pruebas-opensips01 /usr/sbin/opensips[22925]: HEP PROTO TYPE: SIP

Una vez diferenciado el protocolo, lo que nos sucede es que en el caso de SIP no podemos acceder a los datos, no es un mensaje «parsed», pero basta con ejecutar hep_resume_sip:

1.4.7.  hep_resume_sip()

Break hep route execution and resume into the main request route.

WARNING: USE THIS FUNCTION ONLY FROM A ROUTE DEFINED USING hep_route PARAMETER.

Y nos quedaría tal que:

route[hep_route] {

      hep_get("11", "$var(vendor)", "$var(data)");
      xlog("L_DEBUG","HEP PROTO TYPE: $var(data)");

      if ($var(data) == "SIP")
      {
       hep_resume_sip();
       exit;
      }

     hep_get("utf8-string", "0x0011", "$var(vendor)", "$var(correlation_id)");
     xlog("L_DEBUG","RTCP - CallID Domain $(var(correlation_id){s.select,1,@})");
     $du="sip:10.177.88.38:9060";
     hep_relay();

}
route{
      xlog("L_DEBUG","Request $rm desde $si con domain $rd");
      $du="sip:10.10.0.156:1001";
      hep_relay();

      $du="sip:10.10.0.156:1002";
      hep_relay();

}

En este caso, por ilustrar las posibilidades, lo que hemos construido:

  • Si es un reporte RTCP, lo reenviará tal cual a 10.177.88.38 por udp al 9060.
  • Si es una traza SIP, lo enviará a dos destinos por HEP.
    • Sí, comprobado que esas dos llamadas consecutivas funcionan 😉

Cabe destacar en este punto la facilidad que nos da SNGREP para poder probar esto, ya que soporta HEP Capturing, aquí tenéis un tutorial de Nikolay Shopik explicándolo.

Aplicando perspectiva

Como veis, hemos entrado bastante en detalle, siendo todo el trabajo realizado por nuestro ingeniero de voz/rtc Ander Mendiola, pero lo publicamos sobre todo como proof of concept del path, posible, probado e implementado.

Es decir, todos los desarrolladores o explotadores de soluciones multitenant que tengáis como requisito u os interese ofrecer flujos HEP independientes a vuestros clientes, con sólo su info, tenéis camino.

De la misma forma, al igual que cuando estamos trabajando en soluciones de control de cloud con routing de millones de logs o mensajes AMQP contextualizados y duplicamos a analizadores independientes, IDS / Fraud Detection Systems , aquí esto tb nos vale, podemos duplicar los flujos y que cada elemento actúe de forma totalmente estanca – pudiendo morir sin que ello suponga nada serio ni pérdida de info 😉

En el caso de SIPCAPTURE, el gran añadido de poder aportar información contextualizada (Logs), enviando desde nuestro propio soft por HEP o usando HEPIPE  (no es complicarlo hookearlo a Journal – estilo journal2gelf), podemos entregar algo completo y vinculado, estilo:

Por último, comentaros que en caso de mucho mucho tráfico, conviene analizar bien todo lo que vamos a tener que resolver en el HEP Routing (¿Tenemos que atacar una BBDD? ¿Podemos evitarlo añadiendo alguna SIP header ? Hay que aplicar Técnicas de cache si o si o si, tener en cuenta que el RTCP es un tráfico muy muy importante).

 

 

Nada más por hoy. Nos vemos pronto!

 

 



¿Te gusta este post? Es solo un ejemplo de cómo podemos ayudar a tu empresa...
Sobre Gorka Gorrotxategi

CTO en Irontec, en el frente técnico desde un par de lustros ya, para todo lo que tenga que ver con Networking, VoIP y Sistemas, en ese orden :D) Desde @zetagor escribo algo, pero poco verbose la verdad

Queremos tu opinión :)