Uno de los problemas fundamentales de la telefonía IP es el uso del NAT en los router. Cuando un teléfono IP o un servidor de Asterisk situado en la LAN de la empresa se registra en un proveedor externo de telefonía IP a través del router de la organización, el router hace NAT y cambia la IP privada de origen por la propia dirección IP pública del lado WAN del router, en un proceso que es de sobra conocido, manteniendo el puerto de origen, ya que no hay ninguna necesidad de cambiarlo. Es decir, si el puerto de origen es el 5060 UDP y el puerto de destino es también el 5060 UDP, ambos números de puerto son mantenidos cuando los paquetes IP de la petición de REGISTER atraviesan el router.
Pero si en ese momento otro segundo teléfono del lado LAN u otro servidor de Asterisk inician también el registro con el proveedor de telefonía IP, en este caso el router debe hacer obligatoriamente la traslación del número de puerto de origen, ya que en caso contrario habrían salido paquetes desde el router provenientes de dos dispositivos LAN diferentes con la misma dirección IP pública y con el mismo puerto de origen. El router mantiene en todo momento una tabla con la información necesaria para el seguimiento de este proceso de NAT.
Tabla NAT en un Fortigate 100F
Este proceso de traslación de puertos se lleva a cabo en el router con las peticiones SIP de la telefonía IP y con cualquier otro paquete UDP o TCP que lo atraviesa, lo cual puede llevar a un eventual agotamiento de los puertos en salida, por lo que es necesario eliminar estas traslaciones de puerto cuando ya no se necesitan. Los router utilizan estrategias diferentes para las comunicaciones TCP y UDP. En el caso de las comunicaciones TCP el router espera a que la comunicación finalice correctamente vigilando los paquetes FIN y ACK correspondientes. Si esta finalización de conexión TCP no llega, el router espera un tiempo fijado por un temporizador interno, que es diferente para los diversos modelos de router, pero que habitualmente es un tiempo elevado, de varias horas o incluso de varios días.
Proceso de cierre de una conexión TCP
Pero en el caso de las comunicaciones UDP, al no haber una fase de establecimiento de la conexión ni de finalización de la misma, el router simplemente utiliza un temporizador interno, de tal forma que al transcurrir el tiempo fijado sin que hayan circulado nuevos paquetes de esa conexión UDP, la traslación de puerto en el router es finalizada y la comunicación queda interrumpida. Este temporizador para las conexiones UDP suele tener un valor mucho más pequeño, típicamente de algunas decenas de segundos, ya que se sobreentiende que, si en ese tiempo no ha habido nuevas peticiones UDP o nuevas respuestas, es porque la comunicación ya ha finalizado.
Y es en este caso cuando puede surgir un problema con las llamadas entrantes desde el operador. Si la conexión UDP ha sido finalizada por el router, cuando el operador recibe una llamada entrante desde la red pública de telefonía y envía un petición de tipo INVITE al teléfono IP o al servidor de Asterisk, el router impide el paso de esa petición y la llamada entrante no funciona. Para evitar este problema existen diferentes soluciones:
- Enviar paquetes de tipo REGISTER de forma más frecuente, impidiendo con ello que el router cierre la conexión UDP.
- Enviar de forma frecuente paquetes UDP de pequeño tamaño hacia el operador de telefonía IP para mantener abierta esta conexión en el router.
Aun cuando las dos estrategias funcionan perfectamente, es preferible la segunda opción, ya que la sobrecarga de tráfico por el router es mucho menor y al mismo tiempo, tampoco se sobrecarga al servidor del operador de VoIP con peticiones de REGISTER innecesarias. Por ello los teléfonos IP suelen incorporar la funcionalidad de envío automático de paquetes Keep Alive. Estos paquetes son de muy pequeño tamaño, usualmente de 60 bytes o menos, y con un contenido mínimo en su interior. Cuando estos paquetes alcanzan al operador de telefonía IP, éste no hace nada con dichos paquetes pero se consigue el objetivo buscado, que es el mantener abierta la conexión UDP a través del router.
Configuración Keep Alive en un teléfono Yealink T31
Paquetes Keep Alive de tipo UDP enviados por el teléfono Yealink T31
En la captura de imagen anterior se observan los paquetes UDP de tipo Keep Alive enviados por el teléfono Yealink T31 al servidor de Asterisk situado en la dirección IP 10.22.86.245. En este caso, al estar el teléfono IP y el servidor de Asterisk en la misma red, estos paquetes de tipo Keep Alive no son necesarios, pero si estuvieran en redes diferentes, con un router por el medio, servirían para mantener abierta la conexión UDP por el router en el caso de que las peticiones de tipo REGISTER se realicen a intervalos más largos que el tiempo asignado al temporizador UDP del router. Usualmente los router tienen un timer de finalización de las conexiones de UDP de 60 segundos o menos, por lo que es habitual que los teléfonos IP envíen los paquetes de tipo Keep Alive a intervalos más cortos, 30 segundos en el caso de los teléfonos Yealink T31.
Contenido de un paquete de tipo Keep Alive
En la captura de imagen anterior se observa que el contenido de estos paquetes de tipo Keep Alive son 4 bytes con el valor 0d0a0d0a en hexadecimal.
Paquetes de tipo Keep Alive enviados por un softphone MicroSIP
Contenido de los paquetes de tipo Keep Alive enviados por el softphone MicroSIP
Configuración de paquetes Keep Alive en un teléfono GrandStream GXP1625
Y al igual que los teléfonos IP, Asterisk también permite configurar el envío de paquetes de tipo Keep Alive mediante el parámetro keep_alive_interval del fichero pjsip.conf, dentro de la sección [global] dedicada a los ajustes globales, pero esto solo tiene efecto para las comunicaciones orientadas a la conexión como TCP, TLS o Websocket Para las comunicaciones UDP Asterisk utiliza la variable qualify_frequency dentro de la sección de tipo aor en el fichero pjsip.conf.
Parámetro qualify_frecuency en el fichero pjsip.conf
Paquetes de tipo Keep Alive enviados por Asterisk al proveedor de telefonía IP Sarenet
En la captura de pantalla anterior se muestran los paquetes de tipo Keep Alive enviados por un servidor de Asterisk hacia el proveedor de telefonía IP Sarenet. En realidad estos paquetes son peticiones SIP de tipo OPTIONS y las respuestas enviadas por parte del servidor SIP de Sarenet son respuestas SIP de tipo 200 Alive.
Contenido de una petición SIP de tipo OPTIONS
Respuesta SIP de tipo 200 Alive
Para terminar y a modo de curiosidad, se puede observar que si intentamos impedir la conexión de un teléfono de estos con el servidor de Asterisk mediante un firewall como es UFW (Netfilter), el firewall parece fallar ya que la conexión no se finaliza en ningún momento. En realidad el firewall está funcionando correctamente y lo que está sucediendo es que los paquetes de tipo Keep Alive mantienen activa la conexión a través de él. Si se cierra la aplicación del softphone o se desconecta el teléfono físico y luego se vuelven a conectar, se observa que el firewall bloquea correctamente la conexión con el servidor de Asterisk. En el caso del firewall Netfilter, los timeout para las conexiones TCP y UDP están establecidas en el directorio /proc/sys/net/netfilter. La conexión TCP tiene un timer por defecto de 5 días mientras que la conexión UDP tiene un timer de tan solo 30 segundos.