中小站点做DDoS防御,最大的误区就是照搬大厂的方案。你去看那些动辄几百G防御的高防IP、清洗中心方案,对于日均几百IP、服务器只有2核4G的站点来说,既不现实也没必要。攻击者打你,往往不是要打死你的服务器,而是打满你的带宽、耗光你的连接数,或者直接把你那台小VPS的CPU占满。所以,中小站点的防御核心就八个字:分层过滤,保命要紧。

先认清一个现实:你的带宽可能只有5M、10M。一个10G的SYN Flood打过来,还没到服务器,在机房入口就把你的带宽塞死了。这种情况下,你在服务器上做任何优化都是徒劳的。所以,防御的第一层,必须在流量进入你的网络之前完成。

利用CDN和反向代理隐藏源站

这是成本最低、效果最立竿见影的一步。把你的域名解析挂到CDN上,只让CDN节点对外暴露,真实服务器IP严格保密。一旦源站IP泄露,攻击者可以直接绕过CDN打你,所有前置防御瞬间失效。操作上要注意几点:首先,检查你的历史DNS解析记录,确保IP没被标记过;其次,服务器绝对不要直接用IP对外提供Web服务,配置默认站点直接返回444或空响应;再者,所有对外发信的邮件头、论坛附件地址、甚至你登录SSH时泄露的欢迎信息,都可能暴露真实IP。如果源站IP已经泄露,换IP是唯一的办法,不要心存侥幸。

CDN的选择上,没必要追求顶级商业套餐。很多CDN服务商提供的免费或基础套餐,本身就自带一定的DDoS防护能力,对于中小型攻击足够用。关键在于配置好缓存策略,把静态资源缓存时间设长,动态请求做好剥离,这样即使攻击打过来,大部分请求在CDN边缘节点就被消化了,回源请求量很小。如果你的业务对实时性要求不高,甚至可以开启“离线缓存”模式,即使源站暂时不可达,CDN依然能吐出缓存的页面,保证用户基本可访问。

网络层过滤:用云服务商的安全组筑起第一道墙

即使你用了CDN,源站服务器自身的安全组配置也不能马虎。安全组是云服务器最外层的防火墙,它的规则处理在流量到达系统内核之前,几乎不消耗计算资源。你需要做的是构建一个“白名单+最小化”的规则体系。对于Web服务,只开放80和443端口,其他所有端口对公网全部关闭。如果你有固定的办公IP,SSH的22端口就只对这个IP开放,不要图方便对全网开放然后改个高端口,端口扫描器几秒钟就能扫出来。

更进一步的,可以在安全组层面做一些简单的特征过滤。比如,你的站点如果没有UDP服务,就在安全组入方向全部拒绝UDP协议。对于TCP,可以限制单个IP的并发连接数,这个功能多数云服务商的安全组都支持。设置一个合理的阈值,比如单个IP最多同时建立20个连接,就能有效缓解SYN Flood和连接耗尽型攻击。这些规则在云防火墙层面执行,效率远高于你在服务器上用iptables折腾。

系统内核调优:榨干服务器的每一分性能

流量到达服务器后,系统的TCP/IP协议栈参数直接决定了你能扛住多大的压力。默认的内核参数是为普通桌面环境设计的,作为服务器必须调整。这不是什么高深技术,但很多站长容易忽略。核心思路是:缩短超时时间、增大队列长度、快速回收资源。

打开/etc/sysctl.conf文件,加入或修改以下参数:

# 缩短SYN_RECV状态超时时间,默认60秒太长
net.ipv4.tcp_synack_retries = 2
# 减少TIME_WAIT状态连接的超时时间
net.ipv4.tcp_fin_timeout = 30
# 启用TIME_WAIT快速回收
net.ipv4.tcp_tw_reuse = 1
# 扩大半连接队列长度
net.ipv4.tcp_max_syn_backlog = 8192
# 扩大全连接队列长度
net.core.somaxconn = 8192
# 启用SYN Cookie,这是防SYN Flood的关键
net.ipv4.tcp_syncookies = 1
# 增大本地端口范围
net.ipv4.ip_local_port_range = 1024 65535

修改后执行sysctl -p使其生效。其中tcp_syncookies是防御SYN Flood的核心机制,它用算法验证代替资源分配,在攻击流量下能极大降低系统开销。但要注意,SYN Cookie在高并发正常流量下也会增加CPU计算量,如果你的站点正常并发就很高,需要测试后决定是否开启。

Web服务器和应用层的精细化防御

Nginx是中小站点最常用的Web服务器,它的配置直接关系到能否扛住CC攻击和慢速攻击。很多人只配了worker_processes和worker_connections,这远远不够。你需要做三个层面的限制:请求速率、并发连接数、以及缓冲区大小。

在Nginx的http块或server块中,配置limit_req_zone和limit_conn_zone来定义共享内存区域:

# 定义请求频率限制,以客户端IP为键,每秒最多10个请求
limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;
# 定义并发连接数限制,每个IP最多5个并发连接
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;

然后在具体的location中应用:

location / {
    limit_req zone=req_limit burst=20 nodelay;
    limit_conn conn_limit 5;
    # 其他配置
}

burst参数很重要,它允许短时突发流量,超出rate限制的请求会被排队,配合nodelay可以立即处理突发请求而不延迟。对于动态页面,比如登录接口、搜索接口,可以单独设置更严格的限制,比如每秒1个请求,因为这些接口消耗资源大,是CC攻击的重点目标。

慢速攻击的防御同样关键。攻击者建立连接后,以极慢的速度发送请求头或请求体,长时间占用连接资源。通过以下配置应对:

# 客户端请求头读取超时时间
client_header_timeout 10s;
# 客户端请求体读取超时时间
client_body_timeout 10s;
# 响应发送超时时间
send_timeout 10s;
# 关闭保持连接的超时时间
keepalive_timeout 30s;
# 限制请求头大小
client_header_buffer_size 1k;
large_client_header_buffers 2 1k;
# 限制请求体最大大小
client_max_body_size 10m;

这些参数把各种超时和大小限制收紧,让慢速连接快速超时释放资源。如果你的站点用了PHP,还要同步调整php-fpm的request_terminate_timeout,避免PHP进程被长时间占用。

应用层WAF:用开源方案构建智能拦截

对于中小站点,商业WAF动辄数万一年的费用不现实,但开源方案完全可以构建起有效的应用层防线。ModSecurity是目前最成熟的开源WAF模块,可以直接编译进Nginx或作为动态模块加载。它的核心是OWASP维护的核心规则集,包含了SQL注入、XSS、命令注入等常见攻击的检测规则。

部署ModSecurity需要权衡检测强度和性能开销。默认的OWASP CRS规则集有近万条规则,全开的话,一台2核4G的服务器处理每个请求都要消耗额外几十毫秒。建议先开启“异常评分模式”,将阈值调低,只对评分超过阈值的请求进行拦截,这样对正常请求影响最小。同时,一定要关闭那些对你的业务不相关的规则,比如你的站点没有文件上传功能,就把文件上传相关的规则组全部禁用。

如果觉得ModSecurity配置复杂,Nginx+Lua的组合也是一种轻量级选择。利用OpenResty,你可以用Lua脚本在Nginx的access阶段编写自定义的检测逻辑。比如,检测User-Agent是否为空或包含已知的攻击工具特征,检测Referer是否来自异常来源,检测特定URL的访问频率。这些逻辑写起来很简单,但效果非常直接。下面是一个简单的Lua脚本示例,用于封禁特定User-Agent:

access_by_lua_block {
    local ua = ngx.var.http_user_agent
    if not ua or ua == "" then
        ngx.exit(403)
    end
    local bad_agents = {"sqlmap", "nikto", "acunetix", "nessus"}
    for _, agent in ipairs(bad_agents) do
        if string.find(string.lower(ua), agent) then
            ngx.exit(403)
        end
    end
}
日志监控与自动化响应

防御不是一次配置就完事的,攻击手法在变,你的规则也需要迭代。中小站点往往没有专门的运维团队盯着,所以自动化监控和响应机制尤为重要。一个实用的做法是:写一个简单的脚本,定时分析Nginx访问日志,统计每个IP的请求频率和状态码分布。当某个IP在短时间内产生了大量404或5xx错误,或者请求频率远超正常阈值,脚本自动调用云服务商的API,将这个IP加入安全组的黑名单。

这个脚本的逻辑不复杂。用shell配合awk就能实现:每分钟统计一次access.log,提取请求数超过阈值的IP,查一下这个IP的地理位置或威胁情报(有免费API可用),如果确认可疑,就调用云API封禁。注意设置自动解封时间,比如封禁30分钟,避免误伤。同时,保留封禁日志,方便事后分析。

还有一个容易被忽视的点:DNS层面的监控。如果你的域名被DNS劫持或受到了DNS反射放大攻击的波及,你的权威DNS服务器可能会瘫痪。中小站点通常使用域名注册商或CDN服务商提供的免费DNS,它们的防护能力参差不齐。建议至少配置一个备用DNS服务,并在域名注册商处同时设置主备DNS服务器地址。对于关键业务,可以考虑使用支持DNS安全防护的专业服务,成本通常不高。

最后的兜底方案:静态化与降级

当所有技术手段都无法完全抵御攻击时,你需要一个业务层面的兜底策略。把动态网站静态化是最有效的保命手段。如果你的站点内容更新不频繁,完全可以提前生成全站静态HTML文件,攻击发生时,切换到纯静态模式,用Nginx直接返回静态文件,彻底绕过数据库和PHP。即使正常模式下,也可以对关键页面做静态化缓存,减少动态请求的处理开销。

降级策略还包括:临时关闭搜索功能、关闭用户登录注册、关闭评论功能。这些功能都是资源消耗大户,关闭后能显著提升服务器在攻击下的存活能力。提前准备好一个轻量级的“维护页面”或者“降级页面”,当检测到服务器负载过高时,自动将流量引导到这个静态页面,告知用户稍后再试。这比让用户看到502或504错误要好得多。

中小站点的DDoS防御,本质是一场资源精算。你没有无限的带宽和算力,所以必须在每一层都做到极致优化,用最小的代价过滤掉尽可能多的恶意流量。从CDN到安全组,从内核参数到Nginx配置,从WAF规则到自动化封禁,每一层都拦截一部分,最终到达你业务逻辑的恶意请求就所剩无几了。这套体系不需要高昂的成本,但需要你花时间理解原理、精细配置、持续迭代。