nginx: vidage des requêtes HTTP pour le débogage

17
  • Ubuntu 10.04.2
  • nginx 0.7.65

Je vois des requêtes HTTP étranges arriver sur mon serveur nginx.

Pour mieux comprendre ce qui se passe, je veux vider des données de requête HTTP entières pour de telles requêtes. (C'est-à-dire vider tous les en-têtes de demande et le corps quelque part où je peux les lire.)

Puis-je faire cela avec nginx? Sinon, y a-t-il un serveur HTTP qui me permet de le faire hors de la boîte, sur lequel je peux proxy ces demandes par le biais de nginx?

Mise à jour: Notez que cette boîte a un tas de trafic normal, et je voudrais éviter de tout capturer à bas niveau (disons avec tcpdump) et de le filtrer plus tard.

Je pense qu'il serait beaucoup plus facile de filtrer le bon trafic d'abord dans une règle de réécriture (heureusement, je peux en écrire un assez facilement dans ce cas), puis de traiter uniquement le trafic bidon.

Et je ne veux pas canaliser le trafic bidon vers une autre box juste pour pouvoir le capturer avec tcpdump.

Mise à jour 2: pour donner un peu plus de détails, les fausses requêtes ont un paramètre nommé (par exemple) foodans leur requête GET (la valeur du paramètre peut différer). Les bonnes demandes sont garanties de ne jamais avoir ce paramètre.

Si je peux filtrer par ceci dans tcpdumpou en ngrepquelque sorte - pas de problème, je les utiliserai.

Alexander Gladysh
la source
Pouvez-vous caractériser / classer les demandes que vous jugez "bizarres"? Comment pourrait-on trouver une règle pour vous aider si vous ne partagez pas avec nous ce qui est «normal» et «faux»?
hobodave
Je ne demande pas de règle - je peux l'écrire moi-même facilement. Je demande des moyens pour vider les données de requête HTTP.
Alexander Gladysh
@hobodave: mais de toute façon, puisque vous l'avez demandé, j'ai ajouté ces informations à la question.
Alexander Gladysh

Réponses:

30

Ajustez le nombre de lignes pré / post (arguments -B et -A) selon vos besoins:

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

Cela vous permet d'obtenir les requêtes HTTP que vous souhaitez, sur la boîte, sans générer un énorme fichier PCAP que vous devez décharger ailleurs.

Gardez à l'esprit que le filtre BPF n'est jamais exact.S'il y a un grand nombre de paquets qui transitent par n'importe quelle boîte, BPF peut et va supprimer des paquets.

oo.
la source
5

Je ne sais pas exactement ce que vous entendez par vidage de la demande, mais vous pouvez utiliser tcpdump et / ou Wireshark pour analyser les données:

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

Et vous pouvez utiliser Wireshark pour ouvrir le fichier et voir la conversation entre les serveurs.

coredump
la source
Merci, mais j'ai un peu de trafic sur ce serveur (99% est bon), et je pense qu'il serait difficile de filtrer ce tas de données pour ce faux 1% dont j'ai besoin.
Alexander Gladysh
... si je capture tout cela à un niveau aussi bas. :-)
Alexander Gladysh
J'ai mis à jour la question pour refléter cela.
Alexander Gladysh
Alexander - eh bien, cela signifie qu'une demande sur 100 aura les en-têtes étranges que vous recherchez. Exécutez une capture pendant un certain temps, puis recherchez dans le journal résultant la recherche des en-têtes que vous souhaitez - ce n'est certainement pas une quantité insupportable de travail.
EEAA
Le problème n'est pas le travail, mais la quantité de données à traiter. (Cela peut être supportable cependant, mais, de toute façon, j'aimerais voir une solution plus amicale.)
Alexander Gladysh
0

Si vous proxy les demandes à Apache avec mod_php installé, vous pouvez utiliser le script PHP suivant pour vider les demandes:

<?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);

Notez que puisque vous utilisez nginx, cela $_SERVER['REMOTE_ADDR']peut être inutile. Vous devrez transmettre la véritable IP à Apache via proxy_set_header X-Real-IP $remote_addr;, et vous pouvez l'utiliser à la place (ou simplement compter sur sa connexion via getallheaders()).

Hobodave
la source
Je vous remercie. Mais je n'ai pas PHP sur mes serveurs. L'idée est toujours valable pour tout autre langage de programmation compatible avec http. :-)
Alexander Gladysh