apache本身不自带slowloris防御能力,必须通过定制日志识别%t>10秒的极简请求、mod_status实时监控r状态堆积、mod_reqtimeout分阶段限速(header=20-40,minrate=500;body=20,minrate=500)及event mpm连接数限制四层联动,才能阻断“占座式”攻击。

Apache 本身不自带 Slowloris 防御能力,必须通过定制日志识别 + 实时状态监控 + 分阶段超时控制 + 连接资源限制四层联动,才能真正阻断这类“占座式”攻击。单改一个 Timeout 或封几个 IP,基本无效。
一、让日志能“看见慢”,不是靠默认字段
默认 access.log 记录不了 Slowloris 的本质——它看起来像合法请求(常返回 200 或 408),但处理时间极长。必须显式记录耗时和头特征:
- 在 httpd.conf 或虚拟主机中添加自定义日志格式:
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %T %D" slowloris
再启用:CustomLog /var/log/apache2/access.log slowloris - 确保 %h 是真实客户端 IP:若前端有 CDN 或 Nginx,改用 %{X-Forwarded-For}i,并配置 mod_remoteip 指定可信代理 IP 段
- %T(秒级)和 %D(微秒级)是关键——正常用户极少出现 >3 秒的 %T;攻击 IP 往往 1 分钟内集中产生 30+ 条 %T>10 的记录
二、用原生命令快速定位可疑 IP
不用上 ELK 或写脚本,一条 awk 就能筛出高危连接:
Apache Superset 是一个广泛采用的开源 BI 平台,用于 SQL 探索、图表构建和仪表板交付。当代理需要查询仓库数据、组装仪表板或使用成熟的分析界面解释指标而不是临时笔记本代码时,此技能非常有用。
- 查所有处理超 10 秒的请求,并按 IP 统计频次:
awk '$12 > 10 {print $1}' /var/log/apache2/access.log | sort | uniq -c | sort -nr | head -15
(注意:$12 是 %T 所在列号,需按你实际日志字段顺序调整) - 进一步过滤“极简请求头”(无 Host、Accept 等常见字段,典型 Slowloris 特征):
awk '$12 > 10 && $6 ~ /^"GET[[:space:]]+\/[[:space:]]+HTTP\// {print $1}' /var/log/apache2/access.log | sort | uniq -c | sort -nr | head -10
三、用 mod_status 实时确认攻击是否正在发生
日志是“回放”,server-status 才是“直播”。Slowloris 连接几乎全卡在 R(Reading Request Headers) 状态:
- 确保启用:ExtendedStatus On,且 mod_status 已加载
- 执行:curl -s "http://localhost/server-status?auto" | grep '^R ' | wc -l
- 若返回值远超 MaxRequestWorkers(如设 150 却看到 200+ 个 R 状态),基本可判定正在被攻击
四、核心防御:用 mod_reqtimeout 主动掐断,不是等超时
单纯调小 Timeout(默认 300 秒)反而帮倒忙——它只管总等待时间,不区分阶段,攻击者每 20 秒发一个字母也能撑满 5 分钟。真正起效的是分阶段限速:
- 确认模块已启用:LoadModule reqtimeout_module modules/mod_reqtimeout.so
- 在服务器级上下文(不能写在
或 .htaccess 中)添加:
RequestReadTimeout header=20-40,minrate=500
RequestReadTimeout body=20,minrate=500 - 含义:
— header=20-40:20 秒内必须开始传头,40 秒内必须传完,且任意 2 秒内至少传 1000 字节(即 ≥500 字节/秒)
— body=20:每 20 秒内必须收到至少 500 字节请求体,否则立即断连 - HTTPS 站点建议初始值放宽至 header=25-45,minrate=500,避免 TLS 握手延迟误杀










