把DDoS防御的所有希望都寄托在一台高防IP或者一台抗D设备上,这种“单点防御”思维在现在的攻击规模面前已经行不通了。很多运维团队发现,明明购买了超大带宽的清洗服务,应用却依然在攻击期间变得不可用。问题往往不出在清洗能力上,而出在后端的源站架构上。当清洗中心把海量垃圾流量过滤掉,剩下的正常请求回源时,如果源站服务器本身没有针对这种“透传”后的突发流量做适配,源站照样会被打死。这不是清洗服务商的锅,这是源站架构的短板。
要真正把DDoS防护落到实处,必须对源站架构进行彻底的改造。这种改造不是简单地加几台服务器,而是从网络接入层到业务逻辑层都要做出调整。下面这五个核心维度,是源站架构改造中必须啃下的硬骨头。
端口收敛与协议隔离很多业务为了图方便,直接在服务器上开放了SSH的22端口、数据库的3306端口、Redis的6379端口。这在平时看起来没什么,但在DDoS攻击的背景下,这些端口就是定时炸弹。攻击者不需要打你的80端口,只要对22端口发起小规模的精确流量攻击,就足以耗尽服务器的连接数,让你连登录排查的机会都没有。
源站改造的第一步,就是做严格的端口收敛。所有管理类端口必须从公网上消失,只保留业务必须的端口。这需要引入堡垒机或者专有的管理通道,通过内网或者VPN专线进行维护。对于Web业务,只开放443端口,并且在源站前端架设一层反向代理,由这层代理去对接清洗中心的回源流量。这层代理只接受来自清洗中心白名单IP的流量,其他任何来源的请求直接丢弃。这样即使攻击者通过某种手段获取了源站真实IP,也无法直接触达业务端口。
协议隔离也是关键。如果你的业务是HTTPS,那么源站就只处理HTTPS,不要同时挂着HTTP做跳转。多一个协议就多一份计算开销。在极端流量下,HTTP 301跳转这种看似轻量的操作,累积起来也会把CPU吃满。把协议层面的处理逻辑前置到清洗中心或者CDN节点,源站只做最纯粹的加密通信处理,能极大降低资源消耗。
连接池与队列机制的深度优化源站被打垮,90%的情况不是带宽被占满,而是连接数被耗尽。操作系统默认的TCP参数在DDoS回源流量的冲击下,完全不够看。你需要对内核参数进行大刀阔斧的调整。
首先是TCP连接超时时间的调整。默认的time_wait状态可能长达60秒甚至120秒,这在攻击期间会迅速耗尽端口资源。需要把net.ipv4.tcp_fin_timeout调低,同时开启tcp_tw_reuse和tcp_tw_recycle(注意内核版本兼容性)。对于SYN_RECV状态,通过调整tcp_synack_retries减少重试次数,让半连接尽快释放。
其次是文件句柄数的提升。默认的1024或者65535在攻击面前就是纸糊的。需要把nofile限制提升到百万级别,同时调整fs.file-max内核参数。这不仅仅是改个数字,还要同步调整应用程序的连接池配置。Nginx的worker_connections需要与系统的nofile匹配,后端应用如Tomcat、Gunicorn的连接池也要相应扩容。
最关键的是引入队列削峰机制。在源站的反向代理层,配置严格的速率限制和请求队列。不要指望后端应用能处理所有透传过来的请求。在Nginx层面,使用limit_req模块对单个IP的请求速率进行限制,超出限制的请求直接返回503,而不是转发给后端。同时配合limit_conn模块限制并发连接数。这种“丢车保帅”的策略,能保证在攻击期间,核心用户依然有概率获得服务,而不是全体用户一起崩溃。
动静分离与缓存前置如果你的源站还在直接响应每一个动态请求,并且夹杂着大量的静态资源请求,那么在DDoS攻击下,数据库和磁盘IO会最先崩溃。源站架构改造的核心思想之一,就是把源站“变傻”,让它只处理那些真正需要实时计算的核心动态请求。
静态资源必须全部推到CDN或者对象存储上。这里的静态资源不仅包括CSS、JS、图片,还包括那些更新频率极低、但访问量极大的“伪静态”内容,比如商品详情页的框架、文章内容等。对于这些内容,可以在反向代理层配置基于内存的缓存,比如Nginx的proxy_cache或者Varnish。设置合理的缓存过期时间,让这些请求在到达应用服务器之前就被拦截并返回。
对于动态请求,也要做精细化的分级缓存。比如一个API接口,如果它对实时性要求不高,可以在反向代理层缓存几秒钟甚至几分钟。这几秒钟的缓存,在攻击期间能挡住90%的重复请求,为后端数据库争取到宝贵的喘息时间。需要修改业务代码,在响应头中加入Cache-Control和Surrogate-Control等字段,让代理层能够识别并执行缓存策略。这不是一个纯运维的操作,需要开发人员配合改造。
业务逻辑解耦与异步化很多业务在遭受DDoS攻击时,表现出来的症状是数据库CPU 100%或者连接池满。深入排查会发现,攻击流量触发了某些极其消耗资源的数据库查询。比如攻击者专门刷搜索接口,或者刷那些需要全表扫描的报表页面。这种攻击流量经过清洗后,虽然变成了“正常”的HTTP请求,但对源站的杀伤力比流量型攻击更致命。
源站架构改造必须深入到业务逻辑层面,做强制性的解耦。将搜索、推荐、报表生成等重计算服务,从核心Web应用中剥离出来,部署在独立的集群上。在核心Web应用与这些重服务之间,使用消息队列进行异步隔离。当攻击流量触发大量搜索请求时,请求会堆积在消息队列中,而不是直接压垮搜索服务。核心Web应用可以快速返回“系统繁忙”的响应,而不会被拖死。
对于用户登录、注册、下单等核心链路,要做极致的轻量化。检查这些接口的数据库查询次数,能否从10次减少到2次?能否去掉不必要的关联查询?在攻击期间,每一个多余的数据库查询都是在自杀。可以考虑引入Redis作为前置缓存,将用户鉴权token、基础信息全部缓存在内存中,让核心链路尽量不触碰磁盘IO。
源站IP的隐匿与轮转机制源站真实IP泄露是DDoS防护中最致命的漏洞。即使前面挂着清洗服务,一旦攻击者知道了源站IP,就可以绕过清洗直接攻击。传统的做法是只把IP告诉清洗服务商,然后寄希望于攻击者找不到。但这种被动隐匿在实战中经常失效,因为历史DNS记录、邮件头信息、甚至SSL证书的透明度日志都可能暴露源站IP。
更主动的做法是建立源站IP的轮转与生命周期管理机制。不要把源站部署在固定的几个公网IP上。利用云计算的弹性能力,将源站部署在虚拟私有网络内,通过弹性公网IP或者负载均衡器对外暴露。当检测到源站IP泄露或者遭受直接攻击时,能够在一分钟内释放旧IP并绑定新IP。清洗中心的回源配置需要支持动态更新源站地址,这可以通过API自动化完成。
更进一步,可以采用“无源站”或者“全托管”的架构思路。将业务完全运行在容器或者Serverless平台上,通过平台的内网负载均衡与清洗服务对接。这样源站根本就没有固定的公网入口,攻击者无从下手。这种架构需要业务代码做一定程度的改造以适应无状态运行,但换来的是源站安全性的指数级提升。
源站架构改造不是一次性工程,而是需要随着业务和攻击手法演变持续迭代的过程。每一次改造,都要围绕一个核心目标:让源站在极限压力下,依然能够保持核心业务的可用性。这意味着要敢于做减法,砍掉不必要的功能,简化调用链路,把资源集中在最重要的交易闭环上。当你的源站架构足够精干、足够弹性时,DDoS攻击的效果就会被压缩到最低。
