Como se observa en un artículo anterior, el protocolo STUN juega un papel importante en las implementaciones de VoIP: descubrir la presencia de NAT y de aprender y utilizar las asignaciones de NAT que se han realizado para el cliente. En este artículo, vamos a ver en los detalles del protocolo STUN.

El protocolo STUN

STUN es un protocolo cliente-servidor. Un cliente STUN (normalmente integrado en un módulo de software de VoIP, tales como una IP-PBX o un teléfono IP) envía una petición a un servidor STUN para descubrir su IP pública y el o los puertos mapeados, y el servidor STUN devuelve una respuesta. Hay dos tipos de peticiones: “Binding Requests” que suelen ser enviados a través de UDP, y “Shared Secret Requests”, que se envían a través de TLS (comunicación segura) sobre TCP. Las peticiones de tipo “Shared Secret Requests” solicitan al servidor un conjunto de credenciales temporales que luego se utilizan en una petición de tipo “Binding Request” y su correspondiente respuesta, a los efectos de la autenticación y la integridad del mensaje.

Las solicitudes de tipo “Binding Request” son enviadas desde el cliente al servidor STUN para determinar la dirección IP y el o los puertos asignados por el NAT. El cliente STUN envía una solicitud de tipo “Binding Request” al servidor STUN a través de UDP, el servidor examina la dirección IP y el puerto de origen de la solicitud, y los copia en una respuesta de tipo “Binding Response” que se envía de vuelta al cliente. También hay atributos (que son explicados en más detalle más adelante en este artículo) en la solicitud que permiten al cliente pedir que la respuesta sea enviada a otro lugar, es decir a una dirección IP y puerto distinto.

Mensajes STUN

Los mensajes STUN son de tipo TLV (tipo-longitud-valor) codificado en binario con big endian (ordenamiento de red). Todos los mensajes STUN comienzan con un encabezado de STUN, y son seguidos por una carga útil de STUN. La carga útil es una serie de atributos STUN (explicados con más detalle más adelante en este artículo), los cuales dependen del tipo de mensaje. El encabezado de STUN contiene:

  • Tipo de mensaje STUN que típicamente es uno de los siguientes:
    • 0×0001 : Binding Request
    • 0×0101 : Binding Response
    • 0×0111 : Binding Error Response
    • 0×0002 : Shared Secret Request
    • 0×0102 : Shared Secret Response
    • 0×0112 : Shared Secret Error Response
    • Longitud del mensaje – indica la longitud total de la carga útil de STUN en bytes, sin incluir los 20 bytes del encabezado.
    • Identificador de transacción – utilizado para correlacionar los pedidos con sus respuestas.

Atributos del protocolo STUN presentes en los pedidos y sus respuestas

Tanto los pedidos como las respuestas de STUN contienen atributos. Como veremos más adelante, algunos de los atributos no son obligatorios, algunos pueden encontrarse tanto en los pedidos “Binding Request” como en las respuestas “Binding Response”, algunos pueden estar sólo en los pedidos “Binding Request”, y otros pueden estar presentes solamente en las respuestas “Binding Response”. A continuación se muestra una lista de atributos STUN y una breve explicación de cada uno:

0×0001: MAPPED-ADDRESS

Este atributo contiene una dirección IP y el puerto. Siempre se coloca en la respuesta de tipo “Binding Response”, e indica la dirección IP y el puerto de origen que el servidor vio en la solicitud de tipo “Binding Request” enviada por el cliente, es decir, la dirección IP pública del cliente STUN y el puerto donde se lo puede acceder desde Internet.

0×0002: RESPONSE-ADDRESS

Este atributo contiene una dirección IP y el puerto y es un atributo opcional, por lo general en la solicitud de tipo “Binding Request” (enviada desde el cliente al servidor STUN). Indica donde debe enviarse la respuesta de tipo “Binding Response” (desde el servidor STUN al cliente). Si este atributo no está presente en la solicitud “Binding Request”, la respuesta se envía a la dirección IP de origen y el puerto desde donde provino la solicitud, y estos datos se envían en el atributo 0×0001: MAPPED-ADDRESS.

0×0003: CHANGE-REQUEST

Este atributo es opcional y sólo está permitido en la solicitud de tipo “Binding Request”. Contiene dos indicadores, para controlar la dirección IP y el puerto utilizados para enviar la respuesta. Estos indicadores se llaman “cambio de IP” y “cambio de puerto”. Los indicadores “cambio de IP” y “cambio de puerto” son útiles para determinar si el cliente está detrás de un NAT de tipo “restricted cone” o de tipo “restricted port cone”. Le indican al servidor que envíe las respuestas de tipo “Binding Response” de una dirección IP y puerto de origen distintos.

0×0004: SOURCE-ADDRESS

Este atributo generalmente se encuentra presente en respuestas de tipo “Binding Response”. Indica la dirección IP y el puerto de origen desde donde se envió la respuesta, es decir, la dirección IP de la máquina donde está corriendo el cliente (por lo general una dirección IP interna privada). Es muy útil dado que a partir de este atributo, el servidor STUN puede detectar escenarios de doble NAT.

0×0005: CHANGED-ADDRESS

Este atributo generalmente se encuentra presente en respuestas de tipo “Binding Response”. Informa al cliente la dirección IP y el puerto de origen que se utilizaría si el cliente solicita el “cambio de IP” y el “cambio de puerto”.

0×0006: USERNAME

Este atributo es opcional y está presente en una respuesta de tipo “Shared Secret Response” donde también está el atributo “PASSWORD”. Sirve como un medio para identificar el secreto compartido utilizado en la comprobación de la integridad del mensaje.

0×0007: PASSWORD

Este atributo es opcional y está presente en una respuesta de tipo “Shared Secret Response” donde también está el atributo “USERNAME”. El valor de este atributo es de longitud variable y se utiliza como un secreto compartido entre el servidor y el cliente STUN.

0×0008: MESSAGE-INTEGRITY

Este atributo debe ser el último en un mensaje STUN y puede estar presente tanto en mensajes de tipo “Binding Request” como “Binding Response”. Contiene el HMAC-SHA1 del mensaje STUN.

0×0009: ERROR-CODE

Este atributo solo está presente en las respuestas de tipo “Binding Error Response” y “Shared Secret Error Response”. Indica que ha ocurrido un error y el tipo de error que se ha producido. Contiene un valor numérico en el rango de 100 a 699, que representa el código de error y también una frase con la descripción del error codificada en UTF-8.

0x000a: UNKNOWN-ATTRIBUTES

Este atributo está presente en las respuestas de tipo “Binding Error Response” o “Shared Secret Error Response” cuando el código de error es 420. Indica que algunos atributos enviados desde el cliente son desconocidos para el servidor y éste no puede entenderlos.

0x000b: REFLECTED-FROM

Este atributo está presente sólo en la respuesta de tipo “Binding Response” y se utiliza para proporcionar trazabilidad de modo que el servidor STUN no pueda utilizarse como parte de un ataque de denegación de servicio. Contiene la dirección IP de la fuente de donde provenía la solicitud, es decir, la dirección IP del cliente STUN.

Códigos de error más comunes de un servidor STUN

Al igual que muchos otros protocolos, STUN tiene una lista de códigos de error. Los códigos de error del protocolo STUN son similares a los de HTTP o SIP. A continuación se muestra una lista de la mayoría de los códigos de error comunes encontrados al usar el protocolo STUN. Para obtener una lista completa de códigos de error del protocolo STUN refiérase a la RFC 3489 STUN.

Código de error 400

Mala petición, la solicitud estaba malformada. El cliente debe modificar la solicitud e intentar enviarla nuevamente.

Código de error 420

Atributo desconocido, el servidor no ha comprendido un atributo en la solicitud.

Código de error 430

Credenciales caducadas; el secreto compartido enviado en la solicitud ha caducado, el cliente debe obtener un nuevo secreto compartido.

Código de error 432

Falta nombre de usuario, el atributo de nombre de usuario no está presente en la solicitud.

Código de error 500

Error del servidor, error temporal y el cliente debe intentar enviar la solicitud nuevamente.