Як пасивно захопити з розеток домену Unix (моніторинг сокетів AF_UNIX)?


13

Захоплення TCP / IP і UDP можна зробити за допомогою tcpdump/ dumpcapі створює файл pcap / pcapng, який може бути переданий Wireshark для подальшого аналізу. Чи існує подібний інструмент для названих розеток Unix домену? (Загальне рішення, яке працює для абстрактних розеток, було б непогано.)

straceяк-є недостатньо, фільтрувати вводи / виведення доменних розеток Unix нескладно. Проксі з використанням socatабо так теж не підходить , оскільки метою є пасивним аналіз існуючих відкритих програм.

Як я можу отримати захоплення пакетів, які я можу використовувати в Wireshark для аналізу? Прикладами протокольних програм є X11 (Xorg, моя поточна програма) та cURL / PHP (HTTP). Я бачив CONFIG_UNIX_DIAGваріант у ядрі Linux, це певна користь?



@ StéphaneChazelas Спасибі, але оскільки Xorg був запущений -nolisten tcp, TCP-розетки немає. Якщо все не вдасться, я, ймовірно, повернусь до використання xscope або вашого акуратного трюку + text2pcap хитрість. Мені б все-таки цікаво загальне захоплення сокетів Unix (лише для даних, а не для даних про бічні канали).
— Лекенштейн

Крім страз, ви також можете подивитися на аудит та systemtap.
— Стефан Шазелас

systemtap майже схожий на злом GDB, але тоді на рівні ядра. Не знаю про аудит, я знайшов лише гачок LSM, який перевіряв, чи дозволено вам читати / писати. (Я зараз
— копаюсь у

Відповіді:


12

Як і для Linux ядра v4.2-rc5, неможливо зробити захоплення безпосередньо за допомогою інтерфейсів, які використовує libpcap. libpcap використовує специфічний для Linux AF_PACKET(псевдонім PF_PACKET) домен, який дозволяє збирати дані лише для даних, що проходять через " netdevice " (наприклад, інтерфейси Ethernet).

Немає інтерфейсу ядра для захоплення з AF_UNIXсокетів. У стандартних захопленнях Ethernet є заголовок Ethernet з джерелом / адресою тощо. У сокетів Unix немає такого підробленого заголовка, а реєстр типів заголовків на рівні посилань не містить нічого спільного з цим.

Основними точками введення даних є unix_stream_recvmsgі unix_stream_sendmsgдля SOCK_STREAM( SOCK_DGRAMі SOCK_SEQPACKETмають аналогічно названі функції). Дані буферизовані в sk->sk_receive_queueі у unix_stream_sendmsgфункції , немає коду, який в кінцевому підсумку призводить до виклику tpacket_rcvфункції для захоплення пакетів. Дивіться цей аналіз osgx на SO для отримання детальної інформації про внутрішні програми захоплення пакетів загалом.

Поверніться до початкового питання щодо AF_UNIXмоніторингу сокет, якщо вас в основному цікавлять дані програми, у вас є кілька варіантів:

  • Пасивний (також працює для вже запущених процесів):
    • Використовуйте straceта фіксуйте під час можливих системних дзвінків, які виконують введення-виведення. Є багато з них, read, pread64, readv, preadv, recvmsgі багатьох інших ... Див @ Stéphane Chazelas прикладу для xterm. Недоліком такого підходу є те, що спочатку потрібно знайти дескриптор файлу, а потім все-таки пропустити системні дзвінки. За допомогою strace ви можете використовувати -e trace=fileдля більшості з них ( preadохоплюється лише -e trace=desc, але, мабуть, не використовується для Unix-сокетів більшістю програм).
    • Перерва на / змінити unix_stream_recvmsg, unix_stream_sendmsg(або , unix_dgram_*або unix_seqpacket_*) в ядрі і виведення даних, де - то. Ви можете використовувати SystemTap для встановлення таких точок сліду, ось приклад для моніторингу вихідних повідомлень. Потрібна підтримка ядра та наявність символів налагодження .
  • Активний (працює лише для нових процесів):

    • Використовуйте проксі, який також записує файли. Ви можете написати швидкий мультиплексор або зламати щось подібне, що також виводить pcap (будьте обережні, наприклад, AF_UNIXможуть передавати дескриптори файлів, AF_INETне можна):

      # fake TCP server connects to real Unix socket
      socat TCP-LISTEN:6000,reuseaddr,fork UNIX-CONNECT:some.sock
      # start packet capture on said port
      tcpdump -i lo -f 'tcp port 6000'
      # clients connect to this Unix socket
      socat UNIX-LISTEN:fake.sock,fork TCP-CONNECT:127.0.0.1:6000
      
    • Використовуйте спеціальний проксі-додаток. Для X11 існує xscope ( git , посібник ).

Запропонований CONFIG_UNIX_DIAGваріант, на жаль, також тут не корисний, він може використовуватися лише для збору статистики, а не для отримання даних у режимі реального часу під час їх проходження (див. Linux / unix_diag.h ).

На жаль, на даний момент немає ідеальних прошукачів для розеток домену Unix, які виробляють pcaps (наскільки мені відомо). В ідеалі має бути формат libpcap, який має заголовок, що містить джерело PID джерела / цілі (якщо він є) з додатковими додатковими даними (облікові дані, дескриптори файлів) і, нарешті, дані. Не маючи цього, найкраще, що можна зробити, - це відстеження системного виклику.


Додаткова інформація (для зацікавленого читача), ось декілька зворотних зв'язків (придбаних при розбитті GDB unix_stream_*і rbreak packet.c:., Linux у QEMU та socat на основному Linux 4.2-rc5):

# echo foo | socat - UNIX-LISTEN:/foo &
# echo bar | socat - UNIX-CONNECT:/foo
unix_stream_sendmsg at net/unix/af_unix.c:1638
sock_sendmsg_nosec at net/socket.c:610
sock_sendmsg at net/socket.c:620
sock_write_iter at net/socket.c:819
new_sync_write at fs/read_write.c:478
__vfs_write at fs/read_write.c:491
vfs_write at fs/read_write.c:538
SYSC_write at fs/read_write.c:585
SyS_write at fs/read_write.c:577
entry_SYSCALL_64_fastpath at arch/x86/entry/entry_64.S:186

unix_stream_recvmsg at net/unix/af_unix.c:2210
sock_recvmsg_nosec at net/socket.c:712
sock_recvmsg at net/socket.c:720
sock_read_iter at net/socket.c:797
new_sync_read at fs/read_write.c:422
__vfs_read at fs/read_write.c:434
vfs_read at fs/read_write.c:454
SYSC_read at fs/read_write.c:569
SyS_read at fs/read_write.c:562

# tcpdump -i lo &
# echo foo | socat - TCP-LISTEN:1337 &
# echo bar | socat - TCP-CONNECT:127.0.0.1:1337
tpacket_rcv at net/packet/af_packet.c:1962
dev_queue_xmit_nit at net/core/dev.c:1862
xmit_one at net/core/dev.c:2679
dev_hard_start_xmit at net/core/dev.c:2699
__dev_queue_xmit at net/core/dev.c:3104
dev_queue_xmit_sk at net/core/dev.c:3138
dev_queue_xmit at netdevice.h:2190
neigh_hh_output at include/net/neighbour.h:467
dst_neigh_output at include/net/dst.h:401
ip_finish_output2 at net/ipv4/ip_output.c:210
ip_finish_output at net/ipv4/ip_output.c:284
ip_output at net/ipv4/ip_output.c:356
dst_output_sk at include/net/dst.h:440
ip_local_out_sk at net/ipv4/ip_output.c:119
ip_local_out at include/net/ip.h:119
ip_queue_xmit at net/ipv4/ip_output.c:454
tcp_transmit_skb at net/ipv4/tcp_output.c:1039
tcp_write_xmit at net/ipv4/tcp_output.c:2128
__tcp_push_pending_frames at net/ipv4/tcp_output.c:2303
tcp_push at net/ipv4/tcp.c:689
tcp_sendmsg at net/ipv4/tcp.c:1276
inet_sendmsg at net/ipv4/af_inet.c:733
sock_sendmsg_nosec at net/socket.c:610
sock_sendmsg at net/socket.c:620
sock_write_iter at net/socket.c:819
new_sync_write at fs/read_write.c:478
__vfs_write at fs/read_write.c:491
vfs_write at fs/read_write.c:538
SYSC_write at fs/read_write.c:585
SyS_write at fs/read_write.c:577
entry_SYSCALL_64_fastpath at arch/x86/entry/entry_64.S:186

tpacket_rcv at net/packet/af_packet.c:1962
dev_queue_xmit_nit at net/core/dev.c:1862
xmit_one at net/core/dev.c:2679
dev_hard_start_xmit at net/core/dev.c:2699
__dev_queue_xmit at net/core/dev.c:3104
dev_queue_xmit_sk at net/core/dev.c:3138
dev_queue_xmit at netdevice.h:2190
neigh_hh_output at include/net/neighbour.h:467
dst_neigh_output at include/net/dst.h:401
ip_finish_output2 at net/ipv4/ip_output.c:210
ip_finish_output at net/ipv4/ip_output.c:284
ip_output at net/ipv4/ip_output.c:356
dst_output_sk at include/net/dst.h:440
ip_local_out_sk at net/ipv4/ip_output.c:119
ip_local_out at include/net/ip.h:119
ip_queue_xmit at net/ipv4/ip_output.c:454
tcp_transmit_skb at net/ipv4/tcp_output.c:1039
tcp_send_ack at net/ipv4/tcp_output.c:3375
__tcp_ack_snd_check at net/ipv4/tcp_input.c:4901
tcp_ack_snd_check at net/ipv4/tcp_input.c:4914
tcp_rcv_state_process at net/ipv4/tcp_input.c:5937
tcp_v4_do_rcv at net/ipv4/tcp_ipv4.c:1423
tcp_v4_rcv at net/ipv4/tcp_ipv4.c:1633
ip_local_deliver_finish at net/ipv4/ip_input.c:216
ip_local_deliver at net/ipv4/ip_input.c:256
dst_input at include/net/dst.h:450
ip_rcv_finish at net/ipv4/ip_input.c:367
ip_rcv at net/ipv4/ip_input.c:455
__netif_receive_skb_core at net/core/dev.c:3892
__netif_receive_skb at net/core/dev.c:3927
process_backlog at net/core/dev.c:4504
napi_poll at net/core/dev.c:4743
net_rx_action at net/core/dev.c:4808
__do_softirq at kernel/softirq.c:273
do_softirq_own_stack at arch/x86/entry/entry_64.S:970

До речі, якщо ви прочитали kristrev.github.io/2013/07/26/… і бачили вказівки слідкувати за повідомленнями про підключення по мережі через Інтернет-зв’язок і цікавились, чи може діагностика забезпечити нюхання пакетів, відповідь все ще немає . Ця діагностика забезпечує статистику за допомогою опитування, а не в режимі реального часу.
— Лекенштейн

9

Я написав інструмент для збору та скидання трафіку сокетів Unix домену. Він використовується bpf/kprobeдля зондування функції ядра unix_stream_sendmsgта скидання трафіку в простір користувача.

Інструмент залежить від цього bcc, тому потрібно спочатку встановити bcc.

Приклад запуску:

$ sudo ./sockdump.py /var/run/docker.sock # run "docker ps" in another terminal
>>> docker[3412] len 83
GET /_ping HTTP/1.1
Host: docker
User-Agent: Docker-Client/18.06.1-ce (linux)

>>> dockerd[370] len 215
HTTP/1.1 200 OK
Api-Version: 1.38
Docker-Experimental: false
Ostype: linux
Server: Docker/18.06.1-ce (linux)
Date: Tue, 25 Sep 2018 07:05:03 GMT
Content-Length: 2
Content-Type: text/plain; charset=utf-8

OK
...
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.