Как найти другой конец соединения сокета Unix?


44

У меня есть процесс (dbus-daemon), который имеет много открытых соединений через сокеты UNIX. Одним из таких соединений является 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

Исходя из числа соединений, я предполагаю, что dbus-daemon на самом деле является сервером. Что в порядке. Но как я могу найти, какой процесс связан с ним - используя соединение, являющееся 36-м дескриптором файла в dbus-launcher? Пробовал lsof и даже greps на / proc / net / unix, но я не могу найти способ найти клиентский процесс.


Ответы:


25

Совсем недавно я наткнулся на похожую проблему. Я был потрясен, узнав, что есть случаи, когда это может быть невозможно. Я откопал комментарий от создателя lsof (Vic Abell), где он указал, что это сильно зависит от реализации сокетов Unix. Иногда так называемая «конечная точка» информация для сокета доступна, а иногда нет. К сожалению, это невозможно в Linux, как он указывает.

Например, в Linux, где lsof должен использовать / proc / net / unix, у всех сокетов домена UNIX есть связанный путь, но нет информации о конечной точке. Часто нет связанного пути. Это часто делает невозможным определение другой конечной точки, но это результат реализации файловой системы Linux / proc.

Если вы посмотрите на / proc / net / unix, то увидите, что (по крайней мере, в моей системе) он абсолютно прав. Я все еще в шоке, потому что я нахожу такую ​​функцию важной при отслеживании проблем с сервером.



Обратите внимание, что /proc/net/unixБУДЕТ сообщать вам целевой файл о случайной ссылке на сокет домена, из которой вы выкопали /proc/.../fd/.
i336_

27

Этот ответ только для Linux. Основываясь на ответе Unix & Linux Stack Exchange, я успешно определил другой конец сокета домена unix, используя структуры данных в ядре, доступ к которым осуществляется с помощью gdbи /proc/kcore. Вам необходимо включить параметры ядра CONFIG_DEBUG_INFOи CONFIG_PROC_KCORE.

Вы можете использовать lsofдля получения адреса ядра сокета, который принимает форму указателя, например 0xffff8803e256d9c0. Это число на самом деле является адресом соответствующей структуры или типа памяти в ядре struct unix_sock. Эта структура имеет поле с именем, peerкоторое указывает на другой конец сокета. Итак, команды

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

напечатает адрес другого конца соединения. Вы можете получить выходные данные lsof -Uдля этого номера, чтобы определить номер процесса и дескриптора файла этого другого конца.

Некоторые дистрибутивы предоставляют символы отладки ядра в виде отдельного пакета, который заменяет vmlinuxфайл в приведенной выше команде.


Это выглядит интересно, но требование перекомпилировать ядро ​​кажется излишним. Я думаю, что, возможно, было бы возможно сделать это без ядра, сделанного вручную, и без использования gdb, просто посмотрев на значения в kcore и выполнив некоторое «ручное» декодирование значений.

3
@depesz, все, что вам нужно знать, это смещение peerчлена в unix_sockструктуре. В моей системе x86_64 это смещение составляет 656 байт, так что я могу получить другой конец, используя p ((void**)0xffff8803e256d9c0)[0x52]. Вам все еще нужно CONFIG_PROC_KCORE, очевидно.
MvG

12

На самом деле, ssиз iproute2(замена для netstat, ifconfig и т. Д.) Может показать эту информацию.

Вот пример, показывающий сокет домена six-агента unix, к которому подключен sshпроцесс:

$ 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))

Хм. Интересно ... Я упустил возможность сопоставления столбцов "Адрес: порт", даже если столбец "Одноранговый узел" совершенно бесполезен для доменных сокетов Unix.
SamB

9

Unix-сокетам обычно присваиваются номера в парах, и обычно они являются последовательными. Таким образом, пара для вас, вероятно, будет 1013410 +/- 1. Посмотрите, какой из этих двух существует, и догадайтесь на виновника.


8

Я написал инструмент, который использует метод gdb от MvG для надежного получения информации о равноправных объектах сокета, символы отладки ядра не нужны.

Чтобы подключить процесс к данному сокету, передайте ему номер инода:

# socket_peer 1013410
3703 thunderbird 

Чтобы выяснить, все ли процессы используются одновременно netstat_unix, он добавляет столбец к выводу 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       
...

Попробуйте, netstat_unix --dumpесли вам нужен вывод, который легко разобрать.
См. Https://github.com/lemonsqueeze/unix_sockets_peers для деталей.

Для информации взломать inode + 1 / -1 не надежно. Он работает большую часть времени, но потерпит неудачу или (что еще хуже) вернет неправильный сокет, если вам не повезло.


1

Отредактируйте ваш system.conf

В этом файле вы можете добавить больше материала для отладки.

Расположение файла: /etc/dbus-1/system.conf

В целях отладки вы можете отредактировать ваш system.conf, чтобы разрешить подслушивание:

  1. замените раздел политики на:

    <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. Удалите включенную строку: system.d

    <includedir>system.d</includedir>

Источник: http://old.nabble.com/dbus-send-error-td29893862.html


Некоторые другие полезные вещи, касающиеся сокетов Unix

Самый простой способ выяснить, что происходит на шине, - запустить dbus-monitorпрограмму, поставляемую с пакетом D-Bus.

Также вы можете попытаться использовать dbus-cleanup-socketsдля очистки оставшихся сокетов.

Следующая команда покажет вам, сколько раз процесс подключен к сокетам dbus на основе netstatвыходных данных:

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

(проверено на Ubuntu)

Hardcore way: эта команда найдет вручную процессы из / proc и покажет, которые используют больше всего соединений (все типы сокетов):

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")}'

Пример вывода:

(count, PID и следующая строка содержит информацию о процессе)

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

(проверено на Ubuntu)

Повеселись.


Смотрите также соответствующие статьи для справки:

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.