Làm cách nào để chụp thụ động từ ổ cắm tên miền Unix (giám sát ổ cắm AF_UNIX)?


13

Việc chụp TCP / IP và UDP có thể được thực hiện bằng cách sử dụng tcpdump/ dumpcapvà tạo tệp pcap / pcapng có thể được đưa đến Wireshark để phân tích thêm. Có một công cụ tương tự tồn tại cho ổ cắm tên miền Unix được đặt tên? (Một giải pháp chung hoạt động cho các ổ cắm trừu tượng cũng sẽ rất tốt.)

straceas-is là không đủ, nó không đơn giản để lọc cho I / O của socket miền Unix. Một proxy sử dụng socathoặc tương tự cũng không phù hợp vì mục tiêu là phân tích thụ động cho các chương trình mở hiện có.

Làm cách nào tôi có thể có được một gói chụp mà tôi có thể sử dụng trong Wireshark để phân tích? Các ứng dụng giao thức mẫu là X11 (Xorg, ứng dụng hiện tại của tôi) và cURL / PHP (HTTP). Tôi đã thấy một CONFIG_UNIX_DIAGtùy chọn trong nhân Linux, đây có phải là một số sử dụng không?



@ StéphaneChazelas Cảm ơn, nhưng vì Xorg đã được bắt đầu -nolisten tcp, không có ổ cắm TCP. Nếu tất cả đều thất bại, thì tôi có thể sẽ quay trở lại sử dụng xscope hoặc thủ thuật strace + text2pcap gọn gàng của bạn. Tôi vẫn sẽ quan tâm đến việc chụp ổ cắm Unix chung (chỉ cho dữ liệu, không phải dữ liệu kênh bên).
Lekensteyn

Bên cạnh strace, bạn cũng có thể nhìn vào audd và systemtap.
Stéphane Chazelas

systemtap gần giống như hack GDB, nhưng sau đó ở cấp kernel. Không biết về kiểm toán, tôi chỉ tìm thấy một cái móc LSM kiểm tra xem bạn có được phép đọc / ghi không. (Tôi hiện đang đào mã nguồn nhân Linux)
Lekensteyn

Câu trả lời:


12

Kể từ Linux kernel v4.2-rc5, không thể chụp trực tiếp bằng các giao diện được libpcap sử dụng. libpcap sử dụng miền AF_PACKET(bí danh PF_PACKET) dành riêng cho Linux , chỉ cho phép bạn thu thập dữ liệu cho dữ liệu đi qua " netdevice " (chẳng hạn như giao diện Ethernet).

Không có giao diện kernel để chụp từ AF_UNIXsocket. Các bản ghi Ethernet tiêu chuẩn có một tiêu đề Ethernet với nguồn / đích, v.v ... Ổ cắm Unix không có tiêu đề giả như vậy và sổ đăng ký loại tiêu đề lớp liên kết không liệt kê bất cứ điều gì liên quan đến điều này.

Các điểm nhập cơ bản cho dữ liệu là unix_stream_recvmsgunix_stream_sendmsgcho SOCK_STREAM( SOCK_DGRAMSOCK_SEQPACKETcó các chức năng được đặt tên tương tự). Dữ liệu được đệm trong sk->sk_receive_queuevà trong unix_stream_sendmsghàm , không có mã cuối cùng dẫn đến việc gọi tpacket_rcvhàm để chụp gói. Xem phân tích này của osgx trên SO để biết thêm chi tiết về nội bộ của gói chụp nói chung.

Quay lại câu hỏi ban đầu về AF_UNIXgiám sát ổ cắm, nếu bạn chủ yếu quan tâm đến dữ liệu ứng dụng, bạn có một số tùy chọn:

  • Thụ động (cũng hoạt động cho các quy trình đã chạy):
    • Sử dụng stracevà ghi lại các cuộc gọi hệ thống có thể thực hiện I / O. Có rất nhiều trong số họ, read, pread64, readv, preadv, recvmsgvà nhiều hơn nữa ... See @ Stéphane Chazelas ví dụ cho xterm. Nhược điểm của phương pháp này là trước tiên bạn phải tìm mô tả tệp của mình và sau đó vẫn có thể bỏ lỡ các cuộc gọi hệ thống. Với strace bạn có thể sử dụng -e trace=filecho hầu hết trong số chúng ( preadchỉ được bao phủ bởi -e trace=desc, nhưng có lẽ nó không được sử dụng cho ổ cắm Unix bởi hầu hết các chương trình).
    • Phá vỡ / sửa đổi unix_stream_recvmsg, unix_stream_sendmsg(hoặc unix_dgram_*hoặc unix_seqpacket_*) trong kernel và xuất dữ liệu, ở đâu đó. Bạn có thể sử dụng SystemTap để đặt các điểm theo dõi như vậy, đây là một ví dụ để theo dõi các tin nhắn gửi đi. Yêu cầu hỗ trợ kernel và có sẵn các ký hiệu gỡ lỗi .
  • Hoạt động (chỉ hoạt động cho các quy trình mới):

    • Sử dụng proxy cũng ghi tập tin. Bạn có thể tự viết một bộ ghép kênh nhanh hoặc hack một cái gì đó như thế này cũng tạo ra một pcap (hãy cẩn thận với các hạn chế, ví dụ AF_UNIXcó thể vượt qua các mô tả tệp, AF_INETkhông thể):

      # 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
      
    • Sử dụng proxy ứng dụng chuyên dụng. Đối với X11, có xscope ( git , thủ công ).

CONFIG_UNIX_DIAGRất tiếc, tùy chọn được đề xuất cũng không hữu ích ở đây, nó chỉ có thể được sử dụng để thu thập số liệu thống kê, không thu thập dữ liệu thời gian thực khi chúng chảy qua (xem linux / unix_diag.h ).

Thật không may, hiện tại không có bộ theo dõi hoàn hảo nào cho các socket miền Unix sản xuất pcaps (theo hiểu biết tốt nhất của tôi). Lý tưởng nhất là sẽ có một định dạng libpcap có tiêu đề chứa mã nguồn / mệnh đề (khi có sẵn) theo sau là dữ liệu bổ sung tùy chọn (thông tin đăng nhập, mô tả tệp) và cuối cùng là dữ liệu. Thiếu điều đó, điều tốt nhất có thể được thực hiện là truy tìm dấu vết.


Thông tin bổ sung (dành cho người đọc quan tâm), đây là một số backtraces (có được khi phá vỡ GDB unix_stream_*rbreak packet.c:., Linux trong QEMU và socat trên dòng chính 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

Nhân tiện, nếu bạn đã đọc kristrev.github.io/2013/07/26/ và xem hướng dẫn để xem thông báo liên kết qua netlink và tự hỏi liệu chẩn đoán có thể cung cấp gói đánh hơi hay không, câu trả lời vẫn là không . Những chẩn đoán này cung cấp số liệu thống kê thông qua bỏ phiếu, không phải thời gian thực.
Lekensteyn

9

Tôi đã viết một công cụ để nắm bắt và kết xuất lưu lượng ổ cắm tên miền unix. Nó sử dụng bpf/kprobeđể thăm dò chức năng kernel unix_stream_sendmsgvà kết xuất lưu lượng vào không gian người dùng.

Công cụ phụ thuộc vào bcc, vì vậy bạn cần cài đặt bcctrước.

Một ví dụ chạy:

$ 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
...
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.