Strict-Transport-Security
用法
Strict-Transport-Security 头部是 HTTP 严格传输安全(HSTS)背后的机制。当浏览器通过安全连接收到该头部时,会记录该指令,并自动将所有后续对指定域名的 HTTP 请求升级为 HTTPS。如果安全连接不可用,浏览器会完全拒绝访问,而不会回退到普通 HTTP。
只有通过 HTTPS 传送时,该头部才会被遵循。通过普通 HTTP 提供的、包含 Strict-Transport-Security 的响应会被忽略,因为网络路径上的攻击者能够注入或修改该头部。
该头部接受三个指令:max-age、includeSubDomains 和 preload。
max-age
max-age 指令是必需的。其值指定浏览器记住对该域名强制使用 HTTPS 的秒数。常用的生产值为 63072000(两年)。设置 max-age=0 会立即从浏览器缓存中清除该 HSTS 条目。
includeSubDomains
includeSubDomains 指令将 HTTPS 强制扩展到该主机的每个子域。若没有此指令,HSTS 仅适用于响应中的确切域名。添加 includeSubDomains 可防止攻击者利用一个纯 HTTP 的子域来设置 cookie 或重定向流量。
preload
preload 指令不属于 HSTS 规范。浏览器厂商维护 HSTS 预加载列表,preload 指令表明域名所有者希望被纳入的意图。一旦某个域名出现在预加载列表中,浏览器便会从第一次连接起就强制使用 HTTPS,从而消除在收到第一个 Strict-Transport-Security 头部之前的脆弱窗口。将域名提交到预加载列表要求 max-age 至少为一年(31536000 秒)并带有 includeSubDomains 指令。
示例
一台服务器对所有子域强制使用 HTTPS 两年,并具备预加载资格:
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
一种最小化配置,仅对主域名设置为期六个月的 HSTS:
Strict-Transport-Security: max-age=15768000
通过将 max-age 重置为零来清除 HSTS 条目,在迁移或测试期间很有用:
Strict-Transport-Security: max-age=0
疑难解答
HSTS 问题往往表现为即使在服务器变更之后仍持续存在的连接失败或重定向循环,因为浏览器会在本地缓存该策略。
启用带长 max-age 的 HSTS 后被锁在门外。浏览器一旦记录了 HSTS 策略,所有请求都会自动升级为 HTTPS。在 max-age 过期或用户手动清除 HSTS 条目之前,无法恢复到 HTTP。在 Chrome 中,打开 chrome://net-internals/#hsts,在 “Delete domain security policies” 下输入域名,然后删除该条目。在 Firefox 中,关闭浏览器,编辑配置文件夹中的 SiteSecurityServiceState.txt,并移除相应域名行。
includeSubDomains 导致子域故障。添加 includeSubDomains 会对每个子域强制使用 HTTPS,包括内部工具、预发布服务器和缺乏有效证书的旧服务。在启用此指令之前,请确认每个子域都提供受信任的 TLS 证书。若某个子域出现故障,请移除 includeSubDomains 并以 max-age=0 重新部署该头部以清除已缓存的条目。
预加载列表移除耗时数月。HSTS 预加载列表随浏览器发布一同附带,因此移除需要在 hstspreload.org 提交请求,等待下一次列表更新,再等待该更新通过浏览器版本升级到达用户。此过程需要数月。请将 preload 视为一项长期承诺,并在提交前确认已完全就绪支持 HTTPS。
通过普通 HTTP 发送的 HSTS 头部会被忽略。当响应通过未加密连接到达时,浏览器会丢弃 Strict-Transport-Security 头部。该头部仅在 HTTPS 响应上生效。请通过以下方式确认该头部存在于 HTTPS 响应中:curl -sI https://example.re | grep -i strict。
启用 HSTS 后出现混合内容错误。HSTS 会将页面升级为 HTTPS,但仍引用 http:// URL 的嵌入资源会触发混合内容警告或阻止。请审查所有资源 URL(图像、脚本、样式表、API 端点),并更新引用以使用 https:// 或协议相对路径。CSP 指令 upgrade-insecure-requests 会自动处理剩余的硬编码 HTTP URL。
证书续期失败导致整站被锁。受 HSTS 保护的域名上过期或无效的证书会导致硬失败,用户无法绕过。浏览器会拒绝显示该站点,也不会提供”仍然继续”的选项。请将证书续期自动化(Let’s Encrypt certbot 可通过 cron 作业处理这一点)并监控证书到期日期。请在到期前至少 14 天设置告警。