<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Mi Brain-Training Personal &#187; MediaProxy</title>
	<atom:link href="http://saghul.net/blog/tag/mediaproxy/feed/" rel="self" type="application/rss+xml" />
	<link>http://saghul.net/blog</link>
	<description>Para que no se me olviden las cosas...</description>
	<lastBuildDate>Mon, 06 Feb 2012 10:49:34 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>ICE: The ultimate way of beating NAT in SIP</title>
		<link>http://saghul.net/blog/2010/06/04/ice-the-ultimate-way-of-beating-nat-in-sip/</link>
		<comments>http://saghul.net/blog/2010/06/04/ice-the-ultimate-way-of-beating-nat-in-sip/#comments</comments>
		<pubDate>Fri, 04 Jun 2010 20:48:55 +0000</pubDate>
		<dc:creator>saghul</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[ICE]]></category>
		<category><![CDATA[MediaProxy]]></category>
		<category><![CDATA[NAT]]></category>
		<category><![CDATA[OpenSIPS]]></category>
		<category><![CDATA[SIP]]></category>
		<category><![CDATA[VoIP]]></category>

		<guid isPermaLink="false">http://saghul.net/blog/?p=1149</guid>
		<description><![CDATA[Hoy ha sido el día. A las 15:00 he tenido la oportunidad de dar una charla en el Amoocon 2010. La charla trataba sobre cómo &#8216;atravesar&#8217; el NAT utilizando ICE, algo de lo que ya hablamos hace algunos posts. A continuación os dejo las transparencias, que espero sirvan a alguien para aclarar el concepto de [...]]]></description>
			<content:encoded><![CDATA[<p>Hoy ha sido el día. A las 15:00 he tenido la oportunidad de dar una charla en el <a href="http://amoocon.de" target="_blank">Amoocon</a> 2010. La charla trataba sobre cómo &#8216;atravesar&#8217; el NAT utilizando <a href="http://tools.ietf.org/html/rfc5245" target="_blank">ICE</a>, algo de lo que <a href="http://saghul.net/blog/2010/02/28/ice-¿la-solucion-definitiva-al-nat-en-sip/" target="_blank">ya hablamos</a> hace algunos posts.</p>
<p>A continuación os dejo las transparencias, que espero sirvan a alguien para aclarar el concepto de ICE en si, y cómo lo hicimos funcionar correctamente con <a href="http://opensips.org" target="_blank">OpenSIPS</a> y <a href="http://mediaproxy.ag-projects.com" target="_blank">MediaProxy</a>.</p>
<p style="text-align: center;"><iframe src="http://www.slideshare.net/slideshow/embed_code/4414037" width="500" height="413" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe><br/><br/></p>
<p>Njoy! <img src='http://saghul.net/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://saghul.net/blog/2010/06/04/ice-the-ultimate-way-of-beating-nat-in-sip/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>&#8220;Atravesando&#8221; el NAT con OpenSIPS 1.6 y MediaProxy</title>
		<link>http://saghul.net/blog/2010/05/06/atravesando-el-nat-con-opensips-1-6-y-mediaproxy/</link>
		<comments>http://saghul.net/blog/2010/05/06/atravesando-el-nat-con-opensips-1-6-y-mediaproxy/#comments</comments>
		<pubDate>Wed, 05 May 2010 23:09:16 +0000</pubDate>
		<dc:creator>saghul</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[ICE]]></category>
		<category><![CDATA[MediaProxy]]></category>
		<category><![CDATA[NAT]]></category>
		<category><![CDATA[OpenSIPS]]></category>
		<category><![CDATA[SIP]]></category>
		<category><![CDATA[VoIP]]></category>

		<guid isPermaLink="false">http://saghul.net/blog/?p=1127</guid>
		<description><![CDATA[Hoy vamos a ver como configurar OpenSIPS 1.6 y MediaProxy para solucionar los problemas que el NAT nos pueda traer. Configurar el proxy para solucionar los problemas de NAT suele ser de las primeras cosas que se pretende o se hace al configurarlo, pero en muchas ocasiones se olvida el primer paso: entender el NAT. [...]]]></description>
			<content:encoded><![CDATA[<p>Hoy vamos a ver como configurar <a href="http://opensips.org/" target="_blank">OpenSIPS</a> 1.6 y <a href="http://mediaproxy.ag-projects.com/" target="_blank">MediaProxy</a> para solucionar los problemas que el NAT nos pueda traer.</p>
<p>Configurar el proxy para solucionar los problemas de NAT suele ser de las primeras cosas que se pretende o se hace al configurarlo, pero en muchas ocasiones se olvida el primer paso: <strong>entender el NAT</strong>. En su día escribí <a href="http://saghul.net/blog/2007/05/25/howto-solucionando-problemas-de-nat-en-asterisk-parte-1/" target="_blank">un post con una breve introducción al NAT</a>, pero lo que os recomiendo es que os leáis varias veces <a href="http://blog.aliax.net/2007/08/aclarando-sip-y-nat.html" target="_blank">éste post de Iñaki Baz Castillo</a> explicando como afecta el NAT al protocolo SIP así así como los distintos tipos de soluciones.</p>
<p>En este post vamos a ver como &#8220;arreglar&#8221; el NAT con OpenSIPS 1.6 y MediaProxy. El módulo <em>mediaproxy</em> de OpenSIPS nos servirá en combinación con el propio MediaProxy para arreglar el SDP y hacer que el RTP pase por MediaProxy, mientras que para arreglar la parte de señalización utilizaremos el módulo nat_traversal.</p>
<p><strong>El módulo nat_traversal</strong></p>
<p>Este módulos nos servirá para arreglar la cabecera Contact de los mensajes SIP <em>nateados</em> y mantener el NAT abierto haciendo <em>keepalive</em> del lado servidor. El módulo nat_traversal tiene una particularidad que le diferencia de otros módulos similares: fue diseñado para tratar entornos multi-proxy, como por ejemplo el caso en que el proxy que mantiene el keepalive no sea el que gestiona los REGISTER (el registrar). No vamos a entrar en detalle en este post, pero conviene tenerlo en cuenta&#8230;</p>
<p><strong>El módulo mediaproxy</strong></p>
<p>Este módulo gestiona la comunicación con el servidor MediaProxy, de manera que el módulo modificara el SDP para que el audio pase por MediaProxy, que actuara de media relay. Como comente en <a href="http://saghul.net/blog/2010/02/28/ice-%C2%BFla-solucion-definitiva-al-nat-en-sip/" target="_blank">un post anterior</a> MediaProxy soporta ICE, por lo que podremos arreglar el NAT en prácticamente todos los casos (salvo los malditos <a href="http://www.voip-info.org/wiki/view/Routers+SIP+ALG" target="_blank">ALG</a>s).</p>
<p><strong>Antes de empezar</strong></p>
<p>Antes de comenzar la descripción de la configuración necesaria es importante comentar que en este post vamos a utilizar el método <em>fácil</em><em>.</em> El módulo mediaproxy tiene 2 formas de funcionar:</p>
<ol>
<li>Funciones <em>use_media_proxy</em> y <em>end_media_session</em>: han de ser llamadas por el usuario, por lo tanto este ha de saber exactamente cuando quiere que MediaProxy comience o acabe su funcionamiento. Grosso modo tendremos que encargarnos del primer INVITE, los <em>in-dialog-requests</em> y el BYE. Lo veremos en otro post <img src='http://saghul.net/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </li>
<li>Función <em>engage_media_proxy</em>: utiliza el módulo <em>dialog</em> para llamar a las funciones del punto 1 internamente. El usuario solo tiene que llamar a la función engage_media_proxy en el primer INVITE y olvidarse, el resto se realizara internamente. El hecho de que sea tan fácil también trae algunas limitaciones, que veremos mas adelante.</li>
</ol>
<p><strong>Arreglando la </strong><strong>señalización</strong></p>
<p>Primero vamos a configurar el módulo nat_traversal, con el que podremos arreglar el NAT en la señalización.</p>
<p><code>loadmodule "nat_traversal.so"<br />
...<br />
modparam("nat_traversal", "keepalive_interval", 60)<br />
modparam("nat_traversal", "keepalive_method", "OPTIONS")<br />
modparam("nat_traversal", "keepalive_extra_headers", "X-Keepalive: yes\r\n")<br />
modparam("nat_traversal", "keepalive_state_file", "/var/run/opensips/keepalive_state")</code></p>
<p>Con los parámetros indicados haremos que el módulo nat_traversal mande un mensaje SIP OPTIONS cada 60 segundos para mantener el NAT abierto. Ademas, añadiremos la cabecera X-Keepalive, simplemente para identificar estos paquetes mejor.</p>
<p>Para hacer que el módulo comience a enviar los OPTIONS será necesario que llamemos a la función nat_keepalive(). La particularidad de esta función es que no provoca que el mecanismo comience de inmediato, sino que será activado en caso de recibir/generar una respuesta positiva a un REGISTER o SUBSCRIBE y cuando un dialogo comience con un INVITE.</p>
<p><code>...<br />
if ((method=="REGISTER" || method=="SUBSCRIBE" ||<br />
(method=="INVITE" &amp;&amp; !has_totag())) &amp;&amp; client_nat_test("3"))<br />
{<br />
nat_keepalive();<br />
}<br />
...</code><br />
Ademas del keepalive, también tendremos que modificar los mensajes SIP para que la cabecera Contact contenga la IP y puerto reales desde los que vino el paquete en lugar de lo que el terminal del usuario haya puesto. También añadiremos el parámetro rport a la cabecera Via, de manera que OpenSIPS anyadira la IP y el puerto desde los que recibió el paquete a la primera cabecera Via aunque el terminal no indicara soporte para rport. Para ello incluiremos lo siguiente en nuestro <em>request route</em>:</p>
<p><code>if (client_nat_test("3")) {<br />
force_rport();<br />
fix_contact();<br />
}</code></p>
<p>Es posible que las respuestas también vengan nateadas, porque el terminal al que llamamos esta detrás de NAT así que tenemos que tratarlas en un <em>onreply route</em>:</p>
<p><code>if (client_nat_test("1")) {<br />
fix_contact();<br />
}</code></p>
<p>Ya solo nos queda una cosa para terminar con la señalización: fijar el AVP necesario para que OpenSIPS guarde la dirección IP y puerto desde la que se ha registrado el usuario en la tabla location de su base de datos:</p>
<p><code>modparam("registrar", "received_avp", "$avp(s:received_uri)")<br />
...<br />
$avp(s:received_uri) = $source_uri;</code></p>
<p>La pseudovariable $source_uri es exportada por el módulo nat_traversal y contiene la IP, puerto y transporte desde los que se recibió el paquete.</p>
<p><strong>Arreglando el RTP</strong></p>
<p>Una vez tenemos la señalización arreglada necesitamos hacer que el RTP pase por nuestro servidor MediaProxy. Para ello modificaremos el SDP de manera que la IP y puerto desde los que se supuestamente se enviara el RTP sean realmente el servidor de MediaProxy.</p>
<p>Como hemos comentado anteriormente vamos a utilizar el método fácil, por lo que solo tendremos que llamar a la función engage_media_proxy() para el primer invite:</p>
<p><code>if (is_method("INVITE") &amp;&amp; !has_totag()) {<br />
engage_media_proxy();<br />
}</code></p>
<p><strong>Limitaciones</strong></p>
<p>Todo no puede ser perfecto, por lo que el método que aquí hemos utilizado puede no ser el mejor para todos los casos. En concreto estas son las limitaciones que el sistema utilizado conlleva:</p>
<ul>
<li>Se utilizara <strong>siempre</strong> MediaProxy: dado que la función engage_media_proxy() utiliza el módulo dialog para funcionar es necesario llamarla al comienzo del dialogo, así que llamarla al recibir un 200 OK nateado seria demasiado tarde.</li>
<li>Manejo de múltiples diálogos: tanto OpenSIPS como MediaProxy sufren al recibir múltiples respuestas con SDP a un INVITE (dos 183 por ejemplo), por lo que los resultados son inesperados.</li>
</ul>
<p>Dado que la mayoría de usuarios están detrás de NAT y que gracias a la arquitectura escalable de MediaProxy podemos ampliar los recursos a medida que los vayamos necesitando, tendremos que valorar la facilidad en la configuración frente a la flexibilidad en la gestión de NAT.</p>
<p>Happy NAT traversing!</p>
]]></content:encoded>
			<wfw:commentRss>http://saghul.net/blog/2010/05/06/atravesando-el-nat-con-opensips-1-6-y-mediaproxy/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>ICE, ¿la solución definitiva al NAT en SIP?</title>
		<link>http://saghul.net/blog/2010/02/28/ice-%c2%bfla-solucion-definitiva-al-nat-en-sip/</link>
		<comments>http://saghul.net/blog/2010/02/28/ice-%c2%bfla-solucion-definitiva-al-nat-en-sip/#comments</comments>
		<pubDate>Sun, 28 Feb 2010 11:42:14 +0000</pubDate>
		<dc:creator>saghul</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Blink]]></category>
		<category><![CDATA[ICE]]></category>
		<category><![CDATA[MediaProxy]]></category>
		<category><![CDATA[NAT]]></category>
		<category><![CDATA[OpenSIPS]]></category>
		<category><![CDATA[PJSIP]]></category>
		<category><![CDATA[SIP]]></category>
		<category><![CDATA[SIPSIMPLE]]></category>
		<category><![CDATA[VoIP]]></category>

		<guid isPermaLink="false">http://saghul.net/blog/?p=1085</guid>
		<description><![CDATA[Tras estar varias semanas trabajando en éste tema me he decidido a escribir un (largo) post comentando qué es y cómo funciona esto del ICE, ya que no es algo que se esté utilizando demasiado desafortunadamente. Introducción Interactive Connection Establishment (ICE) define un protocolo de actuación gracias al cual dos dispositivos SIP son capaces de mantener [...]]]></description>
			<content:encoded><![CDATA[<p>Tras estar varias semanas trabajando en éste tema me he decidido a escribir un (largo) post comentando qué es y cómo funciona esto del <a href="http://tools.ietf.org/html/draft-ietf-mmusic-ice-19" target="_blank">ICE</a>, ya que no es algo que se esté utilizando demasiado desafortunadamente.</p>
<p><strong>Introducción</strong></p>
<p><a href="http://tools.ietf.org/html/draft-ietf-mmusic-ice-19" target="_blank">Interactive Connection Establishment</a> (ICE) define un protocolo de actuación gracias al cual dos dispositivos SIP son capaces de mantener una sesión multimedia salvando todas las dificultades que el NAT pueda poner de por medio. Aún se encuentra en estado de draft (la última es la revisión 19), pero está en la cola para obtener un número de RFC.</p>
<p>ICE permite que los dispositivos involucrados en la sesión SIP prueben distintos medios o rutas para comunicarse entre sí y acuerden uno común. Gracias a ICE es posible que dos terminales que se encuentran en la misma LAN envíen el tráfico RTP de manera local, en lugar de utilizar un <em>relay</em> como <a href="http://mediaproxy.ag-projects.com/" target="_blank">MediaProxy</a> o <a href="http://www.rtpproxy.org/" target="_blank">RTPProxy</a>, sin realizar ninguna configuración exótica en el servidor. La inteligencia está en los terminales.</p>
<p><strong>¿Cómo funciona?</strong></p>
<p>ICE es un proceso bastante complejo que consta de 9 pasos que intentaré simplificar aquí. Para obtener una información más completa os recomiendo leeros el <em>draft</em>, que aunque es bastante denso describe el mecanismo completo.</p>
<p><strong>Paso 1: Obtención de candidatos</strong></p>
<p>En éste primer paso el llamante obtiene todos los candidados que pueda para posteriormente añadirlos al SDP. Lo habitual es que disponga de dos tipos de candidatos:</p>
<ul>
<li>Host candidates: candidatos que representan tarjetas de red del sistema, incluyendo enlaces VPN etc.</li>
<li>Server reflexive candidates: candidatos obtenidos al realizar consultas a un servidor STUN. Lo habitual es obtener un único candidato de éste tipo con tu propia dirección IP pública.</li>
</ul>
<p><strong>Paso 2: Aplicar prioridades</strong></p>
<p>Tras obtener la lista de candidatos se aplican prioridades, de manera que unos candidatos se prefieran frente a otros. Por ejemplo, la especificación indica que un candidato <em>host</em> ha de ser más prioritario que uno de tipo <em>relayed</em>, es decir, se prefiere mandar el audio por la LAN que a través de un servidor externo que encamina nuestro audio, lo cual tiene bastante sentido.</p>
<p>Al finalizar este paso se construye el SDP que será enviado. Veamos un ejemplo:</p>
<p><code>v=0<br />
o=- 3476345811 3476345811 IN IP4 192.168.99.53<br />
s=sipsimple 0.12.0<br />
c=IN IP4 192.168.99.53<br />
t=0 0<br />
m=audio 60770 RTP/AVP 103 102 9 0 8 117 3 101<br />
a=rtcp:60771 IN IP4 62.131.6.55<br />
a=rtpmap:103 speex/16000<br />
a=rtpmap:102 speex/8000<br />
a=rtpmap:9 G722/8000<br />
a=rtpmap:0 PCMU/8000<br />
a=rtpmap:8 PCMA/8000<br />
a=rtpmap:117 iLBC/8000<br />
a=fmtp:117 mode=20<br />
a=rtpmap:3 GSM/8000<br />
a=rtpmap:101 telephone-event/8000<br />
a=fmtp:101 0-15<br />
a=ice-ufrag:3e0cc9fc<br />
a=ice-pwd:19d32c8c<br />
a=candidate:Sc0a86335 1 UDP 1862270975 62.131.6.55 60770 typ srflx raddr 192.168.99.53 rport 48649<br />
a=candidate:Hc0a86335 1 UDP 1694498815 192.168.99.53 48649 typ host<br />
a=candidate:Ha45450a 1 UDP 1694498815 10.69.69.10 48649 typ host<br />
a=candidate:Sc0a86335 2 UDP 1862270974 62.131.6.55 60771 typ srflx raddr 192.168.99.53 rport 48868<br />
a=candidate:Hc0a86335 2 UDP 1694498814 192.168.99.53 48868 typ host<br />
a=candidate:Ha45450a 2 UDP 1694498814 10.69.69.10 48868 typ host<br />
a=sendrecv</code></p>
<p><strong>Paso 3: Iniciación</strong></p>
<p>En este paso simplemente se envía el INVITE al usuario correspondiente con el SDP creado en el paso 2. SIP atravesará el NAT mediante los mecanismos tradicionales (rport, etc.) por lo que no hay que hacer tratamiento de NAT para el SDP.</p>
<p><strong>Paso 4: Obtención de candidatos (llamado)</strong></p>
<p>Al recibir el INVITE con la oferta en el SDP, el llamado comienza a obtener sus propios candidatos de la misma manera que lo hizo el llamante. Una vez más, lo habitual es obtener candidatos <em>host</em> y <em>server reflexive</em>. Una vez se obtienen los candidatos, se aplican prioridades y se construye el SDP que será enviado.</p>
<p><strong>Paso 5: Información</strong></p>
<p>El llamado responde al INVITE con una respuesta (provisional o definitiva) y en su SDP habrá incluido sus candidatos.</p>
<p>NOTA: Aunque puede tener sentido enviar la respuesta en una respuesta provisional (18X) SIP no especifica como actuar ante la recepción de múltiples respuestas 18X con SDP, por lo que si encima añadimos ICE al asunto lo mas probable es que no podamos establecer la comunicación. En todas las pruebas que he hecho (y han sido muchas) la negociación ICE no lleva más de 2 segundos, por lo que hacerla tras el 200 OK no es un problema IMHO.</p>
<p><strong>Paso 6: Verificación</strong></p>
<p>Cada agente (llamado y llamante) involucrado en la comunación empareja sus candidatos con los candidatos remotos para formar parejas de candidatos. Éstas parejas serán evaluadas por orden de prioridad descendente por el agente controlador. Por simplificar, diremos que el agente controlador siempre el el llamante (esto puede variar, pero en casos bastante peculiares, que creo que añadirían demasiada confusión al tema).</p>
<p>En éste momento ambos agentes comienzan a realizar pruebas de conectividad cada 20ms. Éstas pruebas se llevan a cabo mediante paquetes especiales STUN que contienen <em>binding requests</em>. El agente remoto contestará con la IP y el puerto desde los que ha recibido dicha <em>binding request</em> y así el agente que ha enviado la petición sabrá que el test ha sido satisfactorio y marcará el candidato como válido.</p>
<p>Si uno de los agentes involucrados en la sesión se encuentra tras un NAT simétrico, esto será detectado al ver la diferencia entre el <em>server reflexive candidate</em> publicado y el origen del <em>binding request</em> que mandará. Entonces se crea un nuevo candidato de tipo <em>peer reflexive</em>, que contiene la IP y puerto donde estará el RTP (los test de conectividad de hacen enviando paquetes STUN a los puertos donde posteriormente habrá RTP). Gracias a esto es posible que un usuario tras NAT simétrico y otro tras un NAT no simétrico hablen entre si con audio de router a router. Increíble, ¿no?</p>
<p><strong>Paso 7: Coordinación</strong></p>
<p>Tras la negociación ambos agentes involucrados en ella han de terminar con un par de candidatos válidos por cada componente. Lo habitual es tener dos componentes por cada <em>stream</em> en el SDP: un componente para el RTP y otro para el RTCP.</p>
<p>El agente controlador (habitualmente el que realiza la llamada) elegirá un candidato. A éste proceso se le llama <em>nominación</em>. Para validar éste candidato se envía otra <em>binding request</em> (STUN) pero en esta ocasión se incluye un <em>flag</em>. Ambos agentes utilizarán el par de candidatos que ha pasado las pruebas de conectividad y que además esté nominado.</p>
<p>Recordemos que todo éste proceso ha sido realizado por los agentes utilizando paquetes STUN entre si, sin ninguna interacción por parte del servidor.</p>
<p><strong>Paso 8: Comunicación</strong></p>
<p>Ahora que ambos agentes saben cómo comunicarse, ya pueden enpezar ha hablar, y tenemos garantizado que habrá audio bidireccional, ya que las pruebas de conectividad se realizan en ambas direcciones.</p>
<p><strong>Paso 9: Confirmación</strong></p>
<p>Aunque toda la negociación ha tenido lugar entre los agentes es posible (y habitual) que haya otros agentes en el medio de la señalización, como por ejemplo <em>proxys</em>. Para que los <em>proxys</em> o las <em>middle-boxes</em> entre el llamado y el llamante estén al tanto de lo sucedido, se enviará un re-INVITE o un UPDATE con el resultado de la negociación en el caso de que el candidato seleccionado no sea el candidato por defecto (las líneas c y m del SDP).</p>
<p><strong>¡Qué way!, esto funciona, ¿no?</strong></p>
<p>Pues, para variar, no. Lo habitual para el tratamiento de NAT consiste en que el proxy modifica el SDP si detecta NAT e indica como origen del RTP y RTCP un servidor que hará las veces de <em>media relay</em>.</p>
<p>Al modificar el SDP, no habrá ningún candidato que corresponda a la IP y puerto de las líneas c y m del SDP, por lo que al recibir un INVITE así el otro extremo nos responderá con ésto en su SDP: <em>a=ice-missmatch</em>. Mal tema. ¡Hay que solucionarlo!</p>
<p><strong>&#8220;Arreglando&#8221; la negociación ICE con OpenSIPS y MediaProxy</strong></p>
<p>Para solucionar éste problema ha sido necesario modificar <a href="http://www.opensips.org" target="_blank">OpenSIPS</a> y MediaProxy (los componentes con los que trabajo actualmente, pero lo mismo puede hacerse para Kamailio/SIP-Router y RTPProxy).</p>
<p>Resumiendo un poco (tenéis una explicación más completa <a href="http://mediaproxy.ag-projects.com/wiki/ICE" target="_blank">aquí</a>) lo que sucederá es que OpenSIPS añadirá un nuevo candidato de tipo <em>relayed</em> cuando modifique el SDP, de manera que corresponda con la IP y puerto de las líneas c y m. MediaProxy es ahora capaz de &#8220;dejar pasar&#8221; las pruebas de conectividad STUN, por lo que al modificar el INVITE inicial y su correspondiente respuesta habremos &#8220;engañado&#8221; a los agente insertando un nuevo candidato.</p>
<p>Mediante un parámetro es posible controlar la prioridad del candidato que OpenSIPS insertará, afectando así al resultado de la negociación.</p>
<p>Ahora sí, ¡funciona! puedo hablar con audio P2P en mi LAN aunque fuerce el uso de MediaProxy, porque al detectar una negociación ICE satisfactoria MediaProxy se &#8220;quita de en medio&#8221;. También he probado ha hablar con audio de router a router entre un NAT simétrico y otro de tipo <em>port restricted</em>. How f*c*i*g cool is that?</p>
<p><strong>¡Quiero probarlo!</strong></p>
<p>No tan rápido vaquero. Nos falta hablar de el tema más importante: los clientes SIP. Sólo conozco tres (en esencia uno) que implemente ICE correctamente. Y cuando digo correctamente es que me he leído el draft, el código y he probado que funciona <img src='http://saghul.net/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Los clientes SIP con soporte ICE (draft versión 19) son <a href="http://www.pjsip.org/" target="_blank">PJSIP</a>, <a href="http://sipsimpleclient.com/" target="_blank">SIPSIMPLE client</a> (su core es PJSIP) y <a href="http://icanblink.com/" target="_blank">Blink</a> (su core es SIPSIMPLE).</p>
<p>Si alguien descubre o está desarrollando un cliente SIP que cumpla la especificación ICE (draft 19) me encantaría probar la interoperabilidad con él.</p>
<p>Actualmente no hay ninguna versión (release) de OpenSIPS que incluya el parche para &#8220;solucionar&#8221; el problema de ICE, así que podéis parchear manualmente como se menciona <a href="http://mediaproxy.ag-projects.com/wiki/ICE" target="_blank">aquí</a> o podéis utilizar el servicio gratuito <a href="http://sip2sip.info" target="_blank">SIP2SIP</a>, que ya dispone de todo lo necesario (parches para OpenSIPS y última versión de MediaProxy).</p>
<p><strong>Conclusiones</strong></p>
<p>Tras estar un mes con éste tema por fin he podido comprobar que <strong>funciona</strong>. No obstante, es triste ver que hay muy pocas implementaciones de ICE y que solo una funcione. Es cuanto menos sorprendente que softphones de pago de supuesto prestigio digan que soportan ICE y en el SDP se vea claramente no de la manera correcta.</p>
<p>Hay que agradecer a Benny Prijono y el equipo de PJSIP el buen trabajo que han realizado al respecto acudiendo en enumerosas ocasiones al SIPit para mejorar su SIP stack.</p>
<p>¡Joder que largo me ha quedado esto! Para más información podéis leer el <a href="http://tools.ietf.org/html/draft-ietf-mmusic-ice-19" target="_blank">draft</a> y echarle un ojo a <a href="http://www.jdrosen.net/papers/ice-basic-tutorial.pdf" target="_blank">ésta presentación</a>.</p>
<p>Happy ICE skating! <img src='http://saghul.net/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://saghul.net/blog/2010/02/28/ice-%c2%bfla-solucion-definitiva-al-nat-en-sip/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>

