如何通过HSTS Preload部署实现域名全站HTTPS强制开启的最佳实践?
- 内容介绍
- 文章标签
- 相关推荐
本文共计861个文字,预计阅读时间需要4分钟。
在HTTPS的server块中添加HSTS头,并提交到浏览器的preload列表(preload list),才能真正实现底层强制HTTPS——这不是依赖服务端跳转,而是浏览器主动拦截所有HTTP请求。这一步必须建立在稳定、全覆盖的HTTPS基础上,否则用户将无法访问。
HTTP 跳转与 HSTS 必须分离配置
80 端口的 server 块只做一件事:用 return 301 https://$host$request_uri; 完成一次性重定向。不要在这里加任何 HSTS 头,也不要把跳转逻辑混进 443 的 server 块里。原因很实际:
- HTTP 响应中发 HSTS 头无效,浏览器直接忽略
- 若把
return写在 HTTPS 的 location 里,可能因匹配顺序或缓存规则被绕过 - 使用
$host而非$http_host,可防 Host 头注入攻击 - 建议配合
underscores_in_headers off;和明确的server_name example.com www.example.com;白名单
HSTS 响应头必须稳定出现在所有 HTTPS 响应中
只在首页或主页面加 HSTS 是不够的。它需要在每次 HTTPS 响应(包括 404、500、304)中都存在,否则策略可能中断。关键配置如下:
- 加
always参数:add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; -
includeSubDomains启用前,确认所有子域(如 api、cdn、blog)均已部署有效证书并可稳定响应 HTTPS -
preload不是开关,是承诺——一旦加入浏览器预加载列表,就无法临时关闭;回退需数月甚至更久 - 首次上线建议先设
max-age=300(5 分钟),验证无误后再逐步延长至 6 个月或 2 年
提交 Preload List 前的硬性检查项
向 hstspreload.org 提交前,必须全部满足:
- 主域名和所有声明的子域名,均能通过 HTTPS 正常访问,且证书有效、未过期、覆盖完整(SAN 匹配)
- 所有 HTTPS 响应头中都包含带
preload的 HSTS,且max-age ≥ 31536000(1 年) - 80 端口已配置 301 跳转,确保首次 HTTP 访问也能抵达 HTTPS
- 用
curl -I https://example.com检查响应头,确认 HSTS 字段存在且格式正确 - 用隐身模式访问
http://example.com,确认跳转路径正确(注意:Chrome 对已预载域名会直接阻断 HTTP 请求,不发包)
CDN 或代理层的协同要点
如果用了 Cloudflare、阿里云 DCDN 或其他 CDN:
- 确保 CDN 没有删除或覆盖源站返回的 HSTS 头;部分平台需在控制台单独开启“HSTS”开关
- CDN 自身的证书必须与源站策略一致,尤其启用
includeSubDomains时,CDN 必须能处理所有子域 HTTPS 请求 - 避免在 CDN 层做“HTTP 强制跳转 HTTPS”,而源站又重复配置——双重跳转易引发循环或状态码异常
- 内部 API 或管理后台若走内网直连,也需同步支持 HTTPS,否则 HSTS 生效后将被浏览器拒绝
本文共计861个文字,预计阅读时间需要4分钟。
在HTTPS的server块中添加HSTS头,并提交到浏览器的preload列表(preload list),才能真正实现底层强制HTTPS——这不是依赖服务端跳转,而是浏览器主动拦截所有HTTP请求。这一步必须建立在稳定、全覆盖的HTTPS基础上,否则用户将无法访问。
HTTP 跳转与 HSTS 必须分离配置
80 端口的 server 块只做一件事:用 return 301 https://$host$request_uri; 完成一次性重定向。不要在这里加任何 HSTS 头,也不要把跳转逻辑混进 443 的 server 块里。原因很实际:
- HTTP 响应中发 HSTS 头无效,浏览器直接忽略
- 若把
return写在 HTTPS 的 location 里,可能因匹配顺序或缓存规则被绕过 - 使用
$host而非$http_host,可防 Host 头注入攻击 - 建议配合
underscores_in_headers off;和明确的server_name example.com www.example.com;白名单
HSTS 响应头必须稳定出现在所有 HTTPS 响应中
只在首页或主页面加 HSTS 是不够的。它需要在每次 HTTPS 响应(包括 404、500、304)中都存在,否则策略可能中断。关键配置如下:
- 加
always参数:add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; -
includeSubDomains启用前,确认所有子域(如 api、cdn、blog)均已部署有效证书并可稳定响应 HTTPS -
preload不是开关,是承诺——一旦加入浏览器预加载列表,就无法临时关闭;回退需数月甚至更久 - 首次上线建议先设
max-age=300(5 分钟),验证无误后再逐步延长至 6 个月或 2 年
提交 Preload List 前的硬性检查项
向 hstspreload.org 提交前,必须全部满足:
- 主域名和所有声明的子域名,均能通过 HTTPS 正常访问,且证书有效、未过期、覆盖完整(SAN 匹配)
- 所有 HTTPS 响应头中都包含带
preload的 HSTS,且max-age ≥ 31536000(1 年) - 80 端口已配置 301 跳转,确保首次 HTTP 访问也能抵达 HTTPS
- 用
curl -I https://example.com检查响应头,确认 HSTS 字段存在且格式正确 - 用隐身模式访问
http://example.com,确认跳转路径正确(注意:Chrome 对已预载域名会直接阻断 HTTP 请求,不发包)
CDN 或代理层的协同要点
如果用了 Cloudflare、阿里云 DCDN 或其他 CDN:
- 确保 CDN 没有删除或覆盖源站返回的 HSTS 头;部分平台需在控制台单独开启“HSTS”开关
- CDN 自身的证书必须与源站策略一致,尤其启用
includeSubDomains时,CDN 必须能处理所有子域 HTTPS 请求 - 避免在 CDN 层做“HTTP 强制跳转 HTTPS”,而源站又重复配置——双重跳转易引发循环或状态码异常
- 内部 API 或管理后台若走内网直连,也需同步支持 HTTPS,否则 HSTS 生效后将被浏览器拒绝

