
Rastreador de IPC Linux baseado em BPF para pipes, sinais, sockets Unix, loopback e pseudoterminais com captura de metadados e conteúdo, filtragem e saída JSON.
ipcdump é uma ferramenta para rastrear comunicação entre processos (IPC) no Linux. Ela cobre a maioria dos mecanismos comuns de IPC -- pipes, fifos, sinais, sockets unix, rede baseada em loopback e pseudoterminais. É uma ferramenta útil para depurar aplicações multiprocesso, e também é uma maneira simples de entender como as diferentes partes móveis do seu sistema se comunicam entre si. ipcdump pode rastrear tanto os metadados quanto os conteúdos dessa comunicação, e é particularmente adequado para rastrear IPC entre processos de curta duração, o que pode ser difícil usando ferramentas de depuração tradicionais, como strace ou gdb. Também possui algumas capacidades básicas de filtragem para ajudar a examinar grandes quantidades de eventos. A maior parte das informações que o ipcdump coleta vem de hooks BPF colocados em kprobes e tracepoints em funções chave do kernel, embora também preencha alguns registros do sistema de arquivos /proc. Para isso, o ipcdump faz uso intenso de gobpf, que fornece bindings golang para o framework bcc.
| Ubuntu 18.04 LTS | Ubuntu 20.04 LTS | |
|---|---|---|
| 4.15.0 | Testado | Não testado |
| 5.4.0 | Não testado | Testado |
| 5.8.0 | Não testado | Testado* |
*Requer compilar bcc a partir do código fonte
snap install go --classic
ou diretamente do site do 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).
Execute como 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 é construído a partir de uma série de coletores, cada um responsável por um tipo específico de evento IPC. Por exemplo, IPC_EVENT_LOOPBACK_SOCK_UDP ou IPC_EVENT_SIGNAL.
Na prática, todos os coletores são construídos usando hooks BPF anexados a kprobes e tracepoints. Suas implementações são completamente separadas, no entanto – não há razão particular para assumir que nossas informações sempre virão do BPF. Dito isso, os diferentes coletores precisam compartilhar um único módulo BPF, porque há algum código comum que eles precisam compartilhar. Para isso, compartilhamos um único BpfBuilder (que é essencialmente um wrapper em torno da concatenação de strings de código bcc) e cada coletor registra seu próprio código com esse construtor. O script bcc completo é então carregado com gobpf, e cada módulo coloca os hooks de que precisa.
Atualmente, existem dois tipos de contabilidade compartilhados entre os coletores IPC:
SocketIdentifier (internal/collection/sock_id.go) – mapeia entre struct sock* do kernel e os processos que os utilizam.CommIdentifier (internal/collection/comm_id.go) – mapeia entre números de pid e o nome do processo correspondente (/proc/<pid>/comm).A contabilidade feita em cada um deles é particularmente importante para processos de curta duração; embora essa informação possa ser preenchida posteriormente no modo de usuário analisando /proc, muitas vezes o processo relevante já terá desaparecido quando o evento chegar ao manipulador. Dito isso, às vezes preenchemos informações de /proc. Isso acontece principalmente para processos que existiam antes da execução do ipcdump; não capturaremos eventos como nomeação de processos neste caso. SocketIdentifier e CommIdentifier meio que tentam abstrair essa dualidade entre código bcc e análise de /proc por trás de uma única API, embora não seja super limpo. A propósito, em versões supernovas do Linux (5.8), iteradores BPF podem substituir completamente essa contabilidade, embora para compatibilidade retroativa provavelmente devamos manter o paradigma de hooks e procfs por enquanto.
A saída de eventos é feita através da função comum EmitIpcEvent(), que recebe um formato de evento padrão (processo de origem, processo de destino, pares chave-valor de metadados e conteúdo) e o emite em um formato unificado. Para economizar largura de banda de eventos, os coletores normalmente não emitem conteúdo IPC se a flag -x não for especificada. Isso é feito com alguma mágica de pré-processamento sofisticada em internal/collection/ipc_bytes.go.
Por favor, contribua! Confira TODO para as coisas realmente importantes. A maior parte do trabalho inicial no ipcdump provavelmente envolverá fazer ajustes para diferentes versões e símbolos do kernel.