1. 大流量DDoS早就不只是“打不打得开”的问题
干了几年安全应急,我越来越不愿意把大流量DDoS简单说成“网站被打挂了”。真正在一线扛过攻击的人都清楚,现在的大流量DDoS攻击,本质是一场资源消耗战:攻击方用极低的成本,逼着防守方在带宽、连接数、CPU、内存、云账单、人力值班这六个维度同时失血。你防住了,业务还得继续承担高防费用和误杀带来的转化损失;你没防住,丢的是可用性和口碑。所以这篇内容我想聊的不是“DDoS是什么”这种教科书定义,而是把大流量DDoS的攻击趋势、防御架构选型、落地配置、应急处置和踩坑经验,按一个从业者真实的处理顺序摊开讲。
适合谁看?如果你手上管着一套有公网入口的业务系统,不管是电商、游戏、API服务还是企业内部对外门户,只要你需要在被打的时候做出判断,这篇就有参考价值。新手可以照着第三部分的配置抄作业,有一定基础的可以重点看第二部分的架构取舍和第四部分的处置顺序,那里是我认为最容易出问题、也最考验判断力的地方。
先说一个残酷的现实:大流量DDoS攻击的门槛已经低到不需要什么技术水平了。过去要组织一次几十Gbps的攻击,需要自己攒机器、写工具、控僵尸网络;现在各种按天计费的攻击服务平台把这件事做成了流水线,几十美元就能买到一次持续数小时的混合攻击。攻击者不需要知道你的架构,甚至不需要知道你的业务是干什么的,只要你的IP暴露在公网,就可能被随机扫到,也可能因为一次竞争、一次口角、一次敲诈邮件被点名。这意味着防御思路必须从“事后救火”转向“平时就有余量、随时能切换”。
1.1 攻击方的成本账本,决定了他们会怎么打
理解攻击趋势,最有效的角度是站在攻击方算成本。一次大流量DDoS攻击的成本结构大致分三块:流量来源成本、控制成本、暴露风险成本。流量来源决定了他们偏好什么打法,控制成本决定了攻击的持续性,暴露风险决定了他们会尽量选择“不落地”的方式。
由此推导出的几个趋势非常明显。第一是反射放大类攻击长期占据主流,因为它把攻击者自己的带宽消耗压到极低,用第三方服务的响应报文去砸目标,放大倍数从几倍到上百倍不等。第二是IoT设备僵尸网络成为稳定弹药库,大量家用路由器、摄像头、智能硬件默认口令不改、固件不更新,被批量控制后长期潜伏,需要的时候一次性放出。第三是混合型攻击成为常态,纯流量型攻击容易被清洗设备识别,于是攻击方会把大流量洪峰和应用层慢速请求叠在一起打,前者负责把你的带宽和清洗额度打满,后者负责在清洗设备放行的那部分流量里继续消耗你的后端。
还有一个趋势值得单独提:攻击的“脉冲化”。很多攻击不再是持续几小时的平稳洪峰,而是几十秒到几分钟的短促高峰,间隔几分钟再来一次。这种打法专治“人工发现—上报—开启清洗”这条链路。等人看到告警、确认、联系服务商、切流量,攻击已经结束了,但你的业务在这段时间里已经出现超时、订单失败、用户投诉。更麻烦的是,脉冲攻击会反复触发你的弹性扩容,把你的云账单推到一个很难看的数字上。
1.2 三类主流打法与它们的真实流量特征
我把常见的大流量攻击按流量特征分成三类,这个分类方式在实战里比按协议分更有用,因为它直接对应你该看哪个指标、该动哪一层。
| 攻击类型 | 典型流量特征 | 首先被打满的资源 | 识别关键指标 |
|---|---|---|---|
| 流量型洪泛 | 入向带宽瞬间拉满,包大小分布单一,源IP高度分散 | 公网带宽、上行链路、清洗设备吞吐 | 入向bps、pps、包长分布 |
| 协议型/反射型 | 特定协议报文突增,单包较大,源地址多为第三方服务 | 链路带宽、防火墙会话表 | 按协议端口统计的pps、会话数 |
| 应用层混合 | 流量不大但请求数暴涨,连接建立慢、请求头异常 | CPU、数据库连接、后端并发 | QPS、新建连接数、响应时间 |
流量型洪泛最直观,也最好识别,但它的破坏力在于“快”。一条1Gbps的链路,几十秒就能被打满,路由器接口的丢包率曲线会直接垂直上升。这种场景下,你在主机上做的任何优化都没有意义,因为包根本没到你的网卡。所以这类攻击必须在网络层或者运营商侧解决,这也是后面我要强调“分层防御”的原因。
协议型/反射型更隐蔽一点,因为它在你的监控面板上可能表现为“带宽涨了但不是特别夸张,可服务器就是连不上”。原因是它消耗的是会话表和CPU中断,而不是纯粹带宽。比如大量半连接请求会让内核的SYN队列迅速溢出,正常用户的握手请求排队被丢弃,表现出来就是“部分地区打不开、时快时慢”。
应用层混合最阴,因为它常常伪装成正常流量。攻击方用大量真实IP、真实User-Agent,甚至带着完整的TLS握手,去请求你数据库最重的那个接口。这种情况下你看带宽毫无异常,看QPS也就涨了两三倍,但P99响应时间已经从200ms飙到8秒,数据库连接池全满。很多团队第一次遇到这种攻击,会误判成“代码有bug”或者“数据库慢查询”,排查半天方向都不对。
提示:判断是不是被打,先看三个指标的“形状”而不只是数值——入向bps曲线的斜率、pps与bps的比值、新建连接数与QPS的比值。形状突变比绝对值超标更能说明问题。
2. 防御架构怎么搭:分层消耗与清洗分流的设计取舍
我见过太多团队在防御架构上犯同一个错误:把所有希望寄托在一个“高防IP”或者一台“抗D设备”上。结果是被打的时候,清洗设备成了唯一瓶颈,或者攻击流量绕过防护直接打到源站,又或者清洗设备正常但后端数据库先挂了。大流量DDoS防御的核心不是“找一个更强的盾”,而是建立一套分层消耗、逐级过滤、可快速切换的体系。每一层解决一部分问题,每一层都清楚自己解决不了什么,这才是能扛住真实攻击的架构。
2.1 为什么单点高防一定会出问题
单点高防有三个绕不过去的短板。第一是容量上限是硬约束。清洗设备的吞吐是固定的,攻击流量一旦超过这个值,设备要么进入“全量丢弃”模式,要么直接把流量透传,两种情况业务都会挂。第二是误杀成本高。清洗策略越激进,误伤正常用户越多;策略越保守,漏进来的攻击流量越多。这个平衡点很难调,尤其是业务有大量移动端用户、IP段分散、行为特征不规律的时候。第三是单点故障。所有流量都经过一个入口,这个入口本身就成了攻击目标和故障点。
更现实的问题是成本。大流量清洗的计费方式通常是按清洗峰值或者按套餐内的清洗次数算,一次持续几小时的攻击,账单可能比业务本身的服务器费用还高。所以架构设计里必须考虑“用便宜的手段扛住大部分攻击,把昂贵的清洗资源留给真正扛不住的那部分”。
2.2 分层防御的四个层次与各自边界
我习惯把防御分成四层,从外到内依次是:入口收敛层、边缘缓存层、流量清洗层、源站自保层。每一层的职责和边界要写清楚,出事的时候才不会乱。
入口收敛层的目标是减少暴露面。能不放公网IP的就不放,能用CDN或者反向代理接流量的就不要让源站IP出现在任何地方。域名解析尽量走支持隐藏源站的接入方式,历史解析记录、邮件头、第三方监控探针、甚至代码仓库里的配置文件,都可能泄露源站IP,这是最常见的翻车点。
边缘缓存层的目标是让大部分请求根本不回源。静态资源、图片、视频切片、公共API的GET结果,能缓存的全部缓存,缓存命中率每提高10%,回源带宽和源站QPS就少10%。这一层对应用层混合攻击的效果特别明显,因为攻击方打你首页和静态资源的那些请求,在边缘就被消化掉了。
流量清洗层是真正处理大流量的地方,它的价值在于“吸收”而不是“精确识别”。这一层的策略应该是粗粒度、高吞吐、低延迟,比如基于包特征的过滤、基于连接速率的限制、基于地理区域的封禁。不要指望在这一层做精细的业务逻辑判断,那会把设备拖垮。
源站自保层是最后一道防线,也是最容易被忽略的。很多团队以为流量到了源站就说明清洗成功了,其实不然——清洗设备通常会放行一部分“看起来正常”的流量,攻击方完全可以在这部分流量里混入慢速攻击。源站必须有连接数上限、请求速率限制、超时控制、降级开关,保证在异常流量到达时不会雪崩。
2.3 清洗阈值与带宽容量的计算过程
这部分我给一个可复现的算法。假设你的业务正常峰值入向带宽是300Mbps,正常峰值QPS是8000,单机平均响应时间150ms,后端有6台应用服务器。
第一步,算正常带宽余量。生产环境我一般要求链路带宽至少有3倍余量,也就是正常峰值不超过链路容量的1/3。如果你的公网带宽是1Gbps,正常峰值300Mbps,余量是够的。但注意,这里的“1Gbps”要看你实际的物理链路和云厂商的带宽限制,很多时候瓶颈在云厂商的入向限速而不是物理链路。
第二步,算清洗触发阈值。触发阈值不宜设得太低,否则正常业务高峰会误触发清洗,增加延迟和成本;也不宜太高,否则等触发时业务已经挂了。我的经验值是:带宽触发阈值取正常峰值的1.5到2倍,pps触发阈值取正常峰值的2到3倍,同时设置一个持续时间的判断条件(比如持续30秒以上才触发),避免脉冲抖动误触发。
第三步,算需要多大的清洗容量。这个不能按“我要扛住最大攻击”来算,因为攻击峰值是不可预测的。更合理的算法是按业务分级:核心业务要求清洗容量至少能覆盖历史上同行业出现过的较大攻击规模,并留出50%余量;非核心业务则优先保证“攻击时能快速切到静态降级页”。假设你评估需要扛住20Gbps,清洗套餐就按20Gbps买,同时准备好超过这个量时的降级预案。
第四步,算源站连接数上限。这个经常被忽略。单台应用服务器的最大并发连接数不是拍脑袋定的,要按内存算。以常见的Linux内核参数为例,每个TCP连接在内核里占用的内存大约在几KB到十几KB量级,具体取决于收发缓冲区设置。如果是8GB内存的机器,预留2GB给系统和应用,剩下6GB按每连接8KB估算,理论上是七十多万连接,但实际还要受文件描述符上限、端口范围、应用层线程模型的限制。
# 查看当前系统的连接相关上限 ulimit -n cat /proc/sys/net/core/somaxconn cat /proc/sys/net/ipv4/ip_local_port_range ss -s# 一份常用的内核参数调整示例(按需评估后再改,不要直接套) net.core.somaxconn = 32768 net.ipv4.tcp_max_syn_backlog = 16384 net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_fin_timeout = 15 net.ipv4.tcp_tw_reuse = 1 net.ipv4.ip_local_port_range = 10240 65000 net.core.netdev_max_backlog = 16384 fs.file-max = 1000000注意:
tcp_tw_reuse这类参数在不同内核版本和行为场景下效果差异很大,尤其是走NAT的客户端场景要谨慎开启,改之前一定在预发环境验证,别在生产上直接抄网上的配置。
我要特别强调一个取舍:不要试图用一台机器扛住所有层。清洗设备负责吞吐,源站负责业务逻辑,缓存负责消化重复请求,三者混在一起的结果是每个都做不好。分层之后还有一个好处,就是你可以按成本优化——边缘缓存是最便宜的,源站扩容是最贵的,把流量尽量往外推,账单自然就下来了。
3. 落地实操:从内核参数到边缘节点的具体配置
架构讲完,落到具体配置。这一部分我给的都是能在真实环境里跑起来的东西,但我不会给“一键脚本”,因为每个业务的流量模型不一样,照抄参数往往比不改还糟。我会说清楚每个配置解决什么问题、在什么情况下该调、调错了会怎样。
3.1 主机侧:半连接队列、连接数与速率限制
主机侧的第一要务是让内核在异常流量下不要自己先崩。SYN Flood是最典型的协议型攻击,特征是大量半连接堆积,ss -s里SYNs to LISTEN sockets dropped这个计数会快速上涨。
# 观察半连接队列溢出情况 ss -s netstat -s | grep -i -E "SYNs to LISTEN|listen queue"如果确认是半连接队列溢出,处理顺序是:先确认tcp_syncookies是否开启(开启后在内核层面用无状态方式响应握手,能扛住大量伪造源地址的SYN),再评估是否调大tcp_max_syn_backlog。但要注意,SYN Cookie 开启后会在TCP选项里带时间戳信息,某些老旧客户端或中间设备可能不兼容,所以要观察建立连接的成功率,不能只看“队列没溢出”。
第二是连接数限制。用iptables配合hashlimit或者connlimit做单IP并发限制,是最简单有效的一层过滤。
# 单个源IP到80端口的并发连接数限制(示例值,按业务调整) iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 50 --connlimit-mask 32 -j DROP # 单个源IP新建连接速率限制:每秒最多20个新连接,突发30个 iptables -A INPUT -p tcp --dport 80 -m hashlimit \ --hashlimit-name http_new \ --hashlimit-above 20/sec \ --hashlimit-burst 30 \ --hashlimit-mode srcip \ --hashlimit-htable-expire 60000 \ -j DROP这两条规则的意图要讲清楚:connlimit管的是“占用”,防止单个IP堆积大量长连接把连接表撑爆;hashlimit管的是“速率”,防止单个IP高频建立新连接。两个配合使用,能过滤掉相当一部分低成本的攻击流量。但这两条规则的代价是状态维护开销,规则数量多了会拖慢包处理速度,所以源IP数量特别大的场景下我更倾向用ipset做批量匹配,而不是逐条规则。
提示:生产环境上
iptables规则前,先用iptables -C检查是否已存在,避免重复添加;批量规则建议用独立的链管理,方便一次性清理和回滚。
3.2 应用层:Nginx限速与缓存抗压
到了应用层,工具就是限速和缓存。限速的目的是保证“即使有异常请求,后端也能留出处理正常请求的能力”,而不是把攻击流量全部挡掉——那做不到。
# 定义限速区域:按IP限制请求速率,10MB共享内存大约能存16万个IP状态 limit_req_zone $binary_remote_addr zone=req_per_ip:10m rate=20r/s; # 定义并发连接限制区域 limit_conn_zone $binary_remote_addr zone=conn_per_ip:10m; server { listen 80; server_name example.internal; # 突发允许40个请求,超出排队,排队超时返回503 limit_req zone=req_per_ip burst=40 nodelay; limit_req_status 429; # 单IP并发连接数上限 limit_conn zone=conn_per_ip 30; limit_conn_status 429; # 慢连接防护:客户端读写超时收紧 client_body_timeout 10s; client_header_timeout 10s; send_timeout 10s; # 限制请求体大小,防止大包拖慢处理 client_max_body_size 8m; location /api/heavy { # 针对重接口单独加更严的限制 limit_req zone=req_per_ip burst=10 nodelay; proxy_read_timeout 15s; proxy_connect_timeout 5s; proxy_pass http://backend_pool; } }这里有个容易被忽略的点:limit_req的rate是按“每秒请求数”算的,但真实业务里用户的请求往往不是均匀分布的,一个页面加载可能并发十几个请求。burst设得太小会导致正常用户被误伤,设得太大又起不到防护作用。我的经验是先把rate设成正常单IP峰值的1.5倍左右,burst设成单页面最大并发资源数的2倍,然后观察被限流的请求比例,稳定在千分之几以内是合理的。
缓存这层更值得投入。把可以静态化的接口结果缓存到Nginx或者边缘节点,攻击打过来的时候,大量请求在缓存层就返回了,根本不会穿透到后端。
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=api_cache:100m max_size=10g inactive=10m; location /api/public/list { proxy_cache api_cache; proxy_cache_key "$scheme$request_method$host$request_uri"; proxy_cache_valid 200 30s; proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; proxy_cache_lock on; add_header X-Cache-Status $upstream_cache_status; proxy_pass http://backend_pool; }proxy_cache_use_stale这一行是关键,它让后端出问题时缓存层还能继续对外提供旧内容,这在攻击期间是保命配置。proxy_cache_lock on则防止缓存击穿时大量请求同时回源,等于给后端加了一把闸。
3.3 边缘侧:接入方式与静态化降级
边缘侧的核心思路是“让攻击流量离源站越远越好”。具体的接入方式这里不谈具体厂商,只谈选型逻辑:优先选择支持隐藏源站、支持按域名接入、支持自定义缓存规则和速率限制的方案。接入之后必须做的三件事是:源站IP不对外暴露、缓存规则覆盖高频路径、准备一个静态降级页。
静态降级页这件事我强烈建议每个业务都提前做。做法很简单:把首页做成静态HTML放到边缘节点,配置一条规则,当源站健康检查失败或者QPS超过阈值时自动切换到静态页。静态页上写清楚“系统维护中,预计恢复时间”,再放一个查询入口。看起来简陋,但它在真实攻击里救了太多团队的转化率——用户至少知道你的服务还在,而不是看到一个超时白屏。
3.4 监控告警:哪些指标真的值得盯
监控不是指标越多越好。我见过的大屏上密密麻麻上百个指标,真出事的时候没人看得过来。大流量DDoS场景下,值得盯的指标其实就几个:
| 指标 | 采集位置 | 异常判据 | 处置动作 |
|---|---|---|---|
| 入向bps | 路由器/云监控 | 超过正常峰值2倍且持续30秒 | 确认是否攻击,准备切清洗 |
| 入向pps | 同上 | 超过正常峰值3倍 | 检查包长分布,判断攻击类型 |
| 新建连接数 | 负载均衡 | 超过正常峰值5倍 | 检查源IP分布,加连接限制 |
| 半连接队列溢出 | 主机内核 | 计数持续增长 | 调SYN相关参数,启用Cookie |
| 后端P99响应时间 | APM | 超过基线3倍 | 排查是否应用层攻击 |
| 缓存命中率 | CDN/边缘 | 明显下降 | 检查是否被绕过缓存 |
告警阈值我建议用动态基线而不是固定值。同样的业务,工作日白天的正常峰值可能是凌晨的5倍,用固定阈值要么白天误报要么凌晨漏报。简单做法是取过去7天同一时段的P95作为基线,超过基线的1.8倍告警,超过2.5倍直接触发自动化动作。
注意:自动化动作一定要有“刹车”。我见过配置了自动切清洗的团队,因为一次正常的营销活动流量被误判成攻击,流量被切到清洗设备,清洗设备对正常流量的处理反而引入延迟,导致活动期间用户体验断崖式下降。自动化规则必须配套人工确认通道和一键回滚。
4. 应急响应:真被打的时候按什么顺序动作
架构和配置是平时的事,应急响应是战时的事。这两件事的能力模型完全不同:平时靠规划和积累,战时靠流程和判断。我参与过的处置里,出问题最多的不是技术不够,而是顺序错了——先做了一件看起来很急的事,结果把最关键的线索破坏了,或者把可用的通道堵死了。
4.1 前五分钟做什么:先保住证据和通道
流量刚起来的前几分钟最混乱。我的建议是固定一套动作,按顺序执行,不要临场发挥。
第一件事,确认是攻击而不是业务故障。看三个地方:入向流量的来源分布是否异常集中、包长分布是否单一、请求路径是否集中在少数几个接口。如果这三个都符合,基本可以判定是攻击;如果只是后端响应变慢但入向流量平稳,先查数据库和依赖服务,别急着开清洗。
第二件事,保住管理通道。攻击期间最容易发生的是你自己登不上服务器,因为SSH端口被流量和连接数挤占。所以在攻击开始前就应该准备好带外管理通道、跳板机、独立的运维入口,并且这些入口的访问控制要独立于业务流量。如果已经发生登录困难,先通过带外方式确认链路状态,不要在业务链路上死磕。
第三件事,留证据。把攻击发生前后的流量采样、连接日志、访问日志保留下来,至少保留攻击期间的抓包样本和top源IP列表。这部分对后续的分析、报案、跟服务商沟通额度都很重要。很多团队忙着恢复业务,事后想复盘发现日志被轮转掉了,连攻击规模都说不清楚。
4.2 处置动作清单与回滚条件
处置动作我按优先级排了一个顺序,这个顺序背后的逻辑是:优先做影响面最小、见效最快、最容易回滚的动作。
| 优先级 | 动作 | 生效速度 | 影响面 | 回滚方式 |
|---|---|---|---|---|
| 1 | 开启边缘缓存,静态降级 | 秒级 | 小 | 关闭规则 |
| 2 | 收紧限速阈值 | 秒级 | 中,可能误伤 | 恢复阈值 |
| 3 | 按地域/网段封禁 | 分钟级 | 中,影响部分用户 | 删除规则 |
| 4 | 切换清洗/高防线路 | 分钟到小时级 | 大,引入延迟 | 切回源站 |
| 5 | 黑洞路由/丢弃特定协议 | 秒级 | 大,可能全部不可用 | 取消路由 |
为什么把“静态降级”放在第一步?因为它不依赖任何外部服务商,自己就能做,而且用户看到的至少是“维护中”而不是“超时”。为什么“清洗切换”放在第四步?因为它涉及的链路变更最多,切换过程中可能出现DNS缓存、会话保持、健康检查误判等一系列问题,贸然切换反而可能把还能用的业务切死。
回滚条件必须提前写死。比如:开启清洗后,如果后端错误率超过5%且持续3分钟,自动回滚;如果静态降级页的访问量超过正常首页的3倍说明大量用户被引导,考虑补充提示信息而不是直接关闭。这些条件要在平时就写进预案,不能战时拍脑袋。
4.3 事后复盘要留下什么
复盘不是写个“本次攻击我们成功防御”的报告就完事。我关注的复盘产出有三样东西。第一是攻击画像:攻击类型、峰值规模、持续时间、源IP分布特征、被攻击的接口和路径。这份画像决定了你下一次该往哪个方向加强。第二是处置时间线:从流量异常到告警、到人工确认、到动作执行、到业务恢复,每一段的耗时。这条线能直接暴露你的短板在哪——是告警太慢、判断太慢,还是动作太慢。第三是成本清单:这次攻击消耗了多少清洗额度、多少扩容费用、多少人力工时。成本数据是推动预算和架构改造最有力的材料。
我自己踩过的一个坑是:第一次被大规模攻击后,复盘只关注了“怎么防住”,没关注“为什么会打到我们”。后来才发现源站IP是从一张几年前的DNS历史记录里泄露的。攻击方根本不需要很聪明,他们只要把公开信息翻一遍,就能找到你的真实入口。所以复盘里一定要加一项:暴露面复查。
5. 常见问题与排查实录
这部分我把实际遇到过的、以及同行交流时反复提到的问题整理成速查表,再单独讲几个容易踩的坑。
5.1 典型问题速查表
| 现象 | 可能原因 | 排查手段 | 处理建议 |
|---|---|---|---|
| 部分地区打不开,其他地区正常 | 区域性流量清洗或路由策略 | 多地拨测,看路由路径 | 确认是否清洗设备策略,调整放行 |
| 带宽正常但服务器连接不上 | 半连接队列或会话表被打满 | ss -s、netstat -s | 启用SYN Cookie,调大队列 |
| 缓存命中率骤降 | 攻击请求带随机参数绕过缓存 | 分析URL参数分布 | 配置忽略无关参数,规范化缓存键 |
| 清洗开启后反而更慢 | 清洗设备对正常流量引入延迟 | 对比开启前后P99 | 收紧清洗策略,只清洗异常流量 |
| 后端连接池耗尽 | 慢速请求堆积 | 看连接池活跃数和等待时间 | 收紧超时,加请求队列上限 |
| 攻击停止后业务仍未恢复 | 连接表残留、DNS缓存 | 检查TIME_WAIT、DNS TTL | 清理残留,等待缓存过期 |
| 自动扩容触发但没用 | 瓶颈在带宽而非计算 | 看扩容后带宽是否仍满 | 扩容解决不了流量型攻击,需切清洗 |
5.2 几个用钱和事故换来的实操心得
第一个坑:把限速阈值设得太激进。有一次处置应用层攻击,为了尽快压住QPS,把单IP限速从20r/s直接压到2r/s。攻击确实被压住了,但正常用户的页面加载因为并发资源请求被限流,大量图片和JS加载失败,客诉量比攻击期间还高。教训是:限速要按“资源类型”分,API和静态资源不能用一个阈值,静态资源应该尽量走缓存而不是限速。
第二个坑:只防外网不防内网。攻击方有时候会通过你的公网入口打进来之后,利用一个弱口令或者一个未授权接口在内网横向,从内部发起请求。这时候外网的清洗设备完全看不到。所以内网之间也要有基本的访问控制和速率限制,尤其是数据库、缓存、消息队列这些关键组件,不能假设“内网就是安全的”。
第三个坑:忽略了自己的DNS。攻击不一定是打你的IP,也可能是打你的DNS解析。DNS被攻击的时候表现是“域名解析不了”,用户根本到不了你的清洗设备。所以权威DNS要有冗余,解析服务的QPS要能扛住正常峰值的几十倍,TTL设置要权衡——太长导致切换慢,太短导致解析压力大。我的经验是核心域名TTL设在300秒左右,切换时能接受,平时压力也不大。
第四个坑:预案写了但没演练。很多团队的应急预案写得很漂亮,但从来没有真的切换过。真到攻击的时候,发现清洗线路的健康检查配置是错的、静态降级页的路径是404、负责切流量的人休假了。我的建议是每季度做一次小规模演练,用压测流量模拟一次脉冲攻击,把“发现—确认—切换—验证—回滚”这条链路完整走一遍,记录每一步的耗时。演练暴露出来的问题,比真实攻击便宜太多了。
第五个坑:只关注峰值不关注持续性。攻击峰值50Gbps持续10秒,和峰值5Gbps持续6小时,对业务的影响完全不同。前者考验的是你的瞬时吸收能力,后者考验的是你的成本承受能力和值班耐力。防御方案要能同时覆盖这两种形态,前者靠容量和自动切换,后者靠精细化的策略和分级降级。
第六个坑:把安全当成一次性项目。攻击手法在变,你的业务架构也在变,上个季度有效的策略这个季度可能就漏了。我一直建议把DDoS防御当成一个持续运营的事情:每个月看一次攻击趋势报表,每个季度做一次演练,每次架构变更都过一遍暴露面复查。这件事没有终点,但它带来的确定性是很实在的——你知道最坏情况下业务能撑到什么程度,也知道什么时候该按下哪个开关。
最后分享一个我个人一直坚持的习惯:把“被打的时候要做的第一件事”写在一张纸上,贴在值班位置。不是写在Wiki里,是打印出来贴在显示器旁边。因为真到那个时候,人的判断力会下降,最容易做的就是慌乱中的错误动作。一张纸上的三个步骤,比脑子里的一百个方案都管用。