1. DDoS 与 CC 攻击先搞清楚它们到底是什么很多人一听到“网站被打了”第一反应就是 DDoS分布式拒绝服务攻击。但实际上日常运营里遇到最多的“打”往往是 CC 攻击这种更隐蔽、更难缠的变种。我做网站运维这些年见过太多因为分不清这两者而误判战况的案例——防御方案完全用错钱花了攻击没挡住业务照样崩。先说结论DDoS 和 CC 攻击的目标本质上是同一个——让合法用户访问不到你的服务。但它们的手段、攻击对象、识别特征和防御思路差别非常大。DDoS 攻击打的是“带宽”和“连接”。攻击者用大量被控的机器肉鸡向你的服务器发送海量数据包把机房出口带宽占满或者把服务器的连接数打满。你的服务器 CPU 可能只有 5% 的占用率但带宽已经被塞满了正常用户根本挤不进来。这就像一群人堵在商场门口把门都堵死了里面的店员其实挺闲的但外面的顾客进不来。CC 攻击Challenge Collapsar最早是针对某防火墙产品的攻击方式而得名打的是“应用层”。攻击者模拟真实用户的浏览器行为不断发起看起来完全正常的 HTTP 请求比如反复请求你的登录接口、查询接口、搜索接口。每个请求单独看都没问题但单位时间内的请求量远超正常水平服务器需要花大量 CPU 和数据库资源去处理这些请求最终导致应用层资源耗尽正常用户访问时页面加载不出来或者直接超时。这就像一群人不进商场就在门口反复按自动门的开关把门的控制器搞死机了。搞清楚这个区别是一切防御的前提。带宽被塞满你得找高防 IP、加大带宽清洗应用层被打你得做限频、加验证码、优化业务逻辑。方案反了怎么做都是徒劳。这篇文章我会从实际运维的角度把两类攻击的识别特征、防御手段和踩坑经验一次讲透适合自己做站点、管服务器的开发者以及刚入门的安全运维同学参考。2. 攻击特征识别怎么判断你的站点正在被攻击以及是哪一种在谈防御之前必须先学会识别。我见过太多人把“服务器高负载”和“被 CC 攻击”混为一谈结果排查方向全错。下面这套判断流程是我在实际处理中反复验证过的把它当 checklist 用。2.1 带宽型攻击的典型信号如果你的站点突然打不开先看两个最基础的数据带宽占用和服务器负载。DDoS 攻击发生时最显著的特征是入口带宽瞬间飙升。正常情况下你的站点日均流量 100Mbps突然变成 2Gbps十有八九是被流量打满。你可以在机房控制台或云服务商的监控面板里查看带宽曲线如果是一条近乎垂直的上升直线基本可以断定是 DDoS。此时服务器负载反而可能正常甚至偏低。很多人不理解这点原因是攻击流量在到达服务器之前就已经把带宽填满了数据包根本没机会被 CPU 完整处理。用生活类比说快递仓库的收货通道被货车堵死了仓库里的分拣员反而闲着。判断这种攻击时只看服务器负载会误诊必须看带宽曲线。另一个判断依据是流量分布。正常的业务流量无非是网页、图片、视频资源流量曲线有高有低有规律可循。而 DDoS 流量往往是满速恒定输出或者呈现周期性脉冲配合连接数同步暴涨。看到这种形态基本可以确定是带宽型攻击。2.2 CC 攻击的隐蔽特征负载飙升但带宽不高CC 攻击最让人头疼的就是“隐蔽”。攻击请求和正常用户请求在协议层面几乎一模一样单纯看带宽看不出异常——攻击者不会傻到把带宽打满那样反而容易被流量清洗识别。他们的目标是让每个请求都消耗服务器资源用低带宽成本制造出高 CPU 负载。典型特征包括这么几个服务器 CPU 和内存使用率持续高位。如果你发现 CPU 长时间超过 90%但带宽只有正常水平甚至偏低标准做法是立刻查看 Web 服务日志和数据库慢查询日志。CC 攻击的直接后果是应用层 API 或动态页面被反复请求导致数据库连接耗尽日志里会出现大量重复的请求地址。单 IP 请求频率极高。正常用户一秒内请求两三页就了不起了攻击脚本可以做到一秒几十上百次。你把 access log 按 IP 分组统计请求次数top 的几个 IP 如果每次刷新都在增长基本就是攻击源。这里要注意CDN 开启后你看到的 IP 可能是 CDN 节点的地址需要结合 CDN 日志或回源日志做二次判断否则容易误伤 CDN 节点。请求路径高度集中。CC 攻击通常会盯着几个特定接口打比如登录接口、搜索接口、商品详情接口。原因很简单——这些接口基本都需要查数据库、做复杂逻辑资源消耗大打一个顶十个。如果你发现某个本来正常的接口请求量突然暴增几十倍得立刻查是业务推广了还是被 CC 了。判断方法很简单对比请求来源、频率分布和转化率推广流量会带来成交量CC 流量只有消耗没有产出。2.3 借助外部位点工具辅助判断遇到紧急情况来不及登录服务器看日志时我通常会先在外网用第三方拨测工具做快速判断。从不同地域的多个节点发起 HTTP 请求观察响应时间和成功率。如果全国多地域都超时或 5xx说明服务已经整体不可用如果只有部分地域异常可能是链路问题而非攻击。同时对比移动网络和宽带网络的访问情况能进一步缩小范围。外部位点有个好处它是从攻击者视角看你服务的可用性比你自己在服务器上敲命令更接近用户的真实体验。但要注意拨测工具本身也有局限只能说明“服务不可用”不能直接判定攻击类型。判定类型还是得回服务器看数据。2.4 快速判断是 DDoS 还是 CC把关键特征列成一张表方便对照排查判断维度DDoS 带宽型CC 应用型带宽占用瞬间飙高持续在峰值正常或略高服务器负载正常或偏低CPU、内存持续高位数据库状态基本正常连接数爆满慢查询增多连接特征SYN 半连接大量堆积完整 HTTP 请求大量出现请求内容数据包无意义协议层攻击看似正常的 HTTP 请求日志特征大量握手失败记录特定 URL 请求次数暴增攻击成本高需要大量带宽资源低少量主机即可造成较大影响用这张表对照大多数情况下 10 分钟内就能判断出攻击类型。如果两个特征交叉出现比如带宽飙高且 CPU 也爆了大概率是混合攻击——DDoS 打底CC 跟进补刀。这几年混合攻击越来越常见防御时不能只防一层。3. 防御体系建设从接入层到应用层的分层对抗防御的核心原则是分层设防。不要指望某单一产品把所有攻击都挡住这不现实。我正常的防御架构分四层接入层负责流量清洗网络层负责协议栈加固Web 层负责应用过滤业务层负责逻辑兜底。每一层解决一个层面的问题。3.1 接入层高防 IP 与流量清洗中心面对带宽型 DDoS普通服务器没有任何硬扛的资本。你一个 10G 带宽的服务器攻击流量打到 20G神仙来了也扛不住。唯一可行的方案是把流量引到具备超大带宽清洗能力的节点让攻击流量在到达源站之前被丢弃。高防 IP 的基本原理是 DNS 解析把流量引入高防机房清洗设备实时分析流量特征把攻击包丢弃把正常流量回源到你的服务器。选择高防 IP 时务必关注三个指标最大防护能力、清洗算法、回源带宽。防护能力要大于你日常峰值的 3 倍以上留足余量清洗算法最好支持 TCP 协议栈行为分析回源带宽决定了清洗后的正常流量能否完整回到源站这个参数常被忽略但实际上回源带宽不够照样会把正常用户卡在门外。接入高防后还需要把源站 IP 藏好。攻击者一旦通过其他渠道拿到源站 IP可以直接绕过高防打源站这就是所谓的“绕过防护”。常见做法是仅在防火墙放行高防节点 IP 段其他来源全部拒绝同时关闭源站的非业务端口减小暴露面。3.2 网络层内核参数与防火墙规则加固接入层之外服务器自身的网络层加固也很重要。即使流量清洗帮你挡住了大头但仍可能有少量漏网流量打到源站如果源站自身的协议栈没有加固这些零散的 SYN 包就能把系统搞瘫痪。Linux 服务器上我常用这么几个内核参数调整都是经过多轮实战验证的net.ipv4.tcp_syn_retries 适当减小降低 SYN 重传次数加快半连接清理net.ipv4.tcp_max_syn_backlog 增大允许更多半连接排队配合反向代理使用效果更好net.ipv4.tcp_fin_timeout 调低加快 TCP 连接释放。这些参数不会是万能的但可以显著提高系统在异常连接风暴下的存活率属于“无成本提升抗打击能力”的基础操作。防火墙规则方面通常的做法是封禁 ICMP 协议避免被用于反射放大攻击限制单 IP 的并发连接数用 iptables 的 connlimit 模块即可实现DDoS 高发期主动封禁海外异常 IP 段。这层防御的价值在于“兜底”把清洗中心漏掉的零散攻击流量挡住给 Web 层争取处理时间。3.3 Web 层反向代理、限频与验证码CC 攻击的对抗主战场在 Web 层。攻击者伪装成正常用户发 HTTP 请求但他们的行为和真实用户有明显区别——请求频率高、不加载静态资源、不走正常交互路径。识别这些差异并加以限制是 CC 防御的核心思路。我用 Nginx 做 Web 层防护时首先开启 limit_req 模块做 IP 级别的请求频率限制。以一个典型的 API 接口为例limit_req_zone $binary_remote_addr zoneapi_limit:10m rate10r/s; server { location /api/ { limit_req zoneapi_limit burst20 nodelay; limit_req_status 429; proxy_pass http://backend; } }这段配置限制单个 IP 每秒最多 10 次请求瞬时超过允许最多 20 个突发请求排队超出部分直接返回 429。对于绝大多数 Web 应用单个用户每秒请求 10 次是绝对够用的如果某些场景需要更高的频率比如轮询接口就把阈值适当上调但一定不能取消限制。IP 级别的限频有天然的弱点——攻击者可以分布大量 IP 绕开。更可靠的做法是配合会话识别和验证码机制。具体操作是在 Nginx 层识别无 Cookie 的请求、无 Referer 的请求、访问频率超出人工操作极限的请求将这些流量导向验证码页面。验证码会增加攻击成本让对手必须接入打码平台从而拉高攻击代价。自己开发成本高的话直接用现成的防 CC 模块就能在 Web 层挡住大部分低端 CC。同时开启 Nginx 访问日志的详细记录方便事后分析攻击来源和攻击路径。没有日志的防御是盲人摸象——流量被挡了但攻击请求长什么样、从哪来、打哪个接口一概不知下一次攻击来了照样抓瞎。3.4 业务层接口级防护与资源优化最高效的 CC 防御不只在网络层和 Web 层还要深入业务代码本身。很多开发者把防御思路局限在“外部拦截”忽略了“自身强壮”这个维度。同样一个接口处理请求的代价从 10ms 优化到 1ms服务器能承受的攻击流量就扩大 10 倍。这是最扎实的防御。数据库层的防护优先级最高。CC 攻击对资源的消耗真正的大头常常在数据库。同样一个查询如果走缓存单次耗时可能是零点几毫秒如果绕过缓存查库并做全表扫描可能是几百毫秒消耗差异上百倍。建议针对热点接口设置多级缓存尤其是商品详情、列表页这类常见被打目标。静态资源直接上 CDN 并通过 Nginx 直接返回不回源。动态接口可以做参数级校验减轻无效请求的消耗。比如一个查询接口要求必须传入合法的分页参数和必要的鉴权字段非法请求直接返回参数错误不进入业务逻辑。这个思路很多人都清楚但执行得慢结果防御效果也出不来。接口的鉴权、频率和参数校验必须放在业务逻辑的最前端而不是中间或最后。还有一点容易忽略异常请求的快速失败机制。比如某个接口正常情况下每天调用 1 万次突然涨到 100 万次业务层可以做熔断——直接拒绝后续请求返回“服务繁忙”保住核心链路不被打崩。这属于典型的“断臂求生”比整个服务全部宕机强得多。4. 实操复盘一次典型的混合攻击处理全程理论说多了容易飘我拿一次真实的处置过程来复盘把前文的知识点串起来。这起事件发生在某电商业务大促前的压测阶段攻击者选择这个时间点时机相当讲究。那是一个周四下午我正准备下班前巡检最后一轮监控。负载监控突然弹出告警Web 服务器 CPU 从平时 15% 的基线直接拉到接近 95%。第一反应是业务代码出了问题因为带宽监控显示正常总流量约 800Mbps对于这家业务体量来说不算异常。但我打开 Nginx access log 看一眼马上意识到不对——登录接口每秒请求数超过 3000 次正常峰值只有 200 左右并且请求来源分布在几百个 IP 上。确认了是 CC 攻击我按顺序做了四件事第一件事在 CDN 层临时开启全局频率限制单 IP 每 5 秒最多 30 次请求。这一步可以挡住相当一部分协议特征明显的攻击流量给后端的调整争取时间。效果立竿见影登录接口的请求量迅速降到了 500 次每秒。第二件事登录 Nginx 服务器把登录接口的 limit_req 阈值从正常值调整到 5r/s并开启验证码。有些研发和产品同学提出异议说会影响正常用户体验。我的回复是如果服务器被 CC 打崩所有用户都无法登录现在只是让部分异常用户通过验证码验证身份少数正常用户顶多多一次验证。两害相权取其轻。业务方同意了。第三件事分析 attack log定位攻击请求特征。我导出了最近 10 分钟的日志用数据分析脚本按 IP、User-Agent、Referer 分组统计。结果发现虽然源 IP 分散但 User-Agent 高度集中主要有两类并且请求时间间隔呈现出机器行为的固定节奏。顺着这个线索我直接在 CDN 层加了 User-Agent 过滤规则把这两类 UA 的请求全部拦截。这一步操作后攻击流量又降了一个量级。第四件事排查数据库连接数。CPU 降下来之后我发现数据库连接数还是很高慢查询里有大量重复的登录验证查询。判断是攻击流量已经把数据库连接池打穿存在大量未释放的连接。果断重启了连接池并调整了数据库最大连接数和查询超时阈值。重启后系统才算完全恢复。这四步操作从发现到处理完前后大约 40 分钟。业务实际影响是登录接口出现约 15 分钟的响应缓慢但未发生完全不可用。复盘这起事件我觉得有四个经验值得反复说第一判断攻击类型不能只看单一指标。我最初差点误判成代码问题就是只看了 CPU 而忽略了带宽对比。把带宽、CPU、连接数、日志几个维度放在一起看判断准很多。第二防御操作要分优先级。先做接入层临时限制再做后端限频最后做精细拦截。每一步立刻生效可以快速止血而不是花 20 分钟写一堆精确规则结果后台系统早就被拖垮了。第三业务方沟通是防御工作的一部分。限频可能会短暂影响用户体验如果不提前说清楚理由业务方很容易在压力下叫停防御动作。把技术判断翻译成业务语言内部沟通顺畅了打防御战才不会被自己人打断。第四攻击特征要数据化沉淀。这次用的 User-Agent 特征和请求节奏模式我写进了应急手册并固化成规则下次再遇到同类攻击直接套用。5. 常见误判与踩坑记录这些东西没人告诉你做防御的时间久了你会发现绝大多数问题不是“不知道怎么防”而是“不知道坑在哪里”。我把这几年踩过的坑、以及从同行那里收集到的常见误判整理一下每个都是花过代价换来的。5.1 误把推广流量当攻击电商大促期间运营同学通常会大量投放引流广告流量瞬间暴涨接口请求量和成交量同步上升。如果这时候不看业务指标就急着开启限频等于把花钱买的正常流量拒之门外。我的判断标准很简单请求量暴增但成交量、注册量等业务指标同步上涨十有八九是推广效果请求量暴增但业务指标纹丝不动才放心按攻击处置。5.2 只加防护不压测很多团队上线了高防 IP、加了 WAF 规则就以为万事大吉。结果攻击真来了高防把攻击流量挡在门外但正常流量回源时发现源站代码性能本来就差并发稍微上来一点就垮了。我见过不止一次——攻击被清洗了但站点依然打不开原因就是源站本身只能扛 100 并发而正常高峰需要 200 并发。防御体系上线后一定要做压力回源测试验证“清洗后正常流量能否扛得住”。这个测试建议每季度做一次因为业务代码在持续变化性能基线也在变。定期压测就像是给免疫系统做体检不能等病毒来了才检查。5.3 把所有防御寄托在某种单点方案上任何单一防护方案都有缺陷。高防 IP 挡得住带宽型打但防不住应用层的慢速 CCWAF 能识别规则型攻击但对大量低慢速请求Slowloris 类型攻击的应对能力有限代码层面的防护能力再强也挡不住对手把带宽打到几十 G 的纯粹资源消耗。理想架构是前面说的四层配合。虽然多一层防御就多一份成本但这笔钱不能省。安全建设的本质是风险管理用可控的投入换取业务可用性的确定性。5.4 对 UDP 反射攻击认识不足UDP 反射放大攻击是 DDoS 的重要类别攻击者向开放的 DNS、NTP、Memcached 等服务器发送源 IP 伪造成目标地址的小请求服务端回复的大流量就全部打向目标。这类攻击流量峰值可以做到放大几十倍甚至上百倍带宽型 DDoS 的“大场面”很多来自这种手段。识别特征主要是流量类型高度集中于 UDP、源端口相对固定。防御思路比较简单直接在网络层直接禁掉业务不需要的 UDP 端口需要用的则做 UDP 流量限速。大多数 Web 业务根本不需要对外提供 UDP 服务禁用后这类攻击基本也就废了。5.5 忽视日志事后无法溯源有些团队被攻击之后只关注“现在恢复没有”却忽略了“攻击是怎么打的”。攻击结束后日志里记录了完整的攻击特征这些是宝贵的分析资料。建议每次应急结束后导出完整日志形成一份包含攻击类型、攻击源特征、时间线、处置动作的复盘文档。做得多了你就会形成自己的攻击特征库下次再过招时可能不用登录服务器就能判断对方用的是什么套路。6. 防御的更高层次把安全能力做进系统设计聊完具体的对抗手段我想再往上拔一层。真正让站点难以被打瘫的因素不在于单次防御有多强而在于整体架构能不能承受局部失败。优先把静态资源全部放 CDN。CPU 密集型的图片缩放、文件压缩预处理放到离线任务去做不在线实时计算。数据库全部走连接池并设置合理的最大连接数防止连接被耗尽拖垮整个实例。核心服务做多节点负载均衡单点被攻击或宕机后流量自动切换。这些设计在平时只是在提升性能和稳定性在攻击场景下就是在提高生存概率。另外要明确的一点是安全投入的均衡性。对大多数中小站点来说花大钱买超大防护能力未必划算。攻击者盯上你的原因通常是“好打”而不是“你很重要”。把你的站点做得比同类站点更难打攻击者大概率就会换个目标。安全建设很像加固房门——你不需要做到银行金库级别只要比邻居家难撬小偷就会去撬邻居家。我自己秉持一个基本原则日常巡检多投入一分钟攻击来时就能少花一个小时。把监控告警、日志采集、应急演练这些“平时用不上”的事情做实做透关键时刻它们就是救命的东西。监控不是摆设告警不是骚扰它们是你在攻击发生时的眼睛和耳朵。很多团队的告警发出去没人看或者阈值设置不合理导致告警风暴最后运维人员对告警脱敏了真正出事时反而没人响应。一套靠谱的告警体系值得花时间打磨。最后再分享一个实操经验——把“攻击场景应急预案”写下来。内容包括攻击类型判断流程、操作步骤、责任人和沟通机制。平时每月花 10 分钟演练一次预案攻击真正发生时团队可以像肌肉记忆一样执行而不会乱成一团。从我的体感来说预案演练过的团队平均处置时间至少能缩短一半。这个投入是你为站点安全买的最便宜也最可靠的一份保险。