nginx启用hsts需在443端口server块中配置add_header strict-transport-security "max-age=31536000; includesubdomains; preload" always;,并配合80端口301跳转,分阶段测试max-age,谨慎启用includesubdomains与preload。

在 Nginx 中启用 HSTS 并非简单加一行 add_header 就能生效,关键在于配置位置、响应头作用域、状态码兼容性以及安全边界控制。错误配置可能导致 HSTS 不发送、子域失效、预加载失败,甚至引发用户无法访问的严重问题。
必须在 443 端口的 server 块中设置,且带 always 参数
HSTS 头只能通过 HTTPS 响应传递,HTTP 响应中设置完全无效。务必确保:
- 配置写在
listen 443 ssl的server块内,不能放在 80 端口或 location 块里(除非明确覆盖所有响应路径) - 使用
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; -
always是关键:它保证即使返回 404、500、304 等非 200 状态码,HSTS 头仍会被发出;缺省情况下 Nginx 只对 2xx/3xx 响应添加 header
max-age 要分阶段设置,避免误锁用户
HSTS 生效后,浏览器会在本地强制将 HTTP 请求改写为 HTTPS,且不发包——这意味着一旦配置出错,用户可能直接打不开网站。
- 首次上线建议用短周期测试:
max-age=300(5 分钟),验证跳转、证书、子域 HTTPS 全部正常后再逐步延长 - 正式部署推荐
max-age=31536000(1 年),满足 HSTS 预加载列表最低要求(10886400 秒 ≈ 18 周) - 若需临时禁用,设为
max-age=0并持续返回该头至少 max-age 原有时长,浏览器才会清除缓存策略
includeSubDomains 和 preload 需谨慎启用
这两个参数大幅扩大策略影响范围,启用前必须确认基础设施已就绪:
-
includeSubDomains表示api.example.com、cdn.example.com等所有一级子域也必须支持 HTTPS,否则这些子域将彻底不可访问 -
preload意味着申请加入浏览器内置 HSTS 列表(如 Chrome 的 hstspreload.org),提交后不可快速撤回;需确保主站和全部子域长期稳定 HTTPS、无 HTTP 回退路径 - 未满足预加载全部条件(如重定向闭环、全子域 HTTPS、正确 header)时提前加 preload,会导致审核被拒或上线后无法修复
配合安全跳转,堵住首次请求漏洞
HSTS 解决的是“第二次及以后访问”的降级风险,但首次 HTTP 请求仍可能被劫持(如 SSLstrip)。因此必须与 80 端口跳转协同:
- 单独配置一个
listen 80的server块,仅含return 301 https://$host$request_uri; - 禁止使用
rewrite或拼接$http_host,防止 Host 头注入导致跳转到恶意域名 - 若服务含 API 接口,注意 301 会将 POST 改为 GET;对敏感接口可考虑用
error_page 497 =307 https://$host$request_uri;保持方法不变











