HSTS(HTTP Strict Transport Security)是保护网站 HTTPS 连接的重要安全机制。配置好 HSTS 响应头后,如何快速验证全站域名是否正确返回了该头部?手动逐个访问不现实,curl 批量检测才是高效方案。
本文分享 5 个实战脚本,从最简单的单域名检查到多域名并行检测,覆盖 Shell 和 PowerShell 两大平台,帮你把 HSTS 安全巡检彻底自动化。
一、为什么需要批量检测 HSTS 响应头
在实际运维中,HSTS 配置可能因为以下原因失效:
- Nginx 配置变更后忘记验证 HSTS 头是否正常返回
- CDN 层(如 Cloudflare)覆盖或丢弃了源站的 HSTS 头
- 子域名未配置
includeSubDomains指令 - 多环境(测试/预发/生产)配置不一致
用 curl 批量检测,可以在每次部署后快速发现问题,比手动打开浏览器检查效率高几个数量级。
二、基础:用 curl 检测单个域名的 HSTS 头
先用最简单的方式确认方法可行:
curl -sI https://example.com | grep -i "strict-transport-security"
参数说明:
-s:静默模式,不显示进度条-I:只发送 HEAD 请求,只获取响应头grep -i:不区分大小写匹配 Strict-Transport-Security 头
如果返回了类似 strict-transport-security: max-age=63072000; includeSubDomains; preload 的内容,说明 HSTS 配置正常。如果没有任何输出,说明 HSTS 头缺失,需要排查。
三、脚本1:Shell 多域名循环检测脚本
把需要检测的域名放到一个文本文件中,用循环逐个检查:
#!/bin/bash
# HSTS 批量检测脚本
DOMAINS_FILE="domains.txt"
TIMEOUT=10
echo "=============================="
echo "HSTS 响应头批量检测报告"
echo "检测时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo "=============================="
while IFS= read -r domain; do
# 跳过空行和注释
[[ -z "$domain" || "$domain" == \#* ]] && continue
hsts_header=$(curl -sI --connect-timeout "$TIMEOUT" --max-time "$TIMEOUT" "https://$domain" 2>/dev/null | grep -i "strict-transport-security")
if [[ -n "$hsts_header" ]]; then
echo "[OK] $domain"
echo " $hsts_header"
else
echo "[缺失] $domain - 未检测到 HSTS 响应头!"
fi
done < "$DOMAINS_FILE"
echo "=============================="
echo "检测完成"
创建 domains.txt 文件,每行一个域名:
example.com
api.example.com
cdn.example.com
blog.example.com
运行:bash check_hsts.sh
这个脚本的优点是简单直观,适合域名数量不多(几十个以内)的场景。每个域名独立检测,超时设置为 10 秒防止卡住。
四、脚本2:带评分的 HSTS 安全等级评估
光知道有没有 HSTS 头还不够,我们还可以评估安全等级:
#!/bin/bash
# HSTS 安全等级评估脚本
check_hsts() {
local domain=$1
local header=$(curl -sI --connect-timeout 8 --max-time 8 "https://$domain" 2>/dev/null | grep -i "strict-transport-security" | tr -d '\r\n')
if [[ -z "$header" ]]; then
echo "[D] $domain - 未配置 HSTS"
return
fi
# 提取 max-age 值
max_age=$(echo "$header" | grep -oP 'max-age=\K[0-9]+')
# 检查 includeSubDomains
has_include=$(echo "$header" | grep -ic "includesubdomains")
# 检查 preload
has_preload=$(echo "$header" | grep -ic "preload")
# 评分
score=0
if [[ -n "$max_age" && "$max_age" -ge 31536000 ]]; then
((score+=40))
elif [[ -n "$max_age" && "$max_age" -ge 2592000 ]]; then
((score+=20))
elif [[ -n "$max_age" ]]; then
((score+=10))
fi
[[ "$has_include" -gt 0 ]] && ((score+=30))
[[ "$has_preload" -gt 0 ]] && ((score+=30))
if [[ $score -ge 90 ]]; then
grade="A"
elif [[ $score -ge 70 ]]; then
grade="B"
elif [[ $score -ge 40 ]]; then
grade="C"
else
grade="D"
fi
echo "[$grade] $domain (评分:$score) $header"
}
for domain in "$@"; do
check_hsts "$domain"
done
用法:./hsts_grade.sh example.com api.example.com cdn.example.com
评分规则:
- max-age ≥ 1年(31536000秒):+40分
- max-age ≥ 30天:+20分
- max-age 有值但 < 30天:+10分
- includeSubDomains:+30分
- preload:+30分
五、脚本3:xargs 并行检测(高性能方案)
域名很多时,串行检测太慢。用 xargs -P 实现并行:
#!/bin/bash
# HSTS 并行批量检测
DOMAINS_FILE="domains.txt"
PARALLEL=10 # 并发数
check_one() {
local domain=$1
local hsts=$(curl -sI --connect-timeout 5 --max-time 5 "https://$domain" 2>/dev/null | grep -i "strict-transport-security")
if [[ -n "$hsts" ]]; then
echo "OK|$domain|$hsts"
else
echo "MISS|$domain|"
fi
}
export -f check_one
echo "开始并行检测... ($(grep -cv '^#\|^$' $DOMAINS_FILE) 个域名, $PARALLEL 并发)"
grep -v '^#\|^$' "$DOMAINS_FILE" | xargs -P "$PARALLEL" -I {} bash -c 'check_one "{}"' | sort
echo "检测完成"
核心是 xargs -P 10,表示同时运行 10 个 curl 进程。对于 100 个域名,5 秒超时下大约 50 秒就能全部完成,而串行需要 500 秒。
注意并发数不要设太高,避免触发目标服务器的连接限制。
六、脚本4:PowerShell 版本批量检测
Windows 环境下可以用 PowerShell 实现:
# HSTS 批量检测 PowerShell 版本
$domains = @(
"example.com"
"api.example.com"
"blog.example.com"
"cdn.example.com"
)
Write-Host "==============================" -ForegroundColor Cyan
Write-Host "HSTS 响应头批量检测报告"
Write-Host "检测时间: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
Write-Host "==============================" -ForegroundColor Cyan
$results = @()
foreach ($domain in $domains) {
try {
$response = Invoke-WebRequest -Uri "https://$domain" -Method HEAD -TimeoutSec 10 -UseBasicParsing -ErrorAction Stop
$hsts = $response.Headers['Strict-Transport-Security']
if ($hsts) {
Write-Host "[OK] $domain" -ForegroundColor Green
Write-Host " $hsts" -ForegroundColor Gray
$results += [PSCustomObject]@{
Domain = $domain
Status = "OK"
HSTS = $hsts
}
} else {
Write-Host "[缺失] $domain" -ForegroundColor Red
$results += [PSCustomObject]@{
Domain = $domain
Status = "缺失"
HSTS = "无"
}
}
} catch {
Write-Host "[错误] $domain - $($_.Exception.Message)" -ForegroundColor Yellow
$results += [PSCustomObject]@{
Domain = $domain
Status = "错误"
HSTS = $_.Exception.Message
}
}
}
# 导出 CSV 报告
$reportFile = "hsts_report_$(Get-Date -Format 'yyyyMMdd_HHmmss').csv"
$results | Export-Csv -Path $reportFile -NoTypeInformation -Encoding UTF8
Write-Host "`n报告已保存: $reportFile" -ForegroundColor Cyan
PowerShell 版本的优势是:
- 直接导出 CSV 报告,方便用 Excel 打开分析
- 错误处理更精细,能区分「缺失」和「连接失败」
- 适合集成到 Windows 任务计划程序中定时执行
七、脚本5:持续监控方案(配合定时任务)
把检测脚本接入 cron 或任务计划,实现每日自动巡检:
Linux cron 配置:
# 每天早上 9 点执行 HSTS 检测,结果发送到邮箱
0 9 * * * /opt/scripts/check_hsts.sh | mail -s "HSTS 每日检测报告" admin@example.com
Windows 任务计划:
# 创建每天 9 点运行的定时任务
$action = New-ScheduledTaskAction -Execute "pwsh.exe" -Argument "-File C:\Scripts\check_hsts.ps1"
$trigger = New-ScheduledTaskTrigger -Daily -At 9am
Register-ScheduledTask -TaskName "HSTS每日检测" -Action $action -Trigger $trigger
持续监控的好处是:HSTS 头一旦因为配置变更或 CDN 调整而丢失,你能在当天收到告警,而不是等到安全审计才发现问题。
八、HSTS 检测中的常见问题
1. curl -I 返回 405 Method Not Allowed
部分服务器不支持 HEAD 方法。改用 GET 请求但丢弃响应体:
curl -s -D - -o /dev/null https://example.com | grep -i "strict-transport-security"
2. 检测到 HSTS 头但 max-age 值为 0
max-age=0 表示立即失效,等同于删除 HSTS 策略。这可能是调试残留配置,需要修复。
3. 只在 HTTP 响应中检测不到
HSTS 头只应在 HTTPS 响应中出现,HTTP 响应检测不到是正常的。确保检测 URL 使用 https:// 开头。
4. CDN 层干扰
使用 Cloudflare 等 CDN 时,HSTS 头可能在 CDN 层设置而非源站。此时应检测 CDN 回源后的实际响应,可以用 --resolve 参数绕过 CDN 直接访问源站:
curl -sI --resolve "example.com:443:源站IP" https://example.com | grep -i "strict-transport-security"
九、总结
HSTS 批量检测不难,难的是坚持做。5 个脚本从简单到复杂,根据你的场景选择:
- 快速检查:脚本1(Shell 多域名循环)
- 安全评估:脚本2(带评分系统)
- 大规模扫描:脚本3(xargs 并行)
- Windows 环境:脚本4(PowerShell + CSV)
- 持续监控:脚本5(定时任务集成)
建议把 HSTS 检测纳入部署流程的 CI/CD 中,每次发布后自动跑一遍,确保安全配置不会意外丢失。
相关阅读
版权声明
本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论