全站HTTPS强制跳转与HSTS Preload预加载列表申请

本文从实际运维角度出发,详细拆解全站HTTPS强制跳转的配置要点,并深入介绍HSTS Preload预加载列表的申请条件、操作步骤与潜在风险。帮助站长一次性到位,避免遗漏关键设置导致安全降级或不可逆问题。

全站HTTPS强制跳转与HSTS Preload预加载列表申请
封面图:ZuCDN · ZuCDN 原创

大多数站点完成HTTPS证书部署后,仍会保留一条HTTP到HTTPS的重定向规则。但这条规则存在一个隐性缺口:用户在第一次访问时,如果中间人拦截了HTTP请求,仍可能被拖入钓鱼页面。HSTS(HTTP Strict Transport Security)就是用来封堵这个窗口的强制安全指令。而HSTS Preload则将这条指令写进浏览器内核,彻底消除初次访问的风险。

本文专注于全站HTTPS强制跳转与HSTS Preload预加载列表申请的完整流程。不讨论证书申请,不罗列商业CDN配置,只关注自建服务器或裸机部署下最务实的做法。

全站HTTPS强制跳转的底层逻辑

为什么简单重定向不够

大部分运维人员会在Nginx或Apache中写一条301规则,将80端口流量转到443。这确实能覆盖绝大多数正常访问,但存在两个问题:

  • 首次请求暴露风险:用户输入example.com,浏览器默认走HTTP。这条请求在到达服务器之前,中间人可以篡改内容,甚至直接返回一个伪造的HTTPS证书错误提示,诱导用户放弃访问。
  • SSL剥离攻击:攻击者利用代理将页面中所有https链接替换为http,使得后续请求全部降级。

301重定向只是“请用户走正门”,但门铃按钮仍在街上。HSTS的作用是告诉浏览器:“这个站点只允许HTTPS,以后你看到它的名字,直接走HTTPS,不要尝试HTTP。”

服务器端强制跳转配置(以Nginx为例)

配置要点:server块中监听80,返回301到HTTPS版本。但要注意保留对证书验证相关路径的放行(如.well-known/acme-challenge)。

server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$server_name$request_uri;
}

Apache中类似:

<VirtualHost *:80>
    ServerName example.com
    Redirect permanent / https://example.com/
</VirtualHost>

不要遗漏www域名与裸域名的统一。如果两者都服务,务必让其中一个作为权威域名,另一个301过去。否则HSTS头会因域名不一致而失效。

HSTS首部:Strict-Transport-Security

在HTTPS响应头中加入Strict-Transport-Security字段,告诉浏览器在指定时间内(max-age)必须通过HTTPS访问。典型值:

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
  • max-age:单位秒,31536000即一年。建议至少半年。
  • includeSubDomains:是否覆盖所有子域名。如果启用,务必确保所有子域名均支持HTTPS,否则子域将无法访问。
  • preload:告诉浏览器“我准备申请预加载列表”,但该标记单独存在并不会自动加入列表,需要后续手动提交。

配置方法(Nginx):在443的server块中加入:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

验证方式:curl -I https://yourdomain.com | grep Strict

此时浏览器收到该头部后,会在本地缓存该策略。即使用户手动输入http,浏览器也会自动转为https。

HSTS Preload预加载列表是什么

缓存策略有一个盲区:第一次访问前,浏览器没有该站点的HSTS信息。Preload列表将域名硬编码进浏览器(Chrome/Firefox/Safari/Edge等),即使从未访问过,浏览器也默认只使用HTTPS。

这个列表由Chromium项目维护,每年更新几次。一旦域名成功加入,所有主流浏览器都会识别,新的访问请求从第一毫秒起就是HTTPS。

申请HSTS Preload的硬性条件

在提交前,必须逐条确认。任何一条不满足都会被拒绝,且提交后整改周期较长。

  • 证书有效且链完整:不能有证书错误、过期、主机名不匹配。
  • 所有子域名必须支持HTTPS:包括www、m、api等。如果某些子域只允许HTTP(比如开发环境),请关闭includeSubDomains。
  • 根域名与www域名均需重定向到HTTPS:且重定向目标不能有HTTP。
  • HSTS头部必须包含includeSubDomains和preload标记
  • max-age不小于10886400秒(18周),建议31536000。
  • 检查是否有SSL/TLS漏洞:如RC4、TLS 1.0、弱密钥等会被拒绝。
  • 所有重定向链必须全部走HTTPS:例如从 http://example.com -> https://example.com -> https://www.example.com,每一步都必须是HTTPS。

推荐使用官方检查工具预检。输入域名后,工具会列出所有未满足项。

申请步骤详解

第一步:确认域名所有权

在提交前,你需要在服务器上放置验证文件或使用DNS TXT记录证明你有权操作该域名。这是进入官方列表前的必要环节。

第二步:正式提交

访问hstspreload.org,点击“Submit your site”。输入域名,系统会再次检查。如果全部通过,会引导你完成验证。验证成功后,你的域名会进入待审核队列。

审核时间不定:以前是两周到两个月,近期由于审查收紧,有时需要三个月以上。审核期间不要修改HSTS配置,保持在线。

第三步:等待加入列表

你可以通过提交时留下的邮箱接收通知。也可以在hstspreload.org搜索域名查看状态。一旦显示“Preloaded”,恭喜你,域名已经被硬编码进浏览器。

风险与回滚:加入Preload前必须想清楚

最大的风险是:一旦加入Preload,你几乎无法撤销。因为浏览器更新周期长,即使你从列表中移除,用户设备上的预加载数据要到下次浏览器版本更新才会刷新。这意味着:

  • 如果某天你的HTTPS证书失效,所有浏览器会直接拒绝访问,不再重试HTTP。
  • 如果你需要临时关闭HTTPS做维护,用户端会报错且无法降级。
  • 如果你要切换子域名结构,旧的includeSubDomains策略会锁死所有子域。

回滚方法:

  1. 从hstspreload.org申请移除(通过网站上的“Remove”功能)。
  2. 移除HSTS头部中的preload标记,并将max-age改为0,强制浏览器清除缓存:Strict-Transport-Security: max-age=0
  3. 等待至少一个浏览器版本周期(通常6-12周)才能完全恢复HTTP访问。

务必先在不重要的测试域名上演练。生产环境强烈建议在确认所有子域、CDN、API都稳定HTTPS后再提交。

常见踩坑点与解决方案

  • www与裸域不一致:很多人只给裸域跳转,但HSTS配置在www域上,导致www域访问正常但裸域HSTS头缺失。解决方案:统一处理,让两者都返回相同的HSTS头部。
  • includeSubDomains过多:如果你有无法启用HTTPS的测试子域(如dev.example.com),则不能使用includeSubDomains,除非先让这些子域也支持HTTPS。可以考虑分开域名或使用通配符证书。
  • CDN中转导致HSTS头丢失:如果使用了Cloudflare、CloudFront等CDN,需要在CDN层面添加HSTS头部,而非仅在源服务器。CDN可能会覆盖或删除源站的头。
  • 重定向链中出现HTTP中间跳:比如 http://example.com -> http://www.example.com -> https://www.example.com,中间出现了HTTP。必须调整为全部HTTPS跳转。

总结

全站HTTPS强制跳转是基础,HSTS是加固,而Preload是终极方案。它们组合使用能彻底阻挡HTTP劫持与SSL剥离。但Preload的不可回滚特性要求站长在申请前做足功课。如果你正在运营一个面向用户的网站,且所有子域都已稳定HTTPS,那么申请Preload是值得的。否则,先用max-age较长的HSTS策略观察一段时间再说。

最后一条建议:不要为了追求“绿色锁”而盲目提交Preload。安全是逐步迭代的过程,比“一步到位”更重要的,是“可持续维护”。

延伸阅读