nginx: выводить HTTP-запросы на отладку

17
  • Ubuntu 10.04.2
  • nginx 0.7.65

Я вижу странные HTTP-запросы, поступающие на мой сервер nginx.

Чтобы лучше понять, что происходит, я хочу получить целые данные HTTP-запроса для таких запросов. (Т.е. сбросьте все заголовки запроса и тело, где я смогу их прочитать.)

Могу ли я сделать это с помощью nginx? В качестве альтернативы, есть ли какой-нибудь HTTP-сервер, который позволяет мне делать это «из коробки», на который я могу проксировать эти запросы с помощью nginx?

Обновление: обратите внимание, что в этом блоке есть куча нормального трафика, и я хотел бы избежать захвата всего этого на низком уровне (скажем, с tcpdump) и фильтрации его позже.

Я думаю, что было бы намного проще сначала отфильтровать хороший трафик в правиле перезаписи (к счастью, в этом случае я могу написать его довольно легко), а затем иметь дело только с поддельным трафиком.

И я не хочу перенаправлять фиктивный трафик в другую коробку, чтобы иметь возможность захватить его там tcpdump.

Обновление 2: чтобы дать немного больше подробностей, фиктивный запрос имеет параметр (скажем) fooв своем запросе GET (значение параметра может отличаться). Хорошие запросы гарантированно никогда не будут иметь этот параметр.

Если я могу фильтровать по этому tcpdumpили ngrepкак-то - нет проблем, я буду использовать их.

Александр Гладыш
источник
Можете ли вы охарактеризовать / классифицировать запросы, которые вы считаете "странными"? Как можно придумать правило, которое поможет вам, если вы не поделитесь с нами тем, что является «нормальным» и «поддельным»?
hobodave
Я не прошу правила - я могу легко написать это сам. Я прошу средства для сброса данных HTTP-запроса.
Александр Гладыш
@hobodave: но так или иначе, так как вы спросили, я добавил эту информацию к вопросу.
Александр Гладыш,

Ответы:

30

Отрегулируйте количество строк до / после (аргументы -B и -A):

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

Это позволяет вам получать требуемые HTTP-запросы на коробке без генерации огромного файла PCAP, который вы должны перенести в другое место.

Имейте в виду, что фильтр BPF никогда не бывает точным, если через какой-либо блок проходит большое количество пакетов, BPF может и будет отбрасывать пакеты.

оо.
источник
5

Я не знаю точно, что вы имеете в виду под дампом запроса, но вы можете использовать tcpdump и / или wireshark для анализа данных:

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

И вы можете использовать wireshark, чтобы открыть файл и увидеть диалог между серверами.

CoreDump
источник
Спасибо, но у меня довольно мало трафика на этом сервере (99% это хорошо), и я думаю, что было бы трудно отфильтровать эту кучу данных для этого поддельного 1%, который мне нужен.
Александр Гладыш
... если я поймаю все это на таком низком уровне. :-)
Александр Гладыш
Я обновил вопрос, чтобы отразить это.
Александр Гладыш
Александр - хорошо, это означает, что 1 из каждых 100 запросов будет иметь странные заголовки, которые вы ищете. Запустите перехват на некоторое время, а затем выполните поиск в полученном журнале в поисках нужных заголовков - это, безусловно, не слишком трудоемкая работа.
EEAA
Проблема не в работе, а в количестве данных для обработки. (Хотя это может быть терпимо, но, во всяком случае, я хотел бы увидеть более дружелюбное решение.)
Александр Гладыш
0

Если вы проксируете запросы к Apache с установленным mod_php, вы можете использовать следующий 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()).

hobodave
источник
Спасибо. Но у меня нет PHP на моих серверах. Тем не менее, идея верна для любого другого языка программирования с поддержкой http. :-)
Александр Гладыш