September 05, 2012

Usando lsof para localizar aplicaciones y puertos abiertos

«lsof is a command meaning "list open files", which is used in many Unix-like systems to report a list of all open files and the processes that opened them. This open source utility was developed and supported by Vic Abell, the retired Associate Director of the Purdue University Computing Center. It works in and supports several Unix flavors.»
-- from wikipedia [search: lsof]

Overview

Suele suceder que en ocasiones durante las actividades diarias de mantenimiento, nos encontramos con procesos o aplicaciones que levantan puertos y desconocemos dónde esta esa aplicación o qué archivos usa durante su ejecución. Este solo es una alternativa para saber como usar lsof y obtener la información deseada, claro esta que siempre será posible usar otras herramientas como ps, pstree, pidof y top.

Me agradan las soluciones sencillas, es decir; que sea posible implementarlas en HP-UX, GNU/Linux y OS-X, espero darme el tiempo para hacerlo en Solaris y ofrecer un panorama más amplio.

Buscando puertos

En UNiX todo se refiere con un archivo (handler) por lo tanto es posible mediante esta herramienta ubicar que aplicaciones abrieron un puerto determinado, por el socket (handler) que abren en el sistema operativo.

En esta caso usaremos la opción [ -i ], veamos que dice la documentación:
An open file may be a regular file, a directory, a block special  file,  a  character  special
file, an executing text reference, a library, a stream or a network file (Internet socket, NFS
file or UNIX domain socket.)  A specific file or all  the  files  in  a  file  system  may  be
selected by path.

Esta opción requiere como parámetro una dirección de red en el siguiente formato:
[46][protocol][@hostname|hostaddr][:service|port]

Por lo tanto si estamos buscando, por ejemplo que aplicación abrió el puerto 27017 para escucha de nuevos sesiones de red (LISTEN) podemos usar netstat:
Mac 10.13  andresaquino $> lsof -i @localhost:27017 -i @0.0.0.0:27017
COMMAND PID         USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
vpnkit  644 andresaquino   19u  IPv4 0x923eb2cd687c9465      0t0  TCP *:27017 (LISTEN)
vpnkit  644 andresaquino   21u  IPv6 0x923eb2cd52bda93d      0t0  TCP localhost:27017 (LISTEN)


U optar por lsof:
Mac 10.13  andresaquino $> lsof -i 4@0.0.0.0:27017 -P
COMMAND PID         USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
vpnkit  644 andresaquino   19u  IPv4 0x923eb2cd687c9465      0t0  TCP *:27017 (LISTEN)


Es posible realizar combinaciones entre los parámetros para obtener mejores resultados, algo que es importante mencionar es que lsof podrá realizar la búsqueda de estos archivos siempre y cuando se encuentre en el alcance del usuario (al r00t lo que es del r00t).

Buscando aplicaciones

Para buscar las aplicaciones, es mucho más sencillo pero necesitamos saber el PID asociado al proceso que le ejecutó. Se que podrán pensar, bueno si yo sé que proceso lo inicio para que necesito saberlo, bueno pues este tipo de consultas es muy útil para cuando tienes muchos procesos similares, por ejemplo multiples ejecuciones JAVA, multiples HTTPd y que no es tan sencillo ubicar que proceso levanto que puertos.

Para el caso anterior, el proceso que inicie fue un OpenSSHd, uno independiente de aquel que trae el sistema operativo, por lo tanto la búsqueda quedaría de la siguiente manera:
Mac 10.13  andresaquino $> lsof -p 644 | grep '/bin/'
vpnkit  644 andresaquino  txt      REG                1,9   18015040 4299277076 /Applications/Docker.app/Contents/Resources/bin/vpnkit


La opción que usamos fue [ -p ] y como parámetro usamos el ID del proceso, el cual pudimos obtener buscando el socket que dejó abierto en anteriores pantallas, lo interesante es que logramos obtener la ruta completa del comando que se ejecutó [ /opt/local/sbin/sshd ] y este pues, es el objetivo final.

Veamos la documentación:
An Internet address is specified in  the  form    (Items    in  square  brackets  are
optional.):

[46][protocol][@hostname|hostaddr][:service|port]

where:
     46 specifies the IP version, IPv4 or IPv6 that applies to the following address.
      '6' may be be specified only if the UNIX dialect supports IPv6.  If neither '4' nor
      '6' is specified, the following address applies to all IP versions.
     protocol is a protocol name - TCP, UDP hostname is an Internet host name.  Unless a
      specific IP version is specified, open network files associated with host names
      of all versions will be selected.
     hostaddr is a numeric Internet IPv4 address in dot form; or an IPv6 numeric address in
      colon form, enclosed in brackets, if the UNIX dialect supports IPv6.  When an IP
      version is selected, only its numeric addresses may be specified.
     service is an /etc/services name - e.g., smtp - or a list of them.
     port is a port number, or a list of them.

¡Sencillo!

A practicar...

Referencias

The War of the Worlds - Original drawings, 1906

Original drawings from the 1906 edition of H.G. Wells’ “The War of the Worlds”, illustrated by Brazilian artist Henrique Alvim Corrêa pic.tw...