SIPp – Benchmarking servidores VoIP

SIPp (http://sipp.sourceforge.net/) es una herramienta opensource de prueba que permite inyectar tráfico SIP contra servidores de los cuales deseemos evaluar el rendimiento. Este programa puede actuar tanto actuando como UAC (User Agent Client) o UAS (User Agent Server), de tal forma que es capaz de generar tráfico, así como de reponder a él como si de un telefono o servidor Asterisk se tratase.

Gracias a unos ficheros XML, de los cuales mostraremos alguno, esta herramienta, que está disponible en los repositiorios de debian (ubuntu), permite establecer multiples llamadas y/o registros entre diferentes entidades. Estos ficheros XMLs pueden describir desde simples flujos de llamadas hasta algunos de mayor complejidad (dependerá de nuestro nivel y ganas).

Permite conexiones SIP sobre TCP o UDP, y es totalmente customizable. SIPP también puede enviar tráfico de audio (inyección de RTP) lo cual es muy interesante para poder analizar cuando se degrada el audio, por ejemplo, y/o analizar que nuestro servidor se encuentra completamente operativo.

Es una herramienta muy completa, y en el post actual voy a intentar hacer unas pruebas de concepto para familiarizarme con el, y poderlo utilizar regularmente como herramienta de debug.

Este software debe de ser utilizado con responsabilidad, y en ningún caso para realizar ataques contra terceras entidades. Tal y como yo lo veo, ha de ser una herramienta que nos permita calibrar la capacidad de nuestras máquinas, y así poder ver cuantos recursos tenemos disponibles y el comportamiento de centralitas y SBCs bajos condiciones extremas.

(1) Instalación de SIPP: Bajamos, descromprimimos e instalamos.

Instalamos SIPP, para comenzar a trabajar contra nuestro servidor. Así que abrimos una terminal, y si lo queremos hacer desde source code, nos deberemos de bajar el tar.gz, descomprimirlo, y realizar el ./configure y el make de lo que deseemos

toni@netvoip-sbc001:/home/toni# wget http://sourceforge.net/projects/sipp/files/sipp/3.4/sipp-3.3.990.tar.gz/download

toni@netvoip-sbc001:/home/toni# tar -xvzf sipp-3.3.990.tar.gz

toni@netvoip-sbc001:/home/toni# cd sipp-3.3.990

toni@netvoip-sbc001:/home/toni/sipp-3.3.990#./configure

En el paso de configure, podremos elegir qué soporte queremos para nuestro sipp. En cualquier caso, durante el proceso de instalación cabe destacar que yo tuve que ir haciendo apt-get installs de librerias y dependencias que faltaban.

toni@netvoip-sbc001:/home/toni/sipp-3.3.990#./configure --with-sctp --with-pcap

Instalamos SIPP a através de repositorios, o bajando del source. De modo simple:

toni@netvoip-sbc001:/home/toni#sudo apt-get install sipp

Una vez hecho esto, podemos ver si lo tenemos corriendo del siguiente modo:

toni@netvoip-sbc001:~$ sipp -v
SIPp v3.4.1-RTPSTREAM built Dec 29 2015, 16:36:44.
This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License as
 published by the Free Software Foundation; either version 2 of
 the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 GNU General Public License for more details.
You should have received a copy of the GNU General Public
 License along with this program; if not, write to the
 Free Software Foundation, Inc.,
 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Author: see source files.
toni@netvoip-sbc001:~$

(2) Bajamos y/o generamos un XML para trabajar

La verdad es que me bajé un XML, con el objetivo de generar registros, pero no me funcionó demasiado bien (básicamente no era capaz de hacerlo funcionar, así que me puse a tuneralo un poco y me funcionó contra el Asterisk). El XML que comparto lo he bajado de OpenVoip (http://www.open-voip.org/index.php?title=SIPP_UAC_and_asterisk). Es muy interesante esta página.

 <?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE scenario SYSTEM "sipp.dtd">
<!-- -->
<!-- Sipp Rgistration scenario. -->
<!-- -->
<scenario name="Basic Sipstone UAC">
 <!-- ********************************* -->
 <!-- ***** Send Register packet ****** -->
 <!-- ********************************* -->
 <send retrans="500">
 <![CDATA[

 REGISTER sip:[remote_ip]:[remote_port] SIP/2.0
 Via: SIP/2.0/[transport] [local_ip]:[local_port];port;branch=branchTag.[call_id]
 Route: <sip:[remote_ip]:[remote_port];transport=[transport];lr>
 Max-Forwards: 70
 From: <sip:[service]@[remote_ip]>;tag=[call_number]
 To: <sip:[service]@[remote_ip]>
 Call-ID: [call_id]
 CSeq: 2 REGISTER
 User-Agent: sipp-testing-reg
 Contact: <sip:[service]@[local_ip]:[local_port];ob>
 Expires: 7200
 Content-Length: 0

 ]]>
 </send>
<!--
Contact: <sip:[service]@[local_ip]:[local_port]>;transport=[transport]
-->

<!-- ******************************************** -->
<!-- ***** Getting 100 message is optional ****** -->
<!-- ******************************************** -->
 <recv response="100"
 optional="true">
<!-- ***** Must get 401. auth="true" to take the challenge into account ****** -->
 </recv>
 <recv response="401" auth="true">
 </recv>
<!-- ********************* -->
<!-- ***** Send Ack ****** -->
<!-- ********************* -->
 <send>
 <![CDATA[

 ACK sip:[service]@[remote_ip]:[remote_port] SIP/2.0
 Via: SIP/2.0/[transport] [local_ip]:[local_port];port;branch=branchTag.[call_id]
 From: <sip:[service]@[remote_ip]:[local_port]>;tag=[call_number]
 To: <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]
 Call-ID: [call_id]
 CSeq: 1 ACK
 Contact: sip:[service]@[local_ip]:[local_port]
 Max-Forwards: 70
 Subject: Performance Test
 Content-Length: 0

 ]]>
 </send>
<!-- ********************************************************************************** -->
<!-- ***** Send Registration with the authentication, note the user and password ****** -->
<!-- ********************************************************************************** -->
 <send retrans="500">
 <![CDATA[

 REGISTER sip:[remote_ip] SIP/2.0
 Via: SIP/2.0/[transport] [local_ip]:[local_port];port;branch=branchTag.[call_id]
 From: <sip:[service]@[remote_ip]:[remote_port]>;tag=[call_number]
 To: <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]
 Call-ID: [call_id]
 CSeq: 2 REGISTER
 User-Agent: sipp-testing-reg
 Contact: <sip:[service]@[local_ip]:[local_port];ob>
 [authentication]
 Expires: 7200
 Content-Length: 0

 ]]>
 </send>
<!-- ******************************************** -->
<!-- ***** Getting 100 message is optional ****** -->
<!-- ******************************************** -->
 <recv response="100"
 optional="true">
 </recv>
<!-- ****************************** -->
<!-- ***** Should get 200 Ok ****** -->
<!-- ****************************** -->
 <recv response="200" rtd="true">
 </recv>
</scenario>

In order to modify this XML file, I take into account regular REGISTERs sent from a regular user agent, and I just copied the syntax, emulating the behavior.

(3) Hacemos pruebas

Una vez listo nuestro XML procederemos a ejecutar sipp con los comandos necesarios para poder autenticar nuestro UA simulado contra nuestro Asterisk:

Extension to register: 1001

Password extension to register: p4ss0rdn4d4s3gur4

Source IP of the server (Local): 10.0.0.1

Destination Server (Asterisk): server.testing.netvoip.no-ip.org:5060

File to load:

Resumiendo, ejecutamos lo siguiente:

toni@netvoip-sbc001:/home/toni#sipp -s 1001 -ap p4ss0rdn4d4s3gur4 -i 10.0.0.1:5060 -r 10 server.testing.netvoip.no-ip.org:5060 -sf samplesXML/reg_uac.xml

Nos aparecerá una pantalla como la siguiente la cual se ira actualizando en nuestra consola.

sipp

Resultados de SIPP registrandose contra un servidor Asterisk

Lo aconsejable: ir trasteando y no olvidar el man de sipp.

Bueno, espero que os haya parecido de utilidad la herramienta. La verdad es que sólo le veo posibilidades…

Como siempre, os dejo con las referencias!

Sources:

http://sipp.sourceforge.net/

http://sipp.sourceforge.net/doc/reference.html#Create+your+own+XML+scenarios

http://www.open-voip.org/index.php?title=SIPP_UAC_and_asterisk

http://techvick.blogspot.co.uk/2014/09/how-to-intsall-sipp-on-ubuntu.html

https://www.mail-archive.com/sipp-users@lists.sourceforge.net/msg02305.html

Anuncios

JunOS – Creando ACLs para contar paquetes en una interfaz

A continuación voy a explicar cómo contar los paquetes que llegan de una determinada IP a nuestro router Juniper, a través de filtros y contadores. Esto lo utilizo en mi trabajo para cuando he de demostrar a los clientes que no se está cursando tráfico en una dirección.

En este caso miraremos las IPs que tienen con ver con el audio, de ahí que le demos este nombre al filtro.

Escenario:

IP de Cliente: 8.8.8.13
IP del SBC:    8.8.8.68

 

Pasos:

0) Accedemos al router por ssh o telnet

1) Creamos un filtro para trabajar con el tráfico. Para ello en último termino pondremos “next term” para que se sigan con las políticas siguientes en caso de no coincidir.

set firewall family inet filter count-packets-ip-port-voip-Troubleshooting-Audio-L3 term 10 from source-address 8.8.8.13
 set firewall family inet filter count-packets-ip-port-voip-Troubleshooting-Audio-L3 term 10 from destination-address 8.8.8.68
 set firewall family inet filter count-packets-ip-port-voip-Troubleshooting-Audio-L3 term 10 from protocol udp
 set firewall family inet filter count-packets-ip-port-voip-Troubleshooting-Audio-L3 term 10 then count AUDIO
set firewall family inet filter count-packets-ip-port-voip-Troubleshooting-Audio-L3 term 10 then sample
set firewall family inet filter count-packets-ip-port-voip-Troubleshooting-Audio-L3 term 10 then log set firewall family inet filter count-packets-ip-port-voip-Troubleshooting-Audio-L3 term 10 then accept set firewall family inet filter count-packets-ip-port-voip-Troubleshooting-Audio-L3 term 99 then next term

2) Aplicamos el filtro en la inferfaz. Por favor, es necesario tener en cuenta el orden, dado que este lo queremos aplicar como primero:

edit interfaces irb.9080
delete family inet filter input-list
set family inet filter input-list [count-packets-ip-port-voip-Troubleshooting-Audio-L3 Filter-DSCP Filter-IRB-SPEED]

3) Nos aseguramos de que el filtro está bien aplicado:

toni@JunOSRouter> show configuration interfaces irb.9080 | display set
 set interfaces irb unit 9080 description "IfType[Access:Customer Link]"
 set interfaces irb unit 9080 bandwidth 200m
 set interfaces irb unit 9080 family inet rpf-check
 set interfaces irb unit 9080 family inet filter input-list count-packets-ip-port-voip-Troubleshooting-Audio-L3
 set interfaces irb unit 9080 family inet filter input-list Filter-DSCP
 set interfaces irb unit 9080 family inet filter input-list Filter-IRB-SPEED
 set interfaces irb unit 9080 family inet filter output-list Filter-IRB-OUT
 set interfaces irb unit 9080 family inet address 192.168.1.1/24
 {master}
 toni@JunOSRouter>

4) Hacemos commit de los cambios:

toni@JunOSRouter>commit check
toni@JunOSRouter>commit

6) Hacemos tests y comprovamos que todo funciona correcto:

toni@JunOSRouter> show firewall filter irb.9080-i
 Filter: irb.9080-i
 Counters:
 Name Bytes Packets
 AUDIO-irb.9080-i 7083858 34970
 Policers:
 Name Bytes Packets
 Filter-IRB-OUT.9080-i 0 0
 {master}
 toni@JunOSRouter>
 toni@JunOSRouter> show firewall log | match 8.8.8.13
 15:31:11 pfe A irb.9080 UDP 8.8.8.13 8.8.8.68
 15:31:11 pfe A irb.9080 UDP 8.8.8.13 8.8.8.68
 15:31:10 pfe A irb.9080 UDP 8.8.8.13 8.8.8.68
 15:31:09 pfe A irb.9080 UDP 8.8.8.13 8.8.8.68
 15:31:09 pfe A irb.9080 UDP 8.8.8.13 8.8.8.68
 {master}
 toni@JunOSRouter>

¡Espero que os sea de ayuda!

 

Documentacion:

https://www.juniper.net/techpubs/en_US/idp5.0/topics/task/operational/intrusion-detection-prevention-tcpdump-using-cli.html

http://kb.juniper.net/InfoCenter/index?page=content&id=KB23420&actp=search

Asterisk: baneando IPs “peligrosas” de por paises

Hoy he encontrado una página muy interesante donde se reportan bloques de IP que pueden ser utilizados para realizar ataques. A la hora de securizar nuestro Asterisk, tener estos bloques de IPs denegados, nos ayudará mucho a mitigar malas experiencias, como por ejemplo, fraudes en llamadas.

Mi consejo es siempre banear todas las IPs excepto aquellas que queramos utilizar, conociendo a nuestros clientes, sin embargo, en algunos casos esto no puede ser, y hay que tener nuestro Asterisk abierto a todo el mundo.

¿A todo el mundo? Bueno, a casi todo el mundo. En este post explicaré como poner en funcionamiento un script que he encontrado junto a fail2ban (herramienta que no queremos que se deshabilite).

Este script que he encontrado en http://www.lowendguide.com/ se nutre de la base de datos de http://www.ipdeny.com, donde se pueden encontrar “algunas” (muchas) IPs que no son deseadas ni deseables, y desde las cuales se realizan mucho ataques. Estas están almacenadas por países.

Script:

Este script lo que hace es simplemente conectarse a la página, bajarse un listado de IPs de los países que queramos, y proceder a añadirlas en el IPTables de nuestra máquina. Sí, efectivamente, deberemos tener instalado IPTables en nuestro servidor para poder utilizar dicho script.

Una vez creado este script, el cual tenéis pegado en el siguiente apartado, lo que haremos es crear un fichero, con permisos de ejecución en nuestra máquina e insertar el siguiente código en bash:

#!/bin/bash
### Block all traffic from AFGHANISTAN (af) and CHINA (CN). Use ISO code ###
ISO="af cn"
 
### Set PATH ###
IPT=/sbin/iptables
WGET=/usr/bin/wget
EGREP=/bin/egrep
 
### No editing below ###
SPAMLIST="countrydrop"
ZONEROOT="/root/iptables"
DLROOT="http://www.ipdeny.com/ipblocks/data/countries"
 
cleanOldRules(){
$IPT -F
$IPT -X
$IPT -t nat -F
$IPT -t nat -X
$IPT -t mangle -F
$IPT -t mangle -X
$IPT -P INPUT ACCEPT
$IPT -P OUTPUT ACCEPT
$IPT -P FORWARD ACCEPT
}
 
# create a dir
[ ! -d $ZONEROOT ] && /bin/mkdir -p $ZONEROOT
 
# clean old rules
cleanOldRules
 
# create a new iptables list
$IPT -N $SPAMLIST
 
for c in $ISO
do
 # local zone file
 tDB=$ZONEROOT/$c.zone
 
 # get fresh zone file
 $WGET -O $tDB $DLROOT/$c.zone
 
 # country specific log message
 SPAMDROPMSG="$c Country Drop"
 
 # get 
 BADIPS=$(egrep -v "^#|^$" $tDB)
 for ipblock in $BADIPS
 do
 $IPT -A $SPAMLIST -s $ipblock -j LOG --log-prefix "$SPAMDROPMSG"
 $IPT -A $SPAMLIST -s $ipblock -j DROP
 done
done
 
# Drop everything 
$IPT -I INPUT -j $SPAMLIST
$IPT -I OUTPUT -j $SPAMLIST
$IPT -I FORWARD -j $SPAMLIST
 
# call your other iptable script
# /path/to/other/iptables.sh
 
exit 0

Si os fijáis bien, en la segunda línea del script se puede indicar entre las comillas los países que queremos que se baneen.:

### Block all traffic from AFGHANISTAN (af) and CHINA (CN). Use ISO code ###
ISO="af cn"

Si queremos banear las no deseadas de España, pondremos: “es” entre las comillas.

Una vez realizado esto, ejecutamos el script y a esperar. ¡Ojo! Este script siempre borra todo lo que tengáis en el IPTables, dado que ejecuta una función definida dentro del mismo llamada “cleanOldRules” la cual hace un flush de todas las reglas existentes.

Una vez realizado esto, y para mantener nuestro Fail2Ban trabajando como es de recibo, lo que os aconsejo es que procedáis a realizar un:

/etc/init.d/iptables reload

Con esto volveremos a cargar las chains de reglas del IPtables.

Depués de utilizar este script, y hacer un Word count de IPtables, pues me han aparecido un todal de 57692 reglas que banean (casi nada, y eso que comenté la parte de LOG…)

root@VOIP:/etc/asterisk# iptables -nL | wc -l
57692
root@VOIP:/etc/asterisk#

Mi consejo es que para ver que hace iptables de ahora en adelante, utilicéis un head (y a poder ser que os creéis un alias en la consola http://www.thegeekstuff.com/2010/04/unix-bash-alias-examples/). Las reglas se añaden en una cadena llamada “countrydrop”:

root@VOIP:/etc/asterisk# iptables -nL | head -n 20

Chain INPUT (policy ACCEPT)
target prot opt source destination
fail2ban-ASTERISK-UDP all -- 0.0.0.0/0 0.0.0.0/0
fail2ban-ASTERISK-TCP all -- 0.0.0.0/0 0.0.0.0/0
fail2ban-ssh tcp -- 0.0.0.0/0 0.0.0.0/0
countrydrop all -- 0.0.0.0/0 0.0.0.0/0

Chain FORWARD (policy ACCEPT)
target prot opt source destination
countrydrop all -- 0.0.0.0/0 0.0.0.0/0

Chain OUTPUT (policy ACCEPT)
target prot opt source destination
countrydrop all -- 0.0.0.0/0 0.0.0.0/0

Chain countrydrop (3 references)
target prot opt source destination
DROP all -- 27.116.56.0/22 0.0.0.0/0
DROP all -- 43.231.131.0/24 0.0.0.0/0
DROP all -- 43.249.40.0/22 0.0.0.0/0

Luego para no tener que repetir el proceso cada vez que se reinicie la máquina, haré un:

root@VOIP:/etc/asterisk# /etc/init.d/iptables-persistent save

¡Espero que este post sea de utilidad!

 

Referencias:

http://www.lowendguide.com/3/networking/block-an-entire-country-with-iptables-2/

http://www.ipdeny.com/ipblocks/data/countries

http://jonathanmanning.com/2012/01/17/how-to-iptables-firewall-configuration-for-sipvoip-on-centos-rackspace-cloud/

FoIP – Fax Over IP – Análisis de call Flow de T.38

T.38 es un estándar de 1998 para permitir que los faxes se envíen a través de redes IP entre diferentes terminales G3 (terminales fax), y poder enviar faxes a través de VoIP.

Si intentásemos enviar un fax a través de VoIP, al utilizarse en algunos casos códecs con compresión de voz, no siempre el resultado sería satisfactorio. Esto en gran parte es debido a que si se envía una tasa superior de ciertos baudios (símbolos/muestras por segundo), y luego se comprime la voz (a través de los códecs), se puede perder información propia del fax, quedando este ilegible o imposible de transmitir. El teorema de Nyquist (velocidad de muestreo) aplica aquí, dado que en una señal ya muestreada uno no puede tomar menos muestras por segundos que se ha utilizado para digitalizar la señal.

Generalmente, si se desea enviar un fax convencionalmente a través de VoIP (sin utilizar protocolos auxiliares) se debe de utilizar G711 (a-law o u-law dependiendo si estamos en USA o Europa) y una velocidad máxima de 9600 baudios (por motivos relativos a Nyquist ya explicados). Este método, que consiste en enviar el FAX sin procesado extra, como si de voz se tratase, se conoce como pass-through, dado que lo único que se hace es conectar los dos terminales directamente, y hacer que pase el audio de uno a otro. En este caso el audio lleva un fax dentro (si lo capturamos con Wireshark u otro sniffer podremos ver los tonos que se envían entre ellos sin problema).

El envío de faxes con Pass-Through es muy sensible a problemas en la línea, y si se pierden paquetes durante la transmisión es probable acabar con problemas en los envíos.

Para evitar esto, se crea el protocolo T.38, RFC 3362 (https://tools.ietf.org/html/rfc3362), el cual permite encapsular  T.30 (protocolo PSTN para enviar faxes) a través de IP. El escenario general es el siguiente: se envía faxes a través de de T.30, unos conversores de analógico/digital a IP lo traducen en T.38, encapsulando T.30, y se procede a realizar el envio extremo a extremo, tal y como en la imagen se puede apreciar.

Mucha de la señalización que veremos dentro de este articulo es T.30, dado que T.38 simplemente es el soporte para encapsular señalización T.30 dentro de este protocolo.

1

Este es el caso en que necesitaremos entender qué sucede, dado que es el único que podremos analizar en VoIP (el pass-through sólo podemos averiguar si la calidad de audio es correcta o no).

Cuando se envía un fax existen diferentes fases, las cuales vamos a proceder a detallar.

  • Fase A: Establecimiento de canal.
  • Fase B: Pre-mensajes e intercambio de capacidades. Negociación.
  • Fase C: Transferencia de imagen.
    • Fase C1: Pre-imagen test.
    • Fase C2 : Transferencia imagen.
  • Fase D: Procesos post-mensajes.
  • Fase E: Finalización de la llamada.

Es muy importante recordar las  velocidades de fax que existen, según los estándares. Estas se pueden ver en la siguiente tabla:

2

Dicho esto, vamos a intentar ver que mensajes existen en cada fase y cómo se realiza un flujo de llamada de FAX.

 

Fase A: Establecimiento de canal

Se establece la llamada y se detecta que se quiere transmitir un fax, dado que se envía durante unos tres segundos los famosos tonos de FAX. Aquí estamos dentro del dominio SIP, y lo que es el protocolo T.38 aún no ha empezado a actuar en la transacción.

3

 

El hecho de que un extremo detecte sonido de FAX produce que se realice un RE-INVITE. Estos tonos se conocen como ANS (ANSwering tone) y se dan en la primera fase del fax.

Tal y como se puede ver en la siguiente imagen, cuando se detecta el tono ANS (enviados a través de RTP en la conversación), dentro del dialogo SIP se renegocian las capacidades del medio que se va a retransmitir. Recordemos que SIP significa Session Initation Protocol, y simplemente sirve para que dos end-points se descubran y negocien (a través de SDP) cómo se van a enviar un flujo de datos. Cómo sea ese flujo de datos, es indiferente para SIP.

4

Es entonces cuando comienzan a aparecer los tonos dentro de T.38. Los primeros que se intercambian son conocidos como CNG y CED.

CNG(CalliNG tone): Es el tono que genera la máquina que envía el fax. Es un tono a 1100Hz. En este caso es el RTP (g711A) que se puede ver en primer lugar.

CED (CallED terminal identification tone): Es el tono que genera la máquina que recibe el fax. Es un tono a 2100Hz. Es el RTP (g711A) que se genera después del primer flujo RTP en sentido inverso.

5

En el caso que vemos como se procede a enviar dentro de SDP del mensaje INVITE y su 200OK el protocolo T.38, indicándose algunas de sus capacidades dentro de este.

6

Es importante que no olvidemos que aún nos encontramos en la Fase A: Establecimiento de canal para el envío de fax. Aún no se ha procedido a realizar ningún tipo de negociación a nivel de fax, a pesar de haber intercambiado las capacidades por SIP.

 

Fase B: Pre-mensajes e intercambio de capacidades. Negociación

Una vez que ya se ha detectado que la comunicación era entre dos faxes, y se da como finalizada la Fase A, se procede a realizar la negociación T.38 para intercambiar datos propios de la comunicación de fax, tal y como el llamante, el numero llamado y las velocidades de intercambio.

7

Estos son los mensajes que se intercambian durante esta fase entre los dos dispositivos:

CSI (Called Subscriber): Este mensaje sirve para que las máquinas intercambien sus identidades. Los terminales internacionales realizan su intercambio de identidades a través de este mensaje. En el caso inferior, el número llamado no se identifica (aparece “Number: unkown” en el campo).

8

DIS (Digital Identification Signal): Es un mensaje obligatorio/mandatorio, en cual los faxes que reciben describen sus capacidades para realizar las transferencias de archivos. Es una propuesta de negociación. En este caso, el fax que recibe dispone de v.27 y v.29 para recibir este fax.

9

DCS (Digital Command Signal): A través de este mensaje, los dos extremos de fax informan sobre la velocidad que van a utilizar para la transmisión, dado que el que envía el fax hace un set de las capacidades que va a proceder a utilizar para ello. En el caso de la imagen inferior se puede ver cómo se desea transferir a través de v.29 (9600 baudios).

10

TSI (Transmitting Subscriber Identification): Con este mensaje se informa al terminal que recibirá la llamada quien está generando el fax. En el cuadrado negro de la imagen inferior se puede ver el número llamante.

11

Una vez intercambiados estos mensajes se procederá a realizar la transferencia de la imagen del FAX, tal y como vamos a exponer a continuación.

 

Fase C: Transferencia de la imagen

En la fase C se procede, finalmente, a realizar la transferencia del FAX. Esta fase se divide en dos partes, una de training o pre-testeo del canal, que ayudará a evaluar cómo se encuentra el camino entre origen y destino, y otra donde finalmente se procederá a enviar la información del FAX.

Fase C1: Pre-imagen test

En esta sub-fase se realiza el envío de lo que es la pre-imagen. Para ello se utilizan los mensajes de preámbulo.

TCF (Test Pattern): Este es un mensaje que envía cero de forma continuada durante 1.5 segundos aproximadamente. Sirve como patrón para corroborar  que el canal se puede utilizar a la velocidad que se desea.

12

13

CFR (Confirmation to Receive): Se confirma que se ha recibido correctamente el training enviado por la otra parte (TCF).

14

FTT (Failure To Train): indica que el patrón recibido no es correcto. La máquina llamante deberá de bajar la tasa de transmisión, y enviar de nuevo un mensaje DCS seguido de un TCF para probar el canal con un nuevo datarate. Este proceso de bajar la velocidad se puede llegar a realizar hasta tres veces. En caso de que bajando tres veces la velocidad no resulte suficiente, el fax se desconectará.

15

En esta imagen superior se ve que cuando se recibe un FTT se realiza de nuevo un DCS donde se negocia una velocidad inferior, y los siguientes Trainings se envían a una velocidad inferior (de 9600 baudios a 7200 baudios).

Es importante recordar que entre los diferentes mensajes aparece preámbulos:

VXX-Preamble: Antes de intercambiar un mensaje entre emisor y receptor (y viceversa), se envía un preámbulo con los caracteres 01111110 en binario (0x7E) que se remite durante 1 segundo aproximadamente. De esta forma se controla el acceso al medio. Si un lado no recibe respuesta, después de tres retransmisiones se desconectará.

16

Fase C2: Transferencia imagen

Una vez realizado la transferencia de la pre-imagen y de haber determinado que todo funciona correctamente, finalmente se procederá a enviar los datos del FAX. En la imagen inferior se puede ver el intercambio de mensajes entre las dos entidades donde se la transferencia de la misma.

17

Desde el terminal que origina el fax se podrán enviar los siguientes mensajes:

MPS (Multi-Page-Signal): Lo origina el llamante para indicar que hay más páginas que van a seguir a la transmisión que se ha completado. En la última página del fax se envía un EOP. La entidad receptora contestará con un mensaje de tipo MCF, RTP, o RTN (dependiento del resultado).

EOP (End-Of-Page): Lo origina el llamante, para decir que todas las paginas han sido transmitidas. Si todo ha funcionado correcto, se procede a la última fase del envío de FAX, la fase E.

EOM (End-Of-Message) : Indica el final de una página, para que ambas máquinas (recepción-transmisión) puedan volver a fase B.

NSF (Non  Standard Funtion): Opcionalmente las máquinas de fax puden intercambiar otros mensajes no estándares, los cuales se engloban dentro de estos mensajes NSF, dado que no están soportados por el estándar.

Las respuestas a estos mensajes se analizarán en la siguiente fase, procesos de post-mensajes, que serán las respuestas que el receptor del fax nos dará a estos envíos.

 

Fase D: Procesos post-mensajes

Respuestas del destino de fax:

MCF (Message Confirmation): La imagen se ha recibido correctamente, y se pueden proceder a recibir nuevas páginas sin problema, o en caso de que se haya acabado la transacción, desconectar la llamada.

18

RTP (Re-Train positive): Indica que la imagen ha sido recibida pero que existen algunos errores y que la línea debe de ser re-evaluada antes de enviar el siguiente mensaje. Por ello, lo siguiente será enviar un mensaje de DCS/TCF para retestear la línea, pero no se volverá a enviar la información, dado que es suficientemente buena.

19

RTN (Retrain Negative): El receptor considera que la señal es inaceptable. En este caso se deberá de volver a enviar un DCS/TCF para retestear la línea y se volverá a reenviar el mensaje que no ha llegado correctamente.

Fase E: Finalización de la llamada

El extremo que se encarga de enviar el FAX debe de indicar con un mensaje de tipo DCN que quiere desconectar la comunicación a nivel de T.38. Esto vendrá acompañado de un BYE a nivel de SIP, tal y como se puede ver en las imágenes inferiores.

DCN (Disconnect): Este mensaje se acaba enviando para desconectar la sesión de fax. DCN se utiliza en algunos casos, cuando la transmisión no ha sido satisfactoria, para volver a enviar el fax en pass-through (no siempre es para finalizar la transacción).

20

 

Bueno, espero que esta entrada os haya sido de utilidad. Para mi ha sido clave, dado que ahora puedo entender un poco más cómo funciona esto del FAX y el T.38. Si algo me queda pendiente es analizar a fondo la correspondencia entre el contenido de SDP de T.38 con los mensajes que dentro de este se intercambian (pero esto ya lo haré en posts siguientes).

 

Referencias:

https://tools.ietf.org/html/rfc3362

http://what-when-how.com/voip/pstn-fax-call-phases-voip/

http://wiki.voipinnovations.com/display/VI/T.38

http://www.cisco.com/c/en/us/support/docs/voice/fax-modem-over-ip/20227-faxrelay-tsguide.html#topic1-1

Cabecera SIP – Diversion

En esta entrada voy a tratar con el concepto de “Diversion” en SIP (RFC 5806). Este RFC es una extensión de protocolo SIP, tal y como veremos, y nos va a servir para que el llamante identifique de quien viene redirigida la llamada.

El objetivo de este artículo es explicar en grandes rasgos el funcionamiento de este campo del protocolo SIP, basándome en mi experiencia profesional. Cualquier comentario será más que bienvenido.

Lo primero que me gustaría comentar es el significado de la propia palabra “diversion”, la cual en castellano significa, ni más ni menos que “desviación”.

En el caso de telefonía esto refiere a cuando un llamante (A – Alice) quiere contactar un destino (B – Bob) pero al no estar disponible, la llamada se desvía a un tercer destino (C – Carol). Bob será el “Divertor” de la llamada, es decir, la entidad que va a desviar la llamada hacia Carol.

La desviación Diversion  puede consistir en un cambio en la porción del usuario en el Requested-URI (la primera parte del INVITE). Esto significa que el recurso que queremos alcanzar con nuestra primera llamada va a ser distinto al que indicamos en nuestra primera petición.

Existen dos tipos de estrategia/configuración para utilizar la desviación a través de Diversion:

  • Recursivo

El SIP Proxy, en este caso P2, recibe la llamada para Bob. Dado que sabe que Bob no está disponible, genera una, o varias, peticiones para realizar esta redirección contra una tercera entidad (Carol).

Tal y como se aprecia en la imagen inferior, la R-URI ha sido modificada, para alcanzar este nuevo destino (“INVITE Carol@C”).

recursive

Es interesante ver como en el flujo de la llamada no se realiza una acción de Back2Back User Agent entre la llamada inicial de Alice a Bob, y la conexión final entre Alice y Carol. Como se aprecia, el ACK es enviado directamente de Alice a Carol, generándose un diálogo directo entre estas dos entidades.

 

  • No-Recursivo

El SIP Proxy o entidad que recibe la llamada para Bob no realizará este diversion, y simplemente indica con un mensaje de tipo 3xx.En este caso P2, en lugar de realizar una traducción de la R-URI, lo que hace es simplemente indicar al llamante, Alice, que debe contactar con Carol@C dado que hay un desvio sobre el destino Bob.
no-recursive

Una vez procesado este 302, Carol enviará directamente un INVITE contra Carol@C indicando que llama a esta entidad dado que Bob@P2 no se encuentra disponible.

Cabe destacar que en ambos casos (recursivo y no recursivo) se establece un diálogo directo entre las dos entidades, Alice y Carol, sin embargo el intercambio de mensajes es diferente.

Ambos paradigmas pueden ser combinados, tal y como se aprecia en el siguiente diagrama:

combined

Existen diversas razones para el call Diversion. A continuación enumero las que se describen en el RFC., las cuales vienen heredadas de ISUP e ISDN:

ISUP/ISDN reason code       Diversion reason code

      0001                        “user-busy”

      0010                        “no-answer”

      1111                        “unconditional”

      1010                        “deflection”

      1001                        “unavailable”

      0000                        all others

Cosideraciones:

A la hora de realizar facturación de llamadas, al activar diversion en nuestro escenario es importante considerar todos los escenarios, dado que esta redirecciones pueden hacer peligrar nuestros CDRs.

Es de vital importancia analizar cuando debemos/podemos de utilizar el paradigma recursivo/no-recursivo, así como tener en cuenta si nos interesa que alguno de nuestros SIP Proxies, además de encontrarse en recursivo, nos interesará que trabaje como Back2Back user agent.

En cualquier caso, las llamadas derivadas de Diversion deberían de ser facturadas al número llamado (en nuestro caso Bob) dado que es quien es el responsable de un escenario donde existe esta movilidad.

Enlaces:

https://tools.ietf.org/html/rfc5806

 

QoS sobre nuestras comunicaciones VoIP (SIP y RTP)

Cuando etiquetamos tráfico con diferentes priorirdades, existen dos modos de hacerlo, a nivel de protocolo IP (ToS) o a nivel de VLAN (802.1p). En este post vamos a ocuparnos de la primera parte, de la que se encarga de realizar diferenciación a nivel de IP (ToS).

A pesar de que en la practica presentada vamos a trabajar etiquetando todo el tráfico de VoIP entre dos redes, es necesario comentar que lo que queremos tratar con más alta prioridad no es el tráfico SIP (señalización) o el que se encuentre entre dos redes, sino sólo el RTP (paquetes de voz) que es el que lleva la información que una vez iniciada la conversación nos interesará más.

 

Diferenciación a nivel IP: DSCP (ToS)

El ToS (Type Of Service) es un campo que existe en la cabecera del protocolo IPV4 el cual se ha definido en diferentes RFCs. Es un campo de 6 bits, el cual indica a los routers que a la hora de enrutar los paquetes deben de hacerlo con mayor prioridad que el resto.

En la practica, nunca se ha aplicado a nivel extendido, pero en entornos que controlemos nosotros, es decir, en nuestra red, podemos trabajar sin problema con este parámetro.

Cuanto mayor sea el valor de este campo, mejor. Es decir, cuanto mayor sea más prioridad se le va a dar al paquete. La siguiente tabla se puede encontrar en Wikipedia. En nuestro caso, y como lo que queremos es dar prioridad a tráfico de VoIP vamos a diferenciar los datos RTP de nuestras comunicaciones.

DSCP Name DS Field Value (Dec) IP Precedence (Description)
CS0 0 0 : Best Effort
CS1,AF11-13 8,10,12,14 1 :Priority
CS2,AF21-23 16,18,20,22 2 :Immediate
CS3,AF31-33 24,26,28,30 3 :Flash – mainly used for voice signaling
CS4,AF41-43 32,34,36,38 4 :Flash Override
CS5,EF 40,46 5 :Critical – mainly used for voice RTP
CS6 48 6 :Internet
CS7 56 7 :Network

 

Diferenciación a nivel MAC: 802.1p

Esta técnica consiste, conocica como CoS, es un campo que se engloba dentro del las etiquetas del protocolo VLAN 802.1Q. Consiste en dar un valor a un campo de 3 bits llamado PCP. Su valor va entre 0 y 7 a nivel de prioridad. En la siguiente tabla de Wikipedia se puede ver los diferentes valores y acrónimos que se utilizan para este campo. Paara nuestro caso, el de tráfico VoIP, deberemos de utilizar el nivel 5, dejando los dos superiores a capas de management e internetwork.

PCP Priority Acronym Traffic types
1 0 (lowest) BK Background
0 1 BE Best Effort
2 2 EE Excellent Effort
3 3 CA Critical Applications
4 4 VI Video, < 100 ms latency and jitter
5 5 VO Voice, < 10 ms latency and jitter
6 6 IC Internetwork Control
7 7 (highest) NC Network Control

Es de importancia vital entender que el estandard 802.1p se encuentra intimamente relacionado con los 802.1d y 802.1q.

Implementando DSCP en nuestra red VoIP:

Tal y como hemos comentado anteriormente, vamos a realizar una aproximación. En nuestro caso lo que vamos a etiquetar es el tráfico saliente, para que llegue correctamente identificado a su destino, así como a los saltos intermedios. No tiene sentido etiquetar el tráfico en destino, dado que ya ha recorrido del paquete ya se ha realizado, con el riesgo de que haya sufrido congestión o pérdidas.

En nuestro Asterisk procedemos a realizar un etiquetado de tráfico a nivel de DSCP a través de iptables añadiendo las siguientes reglas con mangle. Siguiendo la tabla al campo DSCP le vamos a asignar el valor EF (que en decimal es 46, y en hexadecimal corresponde a 2E).

iptables -A OUTPUT -t mangle -p udp -m udp --sport 5060 -j DSCP --set-dscp 0x2e
iptables -A OUTPUT -t mangle -p udp -m udp --dport 5060 -j DSCP --set-dscp 0x2e
iptables -A OUTPUT -t mangle -p udp -m udp --sport 10000:20000 -j DSCP --set-dscp 0x2e
iptables -A OUTPUT -t mangle -p udp -m udp --dport 10000:20000 -j DSCP --set-dscp 0x2e

Una vez aplicado esto en nuestro iptables, si hacemos un tcpdump o ngrep, veremos como el tráfico que se envía a con puertos de origen iguales a los que hemos definido (protocolo UDP) aparecen con DSCP EF.

Routers Cisco:

A continuación vamos a configurar las diferentes políticas en nuestros routers Ciscos para que trabajen con DSCP, etiquetando todo el tráfico que entre con un destino determinado.

Configuramos un object-group para identificar todo el tráfico de voz que vamos a enviar:

object-group service voipservice 
 udp eq 5060
 udp gt 10000
 udp lt 20000

Después creamos las ACLs donde identificamos este tráfico. Para nuestro caso, vamos a tratar el tráfico que tiene como origen 192.168.3.0/24 y destino 192.168.1.0/24, pero podríamos haber puesto “any any” para cualquier tipo de tráfico que cumpliese el object-group. El hecho de realizar estos ACLs se realiza para aplicar después a los class-maps:

access-list 100 permit object-group voipservice 192.168.1.0 0.0.0.255 192.168.3.0 0.0.0.255

Creamos un class-map utilizando esta ACL para así poder tener nuestro tráfico clasificado dentro de nuestro router:

class-map match-any voip
 description VoIP-Traffic
 match access-group 100

Y finalmente la aplicamos a este tráfico una acción con policy-map. Es decir, ya lo tenemos identificado dentro de un class-map, y ahora le decimos que lo etiquete como EF en su campo DSCP.

policy-map voipdscppolicy
 description VoIP-Traffic-192168003
 class voip
  set ip dscp ef

Una vez tenemos esto ya configurado, aplicamos este policy-map en las interfaces de entrada. En nuestro caso es una interfaz que va conecta a la LAN del cliente, pero podría ser, perfectamente, una VLAN.

interface FastEthernet0/0
 description LANCLIENTE
 ip address 192.168.3.1 255.255.255.0
 !
 service-policy input voipdscppolicy

Y a generar tráfico y ver qué pasa. En mi caso, a la ACL he añadido una regla para que los ICMPs también los etiquete (he utilizado GNS3 para estas simulaciones).

CapturaTraficoEF

Referencias:

http://en.wikipedia.org/wiki/Type_of_service

http://en.wikipedia.org/wiki/IEEE_P802.1p

Kamailio – Autenticación de troncales por IP (Llamadas entrantes vía atenticacion LCR)

Para autenticar en el route[FROMPSTN] en lugar a través del archivo de configuración, tal y como hemos realizado en el anterior post, lo que vamos a realizarlo es através de mysql, aprovechando el módulo de LCR el cual utiliza soporte de mysql. Esto nos permitirá poder añadir más troncales para llamadas entrantes sin necesidad de editar el archivo de kamailio.cfg y no tener que reiniciar el servicio.

El módulo LCR, en principio, está diseñado para poder tratar a través de mysql las rutas salientes, y añadir diferentes provider para llamadas salientes si necesidad de tener que tocar configuración en kamalio.cfg.

En nuestro caso, lo que vamos a hacer es definir los troncales de entrada, con alguna regla para normalizar los DDIs entrantes (hacer strip de “+34”, “0034”, o “34”) e identificar que son llamadas entrantes. En futuros posts utilizaremos este módulo para lo que está diseñado, para emitir llamadas.

Paso 1: Cargar módulo LCR y configuración básica

Definimos que utilizaremos con LCR en los modulos:

#!define WITH_LCR

E indicamos lo siguiente para que lo cargue cuando se inicie el servicio.

#!ifdef WITH_LCR
loadmodule "lcr.so"
#!endif

Seguidamente, procederemos a definir los parámetros para este módulo:

#!ifdef WITH_LCR
# ----- lcr params -----
modparam("lcr", "db_url", "mysql://kamailio:p4sSw0rds!!@localhost/kamailio")
modparam("lcr", "gw_uri_avp", "$avp(i:709)")
modparam("lcr", "ruri_user_avp", "$avp(i:500)")
modparam("lcr", "tag_avp", "$avp(lcr_tag)")
modparam("lcr", "flags_avp", "$avp(i:712)")
modparam("lcr", "lcr_id_avp", "$avp(s:lcr_id_avp)")
modparam("lcr", "defunct_gw_avp", "$avp(s:defunct_gw_avp)")
#!endif

Paso 2: Añadimos direcciones de providers entrantes en tablas de mysql para este módulo

Procederemos a modificar las siguientes tablas, dado que son las que van a ocuparse de los LCRs y donde definiremos las reglas que se deben de emplear para poder tratar las llamadas entrantes que lleguen de estos troncales:

Tabla lcr_gw: Nos indica los gateways y endpoints donde podemos enviar (en nuestro caso recibir) las llamadas.

Tabla lcr_rule: Nos define las reglas que vamos a aceptar. Es decir, el dialplan para este provider.

Tabla lcr_rule_target: Nos dice qué hacer cuando esta regla coincida, es decir, relaciona los lcr_gw y las lcr_rule.

Vamos por faena, a añadir nuestro provider:

mysql> insert into lcr_gw (lcr_id,gw_name,ip_addr,uri_scheme,transport,strip,flags) VALUES ('1','INBOUND-PROVIDER-001','92.127.224.233','1','1','0','0');

mysql> insert into lcr_rule (lcr_id,prefix,stopper,enabled) VALUES ('1','34','1','1');
mysql> insert into lcr_rule (lcr_id,prefix,stopper,enabled) VALUES ('1','0034','1','1');
mysql> insert into lcr_rule (lcr_id,prefix,stopper,enabled) VALUES ('1','+34','1','1');
mysql> insert into lcr_rule (lcr_id,prefix,from_uri,request_uri,stopper,enabled) VALUES ('1','1','1');


mysql> insert into lcr_rule_target (lcr_id,rule_id,gw_id,priority,weight) VALUES (1,1,1,1,1);

Es interesante mirar los links adjuntos en el apartado de referencias, dado que encontraréis más información al respecto.

Paso 3: Añadimos esta lógica de llamadas en nuestro kamailio.cfg

Nuestro objetivo es cerciorarnos que las llamadas entranes llegan desde un troncal definido como entrante, si es así, ejecutaremos el route[FROMPSTN] el cual está pensado para poder procesar las llamadas

 # Llamadas entrantes
 if (from_gw("1")){
    xlog("*****DEBUGTONI-1: Llamada entrante autenticada por IP desde $src_ip reconocido por nuestro LCR entrante\n");
    route(FROMPSTN);
 }
 # Llamadas salientes
 else{
    xlog("*****DEBUGTONI: Llamada entrante desde usuario\n");
    # user location service
    route(LOCATION);

    # dispatch destinations to PSTN
    route(PSTN);
 }

CUIDADO! Dentro del código fuente de kamailio me encontré esto:

if ((lcr_id < 1) || (lcr_id > lcr_count)) {
 LM_ERR("invalid lcr_id parameter value %d\n", lcr_id);
 return -1;
}

Lo cual significa que los ID de LCRs deben de comenzar por el 1, y ser secuenciales (1,2,3,4…). La verdad es que no me parece normal esto, dado que yo lo que deseaba es crear los 2X para entrantes, y los 3X para salientes, y esto no se puede realizar. Lo apunto como nota para que no perdais vuestro precioso tiempo en esta tonteria.

¡Espero que os sea de ayuda!

Referencias:

http://dopensource.com/least-cost-routing-with-kamailio-v4-1/

http://www.kamailio.org/dokuwiki/doku.php/modules-new-design:lcr-module-design

http://www.kamailio.org/docs/modules/devel/modules/lcr.html#idp2039248

http://kamailio.org/docs/db-tables/kamailio-db-4.2.x.html#gen-db-dr-groups

http://www.open-voip.org/index.php?title=Kamailio_LCR

http://kamailio.org/docs/modules/4.0.x/modules/lcr.html#idp1807136

http://www.kamailio.org/docs/modules/4.2.x/modules/lcr.html

http://git.kamailio.org/gitlist/index.php/sip-router/commit/b1a941a21c7404c6a21df45b988b40695efcb347