Gnash en 64 bits.

Archivado en (Linux) por Gabriel el 26-08-2010

Como sabemos el soporte de Adobe para flash en Linux 64 bits esta mas que muerto: http://labs.adobe.com/technologies/flashplayer10/64bit.html

Hoy en día una pagina que no requiera el plugin de flash para desplegar su contenido es algo difícil de ver cotidianamente.
Gnash es un muy buen proyecto que si bien logra reproducir mucho del contenido flash de cualquier pagina web, la pagina mas famosa que requiere este plugin estaba negada para el.

Sin embargo parece ser que los chicos de Arch Linux, se han puesto las pilas y nos han regalado una actualización con la cual ya es posible visualizar desde youtube cualquier vídeo, para muestra la siguiente imagen.

http://www.gnu.org/software/gnash/
http://www.archlinux.org/

Protocolo SPICE para escritorios virtuales en Linux.

Archivado en (Linux, Virtualización) por Gabriel el 25-07-2010

Aprovechando que seguimos en pruebas con RHEV, pasaremos a checar un punto especifico de esta solución que son los escritorios virtuales, segun nos quieren vender la idea de que con solo una PC ligerita en cuanto a recursos y un navegador web podemos tener acceso a ‘n’ escritorios remotos usando el protocolo Spice que a simple vista tiene cosas bastante interesentas en cuanto a desempeño, facilidad de uso al interactuar con el escritorio virtual y poco costo con respecto al uso de ancho de banda.

Si bien esta aplicación no tiene ningún problema para instalarse en IE mediante un ActiveX, la cosa cambia con respecto a Firefox en Linux.

Aquí existen dos caminos si contamos con una suscripción de RedHat obviamente tenemos acceso a actualizar nuestro sistema y todo el contenido que sigue a continuación en teoria (no cuento con una suscripción) se reduciría al siguiente comando: yum install spice-xpi

En CentOS existe el paquete sin embargo los paquetes de los cuales depende no, al menos no los encuentras en los repositorios predeterminados, pero con un tiempo de busqueda enrpm.pbone.net es facil hallarlos a todos.

El paquete en cuestión se llama spice-xpi, el cual depende de qspice-client y este a su vez depende de unos paquetes mas, como podemos ver en las dependencias faltantes que se muestran a continuación al tratar de instalar estos paquetes.

1
2
3
4
5
6
[root@localhost gabriel]# rpm -ivh spice-xpi-2.2-1.el5_5.i386.rpm
warning: spice-xpi-2.2-1.el5_5.i386.rpm: Header V3 DSA signature: NOKEY, key ID 37017186
error: Failed dependencies:
        liblog4cpp.so.4 is needed by spice-xpi-2.2-1.el5_5.i386
        log4cpp is needed by spice-xpi-2.2-1.el5_5.i386
        qspice-client is needed by spice-xpi-2.2-1.el5_5.i386
7
8
9
10
11
12
13
14
15
16
[root@localhost gabriel]# rpm -ivh qspice-client-0.3.0-2.el5_5.i386.rpm 
warning: qspice-client-0.3.0-2.el5_5.i386.rpm: Header V3 DSA signature: NOKEY, key ID 37017186
error: Failed dependencies:
        libboost_program_options.so.2 is needed by qspice-client-0.3.0-2.el5_5.i386
        libboost_thread.so.2 is needed by qspice-client-0.3.0-2.el5_5.i386
        libcelt051.so.0 is needed by qspice-client-0.3.0-2.el5_5.i386
        liblog4cpp.so.4 is needed by qspice-client-0.3.0-2.el5_5.i386
        libqavcodec.so.51 is needed by qspice-client-0.3.0-2.el5_5.i386
        libqavutil.so.49 is needed by qspice-client-0.3.0-2.el5_5.i386
        libqcairo.so.2 is needed by qspice-client-0.3.0-2.el5_5.i386

Por lo tanto los paquetes necesarios son los siguientes:

1
2
3
4
5
6
7
boost-1.33.1-10.el5.i386.rpm
celt051-0.5.1.3-0.el5.i386.rpm
log4cpp-1.0-9.el5.i386.rpm
qcairo-1.8.7.1-3.el5.i386.rpm
qpixman-0.13.3-4.el5.i386.rpm
qspice-client-0.3.0-2.el5_5.i386.rpm
spice-xpi-2.2-1.el5_5.i386.rpm

Después de instalarlos volvemos a ejecutar nuestro paquete para agregar el plugin a Firefox.

1
2
3
4
[root@localhost gabriel]# rpm -ivh spice-xpi-2.2-1.el5_5.i386.rpm 
warning: spice-xpi-2.2-1.el5_5.i386.rpm: Header V3 DSA signature: NOKEY, key ID 37017186
Preparing...                ########################################### [100%]
   1:spice-xpi              ########################################### [100%]

Verificamos que el plugin se haya instalado correctamente en Firefox.

Debemos desactivar SELinux o ponerlo en modo permisivo de lo contrario no dejara ejecutar Spice, obteniendo en mensaje como este:

1
2
3
Jul 19 16:47:40 localhost setroubleshoot: SELinux is preventing spicec 
from loading /usr/lib/libqavcodec.so.51.71.0 which requires text relocation.
For complete SELinux messages. run sealert -l 1b920bdf-119e-46fb-b812-894ca58fc943

Volvemos a ejecutar nuestra aplicación para acceder con nuestro respectivo usuario.

De esta manera ya podremos visualizar y trabajar con nuestro escritorio virtual que en este caso es un Windows XP.

Esto funciona para distribuciones Linux basadas en RPMS (Red Hat 5.5, Fedora 12, CentOS 5.4), es asignatura pendiente instalar este plugin de Firefox para Debian o Arch, que son las distribuciones que actualmente uso de manera predeterminada.

Mas información:

http://www.redhat.com/about/news/prarchive/2009/spice-os.html
http://www.spice-space.org/
http://www.redhat.com/virtualization/rhev/desktop/

Gusano Kido y Wireshark

Archivado en (Virus, Windows) por Gabriel el 13-07-2010

Los virus, gusanos y demás son un problema nefasto una vez que caemos en las garras de uno, es común encontrar tantas fallas como soluciones existentes para estos enemigos informáticos enfocados hacia el sistema operativo mas popular del mundo: Windows.

A pesar de que Windows es un sistema con muchas fallas y virtudes, debemos reconocer que la gran mayoría de las veces el que un equipo se vea afectado por problemas de virus es por falta de actualizaciones del propio sistema, antivirus desactualizado o ausencia del mismo y la mas posible de las causas; descuido del usuario.

Si un virus o gusano se mete en tu computadora personal puede ser una tragedia, ahora si un virus logra afectar a la red de una empresa esto se traduce muchas veces en una sola cosa: perdida de dinero.

Formas de prevención hay muchas pero si por alguna razón el problema ya lo tienes encima ya sea por que tus sistemas no estaban actualizados con los parches de Microsoft para evitar esta vulnerabilidad (MS08-067, MS08-068, MS09-001) o por algún descuido en el manejo de tu antivirus, lo único que queda es actuar rápido y con algo de paciencia.

En este caso que presento a continuación despues de verificar varios equipos en la red que se encontraban infectados, y para saber en concreto que maquinas estaban propagando el virus y para dar un ejemplo util de utilización de Wireshark nos pusimos a capturar todos los paquetes en un determinado equipo y a esperar que el antivirus reportara una posible infección para verificar desde que equipo se habia originado la misma, obviamente que al ser un gusano este se encuentra por toda la red y la infección pude venir de cualquier dirección IP, sin embargo esta puede ser una manera rápida de identificar ciertos equipos y neutralizarlos rápidamente.

La alimaña en concreto es un gusano llamado Net-Worm.Win32.Kido.ih que utiliza las direcciones IP de los equipos registrados en “Mis sitios de red” para seguir propagandose, en la imagen adjunta vemos exactamente como es infectado el equipo en cuestion pero afortunadamente nuestro antivirus detecta y elimina a tiempo el gusano. Un bocado interesante para este gusano puede ser por ejemplo un servidor Windows con Active Directory, ya que toda maquina en dominio o al ingresar a este automáticamente sera infectada.

Capturando los paquetes.

Obviamente no es buena forma estar esperando equipo por equipo a que se presente algún registro que nos permita actuar, si cuentas con un sistema de administración centralizada de un antivirus lo mejor es atacar desde ahi para lanzar actualizaciones y metodos de desinfección para todos tus equipos registrados, Kaspersky cuenta con una herramienta para tal situación llamada KK (Kido Killer) que es exactamente lo que necesitas para eliminar este gusano.

Información del gusano en cuestión desde Viruslist. Link.
Metodos para la desinfección de tus equipos ya sea de manera local o mediante la consola de administración desde el sitio de Kaspersky. Link.

A pesar de todo es fascinante la manera en que estos programas se replican por toda la red aunque nosotros al menos ya estamos controlando la invasión.

Probando Red Hat Enterprise Virtualization

Archivado en (Linux) por Gabriel el 27-06-2010

Pues siguiendo con la virtualización aquí mostramos una pantalla del manager de Red Hat para su hypervisor, de su producto Red Hat Enterprise Virtualization.

El manager para el control de las maquinas virtuales.

Un maquina virtual con Windows 7.

Server 2003 en una maquina virtual.

Tiene algunos detalles pero sin duda es una buena alternativa (en la parte económica) contra otros productos como VMware o Citrix.

Virtualización con KVM

Archivado en (Linux) por Gabriel el 24-04-2010

KVM es una solución para implementar virtualización completa con Linux sobre hardware x86.
Así que aprovechando los recursos con los que cuenta el área de sistemas haremos uso de un servidor ocioso.

El equipo donde realizaremos las pruebas necesarias es un PowerEdge T110 con la distribución Debian Lenny instalada a partir de su versión net-install, por lo cual contaremos con un sistema básico pero mas que suficiente para nuestro cometido. A medida que necesitemos paquetes los instalaremos según se requiera, cabe resaltar que el modulo KVM ya se encuentra incluido en nuestro kernel instalado con nuestra distribución.

Antes que nada debemos verificar que el procesador del equipo soporte la virtualización.

$ egrep '^flags.*(vmx|svm)' /proc/cpuinfo

http://www.linux-kvm.org/page/FAQ#How_can_I_tell_if_I_have_Intel_VT_or_AMD-V.3F

Si el comando anterior nos arroja algún resultado nuestro procesador es idóneo para la virtualización en caso contrario no podremos hacer uso de KVM.

instalamos los paquetes necesarios.

# aptitude install kvm kvm-source

En la medida que se configuran los paquetes de manera automática en debian, si recibimos las siguientes lineas es por que no habilitamos en el BIOS de nuestro equipo la opción de virtualización.

Setting up kvm (72+dfsg-5~lenny5) ...
FATAL: Error inserting kvm_intel (/lib/modules/2.6.26-2-686/kernel/arch/x86/kvm/kvm-intel.ko)
: Operation not supported
Module kvm_intel failed to load failed!
invoke-rc.d: initscript kvm, action "start" failed.

http://www.linux-kvm.org/page/FAQ#.22KVM:_disabled_by_BIOS.22_error

kvm disabled by bios

En el equipo con el que estoy realizando esto entramos a la configuración del BIOS, en el menú de “Processor Settings” encontraremos la opción llamada “Virtualization Technology” la cual deberemos habilitar para poder trabajar con la virtualización por hardware.

Instalamos qemu para crear nuestros discos virtuales (y muchas cosas mas).

# aptitude install qemu

Si pretendemos que nuestras maquinas virtuales sean a nivel de red como un dispositivo físico mas debemos instalar el siguiente paquete y configurar ciertos parámetros en nuestro sistema anfitrión para poner su red en modo “bridge”.

# aptitude install bridge-utils

Debemos realizar unos cambios en nuestro archivo de configuración de red para modificar las interfaces, el contenido de mi archivo “interfaces” (/etc/network/interfaces) es el siguiente:

# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).
 
# The loopback network interface
auto lo
iface lo inet loopback
 
# The primary network interface
allow-hotplug eth0
auto eth0
iface eth0 inet manual
 
auto br0
iface br0 inet static
        address 192.168.1.161
        netmask 255.255.255.0
        network 192.168.1.0
        broadcast 192.168.1.255
        gateway 192.168.1.254
        bridge_ports eth0
        bridge_fd 9
        bridge_hello 2
        bridge_maxage 12
        bridge_stp off

Reiniciamos los servicios de red.

# /etc/init.d/networking restart

Hecho esto al asignarle una dirección IP a nuestra maquina virtual esta sera como cualquier otro dispositivo en la red.

Realizaremos una instalación para ver que tal luce la nueva beta de Red Hat en su versión 6, la cual podemos descargar desde el siguiente enlace: ftp://ftp.redhat.com/pub/redhat/rhel/beta/6/i386/iso/RHEL6.0-20100414.0-AP-i386-DVD1.iso

Creamos un disco duro de unos 30 GB.

$ qemu-img create disk.RHEL -f qcow2 30G
Formatting 'disk.RHEL', fmt=qcow2, size=31457280 kB

Iniciamos la maquina virtual indicando que inicie desde cdrom a partir de una imagen ISO para instalar el sistema, asignamos 1256 MB de memoria RAM, le indicamos modelo y parámetros de tarjeta de red, teclado en español e iniciar un servicio VNC para visualizar la maquina virtual.

# kvm -hda disk.RHEL -cdrom ../RHEL6.0-20100414.0-AP-i386-DVD1.iso -boot d -m 1256 -k es -net nic,vlan=0,model=rtl8139 -net tap,vlan=0 -vnc :0

Terminada la instalación ahora iniciamos desde la imagen del disco duro.

# kvm -hda disk.RHEL -m 1256 -k es -net nic,vlan=0,model=rtl8139 -net tap,vlan=0 -vnc :0

Sistema RHEL instalado y navegando en Internet.

Un SUSE en plena instalación.

Dominio y alias en OpenSIPS

Archivado en (Linux, OpenSIPS, SIP) por Gabriel el 31-03-2010

Siguiendo el propósito original de estos escritos, continuamos con las configuraciones del proxy OpenSIPS. El post anterior trataba de autenticar los usuarios haciendo uso de MySQL, ahora agregaremos la función de manejar dominios y alias, por lo tanto deberemos realizar modificaciones a nuestro archivo de configuración el cual simbólicamente denominaremos opensips.cfg.3, el cual mostramos a continuación.

Tambien vamos a cambiar una linea en el archivo opensipsctlrc y modificaremos el primer parámetro definiendo el dominio que vamos a utilizar de manera predeterminada al agregar nuevos usuarios: “SIP_DOMAIN=trantor.demerzel.org”

####### Global Parameters #########
debug=3
log_stderror=no
log_facility=LOG_LOCAL0
 
fork=yes
children=4
 
port=5060
 
/* uncomment and configure the following line if you want opensips to bind on a specific interface/port/proto (default bind on all available) */
#listen=udp:192.9.200.161:5060
 
####### Modules Section ########
 
#set module path
mpath="/usr/local/lib/opensips/modules/"
 
/* uncomment next line for MySQL DB support */
loadmodule "db_mysql.so"
loadmodule "auth.so"
loadmodule "auth_db.so"
loadmodule "alias_db.so"
loadmodule "domain.so"
loadmodule "signaling.so"
loadmodule "sl.so"
loadmodule "tm.so"
loadmodule "rr.so"
loadmodule "maxfwd.so"
loadmodule "usrloc.so"
loadmodule "registrar.so"
loadmodule "textops.so"
loadmodule "mi_fifo.so"
loadmodule "uri.so"
loadmodule "xlog.so"
loadmodule "acc.so"
 
# ----- mi_fifo params -----
modparam("mi_fifo", "fifo_name", "/tmp/opensips_fifo")
modparam("rr", "enable_full_lr", 1)
modparam("rr", "append_fromtag", 0)
 
# ----- usrloc params -----
modparam("usrloc", "db_mode",   0)
 
modparam("usrloc", "db_mode",   2)
modparam("usrloc", "db_url", "mysql://opensips:opensipsrw@localhost/opensips")
 
 
# ----- uri params -----
modparam("uri", "use_uri_table", 0)
# ----- acc params -----
/* what sepcial events should be accounted ? */
modparam("acc", "early_media", 1)
modparam("acc", "report_ack", 1)
modparam("acc", "report_cancels", 1)
modparam("acc", "detect_direction", 0)
modparam("acc", "failed_transaction_flag", 3)
modparam("acc", "log_flag", 1)
modparam("acc", "log_missed_flag", 2)
modparam("acc", "db_flag", 1)
modparam("acc", "db_missed_flag", 2)
 
modparam("auth_db", "calculate_ha1", yes)
modparam("auth_db", "password_column", "password")
modparam("auth_db", "db_url", "mysql://opensips:opensipsrw@localhost/opensips")
modparam("auth_db", "load_credentials", "")
 
modparam("alias_db", "db_url", "mysql://opensips:opensipsrw@localhost/opensips")
 
modparam("domain", "db_url", "mysql://opensips:opensipsrw@localhost/opensips")
modparam("domain", "db_mode", 1)
 
route{
 
	if (!mf_process_maxfwd_header("10")) {
		sl_send_reply("483","Too Many Hops");
		exit;
	}
 
	if (has_totag()) {
		if (loose_route()) {
			if (is_method("BYE")) {
				setflag(1); # do accounting ...
				setflag(3); # ... even if the transaction fails
			} else if (is_method("INVITE")) {
				record_route();
			}
			route(1);
		} else {
			/* uncomment the following lines if you want to enable presence */
			if ( is_method("ACK") ) {
				if ( t_check_trans() ) {
					t_relay();
					exit;
				} else {
					exit;
				}
			}
			sl_send_reply("404","Not here");
		}
		exit;
	}
 
	if (is_method("CANCEL"))
	{
		if (t_check_trans())
			t_relay();
		exit;
	}
 
	t_check_trans();
 
	if (!(method=="REGISTER") && is_from_local())  /*multidomain version*/
        {
              if (!proxy_authorize("", "subscriber")) {
                      proxy_challenge("", "0");
                      exit;
              }
              if (!db_check_from()) {
                      sl_send_reply("403","Forbidden auth ID");
                      exit;
              }
 
              consume_credentials();
              # caller authenticated
        }
 
 
	if (loose_route()) {
		xlog("L_ERR",
		"Attempt to route with preloaded Route's [$fu/$tu/$ru/$ci]");
		if (!is_method("ACK"))
			sl_send_reply("403","Preload Route denied");
		exit;
	}
 
	# record routing
	if (!is_method("REGISTER|MESSAGE"))
		record_route();
 
	# account only INVITEs
	if (is_method("INVITE")) {
		setflag(1); # do accounting
	}
 
	if (!is_uri_host_local())
	{
        	if(is_from_local()) {
			route(1);
	        } else {
			sl_send_reply("403","Not here");
        	}	
	}	
 
	if (is_method("PUBLISH"))
	{
		sl_send_reply("503", "Service Unavailable");
		exit;
	}
 
	if (is_method("REGISTER"))
	{
                if (!www_authorize("", "subscriber"))
                {
                      www_challenge("", "0");
                      exit;
                }
 
                if (!db_check_to())
                {
                      sl_send_reply("403","Forbidden auth ID");
                      exit;
                }
 
		if (!save("location"))
			sl_reply_error();
 
		exit;
	}
 
	if ($rU==NULL) {
		# request with no Username in RURI
		sl_send_reply("484","Address Incomplete");
		exit;
	}
 
        # apply DB based aliases (uncomment to enable)
        alias_db_lookup("dbaliases");
 
	# do lookup with method filtering
	if (!lookup("location","m")) {
		switch ($retcode) {
			case -1:
			case -3:
				t_newtran();
				t_reply("404", "Not Found");
				exit;
			case -2:
				sl_send_reply("405", "Method Not Allowed");
				exit;
		}
	}
	# when routing via usrloc, log the missed calls also
	setflag(2);
	route(1);
}
 
route[1] {
	# for INVITEs enable some additional helper routes
	if (is_method("INVITE")) {
		t_on_branch("2");
		t_on_reply("2");
		t_on_failure("1");
	}
 
	if (!t_relay()) {
		sl_reply_error();
	};
	exit;
}
 
branch_route[2] {
	xlog("new branch at $ru\n");
}
 
 
onreply_route[2] {
	xlog("incoming reply\n");
}
 
 
failure_route[1] {
	if (t_was_cancelled()) {
		exit;
	}
}

Leer más »

Cambiar contraseña de root en un disco con LVM

Archivado en (Linux) por Gabriel el 22-03-2010

Si se ha olvidado o se ignora la contraseña de root de algún equipo, en teoría es sencillo cambiar la contraseña para poder recuperar nuestro equipo, en este caso en especifico el disco esta particionado y usa LVM (Logical Volume Manager), por lo tanto el procedimiento tiene unos cuantos pasos mas a diferencia de si tuviéramos un sistema de partición tradicional. Para esto nos ayudaremos del live cd mas famoso últimamente, Ubuntu 9.10

Necesitamos instalar las herramientas necesarias para manejar los volúmenes lógicos.

ubuntu@ubuntu:~$ sudo aptitude install lvm2
Leyendo lista de paquetes... Hecho
Creando árbol de dependencias       
Leyendo la información de estado... Hecho
Leyendo la información de estado extendido      
Inicializando el estado de los paquetes... Hecho
Se instalarán los siguiente paquetes NUEVOS:
  lvm2 watershed{a} 
0 paquetes actualizados, 2 nuevos instalados, 0 para eliminar y 246 sin actualizar.
Necesito descargar 387kB de ficheros. Después de desempaquetar se usarán 1114kB.
¿Quiere continuar? [Y/n/?] Y

Determinamos que grupo contiene nuestra partición física.

ubuntu@ubuntu:~$ sudo pvs
  PV         VG         Fmt  Attr PSize  PFree 
  /dev/sda2  VolGroup00 lvm2 a-   74,41G 32,00M

Ahora podemos visualizar los volúmenes lógicos existente en VolGroup00

ubuntu@ubuntu:~$ sudo lvdisplay /dev/VolGroup00
  --- Logical volume ---
  LV Name                /dev/VolGroup00/LogVol00
  VG Name                VolGroup00
  LV UUID                FjQd7F-xxXz-Q2yd-OID7-eusj-y69S-ewCguZ
  LV Write Access        read/write
  LV Status              NOT available
  LV Size                73,50 GB
  Current LE             2352
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
 
  --- Logical volume ---
  LV Name                /dev/VolGroup00/LogVol01
  VG Name                VolGroup00
  LV UUID                tGFOHq-LzOP-ppnP-d5FX-yNYj-Lu6y-fPso1L
  LV Write Access        read/write
  LV Status              NOT available
  LV Size                896,00 MB
  Current LE             28
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto

Activamos el grupo, de otra manera no podremos montar el volumen como si de una partición tradicional se tratara.

ubuntu@ubuntu:~$ sudo vgchange -a y
  2 logical volume(s) in volume group "VolGroup00" now active

Creamos el directorio donde montaremos el volumen logico.

ubuntu@ubuntu:~$ sudo mkdir /tmp/aguas/ (por Aguascalientes, de donde vino el servidor)

Montamos ahora si como si de una partición se tratara.

ubuntu@ubuntu:~$ sudo mount /dev/VolGroup00/LogVol00 /tmp/aguas/

Cambiamos el directorio raíz de / a /tmp/aguas para que los cambios que hagamos se reflejen en la partición montada.

ubuntu@ubuntu:/tmp/aguas$ sudo chroot /tmp/aguas/

Verificamos los directorios con los que cuenta el sistema montado.

bash-3.00# ls 
bin	    home	misc	    proc	srv	    var
boot	    lib		mnt	    root	sys
dev	    lost+found	net	    sbin	tmp
etc	    media	opt	    selinux	usr
bash-3.00# ls home/
bash			      libpcap-0.9.4-4.fc5.i386.rpm
iftop-0.17-1.fc4.rf.i386.rpm  sistemas
iftop-0.17-1.fc5.rf.i386.rpm

Ahora si cambiamos la contraseña del superusuario.

bash-3.00# passwd root
Changing password for user root.
New UNIX password: 
BAD PASSWORD: it is based on a dictionary word
Retype new UNIX password: 
passwd: all authentication tokens updated successfully.
bash-3.00# exit

Reiniciamos el equipo y debemos poder entrar al sistema satisfactoriamente con la contraseña que cambiamos.

Mas información en el siguiente enlace: http://www.brandonhutchinson.com/Mounting_a_Linux_LVM_volume.html

Transferencia SIP

Archivado en (Asterisk, OpenSIPS, SIP) por Gabriel el 18-03-2010

Una de las cosas mas sencillas en este mundo actual es transferir una llamada. Ya que andamos probando el proxy SIP al que hacemos mención, verificaremos que es lo que pasa cuando realizamos este procedimiento comparándolo con el que hace Asterisk.

Tenemos tres usuarios SIP, 1000, 1001 y 1002. El dispositivo asociado a cada uno respectivamente son un SPA941, SPA2102 y el softphone Zoiper, el mas importante de estos tres es el teléfono IP que gracias a su display podemos verificar el comportamiento que estamos buscando.

Vamos a poner un sencillo ejemplo para ilustrarlo, el cual de manera general sera el siguiente.

1001 recibe una llamada de 1002.
1001 inicia transferencia atendida con 1000.
1000 contesta la llamada y aparece en el CALLERID 1001.
1000 acepta la llamada.
1001 cuelga.
1000 tiene la llamada y el CALLERID cambia de 1001 a 1002.
1002 cambia su CALLERID ahora a 1000.

Vamos a realizar una primera llamada, marcamos del usuario 1002 al 1001.

Establecemos la llamada, y en la lista de contactos de nuestro Softphone se nos muestra que estamos hablando con el usuario 1001.

Ahora 1001 pone en espera a 1002, y le marca a 1000 para transferirle la llamada, en este paso en el display del teléfono asociado al usuario 1000, aparece que esta recibiendo una llamada de 1001, acepta la llamada se establece la llamada y le indican que le van a transferir al usuario 1002. 1001 transfiere la llamada y termina su participación en la llamada.

Y es aquí donde vemos el comportamiento deseado, después de un instante en el display del teléfono se muestra que estamos hablando ahora con el usuario 1002, y en el softphone de igual manera cambia de que ahora hablamos con el usuario 1000.

Con Asterisk no pasa esto, los estados de los teléfonos en su CALLERID no cambian, el teléfono 1002 se queda con el primer numero que marco y el teléfono 1000 mantiene en su pantalla el numero de donde recibió la transferencia.

¿Y cuál es el motivo de esto?,debido a detalles del protocolo SIP que esta implementado en Asterisk esta característica por el momento no se encuentra disponible. Mas información acerca de esto en un buen debate en la lista de asterisk-es en el siguiente hilo: CALLER ID en transferencias atendidas.

Y como anexo, se muestra la traza SIP de la transferencia capturada con Wireshark.
Leer más »

Autenticación en OpenSIPS con MySQL

Archivado en (MySQL, OpenSIPS) por Gabriel el 24-02-2010

En esta parte usaremos una base de datos para registrar mediante una contraseña nuestros usuarios SIP dando un tanto mas de seguridad a nuestro pequeño sistema, y de tener en tablas todas las preferencias de nuestros usuarios, dominios, direcciones y grupos como veremos consecuentemente.

Partimos del echo de que contamos con nuestra base de datos MySQl correctamente instalada y con nuestra contraseña de root configurada. Debemos realizar ciertas modificaciones al archivo opensipsctlrc (/usr/local/etc/opensips/opensipsctlrc), el cual debe quedar de la siguiente forma:

trantor:/usr/local/etc/opensips# cat opensipsctlrc | grep -v "#" | sed -e '/^$/d'
 SIP_DOMAIN=192.168.1.161
 DBENGINE=MYSQL
 DBHOST=localhost
 DBNAME=opensips
 DBRWUSER=opensips
 DBRWPW="opensipsrw"
 DBROUSER=opensipsro
 DBROPW=opensipsro
 ALIASES_TYPE="DB"
 OSIPS_FIFO="/tmp/opensips_fifo"
trantor:/home/gabriel#

Creamos la base de datos.

trantor:/home/gabriel/SIP# opensipsdbctl create
MySQL password for root:
INFO: test server charset
INFO: creating database opensips ...
INFO: Core OpenSIPS tables succesfully created.
Install presence related tables? (y/n): y
INFO: creating presence tables into opensips ...
INFO: Presence tables succesfully created.
Install tables for imc cpl siptrace domainpolicy carrierroute userblacklist? (y/n): y
INFO: creating extra tables into opensips ...
INFO: Extra tables succesfully created.
trantor:/home/gabriel/SIP#

Cambiamos la configuración de opensips.cfg por la configuración que se muestra a continuación la cual simbólicamente denominaremos opensips.cfg.1.

####### Global Parameters #########
debug=3
log_stderror=no
log_facility=LOG_LOCAL0
 
fork=yes
children=4
 
port=5060
 
(default bind on all available) */
#listen=udp:192.168.1.161:5060
 
####### Modules Section ########
 
#set module path
mpath="/usr/local/lib/opensips/modules/"
 
/* uncomment next line for MySQL DB support */
loadmodule "db_mysql.so"
loadmodule "auth.so"
loadmodule "auth_db.so"
loadmodule "signaling.so"
loadmodule "sl.so"
loadmodule "tm.so"
loadmodule "rr.so"
loadmodule "maxfwd.so"
loadmodule "usrloc.so"
loadmodule "registrar.so"
loadmodule "textops.so"
loadmodule "mi_fifo.so"
loadmodule "uri.so"
loadmodule "xlog.so"
loadmodule "acc.so"
 
# ----- mi_fifo params -----
modparam("mi_fifo", "fifo_name", "/tmp/opensips_fifo")
modparam("rr", "enable_full_lr", 1)
modparam("rr", "append_fromtag", 0)
 
# ----- usrloc params -----
modparam("usrloc", "db_mode",   0)
 
modparam("usrloc", "db_mode",   2)
modparam("usrloc", "db_url", "mysql://opensips:opensipsrw@localhost/opensips")
 
 
# ----- uri params -----
modparam("uri", "use_uri_table", 0)
# ----- acc params -----
/* what sepcial events should be accounted ? */
modparam("acc", "early_media", 1)
modparam("acc", "report_ack", 1)
modparam("acc", "report_cancels", 1)
modparam("acc", "detect_direction", 0)
modparam("acc", "failed_transaction_flag", 3)
modparam("acc", "log_flag", 1)
modparam("acc", "log_missed_flag", 2)
modparam("acc", "db_flag", 1)
modparam("acc", "db_missed_flag", 2)
 
modparam("auth_db", "calculate_ha1", yes)
modparam("auth_db", "password_column", "password")
modparam("auth_db", "db_url", "mysql://opensips:opensipsrw@localhost/opensips")
modparam("auth_db", "load_credentials", "")
 
 
route{
 
	if (!mf_process_maxfwd_header("10")) {
		sl_send_reply("483","Too Many Hops");
		exit;
	}
 
	if (has_totag()) {
		if (loose_route()) {
			if (is_method("BYE")) {
				setflag(1); # do accounting ...
				setflag(3); # ... even if the transaction fails
			} else if (is_method("INVITE")) {
				record_route();
			}
			route(1);
		} else {
			if ( is_method("ACK") ) {
				if ( t_check_trans() ) {
					t_relay();
					exit;
				} else {
					exit;
				}
			}
			sl_send_reply("404","Not here");
		}
		exit;
	}
 
	if (is_method("CANCEL"))
	{
		if (t_check_trans())
			t_relay();
		exit;
	}
 
	t_check_trans();
 
        if (!(method=="REGISTER") && from_uri==myself)
        {
              if (!proxy_authorize("", "subscriber")) {
                      proxy_challenge("", "0");
                      exit;
              }
              if (!db_check_from()) {
                      sl_send_reply("403","Forbidden auth ID");
                      exit;
              }
 
              consume_credentials();
              # caller authenticated
        }
 
 
	if (loose_route()) {
		xlog("L_ERR",
		"Attempt to route with preloaded Route's [$fu/$tu/$ru/$ci]");
		if (!is_method("ACK"))
			sl_send_reply("403","Preload Route denied");
		exit;
	}
 
	# record routing
	if (!is_method("REGISTER|MESSAGE"))
		record_route();
 
	# account only INVITEs
	if (is_method("INVITE")) {
		setflag(1); # do accounting
	}
	if (!uri==myself)
	{
		append_hf("P-hint: outbound\r\n"); 
		route(1);
	}
 
	if (is_method("PUBLISH"))
	{
		sl_send_reply("503", "Service Unavailable");
		exit;
	}
 
	if (is_method("REGISTER"))
	{
                if (!www_authorize("", "subscriber"))
                {
                      www_challenge("", "0");
                      exit;
                }
 
                if (!db_check_to())
                {
                      sl_send_reply("403","Forbidden auth ID");
                      exit;
                }
 
		if (!save("location"))
			sl_reply_error();
 
		exit;
	}
 
	if ($rU==NULL) {
		# request with no Username in RURI
		sl_send_reply("484","Address Incomplete");
		exit;
	}
 
	# do lookup with method filtering
	if (!lookup("location","m")) {
		switch ($retcode) {
			case -1:
			case -3:
				t_newtran();
				t_reply("404", "Not Found");
				exit;
			case -2:
				sl_send_reply("405", "Method Not Allowed");
				exit;
		}
	}
	# when routing via usrloc, log the missed calls also
	setflag(2);
	route(1);
}
 
route[1] {
	# for INVITEs enable some additional helper routes
	if (is_method("INVITE")) {
		t_on_branch("2");
		t_on_reply("2");
		t_on_failure("1");
	}
 
	if (!t_relay()) {
		sl_reply_error();
	};
	exit;
}
 
branch_route[2] {
	xlog("new branch at $ru\n");
}
 
 
onreply_route[2] {
	xlog("incoming reply\n");
}
 
 
failure_route[1] {
	if (t_was_cancelled()) {
		exit;
	}
}

Iniciamos OpenSIPS.

trantor:~# opensipsctl start
 
INFO: Starting OpenSIPS :
INFO: started (pid: 28716)

Agregamos el par de usuarios 1000 y 1001, a la base de datos y registramos nuestros agentes SIP.

gabriel@trantor:~$ sudo opensipsctl add 1000 1000
new user '1000' added
gabriel@trantor:~$ sudo opensipsctl add 1001 1001
new user '1001' added

Mostramos la traza SIP del registro de un usuario almacenando previamente en nuestra base de datos.

U 192.168.1.162:5061 -> 192.168.1.161:5060
REGISTER sip:192.168.1.161 SIP/2.0.
Via: SIP/2.0/UDP 192.168.1.162:5061;branch=z9hG4bK-6bdbbdbc.
From: Bozada <sip:1000@192.168.1.161>;tag=ea98cc30d70f560fo1.
To: Bozada <sip:1000@192.168.1.161>.
Call-ID: 5da1e386-fde63540@192.168.1.162.
CSeq: 32475 REGISTER.
Max-Forwards: 70.
Contact: Bozada <sip:1000@192.168.1.162:5061>;expires=3600.
User-Agent: Linksys/SPA2102-3.3.6.
Content-Length: 0.
Allow: ACK, BYE, CANCEL, INFO, INVITE, NOTIFY, OPTIONS, REFER.
Supported: x-sipura.
.
U 192.168.1.161:5060 -> 192.168.1.162:5061
SIP/2.0 401 Unauthorized.
Via: SIP/2.0/UDP 192.168.1.162:5061;branch=z9hG4bK-6bdbbdbc.
From: Bozada <sip:1000@192.168.1.161>;tag=ea98cc30d70f560fo1.
To: Bozada <sip:1000@192.168.1.161>;tag=c97b4d1cb1f3d0da549e06a8d482ef63.be3a.
Call-ID: 5da1e386-fde63540@192.168.1.162.
CSeq: 32475 REGISTER.
WWW-Authenticate: Digest realm="192.168.1.161", nonce="4b85d15b000000039d8eac02cb35f405c16770fd04ba2424".
Server: OpenSIPS (1.6.1-notls (i386/linux)).
Content-Length: 0.
.
U 192.168.1.162:5061 -> 192.168.1.161:5060
REGISTER sip:192.168.1.161 SIP/2.0.
Via: SIP/2.0/UDP 192.168.1.162:5061;branch=z9hG4bK-896f8b1c.
From: Bozada <sip:1000@192.168.1.161>;tag=ea98cc30d70f560fo1.
To: Bozada <sip:1000@192.168.1.161>.
Call-ID: 5da1e386-fde63540@192.168.1.162.
CSeq: 32476 REGISTER.
Max-Forwards: 70.
Authorization: Digest username="1000",realm="192.168.1.161",nonce="4b85d15b000000039d8eac02cb35f405c16770fd04ba2424",uri="sip:192.168.1.161",algorithm=MD5,response="5a8c46a3bd960218616aaed03240e631".
Contact: Bozada <sip:1000@192.168.1.162:5061>;expires=3600.
User-Agent: Linksys/SPA2102-3.3.6.
Content-Length: 0.
Allow: ACK, BYE, CANCEL, INFO, INVITE, NOTIFY, OPTIONS, REFER.
Supported: x-sipura.
.
U 192.168.1.161:5060 -> 192.168.1.162:5061
SIP/2.0 200 OK.
Via: SIP/2.0/UDP 192.168.1.162:5061;branch=z9hG4bK-896f8b1c.
From: Bozada <sip:1000@192.168.1.161>;tag=ea98cc30d70f560fo1.
To: Bozada <sip:1000@192.168.1.161>;tag=c97b4d1cb1f3d0da549e06a8d482ef63.274d.
Call-ID: 5da1e386-fde63540@192.168.1.162.
CSeq: 32476 REGISTER.
Contact: <sip:1000@192.168.1.162:5061>;expires=3600.
Server: OpenSIPS (1.6.1-notls (i386/linux)).
Content-Length: 0.
.

Y como un diagrama a veces vale mas, aquí mostramos la gráfica de la traza SIP anterior.

| 192.168.1.162     			| 192.168.1.161
|         Request: REGISTER             |
|(5061)   ------------------>  (5060)   |
|         Status: 401 Unauthorized      |
|(5061)   <------------------  (5060)   |
|         Request: REGISTER             |
|(5061)   ------------------>  (5060)   |
|         Status: 200 OK                |
|(5061)   <------------------  (5060)   |

Realizamos nuevamente una sencilla llamada del usuario 1001 al 1000, y esta es la traza SIP de la llamada, la principal diferencia respecto al esquema anterior, es la parte de la autentificación.
En este caso al realizar el INVITE de la llamada, el servidor responde con mensaje SIP 407 (autenticación requerida), nuestro agente SIP responde y si son correctos los parámetros dejara realizar el INVITE iniciando la llamada, el resto de la traza SIP es igual a la del post anterior.

| 192.168.1.163     				| 192.168.1.161 (proxy)			| 192.168.1.162
|         INVITE SDP ( h261)            	|                   			|
|(5060)   ------------------>  (5060)   	|                   			|
|         407 Proxy Authentication Required	|                   			|
|(5060)   <------------------  (5060)   	|                   			|
|         ACK       				|                   			|
|(5060)   ------------------>  (5060)   	|                   			|
|         INVITE SDP ( h261)            	|                   			|
|(5060)   ------------------>  (5060)   	|                   			|
|         100 Giving a try              	|                   			|
|(5060)   <------------------  (5060)   	|                   			|
|                   				|         INVITE SDP ( h261)            |
|                   				|(5060)   ------------------>  (5061)   |
|                   				|         100 Trying			|
|                   				|(5060)   <------------------  (5061)   |
|                   				|         180 Ringing                   |
|                   				|(5060)   <------------------  (5061)   |
|         180 Ringing                   	|                   			|
|(5060)   <------------------  (5060)   	|                   			|
|                   				|         200 OK SDP ( h261)            |
|                   				|(5060)   <------------------  (5061)   |
|         200 OK SDP ( h261)            	|                   			|
|(5060)   <------------------  (5060)   	|                   			|
|         ACK       				|                   			|
|(5060)   ------------------>  (5060)   	|                   			|
|                   				|         ACK       			|
|                   				|(5060)   ------------------>  (5061)   |
|         BYE       				|                   			|
|(5060)   ------------------>  (5060)		|                   			|
|                   				|         BYE       			|
|                   				|(5060)   ------------------>  (5061)   |
|                   				|         200 OK    			|
|                   				|(5060)   <------------------  (5061)   |
|         200 OK    				|                   			|
|(5060)   <------------------  (5060)   	|                   			|

Mediante el siguiente comando podemos observar a los usuarios registrados en el servidor.

trantor:~# opensipsctl ul show
Domain:: location table=512 records=2
        AOR:: 1000
                Contact:: sip:1000@192.168.1.162:5061 Q=
                        Expires:: 2336
                        Callid:: 5da1e386-fde63540@192.168.1.162
                        Cseq:: 32476
                        User-agent:: Linksys/SPA2102-3.3.6
                        State:: CS_SYNC
                        Flags:: 0
                        Cflag:: 0
                        Socket:: udp:192.168.1.161:5060
                        Methods:: 5183
        AOR:: 1001
                Contact:: sip:1001@192.168.1.163:5060;transport=udp Q=
                        Expires:: 3596
                        Callid:: d35fe6bb7fc5df8b6c76521a80310ba6@0.0.0.0
                        Cseq:: 2
                        User-agent:: SIP Communicator 1.0 CVS-Wed_Feb_24_19-45-25_CST_2010
                        State:: CS_NEW
                        Flags:: 0
                        Cflag:: 0
                        Socket:: udp:192.168.1.161:5060
                        Methods:: 4294967295

Instalando OpenSIPS

Archivado en (OpenSIPS) por Gabriel el 23-02-2010

OpenSIPS es una proxy SIP, registra y establece llamadas entre clientes SIP a continuación se mostrara la forma de instalarlo y configurarlo poco a poco, todo esto basándome en un libro recién publicado que trata sobre este tema el cual es Building Telephony Systems with OpenSIPS 1.6 de Flavio E. Goncalves.
Mas que nada es como un ejercicio para no olvidar los pasos y procedimientos.

El equipo a utilizar es mi propia portátil con Debian Lenny. Antes que nada necesitamos los siguientes paquetes:

# aptitude install gcc bison flex make openssl libmysqlclient-dev libradiusclient-ng2 libradiusclient-ng-dev mysql-server libxmlrpc-c3-dev

Descargamos, compilamos e instalamos con los módulos correspondientes.

$ wget http://opensips.org/pub/opensips/1.6.1/src/opensips-1.6.1-tls_src.tar.gz
$ tar xfz opensips-1.6.1-tls_src.tar.gz
$ cd opensips-1.6.1-tls
$ make all include_modules=”db_mysql aaa_radius”
$ make install include_modules=”db_mysql aaa_radius”

Los módulos y archivos de configuración se encuentran en /usr/local/lib/opensips/modules/ y /usr/local/etc/opensips/ respectivamente.

Con el archivo por defecto (/usr/local/etc/opensips/opensips.cfg) ya podemos iniciar un simple registro y realizar una llamada entre dos agentes SIP, sin embargo vamos a eliminar del archivo todo el código comentado e innecesario para así poder tener un archivo base mas claro el cual nombraremos simbólicamente opensips.cfg.0 el cual se muestra a continuación:

####### Global Parameters #########
debug=3
log_stderror=no
log_facility=LOG_LOCAL0
 
fork=yes
children=4
 
port=5060
 
#listen=udp:192.168.1.161:5060
 
####### Modules Section ########
 
#set module path
mpath="/usr/local/lib/opensips/modules/"
 
/* uncomment next line for MySQL DB support */
#loadmodule "db_mysql.so"
loadmodule "signaling.so"
loadmodule "sl.so"
loadmodule "tm.so"
loadmodule "rr.so"
loadmodule "maxfwd.so"
loadmodule "usrloc.so"
loadmodule "registrar.so"
loadmodule "textops.so"
loadmodule "mi_fifo.so"
loadmodule "uri.so"
loadmodule "xlog.so"
loadmodule "acc.so"
 
# ----- mi_fifo params -----
modparam("mi_fifo", "fifo_name", "/tmp/opensips_fifo")
modparam("rr", "enable_full_lr", 1)
modparam("rr", "append_fromtag", 0)
 
# ----- usrloc params -----
modparam("usrloc", "db_mode",   0)
# ----- uri params -----
modparam("uri", "use_uri_table", 0)
# ----- acc params -----
/* what sepcial events should be accounted ? */
modparam("acc", "early_media", 1)
modparam("acc", "report_ack", 1)
modparam("acc", "report_cancels", 1)
modparam("acc", "detect_direction", 0)
modparam("acc", "failed_transaction_flag", 3)
modparam("acc", "log_flag", 1)
modparam("acc", "log_missed_flag", 2)
modparam("acc", "db_flag", 1)
modparam("acc", "db_missed_flag", 2)
 
route{
 
	if (!mf_process_maxfwd_header("10")) {
		sl_send_reply("483","Too Many Hops");
		exit;
	}
 
	if (has_totag()) {
		if (loose_route()) {
			if (is_method("BYE")) {
				setflag(1); # do accounting ...
				setflag(3); # ... even if the transaction fails
			} else if (is_method("INVITE")) {
				record_route();
			}
			route(1);
		} else {
			if ( is_method("ACK") ) {
				if ( t_check_trans() ) {
					t_relay();
					exit;
				} else {
					exit;
				}
			}
			sl_send_reply("404","Not here");
		}
		exit;
	}
 
	if (is_method("CANCEL"))
	{
		if (t_check_trans())
			t_relay();
		exit;
	}
 
	t_check_trans();
 
	if (loose_route()) {
		xlog("L_ERR",
		"Attempt to route with preloaded Route's [$fu/$tu/$ru/$ci]");
		if (!is_method("ACK"))
			sl_send_reply("403","Preload Route denied");
		exit;
	}
 
	# record routing
	if (!is_method("REGISTER|MESSAGE"))
		record_route();
 
	# account only INVITEs
	if (is_method("INVITE")) {
		setflag(1); # do accounting
	}
	if (!uri==myself)
	{
		append_hf("P-hint: outbound\r\n"); 
		route(1);
	}
 
	if (is_method("PUBLISH"))
	{
		sl_send_reply("503", "Service Unavailable");
		exit;
	}
 
	if (is_method("REGISTER"))
	{
		if (!save("location"))
			sl_reply_error();
 
		exit;
	}
 
	if ($rU==NULL) {
		# request with no Username in RURI
		sl_send_reply("484","Address Incomplete");
		exit;
	}
 
	# do lookup with method filtering
	if (!lookup("location","m")) {
		switch ($retcode) {
			case -1:
			case -3:
				t_newtran();
				t_reply("404", "Not Found");
				exit;
			case -2:
				sl_send_reply("405", "Method Not Allowed");
				exit;
		}
	}
	# when routing via usrloc, log the missed calls also
	setflag(2);
	route(1);
}
 
route[1] {
	# for INVITEs enable some additional helper routes
	if (is_method("INVITE")) {
		t_on_branch("2");
		t_on_reply("2");
		t_on_failure("1");
	}
 
	if (!t_relay()) {
		sl_reply_error();
	};
	exit;
}
 
branch_route[2] {
	xlog("new branch at $ru\n");
}
 
 
onreply_route[2] {
	xlog("incoming reply\n");
}
 
 
failure_route[1] {
	if (t_was_cancelled()) {
		exit;
	}
}

Iniciamos OpenSIPS.

# opensipsctl start
 
INFO: Starting OpenSIPS :
INFO: started (pid: 6359)

Registramos el usuario 1000 contraseña 1000 y usuario 1001 contraseña 1001 a la IP de nuestro equipo corriendo el proxy, en estos momentos aun no introducimos la autenticación de usuarios, por lo tanto debemos registrarnos sin problemas.

Aquí mostramos la traza SIP al registrar el primer usuario con un ATA de Linksys, vemos el register que realiza y el ok enviado por el servidor, esto lo capturamos con ngrep. (ngrep –p –q –W byline port 5060 > register1000C.txt)

U 192.168.1.162:5061 -> 192.168.1.161:5060
REGISTER sip:192.168.1.161 SIP/2.0.
Via: SIP/2.0/UDP 192.168.1.162:5061;branch=z9hG4bK-37cd1d0c.
From: Bozada <sip:1000@192.168.1.161>;tag=711253242c005ba6o1.
To: Bozada <sip:1000@192.168.1.161>.
Call-ID: 3746d82e-460188b6@192.168.1.162.
CSeq: 20974 REGISTER.
Max-Forwards: 70.
Contact: Bozada <sip:1000@192.168.1.162:5061>;expires=3600.
User-Agent: Linksys/SPA2102-3.3.6.
Content-Length: 0.
Allow: ACK, BYE, CANCEL, INFO, INVITE, NOTIFY, OPTIONS, REFER.
Supported: x-sipura.
.
U 192.168.1.161:5060 -> 192.168.1.162:5061
SIP/2.0 200 OK.
Via: SIP/2.0/UDP 192.168.1.162:5061;branch=z9hG4bK-37cd1d0c.
From: Bozada <sip:1000@192.168.1.161>;tag=711253242c005ba6o1.
To: Bozada <sip:1000@192.168.1.161>;tag=c97b4d1cb1f3d0da549e06a8d482ef63.3318.
Call-ID: 3746d82e-460188b6@192.168.1.162.
CSeq: 20974 REGISTER.
Contact: <sip:1000@192.168.1.162:5061>;expires=3600.
Server: OpenSIPS (1.6.1-notls (i386/linux)).
Content-Length: 0.

Registrados los dos usuarios realizamos una simple llamada desde el usuario 1000 al 1001, y aquí mostramos lo que pasa mediante SIP para establecer la llamada, entre el ultimo ACK y el primer BYE esta el flujo RTP. (capturado con Wireshark)

| 192.168.1.162     			| 192.168.1.161 (proxy)			| 192.168.1.163
|         INVITE SDP ( telephone-event)	|          				|
|(5061)   ------------------>  (5060)   |                   			|
|         100 Giving a try              |                   			|
|(5061)   <------------------  (5060)   |                   			|
|                   			|         INVITE SDP ( telephone-event) |
|                   			|(5060)   ------------------>  (5060)   |
|                   			|         180 Ringing                   |
|                   			|(5060)   <------------------  (5060)   |
|         180 Ringing                   |                   			|
|(5061)   <------------------  (5060)   |                   			|
|                   			|         200 OK SDP ( 97)              |
|                   			|(5060)   <------------------  (5060)   |
|         200 OK SDP ( 97)              |                   			|
|(5061)   <------------------  (5060)   |                   			|
|         ACK       			|					|
|(5061)   ------------------>  (5060)   |                   			|
|                   			|         ACK                           |
|                   			|(5060)   ------------------>  (5060)   |
|         BYE       			|                                       |
|(5061)   ------------------>  (5060)   |                   			|
|                   			|         BYE                           |
|                   			|(5060)   ------------------>  (5060)   |
|                   			|         200 OK                        |
|                   			|(5060)   <------------------  (5060)   |
|         200 OK    			|                                       |
|(5061)   <------------------  (5060)   |                   			|

Por el momento es todo.