Як пасивно захопити з розеток домену 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.