为什么要用curl验证HSTS
配置了HSTS(HTTP Strict Transport Security)之后,最关键的一步就是验证它是否真的生效。很多人配完Nginx就直接完事了,结果浏览器访问时发现Strict-Transport-Security响应头根本没出现,或者max-age值不对,等于白配。用curl验证是最直接、最可靠的方式——不依赖浏览器缓存,不受HSTS preload列表干扰,能看到服务器返回的原始响应头。
命令一:基础检查——直接看响应头
最简单的方式,用curl -I发送HEAD请求,只看响应头:
curl -I https://www.example.com
在返回的响应头中找Strict-Transport-Security这一行:
HTTP/2 200
strict-transport-security: max-age=31536000; includeSubDomains; preload
content-type: text/html; charset=UTF-8
如果看到了这一行,说明HSTS响应头已经正常返回。如果没看到,继续往下排查。
注意:有些服务器对HEAD请求和GET请求返回的响应头不同。如果-I没看到HSTS头,改用-D -试试GET请求:
curl -s -D - -o /dev/null https://www.example.com
命令二:精确提取HSTS头
当响应头很多时,一行一行找太麻烦。用grep直接过滤:
curl -sI https://www.example.com | grep -i strict
输出类似:
strict-transport-security: max-age=31536000; includeSubDomains; preload
如果只想看max-age的值:
curl -sI https://www.example.com | grep -i strict-transport | grep -oP 'max-age=\K[0-9]+'
输出:31536000
命令三:检查HTTP是否被正确重定向到HTTPS
HSTS的核心作用就是强制浏览器使用HTTPS。用curl访问HTTP版本,看看服务器是否正确跳转:
curl -I -L http://www.example.com 2>&1 | grep -i "strict-transport-security"
这里-L让curl跟随重定向,2>&1把stderr也捕获。正常情况下,HTTP会被301/302跳转到HTTPS,最终响应中应包含HSTS头。
重点:HSTS头只会出现在HTTPS响应中,不会出现在HTTP响应中。如果你在HTTP响应里看到了HSTS头,那反而是异常的——浏览器在HTTP连接中收到HSTS头会忽略它。
命令四:对比add_header是否加了always参数
这是HSTS不生效最常见的原因之一。Nginx的add_header指令默认只在响应码为200、201、204、206、301、302、303、304、307、308时生效。404、500等错误页面不会返回HSTS头。
用curl请求一个不存在的页面来验证:
curl -sI https://www.example.com/not-exist-page | grep -i strict
如果404页面没有返回HSTS头,说明Nginx配置中缺少always参数。正确配置应该是:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
加上always后,所有响应(包括404、500)都会携带HSTS头。
命令五:批量检测多个域名
如果管理多个域名,逐个检查太慢。写个简单脚本批量检测:
#!/bin/bash
domains=("example.com" "api.example.com" "cdn.example.com")
for domain in "${domains[@]}"; do
hsts=$(curl -sI "https://$domain" | grep -i strict-transport-security)
if [ -z "$hsts" ]; then
echo "[缺失] $domain - 未返回HSTS响应头"
else
echo "[正常] $domain - $hsts"
fi
done
也可以一行搞定,从文件读取域名:
while read domain; do echo -n "$domain: "; curl -sI "https://$domain" | grep -i strict-transport-security || echo "未返回HSTS头"; done < domains.txt
HSTS验证常见问题速查
- HTTPS响应中没有HSTS头:检查Nginx配置是否写在server块内,是否在正确的listen 443的server块中
- HTTP响应中有HSTS头但浏览器不生效:这是正常的,浏览器只信任HTTPS连接中收到的HSTS头
- 404页面没有HSTS头:给add_header加上always参数
- 子域名不生效:确认HSTS头中包含includeSubDomains指令
- 修改max-age后浏览器没更新:浏览器缓存了旧的HSTS策略,需要清除浏览器HSTS缓存
- curl看到了HSTS头但浏览器没有:可能是CDN或中间层修改了响应头,检查CDN配置
curl验证HSTS的完整检查清单
- ✅ HTTPS访问返回HSTS头,max-age值正确
- ✅ HTTP访问正确301/302跳转到HTTPS
- ✅ 404等错误页面也返回HSTS头(需要always参数)
- ✅ includeSubDomains和preload指令符合预期
- ✅ CDN层没有修改或删除HSTS头
按这个清单逐项验证,你的HSTS配置就不会有问题。
相关文章
版权声明
本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论