前言介绍
在网站运营过程中,CC攻击(Challenge Collapsar,即挑战黑洞攻击)是一种常见的小规模应用层攻击方式。攻击者通过控制大量僵尸IP或单IP发起高频请求,耗尽服务器资源,导致正常用户无法访问。对于中小型网站或业务系统,部署昂贵的硬件防火墙成本过高,而利用系统自带的防火墙工具(如Linux的iptables或firewalld)进行单IP访问频次限制,是一种经济且有效的防护手段。本教程将手把手教你如何通过配置防火墙规则,实现针对单个IP的访问频率控制,从而抵御小规模CC攻击。
前置准备
1. 一台运行Linux系统的服务器(本教程以CentOS 7/8为例,其他发行版操作类似)。
2. 拥有root用户权限或具有sudo执行权限的账户。
3. 确保系统已安装iptables或firewalld(CentOS 7默认使用firewalld,但本教程同时提供两种方案)。
4. 了解当前服务器对外提供的服务端口(如HTTP 80、HTTPS 443等)。
5. 建议先备份当前防火墙规则:`iptables-save > /root/iptables_backup_$(date +%Y%m%d).rules`(iptables方案)或`firewall-cmd --list-all > /root/firewalld_backup_$(date +%Y%m%d).txt`(firewalld方案)。
分步操作步骤
方案一:使用iptables + recent模块限制单IP访问频次
1. 检查系统是否支持recent模块
执行命令 `lsmod | grep xt_recent`。如果没有任何输出,说明模块未加载。执行 `modprobe xt_recent` 手动加载模块,并执行 `echo "xt_recent" >> /etc/modules-load.d/xt_recent.conf` 确保开机自动加载。
2. 创建基础防护规则(以限制HTTP 80端口为例)
执行以下命令,创建一条规则:当某个IP在60秒内访问TCP 80端口超过30次时,将该IP加入黑名单并封禁120秒。
```
iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m recent --name CCATTACK --set
iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m recent --name CCATTACK --update --seconds 60 --hitcount 30 -j DROP
```
参数解释:
- `-p tcp --dport 80`:匹配TCP协议目标端口80的流量。
- `-m state --state NEW`:仅匹配新建连接请求,避免统计已建立的连接。
- `-m recent --name CCATTACK --set`:将源IP记录到名为“CCATTACK”的列表中。
- `--update --seconds 60 --hitcount 30`:在60秒内,如果同一IP的命中次数达到30次,则触发后续动作。
- `-j DROP`:丢弃匹配的数据包(即封禁该IP)。
3. 为其他服务端口添加类似规则(如HTTPS 443)
复制上一步的规则,将端口号改为443即可:
```
iptables -A INPUT -p tcp --dport 443 -m state --state NEW -m recent --name CCATTACK_HTTPS --set
iptables -A INPUT -p tcp --dport 443 -m state --state NEW -m recent --name CCATTACK_HTTPS --update --seconds 60 --hitcount 30 -j DROP
```
注意:每个服务端口应使用独立的recent列表名称(如CCATTACK_HTTPS),避免不同端口的访问次数互相影响。
4. 调整封禁时长和触发阈值
如果你希望更严格或更宽松的防护,可以修改参数。例如,将封禁时间延长到300秒,触发次数降低到20次:
```
iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m recent --name CCATTACK --set
iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m recent --name CCATTACK --update --seconds 300 --hitcount 20 -j DROP
```
注意:`--seconds`是统计窗口时长(秒),`--hitcount`是窗口内允许的最大连接数。触发后,IP会被自动加入recent列表,但不会永久封禁;超过`--seconds`时间后,如果该IP不再发送新连接,记录会自动过期。
5. 保存规则使其永久生效
CentOS 7/8中,执行 `service iptables save` 或 `iptables-save > /etc/sysconfig/iptables`。如果系统提示未安装iptables-services,执行 `yum install iptables-services -y` 安装,然后启动并启用服务:`systemctl enable iptables && systemctl start iptables`。
方案二:使用firewalld + rich-rule实现频次限制
1. 确认firewalld运行状态
执行 `systemctl status firewalld`,确保状态为active (running)。如果未运行,执行 `systemctl start firewalld && systemctl enable firewalld`。
2. 创建直接规则(direct rule)实现类似recent功能
firewalld本身不直接支持recent模块,但可以通过直接规则调用iptables。执行以下命令添加一条针对80端口的限制规则:
```
firewall-cmd --direct --add-rule ipv4 filter INPUT 0 -p tcp --dport 80 -m state --state NEW -m recent --name CCATTACK --set
firewall-cmd --direct --add-rule ipv4 filter INPUT 1 -p tcp --dport 80 -m state --state NEW -m recent --name CCATTACK --update --seconds 60 --hitcount 30 -j DROP
```
参数与iptables方案完全一致。注意:`--add-rule`后面的数字(0和1)是规则的优先级,数字越小优先级越高。第一条规则负责记录,第二条规则负责判断并封禁。
3. 为其他端口重复操作(如443端口)
```
firewall-cmd --direct --add-rule ipv4 filter INPUT 0 -p tcp --dport 443 -m state --state NEW -m recent --name CCATTACK_HTTPS --set
firewall-cmd --direct --add-rule ipv4 filter INPUT 1 -p tcp --dport 443 -m state --state NEW -m recent --name CCATTACK_HTTPS --update --seconds 60 --hitcount 30 -j DROP
```
4. 使规则永久生效
直接规则默认只在当前运行时生效。执行以下命令将规则持久化:
```
firewall-cmd --runtime-to-permanent
```
或者直接使用 `--permanent` 参数重新添加一遍规则(注意:使用`--permanent`添加后需要`firewall-cmd --reload`加载):
```
firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -p tcp --dport 80 -m state --state NEW -m recent --name CCATTACK --set
firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 1 -p tcp --dport 80 -m state --state NEW -m recent --name CCATTACK --update --seconds 60 --hitcount 30 -j DROP
firewall-cmd --reload
```
5. 验证规则是否生效
执行 `firewall-cmd --direct --get-all-rules`,查看输出中是否包含刚才添加的两条规则。如果能看到,说明配置成功。
常见问题
问题1:配置后自己也被封禁了怎么办?
解答:首先检查你的测试IP是否在短时间内发送了大量请求。如果是正常测试,可以将自己的IP加入白名单。iptables方案:执行 `iptables -I INPUT -s 你的IP地址 -j ACCEPT`(注意放在规则最前面)。firewalld方案:执行 `firewall-cmd --permanent --add-source=你的IP地址 --zone=trusted`,然后 `firewall-cmd --reload`。
问题2:如何查看当前被限制的IP列表?
解答:recent模块将记录保存在`/proc/net/xt_recent/`目录下。执行 `cat /proc/net/xt_recent/CCATTACK` 即可看到所有被记录的IP及其命中次数。如果该文件不存在,说明recent模块未正确加载或规则未命中任何IP。
问题3:规则不生效,攻击流量仍然进入?
解答:请确认规则是否添加到了正确的链(INPUT链)。另外,检查是否有其他规则(如默认策略为ACCEPT)在recent规则之前匹配并放行了流量。建议将recent规则放在INPUT链靠前的位置,例如使用 `-I INPUT` 插入到第一条。同时,确保系统没有禁用iptables或firewalld服务。
问题4:封禁时长如何精确控制?
解答:recent模块的封禁是基于时间窗口的滑动记录。当IP触发`--hitcount`后,该IP在`--seconds`时间内继续发送请求都会被丢弃。但一旦超过`--seconds`时间没有新请求,记录自动过期。如果想实现固定时长的封禁,可以结合`iptables`的`-m recent --rcheck`和`-m limit`实现更复杂逻辑,但本教程的简单方案已足够抵御小规模CC攻击。
问题5:如何临时禁用规则?
解答:iptables方案:执行 `iptables -D INPUT -p tcp --dport 80 -m state --state NEW -m recent --name CCATTACK --update --seconds 60 --hitcount 30 -j DROP` 删除对应规则。firewalld方案:执行 `firewall-cmd --direct --remove-rule ipv4 filter INPUT 1 -p tcp --dport 80 -m state --state NEW -m recent --name CCATTACK --update --seconds 60 --hitcount 30 -j DROP`。
收尾总结
通过本教程,你已经学会了如何利用系统自带的防火墙工具,针对单个IP的访问频次进行有效限制。无论是使用传统的iptables还是更现代的firewalld,核心都是利用recent模块记录并统计每个IP的连接行为,在超出阈值后自动丢弃数据包,从而抵御小规模CC攻击。这种方案无需额外安装软件,配置简单,资源占用极低,非常适合中小型网站和业务系统。建议在实际部署前,先在测试环境验证阈值设置是否合理,避免误伤正常用户。同时,定期查看`/proc/net/xt_recent/`下的记录文件,了解攻击趋势,必要时调整参数。如果需要更精细的防护(如针对特定URL或User-Agent),可以结合Nginx或Apache的访问控制模块,与防火墙规则形成多层防御体系。