1. 先说清楚CC攻击到底是什么为什么新手总是后知后觉很多新手站长第一次知道自己的网站被CC攻击往往不是从监控告警里看到的而是从网站突然打不开、服务器CPU飙到100%、重启后过几分钟又卡死这类状况里被动察觉的。等反应过来登录后台一查才发现某几个接口的请求量已经离谱到每秒上千次而自己完全没在第一时间发现异常。这里先给新手补一个基础概念。CC攻击的全称叫Challenge Collapsar原理也并不复杂它模拟大量真实用户的HTTP请求持续不断地访问你网站的动态接口、登录页面、查询功能、下单流程等消耗资源的业务点让服务器把CPU、内存、数据库连接、带宽都耗在应付这些伪造请求上结果正常用户访问时什么都加载不出来。它和传统的流量型DDoS不一样那种是直接打满你的带宽而CC攻击更像是一群人堵在商场门口假装要买东西让真正的顾客进不去。为什么新手总是后知后觉因为CC攻击的流量单看并不大。它可能只有几十兆的带宽占用对于带宽充足的服务器来说毫不起眼但每秒几百上千个动态请求足以把应用层的处理能力拖垮。再加上很多攻击者会刻意做低速率、长时间、分布式的请求让传统按流量大小判断的防护手段完全失灵。这篇文章就是围绕如何在攻击发生时尽早发现、在攻击发生前做好监控来展开的我会把常用的检测思路、具体操作步骤和一些实测心得一次讲清楚适合刚接触运维和网站防护的新手参考。1.1 一个真实请求和一个攻击请求的区别在哪里想要学会检测首先得理解攻击请求和正常请求的差异。这里有个容易误解的地方很多新手以为攻击请求都长得很假比如User-Agent明显是脚本、请求参数非常畸形一看就知道是恶意流量。但实际上现在CC攻击的工具和脚本已经进化了很多轮攻击者会伪造浏览器指纹、随机生成UA、模拟真实的浏览顺序甚至把请求频率控制在人类访问的合理区间内。那差异到底在哪核心在于意图。正常用户访问一个页面他会先加载HTML再加载CSS、JS、图片等静态资源可能停留几秒到几分钟然后点击某个链接进入下一个页面。这一套行为在日志里是有迹可循的请求有先后顺序、有静态资源占比、有思考停顿间隔。而攻击脚本的目标很明确——只打你消耗资源最大的那几个动态接口它不会去加载图片和样式表不会停留也不会按正常人类的节奏去浏览。所以检测CC攻击的第一个思路就是不要只看单个请求是否可疑而要看一组请求组合起来的访问模式是否异常。当然很多人会问如果攻击者也模拟加载静态资源怎么办那他的成本就高得多了因为静态资源也需要消耗带宽和连接数等于攻击者自己也在消耗资源。大多数攻击工具为了追求高并发和高效率不会做得这么逼真这反而是我们检测可以利用的地方。1.2 为什么传统防火墙对CC攻击常常失灵很多新手都配置过防火墙或者云服务商自带的基础防护但被CC攻击打挂之后会发现一个尴尬的事实防护规则形同虚设。这不是防火墙没用而是CC攻击恰好击中了它的盲区。传统的防火墙规则大多工作在网络层和传输层它擅长的是封禁IP、限制并发连接数、拦截特定端口的大流量。CC攻击的请求看起来就是正常的TCP连接加正常的HTTP请求从网络层的角度看没有任何异常单看任何一个连接都是合法访问。而且云服务商提供的DDoS防护包大多针对的是流量型攻击按带宽和包量来清洗对于应用层的慢速CC攻击其实是管不了的。就算你在防火墙里配了单IP每分钟请求数超过X就封禁这样的规则攻击者也早就学会了用代理池和分布式的肉鸡来绕过——每个IP只发很少的请求总量却非常可观。这也是为什么我建议新手不要把全部希望寄托在单一设备上而是要用日志分析应用层特征速率控制应急封禁的组合拳来应对。检测思路要从单点看异常升级为全局看趋势把异常请求放到时间维度和行为维度里去观察。2. 从流量趋势入手这是最快、最省成本的发现方式对于没有专业安全设备的新手来说最现实可行的CC攻击检测方式是从自己手头的流量监控数据入手。不需要额外买硬件不需要装复杂的商业软件只要你的服务器有基础的监控面板、Web服务有访问日志就可以实现第一层检测。我把这一层检测称为粗筛。它的作用是帮你在大规模攻击发生时快速定位问题而不是精确识别每一个恶意请求。虽然精度有限但在实际运维中大部分CC攻击在造成网站不可用之前都逃不过流量趋势上的异常。2.1 先建立你自己的正常值基线很多新手看到某个接口的请求量涨了几倍就开始紧张其实这不一定就是攻击——可能是你发了篇爆款文章、上了个热门活动或者被搜索引擎的爬虫盯上了。所以检测的第一步是要知道你的业务在正常情况下到底是什么样的。所谓基线就是一组历史数据你的站点平均每秒多少个请求、高峰期多少个、某几个核心接口的请求量占比、平均响应时间是多少、错误率是多少。这个基线不需要你手动去统计大部分监控工具都有历史报表功能你只需要把最近7天到30天的数据拉出来记下平均值和峰值就可以。这里我给新手一个非常实用的动作把你们站点的核心动态接口单独列出来逐个记下它们正常情况下的请求频率和服务耗时。比如一个登录接口平时可能一分钟只有几十次调用平均耗时50毫秒一旦被CC攻击它可能一分钟冲到几千次同时因为服务端要不停地查数据库、做密码校验平均耗时可能涨到800毫秒以上。这两个指标的变化是最直观的信号甚至不需要复杂的算法只要盯着这几个重点接口看就能发现大部分问题。2.2 请求量的斜率比绝对值更有判断价值这里分享一个我自己总结的检测心得不要只看请求量的绝对值而要关注请求量上升的斜率。正常业务流量增长一般是缓慢的、平滑的伴随着明显的昼夜规律。如果凌晨三点你的网站请求量突然在几分钟内从峰值200涨到2000而业务上没有任何对应的活动安排那基本可以断定有问题。斜率异常陡峭这一点比当前值是不是超过了某个阈值更加可靠因为它天然过滤掉了正常促销活动带来的流量增长。具体操作上可以在监控面板里设置按5分钟粒度统计的请求量曲线然后写一条简单的规则连续三个统计周期内请求量环比增长超过100%并且这个增长主要集中在某一个或某几个接口上就触发告警。这样可以避免大面积误报也能在大规模攻击的早期发现异常。2.3 连接数与请求速率配合看能发现更多细节请求量曲线只是最基础的信号如果想把检测做得更细致一些我还建议叠加两个指标并发连接数和单连接请求速率。当一个正常用户打开你的网站时他的浏览器通常只会建立少数几个长连接。但CC攻击工具为了让请求尽可能快地发出去往往会产生大量并发连接或者用极快的速率在同一个连接上连续发送请求。你可以在Nginx的日志中记录连接建立时间也可以通过系统的连接状态来观察如果服务器的ESTABLISHED状态连接数在短时间内猛增同时每个连接的存活时间都非常短这就很有可能是攻击在扫接口。我之前遇到一个比较典型的案例某台业务服务器的并发连接数从常态的几十个突然暴增到几千个但带宽占用并不高CPU却被打满了。查日志发现请求全部集中在某个列表查询接口UA都是随机伪造的。这类情况如果用传统的带宽超过阈值才告警的方式去监控根本触发不了但配合连接数和请求速率就很容易发现。3. 深入请求内容从头部和参数特征里找机器的痕迹流量趋势只能告诉你出事了但要确认确实是CC攻击以及是谁在攻击就必须深入请求内容去分析。这一层检测开始有一定的技术门槛但并没有想象中那么难核心思路就是找规律、找破绽、找重复。3.1 User-Agent和Referer是最容易暴露问题的字段尽管很多攻击工具会伪造UA但伪造的质量参差不齐。有些工具默认的UA就那几十个来回换着用有些工具压根没设置UA直接留空还有的会把自己真实使用的爬虫框架名暴露出来比如一些基于开源框架的脚本会带上框架的标识。这就是突破口。推荐的操作是把访问日志里的UA字段做一次分组统计看看前几十个UA占了多大比例。正常情况下一个网站的UA分布是比较分散的因为用户用的操作系统、浏览器版本五花八门。如果发现某一个UA贡献了超过20%甚至更高的请求量或者UA列表里大量出现同一套模板但微调数字的情况就值得警惕。Referer字段同理。正常用户通过搜索、外链、直接输入地址进入你的网站Referer分布相对自然。攻击脚本大部分时候不会设置Referer或者统一伪造为某个固定地址。如果你的日志里出现大量Referer为空、或者Referer集中在某个和业务无关的域名就需要进一步核查。3.2 请求路径和参数的重复模式是重要线索攻击者为了最大化打击效果通常会集中火力打少数几个接口。这就造成一个非常明显的特征请求路径高度集中。比如正常站点的访问分布在几十上百个URL上而攻击时可能90%的请求都集中在/login.php或者/api/search上。参数方面也有规律可循。人工操作时参数的取值是随机的、多样的脚本攻击时参数往往按照固定的字典循环比如遍历ID从1到10000或者在固定的一组关键词里轮换。你可以在日志分析中把相同路径不同参数的请求聚合起来进一步计算参数的取值种类和出现频率。如果发现某个接口的参数取值寥寥无几但请求总量却异常庞大那基本就是脚本在跑。这里我提供一个非常简单的验证方法把疑似攻击期间某个接口的请求日志导出手动翻看几十条请求的完整记录对比它们的UA、Referer、Cookie、参数值。如果发现大量请求在这些字段上高度相似只有参数里个别数字在变那就可以大概率判定为CC攻击。3.3 慢速型和低频型CC攻击怎么识别这一节是给有一定经验的新手看的。有人可能觉得CC攻击就是高并发、高频率的猛攻其实攻击者也在不断升级手段。慢速型CC攻击典型代表是Slowloris这类方式它建立连接之后不发送完整请求而是以极低的速度一点点把数据传完占用服务器的连接资源。这种攻击在请求量上看不出异常因为每秒可能只有几十个新建连接但服务器的连接数会持续攀升直到把连接池耗尽。低频型CC攻击则更阴险攻击方操纵大量IP每个IP每隔几秒才发一个请求整体节奏看起来和正常用户群体没太大区别。但仔细观察会发现这些IP只会访问那一个目标接口从不加载静态资源请求间隔又过于均匀——正常人类的操作停顿是随机分布的机器的定时请求则精确得可怕。识别这两类攻击靠简单的速率阈值已经不够了需要做连接存活时长统计和请求间隔方差分析。我建议新手可以通过Web服务的访问日志来实现记录每个连接的建立时间和该连接上的请求数量再计算请求间隔的标准差。正常用户的标准差大机器的标准差小。4. 行为维度检测用访问序列和资源占比识别真人与脚本内容维度的检测有一个天然的局限性攻击者一旦知道你在查什么就可以针对性地伪造。UA可以随机生成Referer可以做假参数可以做成随机值路径可以选择多个接口轮换。所以真正让攻击者难以模仿的是行为本身。什么叫行为维度就是不看单次请求的内容而是看一个客户端从进入你的网站到离开这整个过程中所有请求的组合方式。行为层面的伪造成本要高得多大多数攻击工具不会花那么大精力去模拟完整的人类浏览过程。4.1 静态资源请求占比是最容易量化的行为指标一个很朴素但非常有效的检测维度计算一段时期内静态资源请求图片、CSS、JS、字体等在所有请求中的占比。正常用户访问一个网页浏览器会自动加载页面上引用的所有静态资源占比通常能达到70%到90%——也就是说100个请求里真正打到后端接口的可能只有10到30个。而CC攻击脚本的请求目标基本都是动态接口静态资源占比可能连5%都不到。你不需要写多复杂的代码用日志分析工具或者一条简单的脚本就能算出这个比例。一旦发现某个IP或某个网段在短时间内的静态资源占比异常低同时请求路径集中在少数动态接口上就可以把这批流量标记为高度可疑。这个指标之所以不容易被绕过是因为攻击者如果要模拟加载静态资源等于要大幅增加自己的请求量和带宽消耗攻击效率会下降一个量级很多攻击者宁愿放弃也不愿付出这种成本。4.2 访问序列的形式感脚本的路线太单一了很多攻击脚本为了提高效率会固定按照某个顺序访问URL比如先访问首页再访问接口A再访问接口B然后循环。这种访问序列如果画出来是一串非常有规律、不断重复的循环。而真实用户哪怕是重度强迫症也做不到这种精确到毫秒级的重复。这套逻辑可以落地成比较简单的检测规则针对单个IP统计它在一段时间内访问URL的序列计算序列的重复度。如果发现某个IP的URL访问序列呈现高度周期性重复比如每次都严格按照同样的顺序访问同样的三个URL那基本就是脚本无疑。这里补充一个实际案例中的体会之前有个站点被刷注册接口攻击脚本每次都是先访问/register页面再提交注册数据到/user/register中间不加载任何其他资源这个双请求序列每两秒循环一次。用行为序列去匹配的话几乎一眼就能看出问题。4.3 设备指纹和代理池特征可以提供辅助判断如果你想更进一步可以在前端埋点采集一些设备指纹信息比如屏幕分辨率、时区、Canvas指纹、WebGL渲染信息等。正常用户的设备指纹是多样化的而同一个攻击者操控的多数设备因为用的是同样的运行环境或模拟器指纹会比较集中。不过我要提醒新手设备指纹属于加分项不建议作为主要判断依据。因为它需要前端埋点配合改造工作量不小而且现在不少攻击者会用无头浏览器来模拟真实环境指纹差异会被大幅抹平。相比之下更容易落地的是代理池特征——大量攻击IP的所在地区分布、运营商信息往往高度集中比如都来自某个IDC机房网段、都使用同一家云服务的IP段。把这些信息做成简单的可视化统计也是行为画像的一部分。在实操中我见过最简单有效的一个动作是拉取攻击时间段内所有访问IP的ASN信息如果发现某个IDC的IP占了异常高的比例而正常业务用户根本不会有那么高的IDC占比那这就是一个很强的攻击信号。5. 落地实操一套完整的通用检测流程照着做就能用讲完了检测原理这一节是很多新手最关心的部分具体怎么操作要用哪些工具每个环节怎么配合我基于自己的运维经验给出一个不需要商业产品的落地流程整体分为日志采集、指标统计、阈值告警、封禁处理四个环节。这套流程对使用Nginx/Apache等主流Web服务的站点都适用工具部分尽量选常见、免费、文档全的方案方便新手直接上手。5.1 日志采集先把要分析的数据留全检测的第一步是确保你手头有足够完整的数据。我见过不少新手在遭遇攻击之后想定位问题结果发现Nginx的访问日志只保留了最近一天的最早的攻击流量已经被覆盖了非常被动。建议在Web服务的配置里把日志格式调整一下额外记录几个关键字段请求处理时间、响应状态码、User-Agent、Referer、连接建立时间。Nginx的配置大致如下log_format main $remote_addr - $remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $request_time $upstream_response_time $connection_requests; access_log /var/log/nginx/access.log main;这里$connection_requests可以记录当前TCP连接上已经发送了多少个请求是识别慢速攻击、评估单连接请求速率的关键字段。$request_time则用来观察接口处理耗时是否异常。日志保留周期建议至少30天如果磁盘空间紧张可以采用按月分割后压缩保存的方式。另外最好是配置日志的异步写盘和缓冲避免高峰期大量日志写入影响业务性能。5.2 指标统计与阈值设定从日志里算出这些关键数拿到日志之后需要把它变成可以判断的指标。这里我不建议新手一开始就上一套复杂的ELK先用最简单的脚本或者现成的日志分析命令跑起来即可。以下这几个指标我建议每天都看一遍指标正常情况攻击时的典型表现单接口请求量波动平缓昼夜规律短时间飙升数倍至数十倍静态资源占比通常过半显著下降单IP请求频率分散高低不均异常集中或异常均匀请求间隔方差较大体现人类随机性较小机器周期性明显错误率/响应耗时稳定在低水平快速上升如果你会用命令行可以直接用下面这个组合快速查看Top IP的请求分布awk {print $1} /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20这条命令的作用是提取日志中所有IP统计每个IP出现的次数按降序排列显示前20个。如果发现某个IP的请求数在总请求中占比异常比如超过5%就需要进一步查看它的详细行为。阈值要怎么定网上搜出来的经验值很多但不能直接照搬——不同站点差异非常大。电商大促期间和平时没有可比性图片站和小程序后端也没有可比性。我的建议是以你站点前30天正常数据的P95值作为告警阈值的起点。比如某接口在近30天中95%的时间里每分钟请求量都低于3000次那就把告警阈值设在3000次连续两个或三个统计周期超过再告警减少瞬时抖动带来的误报。5.3 从检测到处置告警、确认、封禁的闭环流程检测到疑似攻击后不要急着把所有嫌疑IP一刀切封了先走一个闭环流程告警→确认→处置→复盘。第一步告警方式可以用传统的邮件加短信也可以用企业微信或钉钉的自定义机器人。告警内容不要只写请求量过高要附带关键上下文哪个接口、请求量多少、较基线增长多少倍、Top IP的前几个分别是什么。有了这些信息你不需要登录服务器就能快速判断严重程度。第二步确认阶段。登录服务器验证几个问题请求是否集中在某个接口这些请求的UA是否正常分布静态资源占比是否异常有没有大量请求相同参数如果多个信号都指向攻击就可以进入处置环节。第三步处置。最直接的方式是先在防火墙或Web服务器层面对可疑IP做临时封禁。高防IP和CDN上的封禁接口也可以配合使用。这里有个操作细节对于分布式CC攻击单IP封禁的效率很低因为攻击IP可能有几千上万个。更有效的方式是启用Web服务器层面的限流规则按IP限制请求速率超速的IP直接返回503或验证码而不是彻底封死。第四步复盘。攻击结束后把攻击日志存档分析攻击者的目标接口、攻击持续时长、使用的IP池特征把这些信息写入防护规则库。下一次再遇到类似攻击就能更快地识别和处置。6. 新手避坑指南误报、漏报和那些防不住的绕过最后这部分我想专门聊聊新手在实践中最容易栽的跟头。很多东西书本上不会写但实际做运维一定会遇到。6.1 高并发不等于攻击别误伤了搜索引擎和正常用户最常见的误报场景就是站点某个页面突然火了流量大增新手一看请求量曲线飙升CPU也上去了第一反应就是被攻击了然后一通封禁操作把真正带来流量的用户和搜索引擎爬虫都挡在了门外。怎么区分有一个非常实用的方法看访问分布。真实流量暴涨访问的URL一定是分散的不同用户关注不同内容CC攻击的流量则高度集中在少数几个接口。同时真实流量的静态资源占比仍然很高因为用户用浏览器访问页面就会加载图片和样式。另外搜索引擎爬虫的UA非常规律而且会遵循robots协议请求间隔均匀合理。在误判之前先把包含主要搜索引擎爬虫UA的请求筛出来单独统计能避免大量误报。6.2 攻击者比你想象的更会伪装UA能换Cookie能伪造不少新手会把检测逻辑设置为某个UA的请求超过多少就封禁结果攻击者很快就把UA改成随机字符串这套规则就失效了。同样的道理如果你只靠IP频率来判断攻击者用代理池轮换IP你也会被绕过。我的体会是单一维度的规则永远是有破绽的检测必须建立在多个信号的综合评分上。你可以给每个IP计算一个可疑指数综合考量请求频率、静态资源占比、访问序列重复度、UA异常程度等因素超过一定分数才判定为疑似攻击。这样即使某个单一特征被伪造其他维度的异常仍然会拉高总分。6.3 动态调整阈值别让规则变成摆设新手配置防护规则时最容易犯的毛病是一次配置永久生效。实际上业务的正常流量是持续变化的去年日均请求量一万今年做大了变成十万你再拿一万的阈值去告警系统会天天误报最后大家都不看告警了真正的攻击反而被淹没。建议每隔一段时间就要重新校准阈值。频率可以是一两个月也可以在你上线新功能、搞大活动、接了大流量渠道之后马上校准。校准的方法和最初建立基线时一样拉取最近30天的数据重新计算P95值。安全防护是一个需要持续迭代的过程不存在配好就一劳永逸的规则。我在实际运维中还有一个习惯把每一次真实攻击的原始日志都保存下来标记清楚攻击类型、特征、持续时间、处置方式。日积月累这本地资料比任何监控产品的规则库都更适合你自己的业务因为它记录的都是真正打过你的那些攻击手法。下一次检测规则升级时直接用这些历史样本做验证立刻就能看出规则是否有效。如果你也是从零开始接触Web防护的新手希望这篇文章能帮你少走些弯路在攻击发生的时候不再手忙脚乱。