Nginx生产环境HSTS端到端防护需分层验证:用curl确认443响应头含max-age=31536000; includeSubDomains; preload及always参数;清空浏览器HSTS缓存后测试子域HTTP访问是否被强制拦截;验证404等非2xx响应仍携带HSTS头;确保CDN/WAF透传且所有子域证书有效;preload前须灰度测试并满足hstspreload.org全部硬性条件。

验证生产环境中 Nginx 的 HSTS 是否真正实现端到端强制加密防护,不能只看响应头是否存在,而要分层确认策略是否生效、是否覆盖全链路、是否规避常见失效点。重点在于“浏览器行为是否被强制约束”和“异常路径是否仍受保护”。
检查 HSTS 响应头是否正确下发
用 curl 检查 HTTPS 主站及关键子域名是否返回完整、无覆盖的 HSTS 头:
- 执行
curl -I https://example.com,确认响应中包含:Strict-Transport-Security: max-age=31536000; includeSubDomains; preload - 必须含
always参数——若仅用add_header未加always,则 404 或 500 响应里 HSTS 头会丢失,策略实际中断 - 检查是否被后端应用(如 Spring Boot、Node.js)重复添加或覆盖:对比 Nginx 直接返回头与后端直连返回头,确保 Nginx 是唯一且最终的 HSTS 设置点
验证浏览器端强制跳转与缓存行为
HSTS 的核心价值在客户端强制,需模拟真实用户首次/后续访问场景:
- 清空浏览器 HSTS 缓存(Chrome 地址栏输入
chrome://net-internals/#hsts→ Delete domain → 输入主域名) - 先用 HTTP 访问:
http://example.com,观察是否自动跳转至 HTTPS(注意:该跳转由 80 端口 301 完成,不是 HSTS 的作用) - 再访问
http://sub.example.com(已启用includeSubDomains的子域),若浏览器直接拒绝连接并显示“您的连接不是私密连接”或“此网站无法提供安全连接”,说明 HSTS 已生效并强制拦截 HTTP 请求 - 打开开发者工具 → Application → Clear storage → 勾选 “Cookies and other site data” + “Cached images and files”,再重试,排除缓存干扰
确认全链路覆盖与边界风险
端到端防护意味着所有入口、所有子域、所有状态码路径都受控:
- 逐一测试每个子域名(
api.example.com、auth.example.com、www.example.com)是否均返回相同 HSTS 头,且证书有效(curl -I https://api.example.com不报 SSL 错误) - 触发非 2xx 响应:访问一个不存在的路径(如
/nonexistent),用 curl 查看 404 响应头是否仍含 HSTS——这是always参数的关键验证点 - 检查 CDN 或 WAF 是否透传 HSTS 头:若使用 Cloudflare、阿里云 DDoS 防护等,需确认其未移除或覆盖 Strict-Transport-Security 头
- 查看 Nginx error.log,搜索
ssl_handshake_failed或no suitable certificate,避免因某子域 TLS 握手失败导致整个 HSTS 策略被浏览器标记为不可信
灰度上线与预加载状态追踪
特别是启用 preload 后,策略将固化进浏览器内置列表,不可逆,必须前置验证:
- 上线前用低
max-age(如 300 秒)灰度发布至少 15 分钟,监控前端错误日志、用户反馈、HTTP 访问量骤降情况 - 提交预加载前,访问 hstspreload.org,输入域名检查是否满足全部硬性条件(HTTPS 全覆盖、含
includeSubDomains、max-age ≥ 31536000、所有子域返回 200) - 提交后约 2–8 周进入 Chrome 预加载列表;可通过 Chrome 地址栏访问
chrome://net-internals/#hsts→ Query domain 查看static_upgrade_mode是否为FORCE_HTTPS


















