Cambiar el TTL de paquetes IP ya enviados por la aplicación

Cada paquete IP tiene en su cabecera un campo llamado TTL (Time To Live) destinado a evitar que el paquete quede eternamente circulando por la red en caso de algún problema de enrutamiento. Aunque el significado de sus siglas haga referencia al tiempo de vida, en realidad el valor del campo TTL representa el número máximo de saltos que puede dicho paquete realizar entre distintas redes.

Para que esto se cumpla, cada vez que el paquete es enrutado de una red a otra, se decrementa el valor TTL del paquete. Si al pasar de una red a otra el campo TTL alcanza el valor 0 entonces el paquete se descarta sin enviarse a la siguiente red IP.

Cada sistema operativo da un valor por defecto de TTL distinto a los paquetes unicast (con dirección IP de destino de un equipo concreto) que suele ser suficiente para alcanzar cualquier otro equipo del mundo a través de Internet (en Linux este valor es 64). Sin embargo, para los paquetes multicast (con dirección IP de destino de un grupo, no de ningún equipo concreto) el valor por defecto es 1, de modo que los paquetes multicast, por defecto, no puedan ser reenviados a otras redes distintas de aquella en la que se originaron.

Afortunadamente, las aplicaciones pueden indicar que desean aplicar un TTL distinto a los paquetes multicast enviados por cierto socket. Según la norma POSIX se hace de la siguiente forma:

unsigned char ttl = 16;
setsockopt(socket, IPPROTOIP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));

También se puede establecer el TTL de forma genérica para todos los paquetes enviados utilizando la opción IP_TTL, en lugar de IP_MULTICAST_TTL.

Sin embargo, ¿qué se puede hacer si no se puede modificar cierta aplicación y se necesita cambiar el TTL de los paquetes que envía?

Una solución obvia y bastante sencilla consiste en desplegar una aplicación que reciba dichos paquetes y reenvíe su contenido estableciendo el TTL como se desee. Esto se puede hacer de forma bastante sencilla con la aplicación socat. El siguiente ejemplo muestra como utilizarla para recibir unos paquetes multicast y reenviarlos con TTL 16 a otra dirección multicast:

socat UDP4-RECV:$ORIGINAL_DEST_PORT,bind=$ORIGINAL_DESTINATION_IP,ip-add-membership=$ORIGINAL_DESTINATION_IP:$INGRESS_INTERFACE,reuseaddr UDP4-SENDTO:$NEW_DESTINATION_IP:$NEW_DESTINATION_PORT,ip-multicast-ttl=16,bind=$EGRESS_SOURCE_IP

Esta orden abrirá un socket UDP de escucha en el puerto $ORIGINAL_DEST_PORT, asociado al interfaz (o interfaces) que correspondan a la dirección IP multicast $ORIGINAL_DESTINATION_IP y realizando la suscripción IGMP a la dirección de grupo multicast $ORIGINAL_DESTINATION_IP por el interfaz especificado por $INGRESS_INTERFACE. Los paquetes que reciba los enviará a la dirección IP $NEW_DESTINATION_IP y al puerto $NEW_DESTINATION_PORT con TTL 16 utilizando como dirección IP de origen $EGRESS_SOURCE_IP.

Otra solución consiste en utilizar IPTABLES para modificar los paquetes mientras atravesan la cadena de salida, después de que la aplicación solicite al sistema su envío y antes de que el sistema entregue el paquete al interfaz de red.

La modificación del TTL solo se puede realizar en la tabla mangle, por lo que el comando IPTABLES para realizar este cambio sería el siguiente:

iptables -t mangle -A OUTPUT -d $ORIGINAL_DESTINATION_IP -j TTL --ttl-set 16

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.