中小服务器遭遇DDoS攻击时,最尴尬的往往不是带宽被打满,而是防火墙规则还没写好,业务已经因为连接数耗尽而崩溃。市面上多数DDoS防护方案要么按流量计费贵得离谱,要么需要把业务迁移到高防机房,对预算有限、服务器自管的站长或小微企业来说并不现实。轻量型DDoS防御工具的价值就在于:不改变现有网络架构,不引入重型设备,只通过软件层和系统层的合理配置,把攻击流量对中小服务器的实际影响压到可控范围。下面直接讲可落地的工具选择和配置思路。

先界定“轻量型防御”能做什么、不能做什么

轻量型DDoS防御工具主要应对的是资源耗尽型攻击,比如SYN Flood、UDP Flood、CC攻击中的低并发慢速请求,以及少量反射放大流量的第一波冲击。它不能替代大带宽清洗,也无法在数百Gbps的流量型攻击面前保持业务完全在线。但对于中小服务器常见的几十Mbps到几百Mbps攻击、几千到几万并发的CC攻击,合理配置轻量工具完全可以把服务可用性从“秒级宕机”提升到“可接受降级”。核心思路是:用最小的系统开销,在攻击流量到达业务进程之前完成过滤和限制。

内核参数调优是第一步,也是最容易被忽略的一步

很多人一上来就装各种防护软件,却忘了Linux内核本身就有大量抗DDoS相关参数。以CentOS或Ubuntu为例,以下参数可以直接写入/etc/sysctl.conf并执行sysctl -p生效:

net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_abort_on_overflow = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
net.ipv4.ip_local_port_range = 1024 65000
net.core.somaxconn = 8192
net.core.netdev_max_backlog = 8192
net.ipv4.icmp_echo_ignore_all = 1

syncookies开启后,服务器在SYN队列满时不再直接丢弃新连接,而是用cookie机制验证客户端真实性,这对SYN Flood有立竿见影的效果。tcp_abort_on_overflow设为1会让内核在accept队列溢出时直接重置连接,避免业务进程被半连接拖死。icmp_echo_ignore_all直接忽略所有ping,能挡掉一部分基于ICMP的探测和放大。这些参数几乎不消耗额外CPU和内存,属于零成本防御基线。

iptables+nftables:用系统自带防火墙做速率限制和连接追踪

轻量防御的核心工具就是iptables,尤其是它的limit、hashlimit和recent模块。一个典型的配置是:对每个来源IP的新建连接速率做限制,超过阈值的直接丢弃。例如限制单IP每秒新建TCP连接不超过20个:

iptables -A INPUT -p tcp --syn -m limit --limit 20/s --limit-burst 40 -j ACCEPT
iptables -A INPUT -p tcp --syn -j DROP

但limit模块是针对全局规则的,无法精确到单IP。更精细的做法是用hashlimit:

iptables -A INPUT -p tcp --syn -m hashlimit --hashlimit-name synflood --hashlimit-above 20/sec --hashlimit-burst 40 --hashlimit-mode srcip --hashlimit-srcmask 32 -j DROP

这条规则按源IP维度限制SYN包速率,超过20个/秒就丢弃,突发容量40个。对于UDP Flood,同样可以对UDP协议做单IP限速。需要注意的是,hashlimit在攻击规模较大时会消耗一定CPU,因为每个数据包都要查哈希表,但相比业务崩溃的代价,这点开销完全可以接受。如果服务器使用nftables,语法更简洁,性能也更好,但中小服务器上iptables的兼容性和资料丰富度更高。

Fail2ban不只是防暴力破解,也能联动防火墙封禁攻击源

Fail2ban通常被用来防SSH暴力破解,但它的过滤器和动作机制完全可以用来做轻量DDoS防御。思路是:监控Nginx或Apache访问日志,对短时间内产生大量请求的IP自动调用iptables封禁。例如在/etc/fail2ban/jail.local中增加一个针对Nginx的CC防护规则:

[nginx-cc]
enabled = true
port = http,https
filter = nginx-cc
logpath = /var/log/nginx/access.log
maxretry = 300
findtime = 60
bantime = 600

对应的filter文件/etc/fail2ban/filter.d/nginx-cc.conf内容:

[Definition]
failregex = ^<HOST> -.*"(GET|POST).*
ignoreregex =

这个配置的含义是:60秒内同一IP出现300次请求就封禁10分钟。对于中小服务器上常见的CC攻击,300次/分钟已经是很宽松的阈值,正常用户几乎不会触发,而攻击脚本很容易超过。Fail2ban的优势是部署简单、规则灵活,缺点是封禁动作有延迟,且攻击源IP如果不断变化,封禁效果会打折扣。但对于固定源IP的CC攻击,这是性价比最高的方案之一。

Nginx层防御:limit_req和limit_conn模块直接保护业务

如果业务跑在Nginx后面,那么Nginx自带的limit_req和limit_conn模块就是第一道业务层防线。limit_req基于漏桶算法做请求速率限制,limit_conn限制并发连接数。配置示例:

http {
    limit_req_zone $binary_remote_addr zone=perip:10m rate=10r/s;
    limit_conn_zone $binary_remote_addr zone=perconn:10m;

    server {
        location / {
            limit_req zone=perip burst=20 nodelay;
            limit_conn perconn 10;
            proxy_pass http://backend;
        }
    }
}

这里限制单IP每秒10个请求,突发20个,并发连接数10个。对于API类业务,10r/s可能偏紧,需要根据实际业务峰值调整。关键是rate和burst的配比:rate是长期平均速率,burst是允许的突发队列长度。nodelay表示突发请求立即处理而不排队等待,这样可以避免正常用户请求被延迟,同时攻击请求会被快速拒绝。limit_req的返回状态码默认是503,建议改成444(Nginx自定义的非标准码,直接关闭连接不返回任何内容),减少攻击流量对带宽的占用。

轻量级WAF:ModSecurity的DDoS规则集和自定义规则

ModSecurity常被当作WAF使用,但它也能做DDoS防护。对于中小服务器,不建议开启ModSecurity的全部OWASP核心规则集,因为规则太多会显著增加延迟和CPU消耗。更实际的做法是只启用与DDoS相关的规则,或者写几条自定义规则。例如限制User-Agent为空的请求、限制特定URL的访问频率:

SecRuleEngine On
SecRule REQUEST_HEADERS:User-Agent "^$" "id:100001,phase:1,deny,status:444,msg:'Empty UA'"
SecRule &TX:ip_counter "@eq 0" "id:100002,phase:1,pass,nolog,setvar:tx.ip_counter=1,setvar:tx.ip_counter_expire=60"
SecRule &TX:ip_counter "@ge 100" "id:100003,phase:1,deny,status:444,msg:'CC attack detected'"

这套规则对空User-Agent直接拒绝,并用计数器限制单IP在60秒内最多100次请求。ModSecurity的优势是规则可以非常灵活,能针对具体业务路径做精细控制,缺点是配置复杂度较高,且对HTTPS流量的处理需要额外的证书配置。如果服务器资源紧张,ModSecurity可能不是最优选择,但如果是轻度CC攻击且业务逻辑复杂,它比单纯的Nginx限速更精准。

开源DDoS防护脚本:DDoS-Deflate和类似工具的实战价值

DDoS-Deflate是一个老牌的开源轻量DDoS防御脚本,原理很简单:定期用netstat统计每个IP的连接数,超过阈值就调用iptables封禁。它的核心脚本逻辑大致如下:

netstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr | head -n $NO_OF_CONNECTIONS

这个命令列出连接数最多的前N个IP,然后脚本会判断这些IP的连接数是否超过预设阈值,超过就执行iptables -I INPUT -s IP -j DROP。DDoS-Deflate的优点是部署极其简单,一个脚本加一个cron任务就能跑起来,几乎不依赖其他组件。缺点是它只能处理基于连接数的攻击,对UDP Flood这种无连接状态的攻击效果有限,而且netstat在连接数很大时本身就会消耗不少CPU。不过对于日均访问量不大的中小服务器,DDoS-Deflate仍然是一个有效的应急工具。

CDN和反向代理的轻量替代:用Cloudflare免费版做前置过滤

如果服务器IP没有被直接暴露,把域名解析到Cloudflare免费版就能获得基础的DDoS防护。Cloudflare的免费套餐提供一定程度的L3/L4攻击过滤和CC防护,对中小服务器来说往往足够。关键操作是:把域名的NS或CNAME切到Cloudflare,然后在Cloudflare的DNS设置里开启“Proxy”模式(橙色云朵),这样真实服务器IP就被隐藏了。同时开启“Under Attack Mode”可以在检测到异常流量时对所有访客弹出JavaScript挑战,能有效过滤掉大部分自动化攻击脚本。Cloudflare免费版的局限是:如果攻击者直接对源站IP发起攻击,CDN就形同虚设,所以源站IP的保密和防火墙白名单设置非常重要。只允许Cloudflare的IP段访问源站的80/443端口,其他IP一律拒绝,这是配合CDN使用的标准做法。

组合策略比单一工具更有效

轻量型DDoS防御的核心不是某一个工具,而是多层过滤的组合。合理的顺序是:内核参数调优作为底层基线,iptables/hashlimit做网络层速率限制,Nginx limit_req做业务层请求限制,Fail2ban做动态封禁,CDN做前置过滤。每一层拦截一部分攻击流量,最终到达业务进程的流量就变得可控。需要注意的是,每一层规则都要根据实际业务流量做调整,阈值设置过严会误伤正常用户,过松则起不到防护作用。建议在部署后先观察一周的正常流量峰值,把阈值设为峰值的1.5到2倍,这样既能留出余量,又能在攻击时快速触发限制。

中小服务器做DDoS防御,本质上是资源有限条件下的取舍。轻量工具的意义在于用最小的代价获得最大的可用性提升,而不是追求完美防护。把上述工具组合起来,即使面对中等规模的攻击,服务器也有很大概率保持在线,至少不会因为一次攻击就完全瘫痪。