nginx: despeja solicitações HTTP para depuração

17
  • Ubuntu 10.04.2
  • nginx 0.7.65

Vejo algumas solicitações HTTP estranhas chegando ao meu servidor nginx.

Para entender melhor o que está acontecendo, desejo despejar dados de solicitação HTTP inteiros para essas consultas. (Ou seja, despejo todos os cabeçalhos e corpo da solicitação em algum lugar em que eu possa lê-los.)

Posso fazer isso com o nginx? Como alternativa, existe algum servidor HTTP que me permita fazer isso imediatamente, para o qual posso proxy desses pedidos por meio do nginx?

Atualização: observe que esta caixa tem um monte de tráfego normal e eu gostaria de evitar capturá-lo em nível baixo (digamos, com tcpdump) e filtrá-lo mais tarde.

Eu acho que seria muito mais fácil filtrar o bom tráfego primeiro em uma regra de reescrita (felizmente eu posso escrever um facilmente nesse caso) e depois lidar apenas com o tráfego falso.

E eu não quero canalizar tráfego falso para outra caixa apenas para poder capturá-lo lá tcpdump.

Atualização 2: para fornecer um pouco mais de detalhes, a solicitação falsa tem o parâmetro nomeado (por exemplo) fooem sua consulta GET (o valor do parâmetro pode ser diferente). É garantido que os bons pedidos não tenham esse parâmetro.

Se eu puder filtrar por isso tcpdumpou de ngrepalguma forma - não há problema, vou usá-los.

Alexander Gladysh
fonte
Você pode caracterizar / classificar os pedidos que considera "estranhos"? Como alguém poderia criar uma regra para ajudá-lo se você não compartilha conosco o que é 'normal' e 'falso'?
hobodave
Eu não peço uma regra - posso escrever facilmente. Peço meios para despejar dados de solicitação HTTP.
Alexander Gladysh 13/03/11
@ Hobodave: mas de qualquer maneira, desde que você perguntou, eu adicionei essas informações à pergunta.
Alexander Gladysh 13/03/11

Respostas:

30

Ajuste o número de linhas de pré / pós (-B e -A args) conforme necessário:

tcpdump -n -S -s 0 -A 'tcp dst port 80' | grep -B3 -A10 "GET /url"

Isso permite que você obtenha as solicitações HTTP desejadas, na caixa, sem gerar um arquivo PCAP enorme que você precisa descarregar em outro lugar.

Lembre-se de que o filtro BPF nunca é exato; se houver um grande número de pacotes fluindo por qualquer caixa, o BPF pode e soltará pacotes.

oo.
fonte
5

Não sei exatamente o que você quer dizer com despejar a solicitação, mas você pode usar o tcpdump e / ou o wireshark para analisar os dados:

# tcpdump port 80 -s 0 -w capture.cap

E você pode usar o wireshark para abrir o arquivo e ver a conversa entre os servidores.

coredump
fonte
Obrigado, mas tenho bastante tráfego neste servidor (99% é bom) e acho que seria difícil filtrar esse conjunto de dados para esse falso 1% de que preciso.
Alexander Gladysh 13/03/11
... se eu capturar tudo isso em um nível tão baixo. :-)
Alexander Gladysh 13/03/11
Atualizei a pergunta para refletir isso.
Alexander Gladysh
Alexander - bem, isso significa que 1 em cada 100 solicitações terá os cabeçalhos estranhos que você está procurando. Execute uma captura por um tempo e, em seguida, pesquise no log resultante procurando os cabeçalhos que você deseja - isso certamente não é uma quantidade insuportável de trabalho.
EEAA
O problema não é o trabalho, mas a quantidade de dados a serem processados. (Pode ser suportável embora, mas, de qualquer maneira, eu gostaria de ver uma solução mais amigável.)
Alexander Gladysh
0

Se você proxy as solicitações para o Apache com mod_php instalado, você pode usar o seguinte script PHP para despejar as solicitações:

<?php
$pid = getmypid();
$now = date('M d H:i:s');
$fp = fopen('/tmp/intrusion.log', 'a');

if (!function_exists('getallheaders')) 
{ 
    function getallheaders() 
    { 
           $headers = ''; 
       foreach ($_SERVER as $name => $value) 
       { 
           if (substr($name, 0, 5) == 'HTTP_') 
           { 
               $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value; 
           } 
       } 
       return $headers; 
    } 
} 

function ulog ($str) {
    global $pid, $now, $fp;
    fwrite($fp, "$now $pid {$_SERVER['REMOTE_ADDR']} $str\n");
}

foreach (getallheaders() as $h => $v) {
    ulog("H $h: $v");
}
foreach ($_GET as $h => $v) {
    ulog("G $h: $v");
}
foreach ($_POST as $h => $v) {
    ulog("P $h: $v");
}
fclose($fp);

Observe que, como você está usando o nginx, $_SERVER['REMOTE_ADDR']pode ser inútil. Você precisará passar o IP real para o Apache via proxy_set_header X-Real-IP $remote_addr;e poderá usá-lo (ou apenas confiar no logon getallheaders()).

Hobobave
fonte
Obrigado. Mas eu não tenho PHP nos meus servidores. Ainda assim, a ideia é válida para qualquer outro idioma de programação compatível com http. :-)
Alexander Gladysh 13/03/11