quinta-feira, 2 de agosto de 2007

Tcpdump

Quando falamos em sniffers de rede - programas que colocam uma interface de rede em modo promíscuo, capturam o tráfego e mostram para o usuário em um formato amigável -, certamente devemos lembrar do tcpdump. Este software permite a utilização de filtros para capturar somente aqueles pacotes que estamos buscando dentre os milhares de pacotes que trafegam por uma ou outra interface de rede. Neste post tentarei apresentar um pouco como é trabalhar com um sniffer. Antes de mais nada é necessário saber os argumentos mais comuns e o formato do comando:


Para capturar o tráfego da interface eth0 (-i) e não resolver o reverso dos endereços IP (-n); opção que ajuda bastante na velocidade da captura. Capturar até 1500 bytes dos pacotes (-s) ao invés dos 68 bytes capturados na opção padrão. Capturar somente 1000 pacotes (-c) e gravar em um arquivo (-w) chamado file.cap, utilizamos o exemplo abaixo.

root@server# tcpdump -i eth0 -n -s 1500 -c 1000 -w file.cap
A opção -r deve ser utilizada posteriormente para ler o arquivo file.cap. Ou seja, a sintaxe padrão do tcpdump é:
root@server# tcpdump [ opções ] [ expressão ]

E é na parte de expressões que estou interessado hoje. Estas expressões são definidas por palavras reservadas e operadores lógicos para selecionar um determinado tráfego de rede. As principais palavras reservadas são:

- Tipo: host, net, port, ...
- Protocolo: ether, ip, tcp, udp, arp, rarp, ...
- Direção: src, dst, src and dst, src or dst, ...
- Operadores lógicos: and, or, not.


Podemos então montar um filtro para selecionar os pacotes com origem na rede 10.10.10.0/24 e com destino o servidor 192.168.0.1 na porta 80.
root@server# tcpdump -ni eth0 'src net 10.10.10.0/24 and dst host 192.168.0.1 and dst port 80'

Se estivermos em busca dos pacotes de início de uma conexão: pacotes com a flag SYN marcada no cabeçalho do TCP, então podemos utilizar a seguinte combinação:
root@server# tcpdump -ni eth0 'tcp[13] == 2'
Ou seja, o tcpdump irá selecionar somente os pacotes que tiverem o valor 2 (decimal) no décimo terceiro byte do cabeçalho TCP. Se lembrarmos das lições de redes de computadores, sabemos que o décimo terceiro byte do cabeçalho TCP é o byte reservado para as flags do protocolo e o valor 2 em decimal é a representação de 00000010 em binário. Lembre-se também da ordem das flags no cabeçalho: os dois primeiros bits são reservados e os seguintes são URG, ACK, PSH, RST, SYN e FIN. Ou seja, somente o penúltimo bit possui o valor 1 para os pacotes que carregam somente a flag SYN.

Este processo pode também ser utilizado para o protocolo ICMP, como no exemplo abaixo. Para mais detalhes sobre os tipos e códigos do protocolo ICMP consultar o documento oficial da IANA.
root@server# tcpdump -ni en1 'icmp[icmptype]==8' tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on en1, link-type EN10MB (Ethernet), capture size 96 bytes 23:55:33.232659 IP 192.168.0.x > 200.192.y.x: ICMP echo request, id 52993, seq 0, length 64
As possibilidades de combinação são grandes, já que podemos também utilizar operadores lógicos bit-a-bit para selecionar o tráfego, mas este tipo de filtro vou deixar a cargo do leitor pesquisar. Podemos também utilizar estes filtros para fazer assinaturas de ataques e detectar estes ataques somente com a utilização do tcpdump. Existem dois documentos da SANS que auxiliam na utilização do tcpdump para IPv4 e IPv6. Ou ainda a man page oficial do tcpdump.