如何从Unix域套接字被动捕获(AF_UNIX套接字监视)?


13

可以使用tcpdump/ 捕获TCP / IP和UDP,dumpcap并生成一个pcap / pcapng文件,该文件可以提供给Wireshark进行进一步分析。命名的Unix域套接字是否存在类似的工具?(不过,适用于抽象套接字的通用解决方案也不错。)

strace仅凭现状是不够的,要过滤Unix域套接字I / O并不容易。一个使用代理socat或类似的也不适宜为目标,是对现有打开的程序被动分析。

如何获得可在Wireshark中用于分析的数据包捕获?示例协议应用程序是X11(Xorg,我当前的应用程序)和cURL / PHP(HTTP)。我CONFIG_UNIX_DIAG在Linux内核中看到了一个选项,这有什么用吗?



@StéphaneChazelas谢谢,但是由于Xorg是从开始的-nolisten tcp,所以没有TCP套接字。如果全部失败,那么我可能会恢复使用xscope或您的巧妙strace + text2pcap技巧。我仍然对通用的Unix套接字捕获感兴趣(仅用于数据,而不用于边通道数据)。
Lekensteyn

除了strace之外,您还可以查看auditd和systemtap。
斯特凡Chazelas

systemtap几乎看起来像是GDB hack,但是在内核级别。不了解审计,我只发现了一个LSM挂钩,用于检查您是否被允许读/写。(我目前正在研究Linux内核源代码)
Lekensteyn 2015年

Answers:


12

从Linux内核v4.2-rc5开始,不可能使用libpcap使用的接口直接捕获。libpcap使用特定于Linux的AF_PACKET(别名PF_PACKET)域,该域仅允许您捕获通过“ netdevice ”(例如以太网接口)传输的数据的数据。

没有用于从AF_UNIX套接字捕获的内核接口。标准以太网捕获具有带有源/目标的以太网头,等等。Unix套接字没有这样的伪头,并且链接层头类型注册表没有列出与此相关的任何内容。

对数据的基本入口点unix_stream_recvmsg,并unix_stream_sendmsgSOCK_STREAMSOCK_DGRAMSOCK_SEQPACKET有类似命名的功能)。数据sk->sk_receive_queueunix_stream_sendmsg函数中和缓冲区中缓冲,没有代码最终导致调用该tpacket_rcv函数进行数据包捕获。有关包捕获内部的一般细节,请参见osgx在SO上的分析。

回到有关AF_UNIX套接字监视的原始问题,如果您主要对应用程序数据感兴趣,则可以选择以下方法:

  • 被动(也适用于已经运行的进程):
    • strace在执行I / O的可能的系统调用上使用和捕获。有很多人,readpread64readvpreadvrecvmsg以及更多...查看@斯特凡Chazelas例如为xterm。这种方法的缺点是,您首先必须找到文件描述符,然后仍然可能错过系统调用。使用strace可以将-e trace=file它们用于大多数(pread仅由覆盖-e trace=desc,但大多数程序可能不用于Unix套接字)。
    • 打破/修改unix_stream_recvmsgunix_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(gitmanual)。

CONFIG_UNIX_DIAG不幸的是,建议的选项在这里也无济于事,它只能用于收集统计信息,而不能获取流经的实时数据(请参阅linux / unix_diag.h)。

不幸的是,对于产生pcap的Unix域套接字,目前还没有完美的跟踪器(据我所知)。理想情况下,将存在一个libpcap格式,该格式的标头包含源/目标PID(如果可用),后跟可选的附加数据(凭证,文件描述符),最后是数据。缺乏这一点,最好的办法就是系统调用跟踪。


其他信息(供感兴趣的读者使用)是一些回溯记录(通过GDB在unix_stream_*和上中断rbreak packet.c:.,在QEMU中的Linux和在主线Linux 4.2-rc5上的socat所获得):

# 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/…并看到了通过netlink监视链接通知的说明,并且想知道诊断程序是否可以提供数据包嗅探,则答案是否定的。这些诊断通过轮询而非实时提供统计信息。
Lekensteyn

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
...
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.