核心是浏览器主动拦截http请求而非nginx跳转,故无日志;排查三步:一查chrome://net-internals确认hsts是否生效,二用curl检查strict-transport-security响应头,三将max-age设为0并手动删除hsts策略。

这个问题核心在于:HSTS 不是 Nginx 在跳转,而是浏览器自己拦截了 HTTP 请求——它根本没发出去,所以你在 Nginx 日志里找不到 301/302 记录,也查不到任何访问痕迹。
确认浏览器是否已缓存 HSTS 策略
打开 Chrome 或 Edge,地址栏输入:
chrome://net-internals/#hsts
在下方 “Query domain” 输入你的本地开发域名(比如 test.local 或 dev.example.com),点 “Query”。
如果显示 Found,说明浏览器已记住该域名的 HSTS 策略;
如果显示 Not found,那问题不在 HSTS,需排查其他原因(如证书、端口、Nginx 配置等)。
检查 HTTPS 响应头是否还在发送 HSTS
用 curl 检查当前服务是否仍返回 Strict-Transport-Security 头:curl -I https://test.local
观察响应头中是否有类似:Strict-Transport-Security: max-age=31536000; includeSubDomains
- 如果有,说明 Nginx 或 Ingress 还在主动“喂”浏览器这个策略,需修改配置停用
- 检查 Nginx 的 443 端口 server 块,确认没有
add_header Strict-Transport-Security ...行;HTTP(80)块里出现该头无效且应删除 - 若用 Kubernetes Ingress,检查注解(如
nginx.ingress.kubernetes.io/hsts: "true")或 ConfigMap 中 hsts 开关
清除客户端残留策略并验证
仅改服务端不够,浏览器本地缓存会持续生效:
- 把 HSTS 的
max-age改为0,例如:add_header Strict-Transport-Security "max-age=0; includeSubDomains" always;
然后重载 Nginx:nginx -t && systemctl reload nginx - 回到
chrome://net-internals/#hsts,在 “Delete domain security policies” 区域输入域名,点 “Delete” - 立即开一个无痕窗口访问
http://test.local,这是最干净的验证方式——无痕模式不继承 HSTS 缓存
避免本地开发踩坑的建议
本地开发环境一般不需要 HSTS,尤其用自签名证书时:
- 直接从 HTTPS server 块中移除
add_header Strict-Transport-Security行 - 不要对
.local、.test等私有 TLD 启用 preload,它们无法加入预加载列表,反而容易卡住调试 - 若必须测试 HSTS 行为,先用极短周期(如
max-age=300)验证,确认无误再延长 - Chrome 119+ 对本地证书更严格,确保自签名证书包含 Subject Alternative Name(SAN),否则即使禁用 HSTS 也可能被拦截











