网站遭遇DDoS攻击时最直观的表现不是带宽被占满,而是业务逻辑在极短时间内被海量无效请求淹没,导致正常用户无法建立连接或请求超时。要解决“网站宕机”这个结果,必须从流量入口、计算资源、应用逻辑和运维响应四个层面同时下手,单纯加带宽或封IP都属于治标不治本。

先分清攻击类型再决定防御优先级

DDoS不是一种攻击,而是一大类攻击的统称。常见的包括SYN Flood、UDP Flood、HTTP Flood、Slowloris、DNS Query Flood以及反射放大攻击。不同类型的攻击消耗的资源完全不同。SYN Flood打的是TCP握手队列,UDP Flood打的是带宽和防火墙状态表,HTTP Flood打的是Web服务器和数据库连接池,Slowloris打的是连接并发数,DNS Query Flood打的是解析性能。如果连攻击类型都没判断清楚就上防御策略,很可能花了钱加了设备,攻击一来照样宕机。

判断攻击类型不能只看流量图。带宽跑满通常是UDP Flood或反射放大;CPU和内存飙升但带宽没满,多半是HTTP Flood或Slowloris;连接数暴涨但单个连接数据量极小,基本是SYN Flood或连接耗尽型攻击。运维人员要在攻击发生时第一时间抓取netstat、ss、tcpdump的样本数据,同时记录每秒钟新建连接数、半连接数、应用层请求数和响应时间,这些数据比总流量数字更有价值。

网络层防御:把无效流量挡在业务前面

网络层防御的核心思路是“用便宜的资源消耗对抗便宜的攻击流量”。最基础的手段是黑洞路由,也就是运营商把发往目标IP的所有流量全部丢弃。黑洞路由能保住机房其他设备,但等于自己把网站掐了,只能作为最后手段。更实用的做法是流量清洗,把访问流量先引入清洗中心,通过规则过滤掉明显的攻击包,再把正常流量回注到源站。清洗中心可以是运营商提供的服务,也可以是自建的清洗集群。

自建清洗集群时,BGP宣告和流量牵引是关键技术。正常情况下清洗设备不参与路由,检测到攻击后通过BGP向运营商宣告更精确的路由前缀,把流量引到清洗设备上。清洗设备完成过滤后,通过GRE隧道或二层回注把干净流量送回业务服务器。这套方案对运维团队的网络工程能力要求较高,但长期来看比完全依赖运营商清洗更灵活,响应速度也更快。

对于SYN Flood,内核参数调优能起到立竿见影的效果。Linux系统下可以调整tcp_synack_retries、tcp_max_syn_backlog和tcp_syncookies。开启SYN Cookie后,服务器不再为每个SYN包分配完整的连接资源,而是用算法生成一个Cookie回应客户端,只有收到合法ACK才真正建立连接。这个机制能把SYN Flood的防御成本降到极低。但要注意,SYN Cookie在高并发正常访问场景下会增加CPU计算量,需要根据业务情况权衡。

应用层防御:HTTP Flood才是真正的难题

网络层的攻击可以用防火墙和清洗设备处理,但HTTP Flood模拟的是真实用户行为,每个请求都完成TCP握手,甚至带上合法的User-Agent和Cookie。这类攻击的流量可能并不大,但每个请求都会触发数据库查询或动态页面渲染,几十万次请求就能把后端打垮。防御HTTP Flood必须深入到应用逻辑层面。

第一步是限制请求频率。在Nginx或OpenResty层面配置limit_req模块,对单个IP、单个会话或单个URL路径做速率限制。但攻击者会使用大量代理IP来绕过IP限速,所以IP维度的限速只能挡住小规模攻击。更有效的做法是基于用户行为建模,识别正常用户和攻击机器人的差异。正常用户访问网站时,页面请求顺序、停留时间、点击热区、滚动行为都有一定规律,而攻击脚本通常是机械地请求同一个URL或随机跳转。通过在前端嵌入JavaScript挑战,要求客户端执行一段计算并回传结果,可以过滤掉大部分简单脚本。

第二步是设置动态挑战机制。当某个IP或会话的请求频率超过阈值时,不直接拒绝,而是返回一个带有JavaScript跳转或验证码的页面。正常浏览器会自动执行脚本并跳转回原页面,攻击脚本如果不支持JavaScript执行就无法继续。这个方案对用户体验有轻微影响,但能在攻击期间保住核心业务可用。需要注意的是,搜索引擎爬虫和API客户端可能无法执行JavaScript,需要设置白名单机制。

第三步是做好缓存和静态化。如果网站首页或核心页面是动态生成的,每次请求都查数据库,那HTTP Flood的杀伤力会成倍放大。把不频繁变化的内容做成静态文件或CDN缓存,攻击请求打到缓存层就被消化掉,后端压力大幅降低。对于必须动态处理的内容,可以在应用层引入消息队列削峰,把请求先放入队列,后端按固定速率消费,超出处理能力的请求直接返回降级页面。

架构层面的抗DDoS设计

单台服务器无论配置多高,面对大规模DDoS都撑不住。架构上必须做到“分散入口、弹性扩容、隔离故障”。分散入口是指不要把业务放在单一IP或单一机房,使用多个IP、多个机房甚至多个云服务商做负载均衡。攻击者通常只会打其中一个入口,其他入口可以继续提供服务。弹性扩容是指当流量突然增大时,能够快速增加计算资源来吸收攻击流量。云平台的自动伸缩组可以在几分钟内拉起几十台新实例,配合负载均衡把流量分摊开,即使攻击流量很大,也不至于让单台机器过载。

隔离故障是指把不同类型的业务部署在不同的资源池中。静态资源走CDN,动态接口走后端集群,数据库单独部署并做好读写分离。攻击者打静态资源时,动态业务不受影响;打动态接口时,静态页面还能正常展示。很多网站被DDoS打挂的原因是所有服务都挤在同一台服务器上,一个点被打穿,整个系统跟着崩溃。

CDN在抗DDoS中扮演的角色被很多人低估了。CDN节点分布在全球各地,总带宽容量远超单个源站。把网站接入CDN后,用户请求先到CDN节点,CDN节点命中缓存就直接返回内容,只有未命中的请求才会回源。攻击流量如果打在CDN节点上,CDN的分布式架构和超大带宽可以吸收大部分冲击。源站只需要对CDN的回源IP做白名单,其他IP一律拒绝连接,这样攻击者就无法直接打到源站。不过CDN也不是万能的,如果攻击者找到了源站的真实IP,绕过CDN直接攻击源站,CDN就形同虚设。所以源站IP必须严格保密,只对CDN回源开放,同时定期更换源站IP。

运维响应和应急预案

DDoS攻击往往是突发的,从发现到业务受影响可能只有几分钟。如果没有预先准备好的应急预案,运维人员临时摸索处理流程,宕机时间会被无限拉长。应急预案至少要包含以下几个部分:攻击检测方式、责任人分工、处置步骤、降级方案和事后复盘流程。

攻击检测不能只靠人工盯监控。配置自动化告警,当流量、连接数、响应时间等指标超过阈值时,系统自动通知运维人员。告警阈值要根据业务正常波动范围来设定,避免误报。处置步骤要具体到每一条命令和每一个操作界面,比如先执行什么命令抓取现场数据,再联系哪个运营商或云服务商,然后启用哪套清洗策略。降级方案是指当核心业务无法正常提供时,优先保证哪些功能可用。比如电商网站被攻击时,可以暂时关闭搜索和推荐功能,只保留商品浏览和下单功能,把计算资源集中到最关键的业务上。

事后复盘同样重要。每次攻击结束后,要分析攻击类型、流量特征、防御效果和不足之处,把新的攻击样本加入清洗规则库,更新应急预案。DDoS攻击手法在不断演变,防御策略也必须持续迭代。很多企业第一次遭遇大规模DDoS时手足无措,但经历过几次并认真复盘后,防御能力会有质的提升。

自建防御与专业服务的取舍

对于中小企业来说,完全自建DDoS防御体系成本太高,一台像样的清洗设备动辄几十万,还需要专业的网络工程师维护。更现实的做法是组合使用云服务商的基础防护、CDN和第三方DDoS防护服务。云服务商通常提供免费的基礎DDoS防护,能挡住几Gbps到几十Gbps的攻击。超过免费阈值后,可以购买高防IP服务,把业务流量牵引到高防机房,清洗后再回源。第三方DDoS防护服务商则提供更专业的清洗能力和更快的响应速度,适合对业务连续性要求极高的企业。

选择防护方案时要算清楚一笔账:宕机一小时造成的收入损失和用户流失,与购买高防服务的费用相比,哪个更高。很多企业平时觉得高防服务贵,被攻击宕机后才后悔没有提前准备。DDoS防御本质上是一种保险,平时看不出价值,关键时刻能救命。

最后要强调的是,DDoS防御没有一劳永逸的方案。攻击者的成本在降低,攻击规模在增大,攻击手法在进化。防御方必须保持对攻击趋势的持续关注,定期演练应急预案,不断优化架构和规则。只有把防御意识融入日常运维的每一个环节,才能在攻击来临时最大程度地规避网站宕机问题。