systemadmin.es > Kernel > whatsmyip con ping

whatsmyip con ping

Existen muchas webs que permiten ver la IP con la que nos conectamos al servidor web, incluso el propio google nos muestra nuestra IP. Pero, siempre puede existir otra forma de revelar la IP sin recurrir a una página web.

A partir de la necesidad de Gerard, que quería ver su IP desde un router que no tenía curl:

vamcats de Gerard

vamcats de Gerard

E inspirado por la ponencia “Data exfiltration, the ninja way” de la NoConName 2012, pero con la idea contraria ya que es obtención de datos. He programado un pequeño modulo del kernel que mediante dos hooks de netfilter (iptables para entendernos) permite mostrar al cliente la IP origen del ICMP Echo request.

Evidentemente tiene poca gracia si tenemos que modificar el cliente de ping para mostrar más datos, por ello debemos aprovechar algún campo que se muestre por defecto, como puede ser el TTL, ya que el tiempo del paquete puede ser muy poco fiable:

C:\>ping google.com

Haciendo ping a google.com [173.194.41.9] con 32 bytes de datos:
Respuesta desde 173.194.41.9: bytes=32 tiempo=81ms TTL=55
Respuesta desde 173.194.41.9: bytes=32 tiempo=72ms TTL=55
Respuesta desde 173.194.41.9: bytes=32 tiempo=72ms TTL=55
Respuesta desde 173.194.41.9: bytes=32 tiempo=74ms TTL=55

Otros campos como el número de paquetes perdidos o el número de duplicados requiere muchos paquetes:

Estadísticas de ping para 173.194.41.9:
    Paquetes: enviados = 4, recibidos = 4, perdidos = 0
    (0% perdidos),
Tiempos aproximados de ida y vuelta en milisegundos:
    Mínimo = 72ms, Máximo = 81ms, Media = 74ms

El modulo resulta fiable en la misma red excepto porque:

  • El campo TTL es de 8 bits, por lo que dependiendo del número de saltos existirán IPs (las altas) que no podremos devolver correctamente

Para tráfico WAN debemos tener en cuenta que:

  • Se asume que el TTL inicial del cliente es 64, valor que tanto en Windows como en Linux usan
  • El camino de ida y vuelta es simétrico. Tenemos en cuenta la diferencia entre el número de saltos y 64 (valor asumido por el condicionante anterior) para definir el TTL del paquete de vuelta

Lo podéis comprobar mediante whatsmyip.systemadmin.es y el servidor que me han prestado de demo (gracias!):

# ping whatsmyip.systemadmin.es
PING whatsmyip.systemadmin.es (178.63.22.124) 56(84) bytes of data.
64 bytes from 178.63.22.124: icmp_seq=1 ttl=87 time=13.5 ms
64 bytes from 178.63.22.124: icmp_seq=2 ttl=98 time=13.3 ms
64 bytes from 178.63.22.124: icmp_seq=3 ttl=227 time=13.6 ms
64 bytes from 178.63.22.124: icmp_seq=4 ttl=154 time=13.8 ms
^C
--- 178.63.22.124 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3001ms
rtt min/avg/max/mdev = 13.330/13.600/13.833/0.229 ms

Si nos descargamos el paquete icmp2ip, lo podemos compilar e instalar mediante los comandos:

make all
insmod ./icmp2ip.ko

A continuación, si hacemos ping con una máquina de IP origen, por ejemplo 10.25.11.1, veremos:

# ping 172.16.1.1
PING 172.16.0.100 (172.16.1.1) 56(84) bytes of data.
64 bytes from 172.16.1.1: icmp_seq=1 ttl=10 time=2.61 ms
64 bytes from 172.16.1.1: icmp_seq=2 ttl=25 time=1.86 ms
64 bytes from 172.16.1.1: icmp_seq=3 ttl=11 time=2.27 ms
64 bytes from 172.16.1.1: icmp_seq=4 ttl=1 time=2.31 ms

--- 172.16.1.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3002ms
rtt min/avg/max/mdev = 1.869/2.268/2.612/0.266 ms

Vemos como cada octeto de la IP origen se manda con cada ICMP Echo reply con el TTL adecuado para que se nos muestre.

Para localhost también funciona:

$ ping localhost
PING picamoixons (127.0.0.1) 56(84) bytes of data.
64 bytes from picamoixons (127.0.0.1): icmp_req=1 ttl=127 time=0.066 ms
64 bytes from picamoixons (127.0.0.1): icmp_req=2 ttl=0 time=0.059 ms
64 bytes from picamoixons (127.0.0.1): icmp_req=3 ttl=0 time=0.060 ms
64 bytes from picamoixons (127.0.0.1): icmp_req=4 ttl=1 time=0.060 ms
^C
--- picamoixons ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 2999ms
rtt min/avg/max/mdev = 0.059/0.061/0.066/0.006 ms

También se debe tener en cuenta que:

  • Se conserva la posición del octeto que se ha mandado mediante un array fijo de 30 posiciones que se va limpiando función del último en uso
  • Si no recibimos la IP completa, el siguiente ping que mandemos nos mostrará el siguiente byte sin importar el tiempo que haya pasado (siempre que no se haya limpiado por le condición anterior)
  • Dos o más pings concurrentes desde la misma IP origen hará que se mezclen los resultados entre los clientes
  • Creo que nunca se ejecutarán en paralelo dos hooks accediendo al mismo array de IPs origen, pero no he mirado si es así o simplemente es mi imaginación
  • Curiosamente, el tipo de paquete ICMP que veía con icmph->type variaba del define ICMP_ECHO al valor 69 (que no he visto definido ni en el icmp.h ni en la página referente a ICMP de la Wikipedia) dependiendo si era un ping desde el propio equipo (ICMP_ECHO) o a través de la red (valor 69). No he entendido este punto, por lo que simplemente he añadido los dos:
    (...)
    else if((icmph->type == ICMP_ECHO)||(icmph->type == 69))
    {
       if(DEBUG) printk(KERN_DEBUG "echo\n");
    (...)
    

Deja un comentario:

XHTML - Tags permitidos:<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>