
Traceur IPC Linux basé sur BPF pour les pipes, signaux, sockets Unix, loopback et pseudo-terminaux avec capture de métadonnées et de contenu, filtrage et sortie JSON.
ipcdump est un outil pour tracer la communication inter-processus (IPC) sous Linux. Il couvre la plupart des mécanismes d'IPC courants — tubes (pipes), FIFOs, signaux, sockets Unix, réseaux basés sur la boucle locale (loopback) et pseudo-terminaux. C'est un outil utile pour le débogage d'applications multi-processus, et c'est aussi un moyen simple de comprendre comment les différentes parties mobiles de votre système communiquent entre elles. ipcdump peut tracer à la fois les métadonnées et le contenu de cette communication, et il est particulièrement adapté pour tracer l'IPC entre des processus de courte durée, ce qui peut être difficile avec les outils de débogage traditionnels, comme strace ou gdb. Il possède également quelques capacités de filtrage de base pour vous aider à trier de grandes quantités d'événements. La plupart des informations collectées par ipcdump proviennent de hooks BPF placés sur des kprobes et des tracepoints au niveau de fonctions clés du noyau, bien qu'il complète également certaines informations comptables à partir du système de fichiers /proc. Pour cela, ipcdump fait un usage intensif de gobpf, qui fournit des bindings Go pour le framework bcc.
| Ubuntu 18.04 LTS | Ubuntu 20.04 LTS | |
|---|---|---|
| 4.15.0 | Testé | Non testé |
| 5.4.0 | Non testé | Testé |
| 5.8.0 | Non testé | Testé* |
*Nécessite la construction de bcc à partir des sources
snap install go --classic
ou directement depuis le site web de golang
git clone https://github.com/guardicore/IPCDump
cd IPCDump/cmd/ipcdump
go build
./ipcdump -h
Usage of ./ipcdump:
-B uint
max number of bytes to dump per event, or 0 for complete event (may be large). meaningful only if -x is specified.
-D value
filter by destination comm (can be specified more than once)
-L do not output lost event information
-P value
filter by comm (either source or destination, can be specified more than once)
-S value
filter by source comm (can be specified more than once)
-c uint
exit after <count> events
-d value
filter by destination pid (can be specified more than once)
-f string
<text|json> output format (default is text) (default "text")
-p value
filter by pid (either source or destination, can be specified more than once)
-s value
filter by source pid (can be specified more than once)
-t value
filter by type (can be specified more than once).
possible values: a|all k|signal u|unix ud|unix-dgram us|unix-stream t|pty lo|loopback lt|loopback-tcp lu|loopback-udp p|pipe
-x dump IPC bytes where relevant (rather than just event details).
Exécuter en tant que root :
# dump all ipc on the system
./ipcdump
# dump signals sent between any two processes
./ipcdump -t kill
# dump loopback TCP connection metadata to or from pid 1337
./ipcdump -t loopback-tcp -p 1337
# dump unix socket IPC metadata and contents from Xorg
./ipcdump -t unix -x -S Xorg
# dump json-formatted pipe i/o metadata and first 64 bytes of contents
./ipcdump -t pipe -x -B 64 -f json
ipcdump est composé d'une série de collecteurs, chacun étant responsable d'un type particulier d'événement IPC. Par exemple, IPC_EVENT_LOOPBACK_SOCK_UDP ou IPC_EVENT_SIGNAL.
En pratique, tous les collecteurs sont construits à l'aide de hooks BPF attachés à des kprobes et des tracepoints. Leurs implémentations sont cependant entièrement séparées — il n'y a pas de raison particulière de supposer que nos informations proviendront toujours de BPF. Cela dit, les différents collecteurs doivent partager un seul module BPF, car ils ont besoin de partager du code commun. Pour cela, nous partageons un seul BpfBuilder (qui est essentiellement un wrapper autour de la concaténation de chaînes de code BCC) et chaque collecteur enregistre son propre code auprès de ce constructeur. Le script BCC complet est ensuite chargé avec gobpf, et chaque module place les hooks dont il a besoin.
Il existe actuellement deux types de comptabilité partagés entre les collecteurs IPC :
SocketIdentifier (internal/collection/sock_id.go) – mappe entre le struct sock* du noyau et les processus qui les utilisent.CommIdentifier (internal/collection/comm_id.go) – mappe entre les numéros de PID et le nom de processus correspondant (/proc/<pid>/comm).
La comptabilité effectuée dans chacun d'eux est particulièrement importante pour les processus de courte durée ; bien que ces informations puissent être remplies ultérieurement en mode utilisateur en analysant /proc, souvent le processus concerné aura disparu au moment où l'événement atteint le gestionnaire. Cela dit, nous remplissons parfois des informations à partir de /proc. Cela se produit principalement pour les processus qui existaient avant l'exécution d'ipcdump ; nous ne capterons pas les événements comme le nommage des processus dans ce cas. SocketIdentifier et CommIdentifier tentent en quelque sorte d'abstraire cette dualité entre le code BCC et l'analyse de /proc derrière une seule API, bien que ce ne soit pas très propre. Soit dit en passant, dans les versions super-récentes de Linux (5.8), les itérateurs BPF peuvent entièrement remplacer cette comptabilité, bien que pour des raisons de rétrocompatibilité, nous devrions probablement rester pour l'instant au paradigme hooks-et-procfs.La sortie des événements se fait via la fonction commune EmitIpcEvent(), qui prend un format d'événement standard (processus source, processus dest, paires clé-valeur de métadonnées, et contenu) et le produit dans un format unifié. Pour économiser la bande passante des événements, les collecteurs n'affichent généralement pas le contenu IPC si le drapeau -x n'est pas spécifié. Cela se fait avec une certaine magie de prétraitement dans internal/collection/ipc_bytes.go.
N'hésitez pas ! Consultez TODO pour les choses vraiment importantes. La majeure partie du travail précoce sur ipcdump consistera probablement à apporter des ajustements pour différentes versions du noyau et différents symboles.