先说结论:这不是浏览器故障,而是安全策略与客户端能力不匹配。优先恢复访问,但严禁为兼容旧浏览器而降低 TLS 安全标准。
- 紧急恢复:临时注释 HSTS 配置或缩短 max-age,重载 Nginx。
- 安全底线:生产环境严禁开启 TLSv1.0/1.1,旧浏览器应升级而非服务器降级。
- 特殊场景:若域名在 HSTS 预加载列表,需官方申请移除,仅改配置无效。
- 验证必要:修改后务必清除浏览器本地 HSTS 缓存再测试。
核心原因分析
HSTS(HTTP Strict Transport Security)强制浏览器通过 HTTPS 连接,且忽略证书错误。旧浏览器无法访问通常由以下两个原因叠加导致:
- 本地策略缓存:浏览器曾接收过 HSTS 头部,在 max-age 有效期内强制跳转 HTTPS,即使服务端已移除配置,本地缓存仍生效。
- TLS 握手失败:旧浏览器可能不支持 TLS 1.2 及以上版本。若服务端仅启用高版本 TLS,握手直接中断,且因 HSTS 策略用户无法点击“继续访问”。
紧急恢复步骤
第一步:备份当前配置
修改前务必备份,防止配置错误导致服务不可用。
cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
cp /etc/nginx/conf.d/your_site.conf /etc/nginx/conf.d/your_site.conf.bak第二步:调整 HSTS 配置
临时注释掉 HSTS 头部,或大幅缩短有效期以便策略快速过期。
server {
listen 443 ssl;
server_name example.com;
# 方案 A:临时关闭(推荐用于紧急恢复)
# add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# 方案 B:缩短有效期为 1 天(单位秒),便于后续重新启用
# add_header Strict-Transport-Security "max-age=86400" always;
}第三步:检查 TLS 协议版本(安全红线)
生产环境必须禁用 TLSv1.0 和 TLSv1.1,这两种协议存在 POODLE、BEAST 等高危漏洞。旧浏览器无法访问的根本解决方案是升级客户端,而非服务器降级。
# 安全配置:仅启用 TLSv1.2 和 TLSv1.3
ssl_protocols TLSv1.2 TLSv1.3;
# 配套加密套件建议
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
ssl_prefer_server_ciphers off;第四步:重载服务
测试配置语法无误后重载。
nginx -t && nginx -s reload特殊场景处理
1. 域名在 HSTS 预加载列表(Preload List)
如果域名曾提交到 Chrome 等浏览器的 HSTS 预加载列表,即使服务端移除头部,浏览器也会强制 HTTPS。这种情况无法通过 Nginx 配置撤销。
解决方法:
- 访问 hstspreload.org 查询域名状态。
- 若显示 "Pending Removal" 或 "Preloaded",需在同一页面提交移除申请。
- 等待浏览器更新列表(通常需数周),期间用户需手动清除本地缓存。
2. 过渡方案:基于 User-Agent 差异化配置
若必须支持无法升级的旧设备(如内网特定终端),可通过 Nginx map 指令识别 User-Agent,仅对现代浏览器发送 HSTS 头部。
http {
# 定义映射规则,旧浏览器不启用 HSTS
map $http_user_agent $hsts_policy {
default "max-age=31536000; includeSubDomains";
~*"MSIE [6-9]" "";
~*"Android.*[2-4]" "";
}
server {
listen 443 ssl;
# 动态添加头部,若 $hsts_policy 为空则不发送
add_header Strict-Transport-Security $hsts_policy always;
}
}注意:此方案会降低部分用户的安全性,仅建议在受控内网或过渡期使用,公网服务应强制要求客户端升级。
验证与排查
1. 检查响应头
使用 curl 命令查看头部是否已变更或消失。
curl -I https://example.com若已移除,响应头中不应再包含 Strict-Transport-Security 字段。
2. 清除浏览器本地 HSTS 缓存
服务端配置生效后,旧浏览器可能仍记忆策略。Chrome 清除步骤:
- 地址栏输入
chrome://net-internals/#hsts。 - 在 "Delete domain security policies" 输入域名。
- 点击 "Delete" 按钮。
- 重启浏览器测试 HTTP 访问。
3. 开发者工具排查
打开浏览器控制台网络面板,查看请求是否被 307 内部跳转。若状态码为 307 Internal Redirect 且无法取消,说明本地 HSTS 缓存未清除。
常见坑与风险
- includeSubDomains 影响范围:开启该选项后,所有子域名都会强制 HTTPS。若某些子域名尚未配置 SSL,会导致大面积无法访问。
- max-age 设置过长:一旦设置过长(如一年),在配置错误期间,所有访问过 site 的用户都会在很长一段时间内无法通过 HTTP 访问,回滚成本高。建议初始设置较小值(如 1 天)。
- HTTP 端也发送 HSTS:HSTS 头部必须在 HTTPS 响应中发送才有效且安全。若在 HTTP 端口发送,容易被中间人攻击剥离。
参考来源
- MDN Web Docs: Strict-Transport-Security - https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Strict-Transport-Security
- Nginx Documentation: ngx_http_ssl_module - https://nginx.org/en/docs/http/ngx_http_ssl_module.html
- RFC 6797: HTTP Strict Transport Security (HSTS) - https://datatracker.ietf.org/doc/html/rfc6797
- HSTS Preload List Submission - https://hstspreload.org/