核心是确认strict-transport-security是否在所有https响应中稳定、完整、无条件出现;需检查add_header是否被location块覆盖、always参数是否缺失、代理链路是否干扰或覆盖hsts头。

排查 Nginx HSTS 头部丢失,核心是确认 Strict-Transport-Security 响应头是否在所有 HTTPS 响应中稳定、完整、无条件出现。所谓“配置项冲突”,主要指 add_header 指令在多层块(http → server → location)中因覆盖机制导致静默失效,而非语法报错。
检查 add_header 是否被 location 块覆盖
Nginx 的 add_header 不继承,同名头仅保留当前生效块中的最后一条定义。常见冲突场景:
- 在
server块写了 HSTS,但某个location /api或location ~ \.php$内没写 —— 请求命中该 location 时,HSTS 头直接消失 - 多个
location块分别写了不同 HSTS 策略(如一个带preload,另一个不带),实际只生效最后一个匹配的 location 中的那条 - 使用了通用 PHP 或静态资源模板,其内部
location配置覆盖了外层 HSTS 设置
验证是否缺失 always 参数
HSTS 必须对所有状态码生效(包括 301、404、500),否则扫描工具或浏览器可能在错误页中收不到该头,误判为未配置:
- 若配置为
add_header Strict-Transport-Security "...";(无always),则 301/404/500 响应中不会携带 HSTS - 正确写法必须含
always:add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; - 特别注意:Nginx Proxy Manager(NPM)等可视化工具生成的配置常默认省略
always,需手动补全
排查代理链路中的干扰项
当 Nginx 作为反向代理时,后端服务或上游中间件可能主动返回 HSTS,与 Nginx 自身配置形成冲突或覆盖:
- 后端(如 Spring Boot、Node.js)自带安全模块,可能默认注入 HSTS,导致策略不一致或 HTTP 响应中意外下发
- 应在对应
location块中显式清除:proxy_hide_header Strict-Transport-Security; - 清除后,再由 Nginx 统一、可控地用
add_header ... always注入,确保策略唯一且符合部署环境(例如测试环境禁用 HSTS) - 注意:CDN、WAF 或 Nginx Proxy Manager 的 SSL 设置页中,也可能存在“禁用 HSTS”或“自定义响应头”开关,需同步检查
快速定位丢失路径的实操方法
不要只测首页,要覆盖典型响应类型:
-
curl -I https://example.com/(根路径,200) -
curl -I https://example.com/index.php(PHP 脚本,可能触发不同 location) -
curl -I https://example.com/404.html(自定义错误页,验证always是否生效) -
curl -I https://example.com/api/v1/status(API 路径,常独立 location) - 对每个响应,执行
grep -i strict,比对是否全部返回且内容一致











