nginx:デバッグのためにHTTPリクエストをダンプします


17
  • Ubuntu 10.04.2
  • nginx 0.7.65

私のnginxサーバーに奇妙なHTTPリクエストが来るのが見えます。

何が起こっているかをよりよく理解するために、そのようなクエリのHTTPリクエストデータ全体をダンプしたいと思います。(つまり、すべての要求ヘッダーと本文をダンプできる場所にダンプします。)

これをnginxでできますか?あるいは、nginxを使用してこれらの要求をプロキシできる、すぐにこれを実行できるHTTPサーバーがありますか?

更新:このボックスには通常のトラフィックがたくさんあることに注意してください。すべてを低レベル(たとえば、tcpdump)でキャプチャし、後でフィルタリングしないようにしたいと思います。

書き換えルールで最初に適切なトラフィックをフィルター処理し(この場合は非常に簡単に作成できます)、偽のトラフィックのみを処理する方がはるかに簡単だと思います。

また、偽のトラフィックを別のボックスに転送して、そこにキャプチャできるようにしたくないだけtcpdumpです。

更新2:もう少し詳しく説明するために、偽のリクエストのfooGETクエリには(たとえば)という名前のパラメーターがあります(パラメーターの値は異なる場合があります)。適切なリクエストは、このパラメーターを持たないことが保証されています。

この方法で、tcpdumpまたはngrep何らかの方法でフィルタリングできる場合は、問題ありません。これらを使用します。


「奇妙な」と考えるリクエストを特徴付けたり分類したりできますか?「普通」と「偽物」を私たちと共有しない場合、どうすればあなたを助けるルールを思い付くことができますか?
-hobodave

私はルールを求めません。自分で簡単に書くことができます。HTTP要求データをダンプする手段を求めます。
アレクサンダーグラディッシュ

@hobodave:とにかく、あなたが尋ねたので、私はこの情報を質問に追加しました。
アレクサンダーグラディシュ

回答:


30

必要に応じて、前後の行数(-Bおよび-A args)を調整します。

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

これにより、他の場所でオフロードする必要がある巨大なPCAPファイルを生成することなく、必要なHTTPリクエストをボックスで取得できます。

BPFフィルターは決して正確ではないことに注意してください。多数のパケットがいずれかのボックスを流れている場合、BPFはパケットをドロップできます。


5

リクエストをダンプすることの意味は正確にはわかりませんが、tcpdumpやwiresharkを使用してデータを分析できます。

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

また、wiresharkを使用してファイルを開き、サーバー間の会話を確認できます。


感謝しますが、このサーバーにはかなりのトラフィックがあり(99%が良好です)、必要な1%の偽のデータを除外するのは難しいと思います。
アレクサンダーグラディッシュ

...そのような低レベルですべてをキャプチャした場合。:
アレクサンダーグラディッシュ

それを反映するために質問を更新しました。
アレクサンダーグラディッシュ

アレクサンダー-それはつまり、100リクエストごとに1つが探している奇妙なヘッダーを持つことを意味します。しばらくキャプチャを実行してから、結果のログを検索して必要なヘッダーを探します。これは確かに耐え難い作業ではありません。
EEAA

問題は作業ではなく、処理するデータの量です。(しかし、耐えられるかもしれませんが、とにかく、私はより友好的な解決策を見たいです。)
アレクサンダーグラディッシュ

0

mod_phpがインストールされたApacheにリクエストをプロキシする場合、次のPHPスクリプトを使用してリクエストをダンプできます。

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

nginxを使用しているため、これは$_SERVER['REMOTE_ADDR']無意味な場合があることに注意してください。実際のIPをを介してApacheに渡す proxy_set_header X-Real-IP $remote_addr;必要があり、代わりにそれを使用できます(または単にを介してログに記録されることに依存しますgetallheaders())。


ありがとうございました。しかし、サーバーにPHPがありません。それでも、このアイデアは他のhttp対応プログラミング言語にも有効です。:
アレクサンダーグラディシュ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.