Comment capturer passivement des sockets de domaine Unix (surveillance de socket AF_UNIX)?

Les captures TCP / IP et UDP peuvent être effectuées en utilisant tcpdump / dumpcap et produisent un file pcap / pcapng qui peut être envoyé à Wireshark pour une parsing plus poussée. Existe-t-il un outil similaire pour les sockets de domaine Unix nommés? (Une solution générale qui fonctionne pour les sockets abstraites serait bien aussi.)

strace tel quel n'est pas suffisant, il n'est pas simple de filterr les inputs / sorties des sockets du domaine Unix. Un proxy utilisant socat ou similaire ne convient pas non plus car l'objective est l'parsing passive pour les programmes ouverts existants.

Comment puis-je get une capture de packages que je peux utiliser dans Wireshark pour l'parsing? Les applications de protocole sont X11 (Xorg, mon application actuelle) et cURL / PHP (HTTP). J'ai vu une option CONFIG_UNIX_DIAG dans le kernel Linux, est-ce utile?

À partir de Linux kernel v4.2-rc5, il est impossible de capturer directement en utilisant les interfaces utilisées par libpcap. libpcap utilise le domaine AF_PACKET spécifique à AF_PACKET (alias PF_PACKET ) qui ne permet de capturer des données que pour datatables passant par un " netdevice " (comme les interfaces Ethernet).

Il n'y a pas d'interface kernel pour la capture depuis les sockets AF_UNIX . Les captures Ethernet standard ont un en-tête Ethernet avec source / destination, etc. Les sockets Unix n'ont pas un tel en-tête faux et le registre des types d'en-têtes de couche binding ne répertorie aucun élément lié à cela.

Les points d'input de base pour datatables sont unix_stream_recvmsg et unix_stream_sendmsg pour SOCK_STREAM ( SOCK_DGRAM et SOCK_SEQPACKET ont des fonctions nommées de la même manière). Les données sont mises en memory tampon dans sk->sk_receive_queue et dans la fonction unix_stream_sendmsg , aucun code n'entraîne finalement l'appel de la fonction tpacket_rcv pour les captures de packages. Voir cette parsing par osgx sur SO pour plus de détails sur les internes de la capture de packages en général.

Retour à la question initiale sur la AF_UNIX socket AF_UNIX , si vous êtes principalement intéressé par datatables de l'application, vous avez quelques options:

  • Passif (fonctionne également pour les process déjà en cours d'exécution):
    • Utilisez strace et capturez sur les appels système possibles qui effectuent des E / S. Il y en a beaucoup, read , pread64 , readv , preadv , recvmsg et bien d'autres … Voir l'exemple de Stéphane Chazelas pour xterm . Le désavantage de cette approche est que vous devez d'abord find votre descripteur de file et que vous ne puissiez pas utiliser les appels système. Avec strace, vous pouvez utiliser -e trace=file pour la plupart d'entre eux ( pread n'est couvert que par -e trace=desc , mais il n'est probablement pas utilisé pour les sockets Unix par la plupart des programmes).
    • Rompre / modifier unix_stream_recvmsg , unix_stream_sendmsg (ou unix_dgram_* ou unix_seqpacket_* ) dans le kernel et sortir datatables, quelque part. Vous pouvez utiliser SystemTap pour définir de tels points de trace, voici un exemple pour surveiller les messages sortants. Nécessite le support du kernel et la disponibilité des symboles de debugging .
  • Actif (ne fonctionne que pour les nouveaux process):

    • Utilisez un proxy qui écrit également des files. Vous pouvez écrire vous-même un multiplexeur rapide ou pirater quelque chose comme celui-ci qui sort aussi un pcap (attention aux limitations, par exemple AF_UNIX peut transmettre les descripteurs de files, AF_INET ne peut pas):

       # 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 
    • Utilisez un proxy d'application dédié. Pour X11, il y a xscope ( git , manuel ).

L'option CONFIG_UNIX_DIAG suggérée n'est malheureusement pas utile ici, elle ne peut être utilisée que pour collecter des statistics, et non pour acquérir des données en time réel (voir linux / unix_diag.h ).

Malheureusement, il n'y a pas de traceurs parfaits pour les sockets de domaine Unix qui produisent des pcaps (à ma connaissance). Idéalement, il y aurait un format libpcap avec un en-tête contenant le PID source / dest (si disponible) suivi de données supplémentaires optionnelles (informations d'identification, descripteurs de file) et enfin datatables. En l'absence de cela, le meilleur moyen de procéder est le traçage syscall.


Des informations complémentaires (pour le lecteur intéressé), voici quelques backtraces (acquis avec GDB en rupture sur unix_stream_* et rbreak packet.c:. , Linux dans QEMU et socat sur 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