nginx:转储HTTP请求以进行调试


17
  • Ubuntu 10.04.2
  • nginx 0.7.65

我看到一些奇怪的HTTP请求进入我的Nginx服务器。

为了更好地了解发生了什么,我想为此类查询转储整个HTTP请求数据。(即,将所有请求标头和正文转储到我可以读取的位置。)

我可以用Nginx做到吗?或者,是否有一些HTTP服务器可以让我直接执行此操作,我可以通过nginx代理这些请求?

更新:请注意,此框有一堆正常的流量,我想避免捕获所有低级别的流量(例如使用tcpdump),然后再将其过滤掉。

我认为,首先在重写规则中过滤良好的流量会容易得多(幸运的是,在这种情况下,我可以很轻松地编写一个流量),然后仅处理虚假流量。

而且我不想将虚假的流量引导到另一个盒子以便能够用它捕获它tcpdump

更新2:为提供更多详细信息,伪请求foo在其GET查询中具有名为(例如)的参数(该参数的值可以不同)。保证良好的请求永远不会使用此参数。

如果我可以对此进行过滤tcpdumpngrep以某种方式进行过滤-没问题,我将使用它们。


您可以对您认为“怪异”的请求进行表征/分类吗?如果您不与我们分享什么是“正常”和“虚假”,那么如何提出一条规则来帮助您?
hobodave 2011年

我不要求有规则-我自己可以轻松编写它。我要求提供转储HTTP请求数据的方法。
亚历山大·格拉迪什

@hobodave:但是无论如何,自从你问了之后,我已经将此信息添加到了问题中。
亚历山大·格拉迪什

Answers:


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打开文件并查看服务器之间的对话。


谢谢,但是我在该服务器上有很多流量(99%的流量很好),我认为很难为我需要的那1%的虚假数据过滤掉那堆数据。
亚历山大·格拉迪什

...如果我在如此低的水平上捕获所有这些信息。:-)
Alexander Gladysh 2011年

我更新了问题以反映这一点。
亚历山大·格拉迪什

亚历山大-嗯,这意味着每100个请求中就有1个具有您要查找的怪异标题。运行捕获一段时间,然后在结果日志中搜索所需的标题-这肯定不是一件繁重的工作。
EEAA 2011年

问题不是工作,而是要处理的数据量。(尽管这是可以忍受的,但是无论如何,我希望看到一个更友好的解决方案。)
Alexander Gladysh 2011年

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的编程语言,该想法仍然有效。:-)
Alexander Gladysh 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.