mod_headers 是删除响应头的首选方式,因其是 Apache 中唯一可靠、可条件化且支持任意响应头(如 X-Powered-By、ETag)的机制;需启用模块,注意作用域、语法规范,并配合 ServerTokens 等指令及 PHP 层清理。

为什么 mod_headers 是删除响应头的首选方式
因为 Apache 默认不提供“移除响应头”的原生指令,Header unset 是唯一可靠、可条件化、且被广泛验证的方式。其他手段(如用 ServerTokens 控制 Server 头)只覆盖极少数字段,而 mod_headers 能精准处理任意响应头,包括 X-Powered-By、X-AspNet-Version、ETag 等常见泄漏项。
必须确认模块已启用:a2enmod headers(Debian/Ubuntu)或检查 LoadModule headers_module 是否在配置中启用。
Header unset 的写法和生效范围要注意什么
该指令仅对响应头(response headers)有效,不能用于请求头;且作用域取决于它所在的配置块——放在 里只影响该站点,放在 或 .htaccess 中则需确保 AllowOverride FileInfo 开启。
常见误写是漏掉引号或大小写混淆(HTTP 头名实际不区分大小写,但 Apache 配置中建议保持惯例写法):
Header unset X-Powered-By Header unset Server Header unset X-AspNet-Version
如果要批量清除多个头,必须逐行写;不能用通配符或正则(Header unset 不支持正则匹配)。
哪些头不能靠 Header unset 完全隐藏
某些头由 Apache 核心或其它模块硬编码注入,Header unset 可能被后续处理覆盖。典型例子:
-
Server:即使写了Header unset Server,若未配合ServerTokens Prod和ServerSignature Off,仍可能在错误页或响应中泄露 -
Date、Content-Length、Connection:属于 HTTP/1.1 强制头,Apache 不允许删除,强行unset会被忽略 -
ETag:虽可用Header unset ETag,但更稳妥的是从源头禁用生成:FileETag None
如何验证响应头是否真的被删掉了
别只信 curl -I,它默认走 HTTP/1.1 且可能受缓存干扰。实操建议:
- 用
curl -I -H "Cache-Control: no-cache" https://yoursite.com/强制绕过中间缓存 - 检查不同路径(根路径、静态文件、PHP 脚本),因为
Header指令的作用域可能不同 - 用浏览器开发者工具的 Network → Response Headers 面板,注意看「Actual response」而非预检或重定向响应
- 如果用了 CDN 或反向代理(如 Nginx 前置),Apache 的
Header unset对其无效,必须在 CDN 或上游代理层再处理
最易被忽略的是:PHP 应用自身可能通过 header() 函数重设已被 unset 的头,比如 Laravel 默认加 X-Powered-By —— 这时得在 PHP 层同步清理,Apache 配置只是第一道防线。










