apache日志默认无法识别slowloris攻击,必须自定义格式记录%t/%d、结合mod_status实时观察r状态,并启用mod_reqtimeout分阶段超时控制,才能实现识别→确认→拦截闭环。

Apache日志本身不暴露Slowloris攻击的完整行为,必须配合定制日志格式、实时状态监控和主动超时策略,才能完成“识别→确认→拦截”的闭环。单靠access.log默认字段(如%r、%s)几乎无法发现异常,因为攻击请求常返回200或408,且看似合法。
一、让日志真正“看得见慢”
默认combined日志不含处理耗时,根本无法区分“快请求”和“卡住的慢连接”。必须启用%T(秒级处理时间)和%D(微秒级),并显式记录请求头特征:
- 在
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或反向代理,需用%{X-Forwarded-For}i替代,并在mod_remoteip中配置可信源
二、用原生命令快速筛查可疑模式
不用上ELK或写Python,一条awk链就能定位高危IP:
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等常见头):
awk '$12 > 10 && $6 ~ /^"GET[[:space:]]+\/[[:space:]]+HTTP\// {print $1}' /var/log/apache2/access.log | sort | uniq -c | sort -nr | head -10 - 正常用户极少出现>3秒的%T值;攻击IP通常1分钟内集中出现30+条%T>10记录
三、用mod_status实时验证连接状态
日志是“事后回放”,mod_status才是“手术室直播”。Slowloris连接几乎全部卡在R(Reading Request Headers)状态:
- 确认已启用:
ExtendedStatus On,且LoadModule status_module modules/mod_status.so已加载 - 访问
curl "http://localhost/server-status?auto",过滤R状态行:curl -s "http://localhost/server-status?auto" | grep '^R ' | wc -l - 若返回值远超
MaxRequestWorkers设定(如设150却看到200+个R状态),基本可断定正在遭受Slowloris攻击
四、自动防御:不是封IP,而是“精准掐断”
识别只是第一步,防御核心在于让恶意连接在资源耗尽前就被终止。Apache不靠黑名单,而靠分阶段超时控制:
- 启用
mod_reqtimeout(必须加载):LoadModule reqtimeout_module modules/mod_reqtimeout.so - 设置请求头读取限制:
RequestReadTimeout header=15-30,minrate=500
——要求15秒内开始发头、30秒内发完,且平均速率≥500B/s,否则断连 - 设置请求体传输限制(防Slow POST):
RequestReadTimeout body=10,minrate=500
——每10秒至少收到500字节,否则终止 - 同步收紧全局参数:
Timeout 20(总等待上限)、KeepAliveTimeout 3(空闲连接仅保持3秒)
这些配置组合起来,能让Slowloris连接在20秒内被主动释放,而不是任其挂满连接池。实测表明,开启mod_reqtimeout后,攻击者需维持3倍以上的并发连接数才能达到同等效果,成本陡增,攻击自然失效。










