quinta-feira, 26 de julho de 2012

Monitorando um Access Point DD-WRT remotamente com tcpdump, netcat e Wireshark

Há alguns dias venho efetuando uma série de testes em meu access point no sentido de controlar um pouco o tráfego de saída. Eu tenho um AP com o firmware DD-WRT instalado e eu criei uma série de regras usando o "tc", ferramenta do pacote netfilter do kernel linux usada para fazer trafic shaping e gerenciamento de banda. O cenário é o seguinte:

  1. Todo o tráfego de saída por uma interface para um determinado IP não irá bloquear o resto do do tráfego.
  2. Algumas portas e protocolos terão prioridades diferenciadas (SSH, torrent).

No entanto, as regras que eu coloquei vinham falhando frequentemente. Era como se simplesmente não houvesse controle da banda. Foi então que eu pensei em procurar uma forma de monitorar o tráfego passante pelo AP e usar o Wireshark para contabilizar se houve diferença nas velocidades.

Mas, espere aí! Não têm Wireshark para o DD-WRT! Por motivos óbvios ele não caberia nem nos sonhos mais profundos de um psicopata. Claro, tenho o Wireshark instalado na minha máquina virtual em ksa, mas como poderia usá-lo para monitorar uma interface de rede em um dispositivo remoto?


Wireshark, Tcpdump e arquivos PCAP

Googleando um pouco (e fuçando na interface de captura) eu descobri que o Wireshark abre arquivos do tipo PCAP. Esses arquivos nada mais são do que o fluxo de dados de uma interface (ou de todas) salvo em um arquivo, para posterior processamento (eu usei isso no post sobre criptografia de redes sem fio).

Ok, eu ainda tinha um problema. Como gerar esse arquivo PCAP à partir do meu Access Point para carregar depois no Wireshark? Me lembrei na hora do tcpdump. O tcpdump têm uma opção de capturar o stream de uma interface (ou de todas) e salvar em um arquivo. Até aí tudo bem. Fui verificar se o DD-WRT possuía a ferramenta, mas não a encontrei. A solução foi instalar a mesma (a partir do post Installing TCPDump on DD-WRT WRT54GL) e gerar o arquivo.

Mas peraí, eu tenho outro problema! Não há espaço suficiente no AP para armazenar o arquivo! Nessa hora, quase que instantaneamente veio à minha cabeça a idéia de usar o NetCat pra transmitir os dados do tcpdump para o computador.

A solução era simples:

  1. No Computador, executar o netcat em modo servidor e direcionando sua saída em arquivo;
  2. No AP, executar o tcpdump com os parâmetros de captura básicos e enviar sua saída para o netcat rodando em modo cliente, conectado ao servidor no computador;
  3. No Wireshark, carregar o arquivo e quantificar o percentual de pacotes passantes para os protocolos com prioridades especificadas;

Descobrir como enviar o dump para a saída padrão foi fácil, depois de 10 minutos de man eu encontrei a opção -w -, que diz para o tcpdump salvar o fluxo RAW na saída padrão (que estará ligada via pipe com o netcat). No final, o comando inteiro ficou assim:

# tcpdump -i any -s 0 -U -n -w - | nc 172.16.0.117 9999

Explicando:

  1. O parâmetro "-i any" diz para capturar os pacotes de todas as interfaces (mas sem fazer modo promíscuo);
  2. O parâmetro "-s" diz quantos bytes do pacote devem ser salvos (0 indica o pacote inteiro);
  3. O parâmetro "-U" diz para o tcpdump não esperar o buffer de saída encher antes de enviar para o pipe (flush a cada pacote escrito);
  4. O parâmetro "-n" impede que o tcpdump faça a conversão dos endereços ip e de porta para seus nomes;
  5. O parâmetro "-w -" diz que o dump é para ser salvo em um arquivo, no caso, o descritor usado é o da saída padrão.

Até aqui tudo bem. Criei o servidor no Computador, iniciei a captura no AP, mas logo que os pacotes começaram a chegar, notei uma anomalia no tráfego. Haviam MUITOS pacotes vindo do AP em direção ao Computador. Nem precisei pensar muito pra perceber que o próprio processo do NetCat estava gerando seus próprios pacotes de rede, que eram capturados pelo tcpdump, que os enviava pelo netcat, que gerava mais pacotes e ... Você pegou né? Recursão. E essa recursão chegou a um ponto que eu precisei reiniciar o AP pois até mesmo a sessão SSH havia congelado. A solução era simples: excluir a comunicação entre as duas máquinas. Assim, o comando cresceu um pouco:

# tcpdump -i any -s 0 -U -n not host 172.16.0.117 -w - | nc 172.16.0.117 9999

Ok, logo que isso foi feito, o tráfego de pacotes se normalizou mas ... Outra anomalia. O tráfego da sessão SSH e do cliente de Torrent da minha máquina não estavam sendo monitorados. Com um pouco mais de inspeção, percebi que nenhum tráfego estava. Logo, vi que precisaria filtrar melhor esses dados, pois a minha máquina era a máquina de teste. Então, o comando mudou novamente para:

# tcpdump -i any -s 0 -U -n not dst port 9999 and not src port 9999 -w - | nc 172.16.0.117 9999

Com essa regra, somente os pacotes com origem ou destino na porta 9999 serão bloqueados, assim todo o resto do tráfego será capturado.

Configurações Finais

Depois disso, sobra só configurar o Computador. Eu poderia usar um arquivo comum e ficar atualizando no Wireshark que teria o efeito desejado. Mas, é possível fazer isso de forma que o mesmo possa capturar os pacotes de acordo com que eles vão chegando. Para isso, é só criar um arquivo fifo, direcionar a saída do netcat para esse arquivo recém criado e mapear nas opções do Wireshark o path desse arquivo. Esse mapeamento pode ser feito tanto por comando no terminal quanto pelas opções do ambiente gráfico.

Claro que não é nessa ordem que se faz as coisas. Pra funcionar direito, você precisa fazer assim:

Criar o arquivo fifo;

$ rm captura
$ mkfifo captura

Configurar o Wireshark para capturar os pacotes do fifo;

$ wireshark -k -i ./captura &

Criar o servidor netcat e apontar para o arquivo fifo;

$ nc -l -p 9999 > captura

Carregar o tcpdump escrevendo na saída padrão e capturando com o netcat conectado ao servidor criado anteriormente;

# tcpdump -i any -s 0 -U -n not dst port 9999 and not src port 9999 -w - | nc 172.16.0.117 9999

Ser feliz com sua captura remota e começar a analisar o tráfego.

Conclusão.

Essa pode não ser a maneira mais prática de se testar as regras criadas no tc, mas foi a solução mais funcional que encontrei até agora. Ela resolveu uma parte do problema, que foi o de verificar a quantidade de pacotes passantes. Claro que eu não obtive todas as informações que eu precisava mas depois eu descobri a ferramenta iptraf que me dava um relatório bem mais preciso das estatísticas de rede. Agora, só me resta descobrir uma forma de trabalhar com essa estrutura e com o iptraf, já que o iptraf é grande demais para colocar dentro do AP com o DD-WRT.

Fontes:

http://wiki.wireshark.org/CaptureSetup/Pipes
http://blog.notreally.org/2007/01/24/how-to-monitor-packets-from-a-remote-interface/

JNKSNEGVJP8D