1. 从一次线上服务异常说起:DDoS到底在攻击什么
凌晨两点,手机告警响了。某业务系统的公网入口流量在十分钟内从日常的 200Mbps 飙到 8Gbps,负载均衡后面的应用服务器 CPU 全线飘红,正常用户的请求开始大面积超时。登录监控面板一看,连接数曲线几乎垂直拉升,来源 IP 遍布各地,请求特征高度雷同——这就是一次典型的分布式拒绝服务攻击,也就是大家常说的 DDoS。
很多刚接触这块的朋友会把 DDoS 想得很神秘,觉得是某种高深的技术入侵。其实它的核心逻辑非常朴素:用远超系统处理能力的请求量,把目标资源的处理能力占满,让正常用户没法用。注意这里的关键词是“分布式”,攻击者不会傻到用一台机器去打,而是控制大量分散在网络各处的设备同时发难,这样一来,单点封禁就失效了,流量清洗的难度也成倍上升。
这篇文章我想做的事情很明确:把 DDoS 的攻击原理拆开揉碎讲清楚,从它攻击的是哪一层、用的是什么手法、为什么难防,到我们作为防守方该怎么观察、怎么判断、怎么处置。内容会涉及网络分层、协议特性、流量特征分析、防护策略选型这些硬核部分,也会给出可以直接参考的排查思路和配置方向。适合运维、后端开发、安全入门的朋友,也适合对网络攻防感兴趣、想搞明白“攻击到底怎么发生的”的读者。我不会只讲概念,而是尽量把每一步背后的“为什么”说透,让你看完之后不只是知道有这回事,而是能自己动手分析流量、判断攻击类型。
需要先说明一点:本文只讨论攻击原理与防护思路,目的是帮助大家理解并做好自身系统的安全加固,不涉及任何具体的攻击工具、攻击脚本或可被滥用的操作细节。理解攻击是为了更好地防守,这个边界要拎清楚。
2. 攻击原理拆解:DDoS 到底打的是什么
2.1 拒绝服务的本质是资源耗尽
要理解 DDoS,先得理解“拒绝服务”这四个字。任何一个网络服务,它的处理能力都是有上限的,这个上限由几个核心资源决定:网络带宽、连接数、CPU 计算能力、内存、磁盘 IO。攻击者要做的,就是找到其中最薄弱的一环,然后用大量请求把它撑爆。
打个比方,一家小餐馆只有 10 张桌子,正常情况下一桌客人吃完走了下一桌再进来,翻台率是够用的。但如果突然涌进来 200 个人,每人占一张桌子还不点菜,那真正想吃饭的客人就进不来了。DDoS 就是这个逻辑:攻击流量本身可能并不“高级”,它甚至不需要攻破你的任何密码,只需要把你的“桌子”占满就行。
这里有个很重要的认知:DDoS 攻击往往不是利用漏洞,而是利用协议和架构的固有特性。比如 TCP 三次握手需要服务端分配资源、DNS 查询需要递归解析、HTTP 请求需要建立连接,这些正常机制在量级被放大之后,就变成了压垮系统的负担。所以防守 DDoS 的思路,很多时候不是“堵漏洞”,而是“扛量”和“分流”。
2.2 按网络分层看攻击类型
网络通信是分层的,DDoS 攻击也对应着不同的层级。理解这个分层,是判断攻击类型和选择防护手段的基础。我把它整理成一张表,方便对照:
| 攻击层级 | 典型协议 | 攻击目标 | 常见手法 | 防护重点 |
|---|---|---|---|---|
| 网络层 | IP、ICMP | 带宽、路由器 | ICMP 洪水、IP 分片 | 流量清洗、黑洞路由 |
| 传输层 | TCP、UDP | 连接表、端口 | SYN 洪水、UDP 洪水 | 连接限制、SYN Cookie |
| 应用层 | HTTP、DNS | 应用进程、数据库 | HTTP 洪水、慢速攻击 | 行为分析、限流、验证码 |
网络层和传输层的攻击,特点是流量大、特征相对明显,主要拼的是带宽和硬件设备的处理能力。应用层的攻击则阴险得多,它单个请求看起来完全正常,但通过大量并发或者极慢的请求,把应用服务器的线程、数据库连接池耗尽。后者往往流量不大,却能让服务彻底瘫痪,而且很难和正常流量区分开。
2.3 为什么“分布式”让防守变得棘手
单点攻击好办,封一个 IP 就完事了。但分布式攻击的来源是成千上万台被控制的设备,这些设备可能是被恶意程序感染的普通电脑、服务器,甚至是摄像头、路由器这类物联网设备。它们分布在不同地区、不同网络,用的都是正常的公网 IP。
这就带来三个难题。第一,你没法简单封 IP,因为封掉一个还有千千万万个,而且很多 IP 背后可能是无辜的正常用户,误封会造成业务损失。第二,攻击流量和正常流量混在一起,尤其应用层攻击,从单个请求看几乎没区别,只能靠行为特征和频率来识别。第三,攻击成本极低而防守成本极高,攻击者可能只花很小的代价就能发起一次可观的流量,而防守方要投入带宽、设备和人力去应对。
理解了这三点,你就明白为什么 DDoS 防护是一个持续对抗的过程,而不是装个软件就能一劳永逸的事情。
3. 常见攻击手法逐个拆解
3.1 SYN 洪水:利用三次握手的“半开连接”
TCP 建立连接需要三次握手:客户端发 SYN,服务端回 SYN-ACK 并分配资源等待确认,客户端再回 ACK 连接才建立。SYN 洪水的做法是:攻击者发送大量 SYN 包,但故意不回最后的 ACK,或者把源 IP 伪造成不存在的地址。
这样一来,服务端就会为每一个 SYN 分配一块内存、维持一个“半开连接”,等待那个永远不会到来的 ACK。半开连接表是有上限的,一旦被占满,新的正常连接就建立不了。这就像餐馆服务员给每桌客人摆好餐具等着点菜,结果客人全跑了,桌子还被占着,新客人自然进不来。
防守 SYN 洪水的经典手段是SYN Cookie。它的思路是不再为每个 SYN 立即分配资源,而是把连接信息编码进 SYN-ACK 的序列号里发回去,等客户端回 ACK 时再把信息还原出来验证。这样服务端在握手完成前不占用任何存储,半开连接表被撑爆的问题就缓解了。主流操作系统都支持开启这个选项,属于基础加固动作。
3.2 UDP 洪水:无连接的“泼水式”攻击
UDP 是无连接协议,发出去就不管了,没有握手、没有确认。这让它成为发起洪水攻击的天然工具:攻击者只要往目标端口狂发 UDP 包就行,不需要维护任何连接状态。常见的被利用协议包括 DNS、NTP、SSDP 等,因为这些协议有个特点——小请求能换来大响应。
这就是所谓的“反射放大”攻击。攻击者伪造受害者的 IP 作为源地址,向大量开放的公共服务发送小查询,这些服务会把体积大得多的响应发回给受害者。一个几十字节的请求可能换来几百甚至上千字节的响应,放大倍数相当可观。防守这类攻击,一方面要在边界对 UDP 流量做限速和异常检测,另一方面要确保自己网络内的服务不会成为被别人利用的“放大器”。
3.3 HTTP 洪水:最难缠的应用层攻击
HTTP 洪水是我个人认为最需要重视的一类。它不需要伪造 IP,不需要放大倍数,就是老老实实发 HTTP 请求,但量足够大、频率足够高,把 Web 服务器的处理能力、数据库查询能力、后端接口的并发能力全部占满。
更麻烦的是“慢速攻击”变种。比如慢速发送 HTTP 请求头,一个字节一个字节地发,让服务器一直保持连接等待;或者慢速读取响应,占着连接不放。这类攻击单个连接消耗的资源很小,但成千上万个连接累积起来,就能把服务器的连接池和线程池耗尽。它的流量可能只有几 Mbps,从带宽监控上完全看不出异常,但服务已经挂了。
防守 HTTP 洪水的核心思路是区分“人”和“机器”。正常用户的请求有间隔、有页面跳转、会加载静态资源、会带 Cookie 和 Referer;而攻击流量往往请求路径单一、频率恒定、缺少正常浏览行为。基于这些特征做频率限制、行为分析、人机验证,是应用层防护的主要手段。
3.4 攻击手法的对比与识别特征
把上面几种手法放在一起对比,能帮你在遇到异常时快速判断方向:
| 手法 | 流量特征 | 监控指标异常 | 判断要点 |
|---|---|---|---|
| SYN 洪水 | 大量小包,源 IP 分散 | 半开连接数飙升 | netstat 看 SYN_RECV 状态 |
| UDP 洪水 | 单方向大流量 | 带宽打满,出口拥塞 | 抓包看 UDP 包特征 |
| 反射放大 | 响应包远大于请求 | 特定端口流量异常 | 看源端口是否为公共服务 |
| HTTP 洪水 | 请求路径集中 | QPS 飙升,响应变慢 | 分析访问日志频率分布 |
| 慢速攻击 | 流量不大但连接多 | 连接数高,CPU 不高 | 看长连接持续时间和进度 |
这张表不是绝对的,实际攻击经常是混合手法,但有了这个对照,排查时至少知道往哪个方向看。
4. 防守方的实战思路:从观察到处置
4.1 先建立可观测性,别急着上设备
我见过不少团队一遇到攻击就想着买防护设备、上高防,结果连攻击类型都没搞清楚,钱花了效果还不好。正确的顺序应该是先看清楚,再动手。可观测性包括几个层面:网络层的流量采样(比如 NetFlow、sFlow)、传输层的连接状态统计、应用层的访问日志和 QPS 监控。
具体来说,至少要能回答这几个问题:流量是从哪些源 IP 来的、集中在哪些目标端口、包的大小分布如何、请求的 URL 分布是什么样、有没有明显的周期性。这些信息决定了你面对的是哪类攻击,也决定了后续该用什么手段。没有这些数据,所有的防护都是盲打。
4.2 分层防护的架构设计
DDoS 防护讲究分层,单靠一层是扛不住的。我通常建议按下面的层次来设计:
- 第一层:基础加固。操作系统层面开启 SYN Cookie、调优连接队列、限制单 IP 连接数,这些是零成本的,能挡掉一部分低级攻击。
- 第二层:边界限流。在入口做流量清洗和速率限制,把明显异常的流量挡在外面,保护后端设备。
- 第三层:应用层防护。针对 HTTP 洪水做频率限制、行为分析、人机验证,这是应用层攻击的最后一道防线。
- 第四层:弹性扩容。配合负载均衡和自动扩容,在攻击来临时临时增加处理能力,用资源换时间。
这四层不是替代关系,而是叠加关系。基础加固做得好,能省下后面很多麻烦;应用层防护做得好,能挡住那些绕过流量清洗的精细攻击。
4.3 流量清洗与黑洞路由的取舍
流量清洗的思路是把流量引到清洗中心,识别出恶意流量丢弃,把干净流量回注给源站。黑洞路由则是简单粗暴:发现某个 IP 被攻击,直接把所有发往它的流量丢弃,牺牲这个 IP 保住整体网络。
这两者怎么选?我的经验是:核心业务用清洗,非核心或已经无法挽救的用黑洞。清洗的好处是业务还能继续,但成本高、有延迟;黑洞的好处是立竿见影,但被黑洞的 IP 在攻击期间完全不可用。实际处置时,往往是先黑洞止血,再切清洗恢复,根据业务重要性和攻击规模灵活切换。
4.4 应用层的限流与验证策略
应用层防护是精细活。限流要分维度:按 IP 限、按用户限、按接口限、按全局限,不同维度组合使用。比如登录接口按 IP 限频,防止撞库;查询接口按用户限频,防止爬取;全局再设一个总闸,防止整体被打爆。
人机验证是区分正常用户和自动脚本的有效手段,但要注意别把体验做坏了。我的建议是分级触发:正常流量不验证,频率超过阈值才弹验证,验证通过后给一段时间豁免。这样既挡住了机器流量,又不影响正常用户。
5. 排查与处置的实操记录
5.1 一次 SYN 洪水的现场排查
回到开头那次告警。我当时的排查顺序是这样的:先看流量曲线,发现是上行流量突增,包速率很高但平均包大小很小,初步判断是传输层攻击。然后登录服务器执行netstat -ant | awk '{print $6}' | sort | uniq -c,看到 SYN_RECV 状态的连接数异常高,基本确认是 SYN 洪水。
接着看源 IP 分布,发现非常分散,没有明显的集中段,说明是分布式来源。这时候单 IP 封禁没意义,我做了两件事:一是确认 SYN Cookie 已经开启,二是联系上游做流量清洗。SYN Cookie 开启后,半开连接表不再被占满,服务端的连接建立能力恢复了,虽然流量还在,但正常用户已经能进来了。
这里有个细节值得说:SYN Cookie 开启后,某些依赖 TCP 选项的功能可能受影响,比如 TCP 时间戳、窗口缩放。如果你的业务对这些有依赖,开启前要评估。大多数场景下没问题,但心里要有数。
5.2 应用层慢速攻击的识别过程
另一次比较隐蔽的是慢速攻击。监控上带宽正常、CPU 正常,但用户反馈页面打不开。我看连接数,发现大量连接处于 ESTABLISHED 状态但持续时间极长,而且这些连接的请求进度几乎不动。
抓包分析后确认,攻击者在极慢地发送请求头,每个连接占用一个工作线程。因为流量小,流量清洗设备根本没触发。处置办法是在反向代理层设置请求头和请求体的超时时间,比如请求头 10 秒内没发完就断开,请求体读取超过 30 秒就断开。这个配置一上,慢速连接被快速清理,服务恢复正常。
这个案例的教训是:不要只盯着带宽和 CPU,连接的生命周期和状态分布同样重要。很多应用层攻击就是钻了“流量不大所以监控不报警”的空子。
5.3 常见问题速查表
把实际处置中经常遇到的问题整理成一张表,遇到情况可以对照排查:
| 现象 | 可能原因 | 排查动作 | 处置方向 |
|---|---|---|---|
| 带宽打满,服务不可用 | 流量型攻击 | 看流量来源和包特征 | 清洗或黑洞 |
| 连接数高但流量不大 | 慢速攻击或连接耗尽 | 看连接状态和持续时间 | 超时配置、连接限制 |
| QPS 飙升,响应变慢 | HTTP 洪水 | 分析访问日志频率 | 限流、人机验证 |
| 特定端口流量异常 | 反射放大 | 看源端口和包大小 | 边界过滤、限速 |
| 数据库连接池耗尽 | 应用层攻击穿透 | 看慢查询和并发 | 应用层限流、缓存 |
5.4 几个容易踩的坑
第一个坑是误封正常用户。有次为了快速止血,按 IP 段封禁,结果封掉了一个大客户的出口 IP,业务投诉比攻击本身还严重。后来我学乖了,封禁前一定先确认 IP 归属和影响范围,能用限流就不用封禁。
第二个坑是只防不练。防护策略配好了就放着,真遇到攻击时发现规则过期、阈值不合理。我的做法是定期做压测和演练,模拟攻击流量验证防护是否生效,阈值是否合适。
第三个坑是忽视日志留存。攻击发生时的流量日志、访问日志是事后分析和追责的关键,但很多团队日志保留时间太短,等想起来分析时数据已经没了。建议至少保留足够长时间的高峰期日志,具体时长根据业务和合规要求定。
6. 从原理到体系:把防护做成常态能力
把上面这些串起来看,DDoS 防护其实是一个从“理解原理”到“建立体系”的过程。理解原理让你知道攻击打的是哪里、为什么这么打;建立体系让你在攻击来临时有章可循、有工具可用、有人负责。
我个人的体会是,防护能力不是买来的,是练出来的。设备再好,如果没人会用、没有预案、没有演练,真打起来照样手忙脚乱。反过来,哪怕资源有限,只要把可观测性做好、把分层防护搭起来、把处置流程跑通,也能扛住大部分常见攻击。
最后分享一个我觉得很实用的习惯:给系统做一次“攻击面梳理”。把对外暴露的 IP、端口、服务列出来,逐个问自己:这个如果被打,影响是什么?有没有备用方案?能不能快速切换?这个梳理做完,你对自家系统的抗打击能力就有了底,遇到攻击也不会慌。防护这件事,说到底就是比谁准备得更充分。