Páginas

lunes, 22 de agosto de 2011

¿de quien carajo es este socket? II

Continuando con lo explicado la semana pasada vamos a ver donde podemos encontrar la información que conseguimos por comandos, pero esta vez lo haremos de el fabuloso FS "/proc".

"/proc" realmente es un pseudo-file system (tipo procfs), este no consume espacio de almacenamiento y ocupa una cantidad de memoria baja, en él el kernel nos vuelca información sobre los procesos, hardware, memoria, almacenamiento, vamos información sobre el sistema en si.

Para un estudio mas profundo aconsejo mirar un "man proc" donde viene explicado el contenido de sus directorios y ficheros.

Yendo la grano, para encontrar información sobre los sockets, podemos mirar en el siguiente directorio "/proc/net/", ahí dependiendo del tipo de socket del que queramos información miraremos en el archivo con dicho nombre, en nuestro caso vamos a mirar sockets tcp (tcp6 para ipv6).

Dentro de este archivo nos encontramos con algo como esto.

#cat /proc/net/tcp
sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode                                                    
   0: 0301A8C0:994C BF9255D1:0050 01 00000000:00000000 00:00000000 00000000  1000        0 120913 1 00000000 30 4 28 5 3   


Vale, una vez tenemos este armatoste de datos en hexadecimal little-endian, vamos a ver las columnas que tienen los datos que nos hacen falta para lanzar nuestro tcpdump, como ya hicimos en el articulo anterior. 

local_addres -> aqui tenemos la ip:puerto origen.
rem_address -> ip:puerto destino
inode -> inode del socket (este dato viene en decimal).

Ya sabemos los datos ahora solo nos falta pasarlos a formato decimal, mas que nada para enterarnos nosotros de que pone.

Al estar en little-endian se lee de derecha a izquierda, por ejemplo para la ip y el puerto tenemos lo siguiente según la salida.

ip:port ------> 0301A8C0:994C

Sabemos que la ip es de la forma x1.x2.x3.x4, la parte de la ip consta de 8 digitos hexadecimales por lo que cada dos digitos corresponden a una de las x del formato ip, y al estar en little-endian x1 es la pareja de digitos mas a la derecha, vamos a verlo en nuestra salida.

Hexadecimal              Decimal               
03.01.A8.C0      ---->   3.1.168.192

De tal modo si lo pasamos a big-endian, cambiando el orden de los digitos de izquierda a derecha, obtenemos nuestra dirección ip.

192.168.1.3

El puerto seria igual, pero ya que solo hay un digito no habría que darle la vuelta. 

Hexadecimal              Decimal               
994C               ---->    39244

Una vez tenemos todos los datos en decimal, podemos obtener información del socket con tcpdump igual que hicimos en el articulo anterior. Lo único que nos queda es saber a que proceso pertenece.

Entre los directorios que podemos encontrar en /proc vamos a fijar nuestra atención en aquellos que tienen por nombres números. Cada vez que se ejecuta un proceso, durante el tiempo que este corriendo se le asigna una de estas carpetas cuyo nombre coincide con su pid. Dentro de cada una de estas carpetas hay un directorio llamado fd, pues bien aquí se encuentran lo descriptores de ficheros de los archivos que tiene abiertos, y como nuestro socket necesita un descriptor de fichero pues aquí lo encontraremos.

Bien, ya sabemos la carpeta donde buscar, ahora nos hace falta saber como saber que un determinado fd es un socket y que inode tiene ese socket, un listado del directorio con -l nos sacara de dudas, escogeremos un pid al azar, el uno por ejemplo.

#ls -li
total 0
167690 lrwx------ 1 root root 64 2011-08-22 21:02 0 -> /dev/null
167691 lrwx------ 1 root root 64 2011-08-22 21:02 1 -> /dev/null
167700 lrwx------ 1 root root 64 2011-08-22 21:02 10 -> socket:[7298]



Antes de proseguir, apuntar un par de cosas sobre el archivo, primero vamos a ver como esta formado su nombre. 

fd->tipo:[inode]
10->socket:[7298]

Como ya os estaréis preguntando, si la primera columna que sale es el inode, ¿como que no es el mismo?  


167700 lrwx------ 1 root root 64 2011-08-22 21:02 10 -> socket:[7298]

La respuesta es que el inode que nos muestra "ls -i" es el del descriptor de fichero y el que sale entre paréntesis es del socket.

Pues por fin solo nos queda buscar /proc el directorio donde esté uno de estos archivos y tendremos el pid del proceso dueño del socket, una posible solución podría ser la siguiente, aunque es un poco enrevesada, si tenéis alguna manera mejor, soy todo oídos.

#find /proc -inum `ls -Rli /proc/[0-9]{1,}/fd|egrep 'socket:\[120913\]'|awk '{print $1}'` 2> /dev/null
/proc/3514/fd/13

Ahí lo tenemos pid 3514 con el fd 13, en mi caso si miro en /proc/3514/cmdline veo que el pid pertenece a firefox.

#cat /proc/3514/cmdline
/usr/lib/firefox-6.0/firefox-bin

Esto es todo por hoy, la próxima semana pondré como hacerlo por C.

Un saludo.

No hay comentarios:

Publicar un comentario