是否可以使用 Apache 记录所有 HTTP 请求标头?

Posted

技术标签:

【中文标题】是否可以使用 Apache 记录所有 HTTP 请求标头?【英文标题】:Is it possible to log all HTTP request headers with Apache? 【发布时间】:2012-04-14 10:32:14 【问题描述】:

如何将apache接收到的HTTP请求头(全部)的内容记录到日志文件中?

目前我的apache合并日志格式配置为:

LogFormat "%h %l %u %t \"%r\" %>s %b \"%Refereri\" \"%User-Agenti\" \"%Cookiei\"" combined

我知道可以这样做:

LogFormat "%h %l %u %t \"%r\" %>s %b \"%Refereri\" \"%User-Agenti\" \"%Cookiei\" \"%heading namei\" \"%heading namei\" \"%heading namei\"" combined

但这不合逻辑,也不可能知道哪些标题。

【问题讨论】:

【参考方案1】:

mod_log_forensic 是您想要的,但默认情况下它可能不包含在您的 Apache 安装中/不可用。

这里是如何使用它。

LoadModule log_forensic_module /usr/lib64/httpd/modules/mod_log_forensic.so 
<IfModule log_forensic_module> 
ForensicLog $APACHE_LOG_DIR/forensic.log
</IfModule> 

注意:您的路径可能会有所不同,例如/usr/lib/apache2/modules/mod_log_forensic.so

【讨论】:

谢谢,这是正确的答案。以下是如何在 httpd.conf 中进行设置。 (呃,cmets 中没有换行符??)LoadModule log_forensic_module /usr/lib64/httpd/modules/mod_log_forensic.so&lt;IfModule log_forensic_module&gt; ForensicLog /var/log/httpd/forensic_log &lt;/IfModule&gt; 现在你可以检查Shellshock 这样的尝试:grep "() " /var/log/httpd/forensic_log 注意,如果你使用a2enmod log_forensic启用模块,你不需要使用LoadModule这一行。 我更喜欢使用LoadModule而不是a2enmod,因为它只能为特定的虚拟主机激活,然后我可以评论该行并重新加载apache,一切恢复正常! 在最新版本的 apache 或根据您的系统,mod 的路径可能是 /usr/lib/apache2/modules/mod_log_forensic.so,保存日志的典型文件夹是 $APACHE_LOG_DIR/forensic.log 感谢 apache 2.4 的链接更新 httpd.apache.org/docs/2.4/mod/mod_log_forensic.html【参考方案2】:

这里是所有 http-headers 的列表:http://en.wikipedia.org/wiki/List_of_HTTP_header_fields

这里是所有 apache-logformats 的列表:http://httpd.apache.org/docs/2.0/mod/mod_log_config.html#formats

正如您正确编写的那样,记录特定标头的代码是 %foobari 其中 foobar 是标头的名称。因此,唯一的解决方案是创建一个特定的格式字符串。当您期望像 x-my-nonstandard-header 这样的非标准标头时,请使用 %x-my-nonstandard-headeri。如果你的服务器要忽略这个非标准头文件,你为什么要把它写到你的日志文件中呢?未知的标头对您的系统绝对没有影响。

【讨论】:

它仍然足够有用,能够记录传递到 apache 机器上的所有 HTTP 标头。我宁愿拥有一个更灵活的系统,也不愿每次引入新标头时都编辑LogFormat 如链接文章中所述,服务器可能包含非标准的、自定义的、特定于应用程序的标头。如果配置 Apache 的人不知道,此解决方案将不会捕获它们。至于“对您的系统没有影响的未知标头”,您知道是否是这种情况。任何数量的 Web 框架都可能会利用您没想到的标头。 @Ehtesh 我第二,在修改标头的负载平衡器后面。我很想看看我得到了什么,比如带有名字的 %i,*。【参考方案3】:

如果您有兴趣查看远程客户端发送到服务器的特定标头,并且您可以使请求运行 CGI 脚本,那么最简单的解决方案是让您的服务器脚本将环境变量转储到文件在某处。

例如从脚本中运行 shell 命令“env > /tmp/headers”

然后,查找以HTTP_开头的环境变量...

你会看到这样的行:

HTTP_ACCEPT=text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
HTTP_ACCEPT_ENCODING=gzip, deflate
HTTP_ACCEPT_LANGUAGE=en-US,en;q=0.5
HTTP_CACHE_CONTROL=max-age=0

每一个都代表一个请求标头。

请注意,标头名称是根据实际请求修改的。例如,“Accept-Language”变成“HTTP_ACCEPT_LANGUAGE”,以此类推。

【讨论】:

太棒了。如此简单明了,它飞到了其他人的视线范围内。 ;)【参考方案4】:

在我的情况下,获取浏览器标题的最简单方法是使用 php.ini。它将标题附加到文件并将它们打印到测试页面。

<?php
$fp = fopen('m:/temp/requests.txt', 'a');
$time = $_SERVER['REQUEST_TIME'];
fwrite($fp, $time + "\n");
echo "$time.<br>";
foreach (getallheaders() as $name => $value) 
    $cur_hd = "$name: $value\n";
    fwrite($fp, $cur_hd);
    echo "$cur_hd.<br>";

fwrite($fp, "***\n");
fclose($fp);
?>

【讨论】:

以上是关于是否可以使用 Apache 记录所有 HTTP 请求标头?的主要内容,如果未能解决你的问题,请参考以下文章

在 Apache CXF 中内置 HTTP 服务器

是否可以使用 Apache HTTPClient 4.2.5 发出 HTTP/2 请求?

如何在apache中打开一个新端口

如何记录 HTTP POST 请求

如何让 Apache 停止记录我的一些网址

更新所有过去 3 天的记录