无法移除“Server: Apache”标头

37

我的 HTTP 响应头中有 "Server: Apache",我想要将其移除。

我按照指示进行操作,例如添加下面的内容到 httpd.conf

ServerSignature Off  
ServerTokens Prod
Header unset Server

但是最后一行没有任何效果。前两行已经更改了标题的内容(之前它还包含操作系统和PHP的信息),但我需要将其完全删除。如何做到这一点?


您是否已启用 mod_headers 模块?这是取消标题字段所必需的。 - maxhb
我做了。它已启用并正常工作,但无法删除此标题。 - Audiophile
2
OK。我刚刚用自己的Web服务器进行了测试,发现这一个头字段真的无法工作 :-( - maxhb
尝试使用“Header always unset Server”命令。 - Raj Kumar Samala
前往 https://stackoverflow.com/questions/20803348/how-to-remove-apache-information-completely-from-response-headers/54634628#54634628。 - Washington Souza
请查看我的回答:https://dev59.com/BVsW5IYBdhLWcg3wI0RH#66667833 我已经提到了如何使用源代码进行删除。 - Example person
6个回答

79

Apache不允许您完全取消设置此选项。实际上,尽管多次建议(甚至编写!),其中一些开发人员强烈反对添加它。请参见此处此处的一些讨论。

他们给出了各种原因,包括:

  1. 这可能会使在野外计算Apache安装数量更加困难。我认为这是主要原因。Web服务器使用率竞争激烈,Apache的一些竞争对手(可能以N开头)经常发布它正在赶超Apache的消息,并且大多数扫描将基于HTTP标头,因此我可以理解不愿意让其更容易隐藏的不情愿。

  2. 模糊性安全是一种谎言,并且会给出错误的安全感,因为很容易通过指纹识别服务器来查看它可能是哪种软件,基于它如何响应某些请求。虽然这里有一点真相,但默认情况下将ServerTokens指定为Full绝对是一个安全问题,泄露了过多的信息,不应该在公共网站上显示。

  3. 可能违反了HTTP规范不提供服务器标头。这似乎存在争议,并且仍然无法回答为什么他们不允许您更改为某个随机字符串而不是Apache。

  4. 这使得调试问题变得困难,但您会认为需要调试的任何人都要知道或能够找出确切的版本。

  • 如果代理服务器知道另一端的服务器类型,则“可能”会以不同方式处理请求。在我看来,这是代理服务器的错误之处,而且我怀疑现在已经很少这样做了。

  • 如果人们真的想修改或隐藏此标题,他们可以编辑源代码。说实话,这是一个危险的建议,因为没有编程经验的人这么做可能会导致其他安全问题,尤其是如果他们运行的是非打包版本。

  • 他们甚至在官方文档中加入了以下内容:

    将ServerTokens设置为小于minimal是不推荐的,因为它会使调试互操作问题更加困难。同时要注意,禁用Server: 标题根本无法增强服务器的安全性。 "安全通过混淆"的想法是一种谬论,会导致虚假的安全感。

    在我看来,这种推理是荒谬的。如果这是不允许它的主要原因,那么我不明白他们为什么不改变自己的立场。最坏的情况下,它不会增加任何内容,正如他们所说,它会阻止这个问题不时被提出,但我个人认为你给出的无关信息越少越好,因此希望能够关闭它。

    在这种情况下,您可以选择以下方法:

    1. 将其设置为minimal(因此它将显示“Apache”)- 这可能已经足够了
    2. 编辑源代码- 对于最多疑的人来说是一种过度的做法,并且意味着每个新版本都需要应用相同的更改。
    3. 安装ModSecurity - 它(至少曾经)允许您覆盖(但不能删除)此标题以隐藏服务器软件。可能仅为此安装过度,但是Web应用程序防火墙还有其他好处。
    4. 使用另一个允许您更改此字段的Web服务器代理Apache。
    5. 切换到另一个网络服务器。

    需要注意的是,就点4和点5而言,大多数其他网络服务器也不允许你关闭这个功能,因此这不是Apache特有的问题。例如,Nginx在没有同样编辑源代码的情况下也不允许关闭它。


    5
    隐藏引擎盖下的东西不仅仅是出于安全考虑,还可以隐藏你正在使用的技术,以避免被竞争对手得知。官方文档清楚地说明这一点。公开透明地展示:“揭露Apache有利于我们的利益和收入”,不要让我觉得这是我必须做的事情。 - user2914191
    请查看我的回答:https://dev59.com/BVsW5IYBdhLWcg3wI0RH#66667833 我已经提到了如何使用源代码进行删除。 - Example person

    18

    头部检索

    获取头部信息,如果在服务器上(所有测试都在Ubuntu 14.04 Trusty Tahr上完成),似乎可以适当地使用以下方法:

    curl -v http://localhost:80/ | head
    

    这会产生类似于:

    < HTTP/1.1 200 OK
    < Date: Mon, 25 Jan 2021 09:17:51 GMT
    * Server Apache/2.4.7 (Ubuntu) is not blacklisted
    < Server: Apache/2.4.7 (Ubuntu)
    

    移除版本号

    移除版本号,请编辑文件/etc/apache2/conf-enabled/security.conf并修改以下行:

    • ServerTokens OS改为ServerTokens Prod
    • ServerSignature On改为ServerSignature Off

    然后重新启动Apache:

    sudo service apache2 restart
    

    现在你应该得到类似下面的响应:

    < HTTP/1.1 200 OK
    < Date: Mon, 25 Jan 2021 09:20:03 GMT
    * Server Apache is not blacklisted
    < Server: Apache
    

    移除“Apache”这个词

    要完全移除“Apache”这个词,首先安装ModSecurity

    sudo apt-get install libapache2-mod-security2
    

    以下几行代码看起来好像不需要(启用该模块并重新启动Apache),但供参考

    sudo a2enmod security2
    sudo service apache2 restart
    

    检查模块是否已启用:

    apachectl -M | grep security
    

    应该显示:

    security2_module (shared)
    

    然后,尽管您可以修改/etc/modsecurity/modsecurity.conf(通过将modsecurity.conf-recommended重命名),但最好修改/etc/apache2/apache.conf,这样看起来更容易(请注意,您可以使用任何名称,在此示例中我仅使用了一个空格)
    <IfModule security2_module>
        SecRuleEngine on
        ServerTokens Min
        SecServerSignature " "
    </IfModule> 
    

    使用Min而不是Full还可以防止诸如mod_fastcgi之类的模块出现在空白服务器名称之后。

    然后重新启动Apache:

    sudo service apache2 restart
    

    最终检查

    现在当您运行以下命令时:

    curl -v http://localhost:80/ | head
    

    你应该得到:

    < HTTP/1.1 200 OK
    < Date: Mon, 25 Jan 2021 09:31:11 GMT
    * Server  is not blacklisted
    < Server:
    

    需要注意的是,mod_security2 不带有可行的默认配置,这意味着您必须经过智能更改,使其在您的情况下正常工作。请确保您测试所有内容,因为已知它可能会在意想不到的地方破坏事物 - UncaAlby

    2
    这种方法:
    Header always set "Server" "Generic Web Server"
    

    仅适用于2XX响应。如果您具有带有重定向的重写规则,则会忽略它并返回由ServerTokens选项设置的值。

    最后,我修改了定义产品名称的变量,位于include/ap_release.h中。更简单,可以使用单个sed完成:

    sed 's/AP_SERVER_BASEPRODUCT\ "Apache"/AP_SERVER_BASEPRODUCT\ "Generic Web Server"/' include/ap_release.h
    

    2

    我不对任何可能造成的后果负责!
    请确保您遵循随附的许可文件!

    以下内容适用于Apache版本2.4.46:

    要完全删除Server:头信息:

    1. Download the Apache source from https://httpd.apache.org, extract it, and edit it.

    2. Edit the file httpd-2.4.46/server/core.c, and change the following lines:

      enum server_token_type {
          SrvTk_MAJOR,         /* eg: Apache/2 */
          SrvTk_MINOR,         /* eg. Apache/2.0 */
          SrvTk_MINIMAL,       /* eg: Apache/2.0.41 */
          SrvTk_OS,            /* eg: Apache/2.0.41 (UNIX) */
          SrvTk_FULL,          /* eg: Apache/2.0.41 (UNIX) PHP/4.2.2 FooBar/1.2b */
          SrvTk_PRODUCT_ONLY   /* eg: Apache */
      };
      

      TO:

      enum server_token_type {
          SrvTk_MAJOR,         /* eg: Apache/2 */
          SrvTk_MINOR,         /* eg. Apache/2.0 */
          SrvTk_MINIMAL,       /* eg: Apache/2.0.41 */
          SrvTk_OS,            /* eg: Apache/2.0.41 (UNIX) */
          SrvTk_FULL,          /* eg: Apache/2.0.41 (UNIX) PHP/4.2.2 FooBar/1.2b */
          SrvTk_PRODUCT_ONLY,  /* eg: Apache */
          SrvTk_NONE           /* removes Server: header */
      };
      
    3. Change this other line:

          if (ap_server_tokens == SrvTk_PRODUCT_ONLY) {
              ap_add_version_component(pconf, AP_SERVER_BASEPRODUCT);
          }
          else if (ap_server_tokens == SrvTk_MINIMAL) {
              ap_add_version_component(pconf, AP_SERVER_BASEVERSION);
          }
          else if (ap_server_tokens == SrvTk_MINOR) {
              ap_add_version_component(pconf, AP_SERVER_BASEPRODUCT "/" AP_SERVER_MINORREVISION);
          }
          else if (ap_server_tokens == SrvTk_MAJOR) {
              ap_add_version_component(pconf, AP_SERVER_BASEPRODUCT "/" AP_SERVER_MAJORVERSION);
          }
          else {
              ap_add_version_component(pconf, AP_SERVER_BASEVERSION " (" PLATFORM ")");
          }
      

      TO:

          if (ap_server_tokens == SrvTk_PRODUCT_ONLY) {
              ap_add_version_component(pconf, AP_SERVER_BASEPRODUCT);
          }
          else if (ap_server_tokens == SrvTk_MINIMAL) {
              ap_add_version_component(pconf, AP_SERVER_BASEVERSION);
          }
          else if (ap_server_tokens == SrvTk_MINOR) {
              ap_add_version_component(pconf, AP_SERVER_BASEPRODUCT "/" AP_SERVER_MINORREVISION);
          }
          else if (ap_server_tokens == SrvTk_MAJOR) {
              ap_add_version_component(pconf, AP_SERVER_BASEPRODUCT "/" AP_SERVER_MAJORVERSION);
          }
          else if (ap_server_tokens == SrvTk_NONE) {
              ap_add_version_component(pconf, "");
          }
          else {
              ap_add_version_component(pconf, AP_SERVER_BASEVERSION " (" PLATFORM ")");
          }
      
    4. And change this:

          if (!strcasecmp(arg, "OS")) {
              ap_server_tokens = SrvTk_OS;
          }
          else if (!strcasecmp(arg, "Min") || !strcasecmp(arg, "Minimal")) {
              ap_server_tokens = SrvTk_MINIMAL;
          }
          else if (!strcasecmp(arg, "Major")) {
              ap_server_tokens = SrvTk_MAJOR;
          }
          else if (!strcasecmp(arg, "Minor") ) {
              ap_server_tokens = SrvTk_MINOR;
          }
          else if (!strcasecmp(arg, "Prod") || !strcasecmp(arg, "ProductOnly")) {
              ap_server_tokens = SrvTk_PRODUCT_ONLY;
          }
          else if (!strcasecmp(arg, "Full")) {
              ap_server_tokens = SrvTk_FULL;
          }
          else {
              return "ServerTokens takes 1 argument: 'Prod(uctOnly)', 'Major', 'Minor', 'Min(imal)', 'OS', or 'Full'";
          }
      

      TO:

          if (!strcasecmp(arg, "OS")) {
              ap_server_tokens = SrvTk_OS;
          }
          else if (!strcasecmp(arg, "Min") || !strcasecmp(arg, "Minimal")) {
              ap_server_tokens = SrvTk_MINIMAL;
          }
          else if (!strcasecmp(arg, "Major")) {
              ap_server_tokens = SrvTk_MAJOR;
          }
          else if (!strcasecmp(arg, "Minor") ) {
              ap_server_tokens = SrvTk_MINOR;
          }
          else if (!strcasecmp(arg, "Prod") || !strcasecmp(arg, "ProductOnly")) {
              ap_server_tokens = SrvTk_PRODUCT_ONLY;
          }
          else if (!strcasecmp(arg, "Full")) {
              ap_server_tokens = SrvTk_FULL;
          }
          else if (!strcasecmp(arg, "None")) {
              ap_server_tokens = SrvTk_NONE;
          }
          else {
              return "ServerTokens takes 1 argument: 'Prod(uctOnly)', 'Major', 'Minor', 'Min(imal)', 'OS', 'Full' or 'None'";
          }
      
    5. Compile Apache from the source you have modified. See: http://httpd.apache.org/docs/current/install.html

    6. Set the following in httpd.conf:

      ServerSignature Off
      ServerTokens None
      

    或者:

    1. Download the Apache source from https://httpd.apache.org, extract it, and edit it.
    2. Edit the file httpd-2.4.46/server/core.c, and change the following:
          if (ap_server_tokens == SrvTk_PRODUCT_ONLY) {
              ap_add_version_component(pconf, AP_SERVER_BASEPRODUCT);
          }
          else if (ap_server_tokens == SrvTk_MINIMAL) {
              ap_add_version_component(pconf, AP_SERVER_BASEVERSION);
          }
          else if (ap_server_tokens == SrvTk_MINOR) {
              ap_add_version_component(pconf, AP_SERVER_BASEPRODUCT "/" AP_SERVER_MINORREVISION);
          }
          else if (ap_server_tokens == SrvTk_MAJOR) {
              ap_add_version_component(pconf, AP_SERVER_BASEPRODUCT "/" AP_SERVER_MAJORVERSION);
          }
          else {
              ap_add_version_component(pconf, AP_SERVER_BASEVERSION " (" PLATFORM ")");
          }
      
      TO:
          if (ap_server_tokens == SrvTk_PRODUCT_ONLY) {
              ap_add_version_component(pconf, AP_SERVER_BASEPRODUCT);
          }
          else if (ap_server_tokens == SrvTk_MINIMAL) {
              ap_add_version_component(pconf, AP_SERVER_BASEVERSION);
          }
          else if (ap_server_tokens == SrvTk_MINOR) {
              ap_add_version_component(pconf, AP_SERVER_BASEPRODUCT "/" AP_SERVER_MINORREVISION);
          }
          else if (ap_server_tokens == SrvTk_MAJOR) {
              ap_add_version_component(pconf, AP_SERVER_BASEPRODUCT "/" AP_SERVER_MAJORVERSION);
          }
          else {
              ap_add_version_component(pconf, AP_SERVER_BASEVERSION " (" PLATFORM ")");
          }
          ap_add_version_component(pconf, "");
      
    所以,如果你改变了主意,你可以将ServerTokens设置为Prod或其他内容...然后头部就会回来了。再次改为None,它就消失了 :) 我知道这是一个晚回答,但是它仍然可以帮助很多人!

    我很想尝试一下,但需要找到httpd-2.4.46/server/core.c。我使用的是2.4.48版本,但路径不同:/etc/httpd - 我在哪里可以找到core.c? - infiniteshi
    2
    @infiniteshi,您需要从httpd.apache.org下载源代码,使用上面的答案进行编译并使用它。它无法与常规的apt,yum安装一起使用,我肯定。 - Example person
    喜欢这个答案,但很难看出你在“将<此>更改为<那>”示例中做了哪些更改。在我看来,它们在“统一差异”格式中更易读,即 https://dev59.com/rF4b5IYBdhLWcg3wdxcv#29113646 - egherrmann
    @egherrmann,嗯...让我稍后也加上。 - Example person

    0
    如果您只是需要隐藏有关正在运行的 Web 服务器的信息,则可以尝试在配置文件中添加以下行:
    Header set "Server" "Generic Web Server".
    

    很不幸,“Server”似乎是一个受限制的参数,无法进行编辑:https://serverfault.com/questions/113650/apache-header-set-server-not-working - SharpC

    -3

    你可能还没有启用mod_headers模块。

    请检查是否已启用:

    root@host: a2query -m headers
    

    如果启用了mod headers,输出应该类似于headers(已启用...)
    如果没有启用,请使用以下方式激活模块:
    a2enmod headers
    

    1
    它已启用,我可以通过htaccess添加其他标头,但无法删除此标头。 - Audiophile

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接