ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

DDoS攻击防御实战:从带宽耗尽到应用层CC攻击的应对指南

DDoS攻击防御实战:从带宽耗尽到应用层CC攻击的应对指南

DDoS攻击这事儿,我在某公司的业务运维岗位上折腾了快五年。从最开始被大流量打得完全懵圈,到后面能把攻击拆解、分层防御、带着团队做演练,中间踩过的坑比我写过的报告还多。所以今天这篇东西,不跟你讲操作系统里的百科词条,也不复读那些安全厂商的宣传手册,就聊聊我实际打防御战打出来的心得。标题里的核心关键词就是DDoS,但它的边界其实比你想象得宽得多,从单点几百兆的流量冲击,到打满你的CPU连接表,再到慢速攻击拖垮后端,攻击者总在换着花样试探你的底线。这篇文章适合正在搭建防御体系的后端和运维工程师,也适合那些刚接到“你来负责抗D”这个任务、兜里还没底的朋友,看完你至少能知道从哪儿下手、怎么排优先级、哪些钱能省哪些不能省。

1. 先把敌情摸清楚:DDoS攻击的真实面目

1.1 不是只有把带宽打满才叫DDoS

我在早年间有个很大的认知误区,以为DDoS就是把流量灌到带宽的上限,让正常的用户挤不进来。这个理解只对了一半。带宽耗尽确实是攻击的经典形态,但远不是唯一形态。实战中我遇到过四种打法,每一个都能让业务在用户端表现为“打不开”“卡死”“一闪而过空白页”。

第一种是流量型攻击,也是最直观的,用UDP洪水、TCP SYN Flood这类手段把入口带宽打满。第二种是连接耗尽型,不跟你抢带宽,而是把连接表撑爆,服务器连新建连接都做不到。第三种是应用层攻击,也就是常说的CC攻击,慢速请求、频繁查询、重放登录接口,这类攻击的流量通常不大,规模小的甚至只有几十兆,但能把CPU和数据库打挂。第四种是慢速攻击,比如Slowloris,跟你建立一个连接然后一直保持半开状态,占住线程不放手。

我自己经历过最有迷惑性的一次,就是某个业务下午突然响应很慢,排查了硬盘、数据库、缓存都没问题,最后看服务器并发连接数才发现,几千个来自不同IP的半开连接把工作线程全部占满。当时流量监控上几乎没有波动,但业务已经快死了。那次之后我定下一条铁律:把连接数堆叠情况和TCP状态分布纳入所有监控大盘,光看带宽阈值根本不够。

1.2 攻击者的资源从哪里来,决定了你面对的压力

理解攻击的资源来源,本质上是在给自己做风险预判。我实战下来,攻击者手里的“弹药”大概分三个档次。

第一档是单台肉鸡发起的小打小闹,打出来的效果通常有限,但这种攻击在测试阶段特别多,目的是探测你的防御姿态。第二档是僵尸网络,规模从几百台到几万台不等,能够产生几十Gbps到上百Gbps的流量,国内常见业务遇到的大多是这一档。第三档是反射放大攻击,攻击者向开放DNS、NTP、Memcached这类服务发送伪造源地址的小请求,放大几十甚至几百倍后砸向目标,这类攻击能把几百G的流量放大到几T,是最头疼的一种。

知道弹药档次有什么用?有大用处。防不住的时候你要判断对方是在试探还是真的要往死里打。我在一次年中活动前收到一封勒索邮件,说当天下午要打我们,还附了一个流量波形图。团队当场就启动了预案,跟云服务商确认了高防IP的弹性能力,然后业务侧做了跨机房容灾切换。结果对方就来了个两分钟的试探性攻击,看到我们直接把流量切走后就没再跟进了。这个判断不是靠直觉,而是依靠对攻击模型的既有认知加上预案。

1.3 数据链路俯瞰:从攻击者到你的业务

把攻击链捋清楚是防御思路的起点。简化来看,整个链路是攻击者控制端→控制僵尸网络或反射源→发起攻击流量→经过网络链路→进入你的接入层→穿透到后端服务。防御方的核心思路就是在链路上找可以拦截和缓冲的位置,越靠近攻击源拦截成本越低,越靠近业务拦截效率越可控,但绝对没有一种单点方案能独立扛下所有攻击。

我习惯把整个链路切成三段来看:链路层、接入层、应用层。链路层对应到运营商和云服务商的骨干网络,能在这里做清洗就最理想,相当于在源头把洪水导流掉。接入层对应到你的公网入口、负载均衡和防火墙,可以在这里做限速、黑白名单、协议校验。应用层对应到业务服务本身,需要靠限流、熔断、缓存设计来兜底。防御体系的核心就是把这三段的动作串起来,而不是把希望寄托在某一台设备上。

2. 防御体系的设计思路:为什么堆硬件不是最优解

2.1 分层防御的总体架构

我最早接触DDoS防御的时候,第一直觉也是去买台硬件防火墙,一台号称能扛几百G流量的设备放在机房里,心里就觉得稳了。后来现实教育了我。先不说硬件设备的清洗能力在真实流量下会不会打折,单说流量打到几百G的时候,机房上联带宽本身就不够,设备再好也没有用,因为流量根本到不了你手里,你机房的上联就已经被灌满了。

从那时候开始,我转向了分层防御的思路。典型的分层结构是这样:最外层是云清洗或高防IP,负责处理大流量攻击,把流量先引到具备大带宽清洗能力的节点,过滤后再把干净流量回源到你的机房;中间层是机房入口的流量分析设备和防火墙,负责拦截过了清洗但仍存在风险的部分;最内层是应用自身的防护,比如Web应用防火墙、接口限流、动态令牌,负责应对CC和慢速攻击。云清洗管“大”,接入层设备管“准”,应用层管“精”,三者各司其职。

2.2 为什么单靠带宽冗余不够

很多刚入行的人会有一个朴素的思路:把带宽买大一点,不就能硬扛了吗。理论上没错,但算一笔账你就不这么想了。某个核心业务日常带宽占用是2Gbps,为了扛住一次可能高达100Gbps的攻击,直接把带宽永久性地买大到100Gbps,价格不是几倍增长而是几十倍增长。还是同样那句话,流量到达你的机房之前,你的上联带宽就已经决定了极限。就算你愿意花这个钱,防火墙的会话处理能力、CPU的处理速度也会成为新的瓶颈。

我做过的成本测算里面,自建硬扛只在攻击规模预计不超过自身带宽三到五倍的前提下是合理的,超过这个量级,把流量交给云清洗显然划算得多。更现实的是,攻击是突发的,不是常态,带宽平时用不满的时候基本都是浪费,所以更务实的方案是把基础带宽保持在日常水位,把弹性能力放在云侧。相当于平时自带宽带够用,被打了才把流量动态牵引到云端清洗节点,洗完了再送回来。

2.3 选择云清洗和高防IP时的三个权衡点

用云服务商的高防IP需要做三个权衡,这些全是我实际踩过的坑凑出来的经验。

第一个权衡点是回源方式。推荐使用主备回源加健康检查的方式,清洗节点在前端做负载,源站出问题时能自动切换。我一开始贪简单,直接做了单回源地址,结果清洗节点健康检查一抖动,整条链路全断。

第二个权衡点是防护性能和套餐峰值的关系。高防IP宣称的峰值是“尽力而为”的,同一个清洗节点上的其他客户被攻击时,大家会共享资源池。所以我选择时不会卡着峰值来,会留三成到五成余量,否则阈值被击中后直接进入黑洞,业务就完全不可用了。

第三个权衡点是流量牵引的切换时间。好的清洗节点切换必须在攻击峰值前完成,这个“提前”完全依赖监控和自动化。我在演练中发现,攻击发生到切换完成如果超过一分钟,业务侧的请求错误率就会明显上升。所以必须把切换动作自动化,不能等人工看到告警再登录控制台去点。

3. 实战拆解:一套我自己验证过的抗D方案

3.1 云侧清洗的落地配置参考

我负责的某个核心业务,日常带宽水位在1.5Gbps到2Gbps之间,公网入口是一些直接面向用户的服务。经过对比之后,最终选择的方案是云高防IP加源站负载均衡,架构是:用户流量→云清洗节点→回源到源站负载均衡集群→分发到后端服务节点。

这里有一个关键配置点是回源段IP的放行。因为高防IP回源到源站时,源IP是固定的回源段,所以源站的防火墙必须把安全组和系统防火墙策略调整成只放行回源段IP和运维跳板机IP,其他地址一律拒绝。如果这一步不做,就会出现两种情况:攻击流量穿透清洗节点后,直接绕过策略打到源站,源站还是会被打垮;或者清洗节点回源的真实流量被误杀,业务直接断掉。这个我在初期就吃过亏,放行策略写得太宽,结果攻击者知道了源站IP之后,直接绕过高防IP打源站,防御变成了虚设。

具体配置上,我把清洗节点的高防IP绑定到域名解析,源站IP不做任何公网暴露,运维和API调用的域名单独解析到另一套非核心业务入口上。同时打开TCP选项中的ACL防护、UDP分片过滤,并把ICMP协议直接丢弃,这类控制报文在真实业务中基本不需要透传。

3.2 接入层服务器的内核参数调优实录

云侧清洗也只是第一层屏障,真正到了源站的部分,服务器也得自身硬。在源站服务器的Linux内核设置上,我调优过几个非常关键的参数,这里直接写出来供参考。

# 开启SYN Cookies,严重SYN Flood时内核能自动丢弃一些半连接 sysctl -w net.ipv4.tcp_syncookies=1 # 提高SYN队列容量,让大量半连接有机会被处理而不是直接丢包 sysctl -w net.ipv4.tcp_max_syn_backlog=65535 # 提高全连接队列长度,让应用层有足够时间处理请求 sysctl -w net.core.somaxconn=65535 # 加快TIME_WAIT状态的回收和复用,降低连接表占用 sysctl -w net.ipv4.tcp_tw_reuse=1 sysctl -w net.ipv4.tcp_fin_timeout=15 # 扩大本地端口范围,避免高并发下端口耗尽 sysctl -w net.ipv4.ip_local_port_range="1024 65535"

这几个参数每组都不是随便调的。第一个参数SYN Cookies,是内核在SYN队列满时自动启动的机制,能扛住部分SYN Flood,但对CPU有额外开销,所以不能配置成无条件开启。第二个和第三个是队列长度,要根据前面负载均衡的转发策略来调整,如果入口直接是Nginx,两者的合理值是相互配合的,只调一个作用有限。第四个参数里的tcp_tw_reuse只对客户端角色生效,在纯服务端场景下意义不大,但如果源站同时也在向上游发起请求,效果就会显现出来。

调优后我有一次特别深的感受,某个晚上来了一个大约4Gbps的SYN Flood,清洗节点扛掉了绝大部分,回源到源站的只有很小一部分,但即使很小,也让源站连接数明显飙升。当时那些内核参数帮我兜住了底,业务只是变慢没有挂掉,等攻击结束后几十秒就恢复了。如果当初没有调优过,那一轮可能直接就雪崩了。

3.3 应用层限流与熔断的实操细节

应用层的防护是最后一道防线。我的习惯是在Nginx层面做连接和请求的双重限制,同时在后端服务里埋入信号量限流和熔断逻辑,防止数据库被慢查询拖垮。

Nginx层的关键配置我给出一个精简但可以落地的骨架:

# 每个IP的并发连接数限制,防止CC攻击耗尽工作线程 limit_conn_zone $binary_remote_addr zone=perip:10m; server { listen 80; server_name app.example.com; limit_conn perip 20; # 每个IP的请求速率限制,超过后直接返回503 limit_req_zone $binary_remote_addr zone=perip_req:10m rate=10r/s; limit_req zone=perip_req burst=20 nodelay; location / { proxy_pass http://backend_upstream; proxy_connect_timeout 5s; proxy_read_timeout 10s; } }

这里有一个非常容易踩的坑:limit_req写好后,正常用户也会偶尔被限流,尤其在活动高峰期。我刚开始上线时,阈值设得太激进,结果活动一开始大量真实用户被503拦截,后台告警直接爆炸。后来我把rate调宽,同时把burst调成正常波峰的1.5到2倍才平衡下来。限流的本质是牺牲很少一部分峰值请求来保护系统整体,这个度要拿捏好。

后端应用里的熔断逻辑同样关键。我用的是一个简单的计数器模式:统计最近10秒内的失败请求数,如果超过100次就把该接口标记为熔断状态,所有请求直接返回兜底数据或快速失败,而不是打进数据库加重负载。熔断之后定时探测接口是否恢复,恢复后才放量。这个方法看起来简单,但在实战中救了我好几次命。

4. 应急响应与常见问题排查实录

4.1 从告警到恢复:一次完整应急演练的过程记录

2024年下半年我组织团队做了一次无预告应急演练。我当时只告诉值班组“可能有突发情况”,没有说具体时间。等到下午两点半,我让一个测试脚本开始持续请求业务入口,同时由网络组配合压制部分带宽,业务侧的告警系统瞬间被触发。

最开始的3分钟,值班同事按照SOP检查了机房带宽、负载均衡、源站CPU。发现带宽占用并没有异常,但请求错误率已经在攀升。排查到第5分钟,发现高防IP的控制台显示“防护阈值告警”,因为测试流量已经触发了清洗规则。第7分钟,自动牵引脚本被触发,流量在清洗节点完成识别后回源,错误率开始回落,第12分钟业务完全恢复。

整个演练复盘给我的核心教训是:告警确认慢是最大的瓶颈。我们排障过程有将近一半时间浪费在“确认这是不是攻击”上,而不是直接跑启动预案。后来我在SOP第一页加了一行字:“看到带宽异常或错误率陡增且无对应变更时,先启动应急预案再排查根因。”这个顺序的改变,让真实出警时间缩短了差不多60%。

4.2 我踩过的三个最隐蔽的坑

第一个坑是清洗节点的黑洞策略。高防IP一般在攻击流量超过套餐峰值或按量付费阈值时,会自动进入黑洞,把所有流量直接丢弃。一开始我没有配置好告警阈值和黑洞恢复时间,结果一个客户被攻击,整个业务入口IP被黑洞掉,所有用户全部无法访问,时间长达30分钟。后来我把高防套餐升级到了带弹性能力的版本,并设置了独立的黑洞告警通道,这以后再没有出现过黑洞长时间无人知晓的问题。

第二个坑是回源健康检查被攻击流量干扰。清洗节点需要不断检查源站是否健康,这些健康检查请求本身看起来也像流量。有一次源站防火墙误把清洗节点的健康检查IP当成了攻击源给拉黑了,结果清洗节点判定源站宕机,把入口IP直接切换到了备用节点,备用节点没有对应业务配置,用户访问直接报502。解决方法是把清洗节点的健康检查源IP做成白名单,写入系统防火墙和云安全组的最前面。

第三个坑是业务侧自己引发的“伪DDoS”。简单说就是某个热门活动或定时任务在整点触发大量并发请求,看起来就像一场CC攻击。我遇到过好几次,刚开始也以为是被人打了,排查半天发现是内部数据同步任务没有做限速。所以我后来要求所有定时任务上线前必须做压测,并在网关层预留一个“内部任务专用”的限流通道,从根上规避这类误报。

4.3 日常监控指标:哪些数字是救命信号

监控做得好不好,直接决定应急响应的速度。我梳理出一个最小但不漏项的监控指标集,这些数据在攻击发生时都是救命信号。

指标项正常基线攻击表征建议监控周期
入口带宽利用率30%以下突然打满,持续不走低1分钟
TCP SYN队列长度低水位长时间处于高水位10秒
TCP连接状态分布TIME_WAIT较多SYN_RECV暴涨10秒
源站CPU负载日常波动快速飙升或持续高负载30秒
应用层请求错误率小于0.1%陡增到1%以上30秒
高防IP清洗流量占比无清洗量突然占大头1分钟

这里面最容易忽略的是SYN_RECV这个状态。一次正常的用户请求会在几秒内完成握手进入ESTABLISHED,大量SYN_RECV堆积在半队列里,是典型的SYN Flood特征。我监控系统里专门加了一条规则:SYN_RECV数量超过阀值持续30秒,自动触发高优告警,这条规则帮我提前发现了至少三波试探性攻击。

4.4 常用排查命令与工具速查

应急排查时,我一般直接用标准Linux工具链就能完成大部分工作。这里整理几个高频使用的命令,方便大家直接查。

# 查看实时带宽占用 nload -m # 查看当前TCP连接状态分布 ss -ant | awk '{print $1}' | sort | uniq -c # 查看SYN队列当前堆积情况 ss -lnt | grep -c SYN-RECV # 查看Nginx当前活跃连接数 curl -s http://127.0.0.1/nginx_status | awk '/Active/{print $NF}' # 抓取当前与某个IP的通信流量特征 tcpdump -n -i eth0 host 192.0.2.10 -c 1000

tcpdump那一条要注意样本量,抓太多会生成大文件,安全做法是先抓个几百包分析特征,再决定是否持续。这些命令在平时要多练,真到告警炸锅的时候,脑子里要能自然反射出来该敲哪一个。

5. 日常运营经验:如何让防御体系不沦为摆设

5.1 定期演练的必要性与频率

防御体系最怕的就是从上线那天起就没人再碰它,等到被攻击时才想起来,大概率已经晚了。我规定团队每季度至少做一次完整攻击模拟演练,覆盖流量攻击、CC攻击、源站被打这三个场景。每次演练按真实事件的流程走,包括通知、接管控制台、执行应急预案、事后复盘。

演练的收获不仅是验证设备配置和流程,更重要的是让团队形成肌肉记忆。我之前碰到过一次真实攻击,值班同事能在一分钟内完成流量牵引,靠的是连续三次演练养成的熟悉度。没有演练过的团队,第一次面对攻击时,手点在哪个菜单都不确定,更别谈快速恢复。

5.2 情报共享与攻击趋势跟踪

很多公司做好了内部防御就以为万事大吉,但攻击者的手法是在不断迭代的。我日常工作里会花两到三成的时间跟踪外部情报,包括攻击趋势公告、常见漏洞利用报告、新型攻击手法分析。这些情报不一定要买高价的商业服务,公开渠道里已经有很多有价值的信息可参考。

举个真实的例子。前年某个安全社区爆出大量开放在公网的数据库服务被利用发起反射放大攻击,我当天就检查了我们所有公网入口是否暴露了相关端口,发现有一台老旧数据库的备份复制端口确实暴露在外网,立刻做了安全组限制,堵了一个潜在的放大器。这一步几乎没花成本,但它让我的防御墙少了两个主动被利用的破绽。

5.3 成本控制与预算的合理分配

DDoS防御经常被看成纯烧钱项目,但实际上钱花在刀刃上,才能做到性价比最优。我的建议是:把预算大头放在云清洗能力上,因为这是大流量攻击时唯一能扛住的方案;中间层用开源软件加合理的服务器配置就能解决,不必买高价商业设备;应用层的限流和熔断,本质上花的是研发工时,这部分投入最容易被忽视,但反而是灵活性最高的防线。

另外要给“不可用时间”标价。比如瞬时不可用5分钟的损失是多少钱,不可用1小时的损失又是多少,按这个倒推你愿意在哪些环节加预算。这个方法看起来像是在做财务工作,但确实是说服上级批预算最有力的方式。我拿这个逻辑成功申请过云清洗的弹性扩容包,一年里真正用到的次数不多,但每一次都帮业务挽回了远超成本的损失。

6. 写在最后:防御心态比防御技术更重要

我做了这么多年DDoS防御,技术方案迭代了很多轮,但最深的体感是:防御心态比堆技术更重要。DDoS不是一次性的问题,它是一场持续性的动态对抗,攻击者的工具在变,防御者的策略也永远在追。单次打赢一场防御战并不代表什么,真正有价值的是把防御变成一个可以被演练、衡量、优化的流程。

另一个心态是别追求“绝对安全”。DDoS攻击没有彻底防御这个说法,正常业务的真实用户特性就和攻击流量高度相似,你不可能杀死所有可疑请求而不误伤正常用户。防御的目标是把攻击影响控制在可接受的范围内,让业务在极端情况下依然能服务绝大多数正常用户,而不是追求一个不被任何流量打垮的幻想。

根据我个人的实际经验,每次被攻击之后,不要急着让事情过去,一定要花至少半小时复盘,记录攻击的类型、影响面、防御动作的耗时和效果。日积月累下来,这套复盘记录就是整个团队最宝贵的安全财富。下次再遭遇攻击时,你能在第一分钟就判断出“这是什么打法”“应该按哪套预案走”,那种从容感,就是平时积累换来的底气。

返回列表