单纯靠 Header unset Server 无法真正擦除 Server 响应头,因其由 Apache 核心模块硬编码注入;必须配合 ServerTokens Prod、ServerSignature Off 和 UseCanonicalName On + ServerName 显式声明三项全局配置才生效。

单纯靠 Header unset Server 无法真正擦除 Server 响应头——这是 Apache 的硬编码行为,必须配合全局配置项才能生效。
Server 头不是普通响应头,而是核心模块输出
Apache 在构建响应时,由核心模块(而非 mod_headers)直接写入 Server 字段。即使你在虚拟主机或目录中写:
-
Header unset Server—— 不起作用 -
Header always set Server ""—— 会被忽略或覆盖 -
Header edit Server ".*" ""—— 同样无效
根本原因:它在响应生成链路的更底层注入,mod_headers 的操作发生在其之后,且无权覆盖该字段。
真正有效的三步配置组合
要让 Server 头彻底不出现(或仅显示极简标识),必须同时设置:
FastAPI + Flask 混合部署最佳实践,解决路由定义、API 代理等常见问题,适用于同时运行 FastAPI API 与 Flask 前端的场景。
-
ServerTokens Prod:让 Apache 只输出
Server: Apache,不带版本、模块等信息 - ServerSignature Off:禁用错误页底部的 Server 行(如 404/500 页面)
- UseCanonicalName On + ServerName 显式声明:避免因 Host 头污染导致 Server 字段意外回显(尤其在反向代理场景下)
这三项需放在主配置(httpd.conf 或全局 apache2.conf)中,不能仅置于 <VirtualHost> 内——因为 Server 头生成早于虚拟主机匹配。
mod_proxy 场景下的额外注意事项
如果你用 Apache 做反向代理(ProxyPass / ProxyPassReverse),后端服务(如 Tomcat、Node.js)可能自带 Server 头。此时 Apache 默认会透传该头。要擦除它,才轮到 mod_headers 生效:
- 确保
mod_headers已启用(LoadModule headers_module modules/mod_headers.so) - 在代理配置同级位置添加:
Header always unset Server - 注意作用域:该指令必须放在
<VirtualHost>或<Location>中,且位于ProxyPass之后(顺序影响执行时机)
例如:
<VirtualHost *:80>
ServerName api.example.com
ProxyPass / http://127.0.0.1:3000/
ProxyPassReverse / http://127.0.0.1:3000/
Header always unset Server
</VirtualHost>
验证是否真正擦除成功
别只依赖 curl -I,它可能受缓存或 HTTP/1.1 连接复用干扰:
- 用
curl -I -H "Cache-Control: no-cache" -H "Connection: close" https://yoursite.com/ - 检查多个路径:根路径、静态资源(.js/.css)、动态接口(/api/xxx),因配置作用域不同可能表现不一
- 若前端有 CDN 或 Nginx 前置,Apache 的设置对其无效——必须在 CDN 控制台或 Nginx 的
proxy_hide_header Server中另行处理

















