DDoS防护实战:从攻击场景到分层拦截的完整体系
1. 从真实攻防视角理解DDoS:为什么它至今仍是最头疼的问题
搞过线上业务的人都有一个共识:DDoS攻击(分布式拒绝服务攻击) 这东西,技术含量未必最高,但恶心程度绝对排前列。它不像数据泄露那样悄无声息,也不像勒索病毒那样直接要钱,它的逻辑非常粗暴——用海量垃圾流量把你的带宽、连接数、CPU、数据库连接池全部占满,让正常用户根本进不来。你花几个月打磨的产品,可能被一波持续十分钟的攻击直接打到不可用。
我最早接触DDoS是在一个电商大促项目上。当时凌晨两点,监控告警疯狂响,源站带宽被打满,Nginx的active connections从平时的几百飙升到几万,后端Java服务的线程池全部耗尽,用户下单页面直接502。事后复盘发现,攻击流量峰值大概在40Gbps左右,混合了SYN Flood和HTTP Flood两种模式。那次之后我才真正意识到,DDoS防护不是“买个高防就完事”的简单命题,而是一套从网络层到应用层、从架构设计到应急响应的完整体系。
这篇文章我想聊的不是教科书上的DDoS分类,而是真实攻击场景下,攻击者到底怎么打、我们该怎么防。核心会围绕几个关键词展开:DDoS检测、攻击场景、API防护、CDN调度、内网攻防。适合正在做后端开发、运维、安全防护的同行参考,也适合产品经理和创业者了解自己业务的真实风险面。不管你是刚接触安全的新手,还是已经踩过几次坑的老兵,下面这些从实战里抠出来的细节,应该都能让你少走点弯路。
2. DDoS攻击的典型场景拆解:攻击者到底在打哪里
2.1 流量型攻击:带宽打满是最直接的死法
流量型攻击的核心目标就一个——把你的入口带宽吃干净。最常见的两种是UDP Flood和ICMP Flood,攻击者通过大量肉鸡向目标IP发送无用数据包,占满上行和下行的带宽资源。这类攻击的特点是流量特征明显,峰值动辄几十G甚至上百G,但技术门槛低,网上现成的工具一大把。
我实测过一个模拟环境,用几台云主机跑hping3对一台测试机发UDP Flood,不到30秒,目标机的入站带宽就从1Mbps飙到接近100Mbps,正常SSH连接直接卡死。这个实验说明一个问题:如果你的业务入口没有足够的带宽冗余和清洗能力,流量型攻击几乎是无解的。你自己机房的带宽再大,也扛不住对方用僵尸网络堆出来的流量。
注意:流量型攻击的防护重点不在源站,而在于入口处的流量清洗。指望在服务器上装个软件防火墙来扛几十G的流量,基本等于用脸接拳头。
2.2 连接型攻击:SYN Flood与连接池耗尽
比流量型更“聪明”一点的是连接型攻击,典型代表是SYN Flood。攻击者发送大量伪造源IP的SYN包,服务器回复SYN-ACK后等待ACK,但攻击者根本不回,导致服务器维护大量半连接队列,最终队列满,正常用户的连接请求被丢弃。
这个问题在Linux上有个经典的内核参数可以缓解:net.ipv4.tcp_syncookies = 1。开启后,内核在SYN队列满时会用cookie机制验证连接,而不是直接丢弃。但我要提醒一句,syncookies只是缓解手段,不是根治方案。如果攻击流量足够大,CPU会被大量SYN包的处理逻辑拖垮。更稳妥的做法是在入口层用负载均衡设备或云清洗中心做SYN代理,让清洗设备先完成三次握手,再把完整连接转发给源站。
2.3 应用层攻击:HTTP Flood与API滥用
这是目前最让人头疼的一类,因为它看起来像正常流量。攻击者用大量代理IP,模拟真实用户请求你的API接口,比如登录、搜索、下单。每个请求都合法,但量级远超正常业务。你的Nginx可能扛得住,但后端的Java服务、数据库连接池、Redis缓存会被瞬间打爆。
我遇到过最阴的一次是攻击者专门打/api/v1/user/login这个接口,QPS从正常的200飙到8000,每个请求都带完整的Header和Cookie,看起来跟真用户一模一样。当时我们的WAF规则没来得及更新,源站直接被拖垮。后来复盘发现,攻击者用的是分布式的代理池,IP段分散,单IP限流根本拦不住。
这类攻击的防护重点在于行为分析和速率控制。单纯靠IP限流不够,要结合设备指纹、请求频率、参数特征做综合判断。比如同一个接口,正常用户的请求间隔通常在秒级以上,而攻击脚本可能在毫秒级重复调用。通过统计单位时间内的请求分布,可以识别出异常模式。
2.4 反射放大攻击:DNS与NTP的“帮凶”角色
反射放大攻击的原理是利用UDP协议的无连接特性,攻击者伪造受害者IP向开放的DNS或NTP服务器发送小请求,服务器返回大响应,流量被放大几十甚至上百倍后打到受害者身上。一个典型的DNS放大攻击,请求可能只有60字节,响应却有3000字节,放大倍数接近50倍。
这类攻击的防护有两个方向:一是关闭不必要的UDP服务,尤其是对外暴露的DNS递归查询和NTP服务;二是在入口做UDP流量限速和特征过滤。很多云厂商的高防IP默认会拦截异常的UDP大包,但如果你用的是自建机房,就需要自己在边界路由器上做ACL规则。
2.5 内网横向攻击:被忽视的“后院起火”
大部分讲DDoS的文章都在说外部攻击,但内网攻防防护同样重要。我见过一个案例,攻击者先通过一个弱口令拿下一台边缘服务器,然后在内网发起ARP欺骗和流量泛洪,导致核心业务网段瘫痪。这种攻击从外部看流量不大,但内部已经被搅得天翻地覆。
内网防护的重点在于网络分段和流量基线监控。把Web层、应用层、数据层放在不同的VLAN,限制跨网段的直接通信。同时建立正常的流量基线,一旦某个内网IP的流量突增或出现异常端口扫描,立即告警。别觉得内网就是安全的,很多大事故都是从内网一台不起眼的机器开始的。
3. 防护体系的核心思路:分层拦截,别把鸡蛋放一个篮子
3.1 为什么单一防护手段必然失效
很多人对DDoS防护的理解还停留在“买个高防IP”的阶段。高防IP确实能扛流量型攻击,但它对应用层攻击的识别能力有限。同样,WAF能拦HTTP Flood,但对SYN Flood无能为力。没有任何一种单一手段能覆盖所有攻击场景,这是由DDoS攻击的多样性决定的。
我的经验是,防护体系必须分层:网络层做流量清洗,传输层做连接代理,应用层做行为分析,数据层做降级预案。每一层只解决自己擅长的问题,层与层之间通过CDN和负载均衡串联起来。这样即使某一层被突破,后面的层还能兜底。
3.2 CDN在DDoS防护中的真实价值
CDN在DDoS防护里的角色经常被低估。很多人觉得CDN只是加速静态资源的,其实它天然具备分布式吸收流量的能力。攻击者打你的源站IP,但你的域名解析到CDN节点,流量先打到CDN的分布式节点上,源站IP根本不暴露。CDN节点通常有较大的带宽储备和清洗能力,能吸收掉大部分流量型攻击。
但CDN防护有个前提:源站IP绝对不能泄露。我见过太多案例,攻击者通过历史DNS记录、邮件头、第三方接口等方式找到源站真实IP,然后绕过CDN直接打源站。所以一旦接入CDN,就要确保所有对外服务都走CDN回源,源站防火墙只允许CDN回源IP段访问。
提示:定期检查你的源站IP是否在公网可直连。可以用在线工具从外部扫描你的源站IP,如果发现80/443端口直接开放,说明CDN配置有漏洞。
3.3 API防护的特殊性:为什么传统WAF不够用
API接口的DDoS防护比普通网页复杂得多。网页请求有静态资源、有浏览器指纹、有Referer,而API请求往往是纯JSON或表单,Header可以伪造,User-Agent可以随便改。攻击者用脚本模拟API调用,传统WAF基于规则的匹配很容易被绕过。
更麻烦的是,很多API接口本身就有高频调用的业务需求,比如股票行情推送、实时消息拉取。你没法简单地把高频请求全部拦掉,否则正常业务也挂了。这时候需要基于业务逻辑的速率控制:比如按用户维度限流、按接口维度限流、按参数组合限流。同一个用户Token,每秒最多调多少次;同一个IP,每分钟最多调多少次;同一个手机号,每天最多发多少次验证码。
我在Java的Controller层做过一套简单的防护逻辑,核心思路是在拦截器里做令牌桶限流,结合Redis记录调用频次。代码不复杂,但效果很直接:
这段代码的关键在于滑动窗口而不是固定窗口。固定窗口在窗口切换时会有双倍流量的突刺问题,滑动窗口则平滑得多。当然,这只是应用层防护的一小部分,真正的API防护还需要结合网关层的限流、WAF的规则、以及CDN的边缘计算能力。
3.4 检测能力:没有告警的防护等于没有防护
DDoS检测是防护体系的眼睛。你连攻击什么时候来、打哪里、流量多大都不知道,谈何防护?检测的核心是建立基线,识别偏离。正常业务在每天的同一时段,QPS、带宽、连接数都有相对稳定的范围。一旦某个指标突然偏离基线超过阈值,就应该触发告警。
我通常会在几个关键位置埋监控点:入口路由器的流量镜像、Nginx的access_log和error_log、Java应用的QPS和线程池状态、Redis的连接数和慢查询、MySQL的活跃连接数。这些数据汇总到监控平台,设置动态阈值告警。比如Nginx的5xx错误率在1分钟内超过5%,或者Java线程池的活跃线程数超过80%,就立即通知值班人员。
检测的难点在于区分正常业务高峰和攻击流量。大促期间QPS本来就会涨,如果阈值设得太死,会误报;设得太松,真攻击来了又发现不了。我的做法是结合多个指标综合判断:如果QPS涨了但转化率没降,可能是正常流量;如果QPS涨了、转化率暴跌、且请求来源IP分散,那大概率是攻击。
4. 实操落地:从零搭建一套可用的DDoS防护方案
4.1 架构设计:CDN + 高防 + WAF + 源站隐藏
一套完整的防护架构,从外到内大概是这样的:DNS解析到CDN,CDN回源到高防IP,高防清洗后转发到WAF,WAF过滤应用层攻击后到达源站。源站本身只允许WAF的回源IP访问,公网无法直连。
这个架构的好处是每一层各司其职。CDN负责分布式吸收和静态缓存,高防负责流量清洗和连接代理,WAF负责应用层规则过滤,源站只处理干净的业务请求。成本上,CDN按流量计费,高防按月或按峰值计费,WAF按域名或QPS计费,可以根据业务规模灵活组合。
但要注意,层数越多,延迟越大。每经过一层代理,都会增加几毫秒到几十毫秒的延迟。对于延迟敏感的业务(比如实时对战游戏),可能需要简化架构,把清洗能力下沉到离用户更近的边缘节点。
4.2 源站隐藏的具体操作步骤
源站隐藏是整套方案的基础,如果源站IP暴露,前面所有防护都是白搭。具体操作步骤如下:
- 更换源站IP:如果原IP已经暴露,先换一个新的公网IP,确保历史记录里没有关联。
- 配置CDN回源:在CDN控制台设置回源地址为新IP,回源端口只开放必要的80/443。
- 源站防火墙白名单:在源站服务器的iptables或安全组里,只允许CDN和高防的回源IP段访问,其他一律DROP。
- 检查信息泄露:检查网站的邮件头、API返回的Header、错误页面、第三方统计代码,确保没有泄露源站IP。
- 定期扫描验证:用外部端口扫描工具定期扫描源站IP,确认没有意外开放的端口。
注意:很多云厂商的负载均衡器会默认在响应头里带上真实IP,接入CDN后要在负载均衡器上关闭这个Header,否则攻击者通过响应头就能找到源站。
4.3 Nginx层的防护配置
Nginx作为源站的第一道入口,可以做很多轻量级的防护。以下是我在生产环境验证过的配置片段:
limit_conn和limit_req是Nginx自带的模块,配置简单但效果明显。limit_conn限制单IP的并发连接数,防止一个IP占用过多连接;limit_req限制单IP的请求速率,用令牌桶算法控制。burst参数允许一定的突发流量,nodelay表示突发流量不延迟处理。这两个参数要根据业务实际情况调整,设得太小会误伤正常用户,设得太大又起不到防护作用。
4.4 Java应用层的防护要点
到了Java应用层,防护的重点从流量转向了业务逻辑和资源控制。我总结了几条实战经验:
- 线程池隔离:不同的API接口用不同的线程池,防止某个接口被攻击时拖垮整个应用。比如登录接口用一个线程池,查询接口用另一个,互不影响。
- 信号量限流:用
Semaphore控制同时处理的请求数,超过阈值的请求直接快速失败,返回429状态码。 - 缓存前置:热点数据尽量走Redis缓存,减少数据库压力。攻击者打数据库比打应用层更致命。
- 异步化:非核心逻辑(如日志记录、消息通知)改成异步处理,缩短请求处理链路。
- 降级预案:提前准备好降级开关,一旦检测到攻击,立即关闭非核心功能,保住核心业务。
这段代码看起来简单,但在真实攻击场景下非常有效。当攻击流量涌入时,信号量保证只有100个请求能同时进入业务逻辑,其余的快速失败,保护了后端资源不被耗尽。
4.5 内网防护的落地措施
内网防护经常被忽略,但一旦被突破,后果比外部攻击更严重。我的建议是:
- 网络分段:Web服务器、应用服务器、数据库服务器放在不同的子网,通过防火墙控制访问关系。Web层只能访问应用层的特定端口,应用层只能访问数据库的特定端口。
- 流量基线:用NetFlow或sFlow采集内网流量,建立正常通信矩阵。一旦出现异常的端口扫描或大流量传输,立即告警。
- 主机加固:关闭不必要的服务,更新补丁,限制SSH登录来源IP,使用密钥认证代替密码。
- 日志审计:所有内网主机的登录日志、命令执行日志集中收集,便于事后追溯。
5. 常见问题与排查技巧实录
5.1 攻击来了但监控没告警,怎么排查
这种情况通常是监控阈值设置不合理或者监控覆盖不全。先检查几个关键点:入口路由器的流量监控是否开启?Nginx的日志是否实时采集?Java应用的JVM指标是否上报?如果这些都有,再看阈值是不是设得太高。我的经验是,告警阈值应该基于历史数据的P99值来定,而不是拍脑袋。比如过去30天同一时段的QPS P99是500,那阈值可以设在800左右,留出一定的缓冲。
另一个常见原因是监控数据延迟。有些监控系统是每分钟采集一次,攻击在30秒内打完就结束了,监控还没反应过来。对于DDoS这种秒级攻击,监控采集频率至少要10秒一次,关键指标甚至要5秒一次。
5.2 误封正常用户怎么办
限流和封禁策略太激进,很容易误伤正常用户。我踩过最大的坑是在一次促销活动中,把单IP的请求速率限制设成了5r/s,结果大量用户通过公司出口IP访问,整个公司都被封了。后来改成基于用户Token限流为主、IP限流为辅,误封率大幅下降。
如果已经误封,要提供快速的解封通道。比如在封禁页面上放一个验证码,用户通过验证后自动解封。或者提供客服入口,人工解封。千万别让用户干等着,体验太差。
5.3 高防IP回源流量异常怎么处理
高防IP回源流量异常通常有两种情况:一是回源IP段配置错误,导致源站不认高防的流量;二是回源协议不匹配,比如高防用HTTP回源但源站只监听HTTPS。排查步骤:先在高防控制台确认回源IP段,然后在源站防火墙里检查白名单是否包含这些IP;再确认回源端口和协议是否与源站配置一致。如果还不行,抓包看回源请求的Header和源站响应,通常能定位到问题。
5.4 常见问题速查表
| 问题现象 | 可能原因 | 排查方向 | 解决措施 |
|---|---|---|---|
| 源站带宽被打满 | 流量型攻击或CDN回源异常 | 查看入口流量曲线和CDN回源日志 | 启用高防清洗,检查CDN缓存命中率 |
| API响应变慢但QPS不高 | 慢速攻击或连接池耗尽 | 检查Nginx连接数和Java线程池 | 调整超时参数,增加连接池上限 |
| 监控无告警但用户反馈卡顿 | 监控覆盖不全或阈值过高 | 检查监控采集点和告警阈值 | 补充监控指标,降低告警阈值 |
| 误封大量正常用户 | 限流策略过于激进 | 分析封禁IP的分布和请求特征 | 改为基于用户维度限流,增加验证码解封 |
| 内网出现异常流量 | 内网横向攻击或病毒传播 | 检查内网流量基线和主机日志 | 网络分段,隔离异常主机,排查病毒 |
5.5 几个容易被忽略的防护细节
第一个细节是DNS解析的TTL。如果TTL设得太长,攻击发生时切换高防IP需要等很久才生效。建议把关键域名的TTL设在60秒到300秒之间,兼顾解析效率和切换速度。
第二个细节是API密钥的保护。我见过不少项目把API Key硬编码在前端代码里,攻击者直接提取Key后疯狂调用。API Key必须放在服务端,前端通过临时Token访问,Token要有有效期和权限范围。
第三个细节是日志的磁盘空间。攻击发生时日志量会暴增,如果磁盘满了会导致服务不可用。建议给日志分区单独挂盘,配置日志轮转和自动清理,保留最近7到14天的日志即可。
第四个细节是备用入口。主入口被攻击时,如果有一个备用的域名或IP可以切换,能争取到宝贵的应急时间。备用入口平时可以不用,但要保持配置同步,确保随时能切。
6. 个人实操体会与后续扩展方向
做了这么多年防护,我最大的体会是:DDoS防护不是一次性的项目,而是持续运营的过程。攻击手法在变,业务形态在变,防护策略也必须跟着变。今天有效的规则,明天可能就被绕过了。所以别指望配好一套规则就一劳永逸,定期演练、定期复盘、定期更新才是常态。
另外,成本和安全永远是一对矛盾。高防IP很贵,CDN流量也不便宜,WAF按QPS收费更是烧钱。我的建议是根据业务的实际风险来分配预算:核心交易链路必须上全套防护,边缘业务可以用轻量级方案。别为了防一个日活几百的小程序,去买几十万的高防套餐。
后续如果还想深入,可以研究几个方向:一是基于机器学习的异常流量检测,用历史数据训练模型,自动识别未知攻击模式;二是边缘计算与防护的结合,把部分清洗逻辑下沉到CDN边缘节点,降低回源压力;三是零信任架构在内网防护中的应用,不再依赖网络边界,而是对每个请求都做身份验证。这些方向我还在摸索,有新的心得再跟大家分享。