最可靠方式是在Nginx的HTTPS server块中用add_header Strict-Transport-Security并带always参数;仅限listen 443 ssl配置,需全覆盖验证子域HTTPS、分阶段提升max-age,启用preload前须稳定运行7天。

直接在 Nginx 的 HTTPS server 块中用 add_header Strict-Transport-Security 添加响应头,是最可靠的方式。重点不是加不加,而是加在哪、参数怎么设、后续怎么验证。
只在 HTTPS server 块中配置
HSTS 头必须由加密连接下发,浏览器才接受并缓存。如果误写在监听 80 端口的 HTTP server 块里,浏览器会直接忽略——不仅无效,还可能暴露配置意图。
- 仅在
listen 443 ssl http2;这类已启用 SSL 的 server 块中添加 - 确保该块已正确配置
ssl_certificate和ssl_certificate_key - 不要在 HTTP server 或 location 中重复添加,避免覆盖或遗漏
必须带 always 参数
默认情况下,Nginx 只对 2xx/3xx 响应添加 add_header。但错误页(如 404、502)、重定向(304)、网关超时等场景同样需要传递 HSTS 策略,否则用户可能在异常状态下“掉出”安全通道。
- 正确写法:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; - 没有
always,遇到后端返回 500 或 CDN 返回 304 时,HSTS 头就消失了 - 反向代理场景下,还需确认后端未用相同 header 覆盖——可在日志中检查响应头实际输出
includeSubDomains 启用前要全覆盖验证
开启 includeSubDomains 不是多加几个字,而是把整个子域生态纳入强制 HTTPS 范围。一旦启用,浏览器会拒绝加载任何未配 HTTPS 的子域名(如 blog.example.com),且无提示、不可绕过。
- 逐个执行:
curl -I https://sub.example.com,确认全部返回 200 且证书有效 - 特别注意:CDN 回源域名、监控探针地址、内部测试子域也需支持 HTTPS
- 若暂无法全覆盖,可先去掉
includeSubDomains,仅保护主站,后续再逐步扩展
上线节奏要可控,别一步到位
HSTS 是“单向开关”,尤其启用 preload 后,撤回需数月周期。生产环境切忌首次就设 1 年 + preload。
- 灰度阶段建议:
max-age=300(5 分钟),观察 15 分钟内所有子域访问是否正常 - 确认无混合内容、无证书告警、无跳转循环后,逐步提升为
3600(1 小时)、86400(1 天) - 稳定运行至少 7 天且日志无异常后,再设为
31536000并提交预加载申请











