¿Cómo encontrar el otro extremo de la conexión de socket Unix?

44

Tengo un proceso (dbus-daemon) que tiene muchas conexiones abiertas a través de sockets UNIX. Una de estas conexiones es fd # 36:

=$ ps uw -p 23284
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
depesz   23284  0.0  0.0  24680  1772 ?        Ss   15:25   0:00 /bin/dbus-daemon --fork --print-pid 5 --print-address 7 --session

=$ ls -l /proc/23284/fd/36 
lrwx------ 1 depesz depesz 64 2011-03-28 15:32 /proc/23284/fd/36 -> socket:[1013410]

=$ netstat -nxp | grep 1013410
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
unix  3      [ ]         STREAM     CONNECTED     1013410  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD

=$ netstat -nxp | grep dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1013953  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1013825  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1013726  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1013471  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1013410  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1012325  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1012302  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1012289  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1012151  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011957  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011937  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011900  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011775  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011771  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011769  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011766  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011663  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011635  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011627  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011540  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011480  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011349  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011312  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011284  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011250  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011231  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011155  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011061  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011049  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011035  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011013  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1010961  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1010945  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD

Según las conexiones de números, supongo que dbus-daemon es en realidad servidor. Lo cual está bien. Pero, ¿cómo puedo encontrar qué proceso está conectado a él, usando la conexión que es el 36o identificador de archivo en dbus-launcher? Intenté lsof e incluso greps en / proc / net / unix pero no puedo encontrar una manera de encontrar el proceso del cliente.


fuente

Respuestas:

25

Hace poco me topé con un problema similar. Me sorprendió descubrir que hay casos en que esto podría no ser posible. Desenterré un comentario del creador de lsof (Vic Abell) donde señaló que esto depende en gran medida de la implementación del socket Unix. A veces, la información denominada "punto final" para el socket está disponible y otras no. Desafortunadamente, es imposible en Linux como él señala.

En Linux, por ejemplo, donde lsof debe usar / proc / net / unix, todos los sockets de dominio UNIX tienen una ruta enlazada, pero no información de punto final. A menudo no hay un camino limitado. Eso a menudo hace que sea imposible determinar el otro punto final, pero es el resultado de la implementación del sistema de archivos Linux / proc.

Si miras / proc / net / unix puedes ver por ti mismo, que (al menos en mi sistema) él tiene toda la razón. Todavía estoy sorprendido, porque considero que esa característica es esencial al rastrear los problemas del servidor.

Jacek Prucia
fuente
Tenga en cuenta que le /proc/net/unixdirá el archivo de destino de una referencia de socket de dominio aleatorio que ha extraído /proc/.../fd/.
i336_
27

Esta respuesta es solo para Linux. Basado en una respuesta de Unix & Linux Stack Exchange, identifiqué con éxito el otro extremo de un socket de dominio de Unix usando estructuras de datos en el núcleo, accedí usando gdby /proc/kcore. Debe habilitar las opciones CONFIG_DEBUG_INFOy CONFIG_PROC_KCOREkernel.

Puede usar lsofpara obtener la dirección del núcleo del zócalo, que toma la forma de un puntero, por ejemplo 0xffff8803e256d9c0. Ese número es en realidad la dirección de la estructura o tipo de memoria relevante en el núcleo struct unix_sock. Esa estructura tiene un campo llamado peerqué puntos en el otro extremo del zócalo. Entonces los comandos

# gdb /usr/src/linux/vmlinux /proc/kcore
(gdb) p ((struct unix_sock*)0xffff8803e256d9c0)->peer

imprimirá la dirección del otro extremo de la conexión. Puede seleccionar la salida de lsof -Uese número para identificar el proceso y el número de descriptor de archivo de ese otro extremo.

Algunas distribuciones parecen proporcionar símbolos de depuración del núcleo como un paquete separado, que tomaría el lugar del vmlinuxarchivo en el comando anterior.

MvG
fuente
Esto parece interesante, pero el requisito de recompilar el núcleo parece ser una exageración. Estoy pensando que tal vez sería posible hacerlo, sin kernel hecho a mano, y sin usar gdb, simplemente mirando los valores en kcore y haciendo una decodificación de valores "manual".
3
@depesz, todo lo que necesita saber es el desplazamiento del peermiembro en la unix_sockestructura. En mi sistema x86_64, ese desplazamiento es de 656 bytes, por lo que podría obtener ese otro extremo usando p ((void**)0xffff8803e256d9c0)[0x52]. Todavía lo necesitas CONFIG_PROC_KCORE, obviamente.
MvG
12

En realidad, ssfrom iproute2(reemplazo de netstat, ifconfig, etc.) puede mostrar esta información.

Aquí hay un ejemplo que muestra un socket de dominio ssh-agent unix al que sshse ha conectado un proceso:

$ sudo ss -a --unix -p
Netid  State      Recv-Q Send-Q Local                             Address:Port          Peer    Address:Port
u_str  ESTAB      0      0      /tmp/ssh-XxnMh2MdLBxo/agent.27402 651026                *       651642                users:(("ssh-agent",pid=27403,fd=4)
u_str  ESTAB      0      0       *                                651642                *       651026                users:(("ssh",pid=2019,fd=4))
Zulakis
fuente
Hmm Interesante ... Me había perdido que las columnas "Dirección: Puerto" pueden coincidir, a pesar de que la columna "Par" es totalmente inútil para los sockets de dominio Unix.
SamB
9

Los sockets Unix generalmente tienen números asignados en pares, y generalmente son consecutivos. Entonces el par para ti probablemente sería 1013410 +/- 1. Vea cuál de esos dos existe y adivine al culpable.

Devdas
fuente
8

Escribí una herramienta que usa el método gdb de MvG para obtener de manera confiable información de pares de socket, no se necesitan símbolos de depuración del kernel.

Para conectar el proceso a un socket dado, páselo con el número de inodo:

# socket_peer 1013410
3703 thunderbird 

Para descubrir todos los procesos a la vez netstat_unix, agrega una columna a la salida de netstat:

# netstat_unix
Proto RefCnt Flags       Type       State         I-Node   PID/Program name     Peer PID/Program name  Path
unix  3      [ ]         STREAM     CONNECTED     6825     982/Xorg             1497/compiz            /tmp/.X11-unix/X0
unix  3      [ ]         STREAM     CONNECTED     6824     1497/compiz          982/Xorg                 
unix  3      [ ]         SEQPACKET  CONNECTED     207142   3770/chromium-brows  17783/UMA-Session-R       
unix  3      [ ]         STREAM     CONNECTED     204903   1523/pulseaudio      3703/thunderbird       
unix  3      [ ]         STREAM     CONNECTED     204902   3703/thunderbird     1523/pulseaudio           
unix  3      [ ]         STREAM     CONNECTED     204666   1523/pulseaudio      3703/thunderbird       
...

Pruebe netstat_unix --dumpsi necesita una salida que sea fácil de analizar.
Consulte https://github.com/lemonsqueeze/unix_sockets_peers para más detalles.

Para obtener información, el hack inode + 1 / -1 no es confiable. Funciona la mayor parte del tiempo, pero fallará o (peor) devolverá el socket incorrecto si no tiene suerte.

exprimir
fuente
1

Edite su system.conf

En este archivo, puede agregar más cosas para la depuración.

Ubicación del archivo: /etc/dbus-1/system.conf

Para fines de depuración, puede editar su system.conf para permitir escuchas:

  1. reemplace la sección de política por:

    <policy context="default">

    <!-- Allow everything to be sent -->

    <allow send_destination="*" eavesdrop="true"/>

    <!-- Allow everything to be received -->

    <allow eavesdrop="true"/>

    <!-- Allow anyone to own anything -->

    <allow own="*"/>

    <!-- XXX: Allow all users to connect -->

    <allow user="*"/> </policy>

  2. Elimine la línea incluida: system.d

    <includedir>system.d</includedir>

Fuente: http://old.nabble.com/dbus-send-error-td29893862.html


Algunas otras cosas útiles con respecto a los zócalos Unix

La forma más sencilla de descubrir qué sucede en el bus es ejecutar el dbus-monitorprograma, que viene con el paquete D-Bus

También puede intentar usar dbus-cleanup-socketspara limpiar sockets sobrantes.

El siguiente comando le mostrará qué proceso está conectado cuántas veces a los zócalos dbus en función de la netstatsalida:

sudo netstat -nap | grep dbus | grep CONNECTED | awk '{print $8}' | sort | uniq -c

(probado en Ubuntu)

Hardcore: este comando buscará manualmente los procesos de / proc y mostrará cuáles están usando la mayoría de las conexiones (todo tipo de sockets):

ls -lR */fd/* | grep socket | sed -r "s@([0-9{1}]+)/fd/@_\1_@g" | awk -F_ '{print $2}' | uniq -c | sort -n | awk '{print $1" "$2; print system("ps "$2"|tail -n1")}'

Salida de ejemplo:

(cuenta, PID y la siguiente línea contiene detalles sobre el proceso)

25 3732
 3732 ?        Ss     0:38 /usr/bin/wineserver
89 1970
 1970 ?        Ss     0:02 //bin/dbus-daemon --fork --print-pid 5 --print-address 7 --session

(probado en Ubuntu)

Que te diviertas.


Ver también artículos relacionados para la referencia:

kenorb
fuente