0

Nginx HSTS max-age设置错误排查:6个常见问题逐一击破

2026.06.01 | youres | 29次围观

HSTS max-age 到底是什么

HSTS(HTTP Strict Transport Security)是网站安全的重要一环,而 max-age 参数则是整个策略的核心——设错了,要么浏览器根本不记,要么记了没法改。本文整理了6个 Nginx HSTS max-age 设置时最常见的错误,逐一给出排查方法和正确配置。

max-age 告诉浏览器:在多少秒内,访问这个域名时必须使用 HTTPS。比如 max-age=31536000 就是一年。这个参数有几个关键点:

  • 单位是秒,不是天
  • 设为 0 会立即让浏览器忘记 HSTS(用于紧急回退)
  • preload 要求 max-age 至少两年(63072000 秒)

错误一:max-age 单位搞错,写成天数

这是最常见的低级错误。Nginx 配置里直接写了天数:

# 错误写法
add_header Strict-Transport-Security "max-age=365; includeSubDomains" always;

# 正确写法
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

365 秒只有6分钟,浏览器几乎不会生效。一年是 31536000 秒,两年是 63072000 秒。

错误二:忘记加 always 参数,404页面安全头丢失

Nginx 的 add_header 有个坑:如果在子层级(比如 location 块)写了 add_header,父层级的 add_header 会被覆盖,导致 404 等错误页面没有 HSTS 头。

解决方法有两个:

  1. 在每条 add_header 后面加 always 参数
  2. 把 HSTS 配置放在 server 块,而不是 location
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

相关阅读:Nginx add_header always参数用法详解:为什么安全头在错误页面消失了

错误三:max-age 先用小值测试,但忘记改大

很多教程建议先用 max-age=60(60秒)测试,确认没问题再改大。但问题是:测试通过后,很多人忘了改回来。

正确做法是用分阶段方案:

  • 第一阶段:max-age=60,测试 1-2 天
  • 第二阶段:max-age=86400(1天),观察 1 周
  • 第三阶段:max-age=31536000(1年),稳定运行
  • preload 前:max-age=63072000(2年)+ preload 指令

相关阅读:Nginx HSTS max-age设置建议:分阶段配置方案与最佳实践

错误四:includeSubDomains 和 max-age 同时配置但逻辑矛盾

有些配置里 max-age 设得很短,但却加了 includeSubDomains; preload,这是矛盾的——preload 要求 max-age 至少两年,短了提交 hstspreload.org 会被拒。

提交 preload 前,响应头必须同时满足:

  • max-age=63072000(至少两年)
  • includeSubDomains
  • preload

错误五:浏览器已经记住旧 max-age,改了配置不生效

HSTS 是浏览器端的机制。一旦浏览器记住了 max-age=31536000,在这 365 天内,即使服务器把 max-age 改小了,浏览器也不会理你。

如果需要紧急回退:

  1. 把 max-age 设为 0
  2. 让用户访问一次 HTTP 版本(或者用 Chrome 的 chrome://net-internals/#hsts 删除)
  3. 等待旧 max-age 自然过期

相关阅读:Nginx HSTS max-age设置为0会怎样:紧急回退的完整操作指南

错误六:多个 server 块重复设置 max-age,值不一致

如果 Nginx 里有多个 server 块(比如一个处理 HTTP、一个处理 HTTPS),两边 HSTS 的 max-age 值不一样,会导致浏览器行为不一致。

正确做法:HSTS 头只应该在 HTTPS 的 server 块里设置,HTTP 块只做 301 跳转,不设置 HSTS。

# HTTP server 块:只跳转,不设置 HSTS
server {
    listen 80;
    server_name example.com;
    return 301 https://$host$request_uri;
}

# HTTPS server 块:设置 HSTS
server {
    listen 443 ssl;
    server_name example.com;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    ...
}

如何验证 max-age 是否生效

用 curl 验证:

curl -I https://www.youres.cn 2>/dev/null | grep -i strict

输出应该包含:

strict-transport-security: max-age=31536000; includeSubDomains

也可以用 Chrome 开发者工具 → Network → 点击页面请求 → Headers → Response Headers 查看。

总结

HSTS max-age 的设置看似简单,但细节很多。核心记住几点:单位是秒、别忘了 always 参数、preload 要求两年、浏览器会缓存旧值。按照分阶段方案慢慢来,比一次性配错再救火要省心得多。

相关阅读:Nginx HSTS配置错误排查:常见原因与解决方法

版权声明

本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论