CentOS服务器安全防护中,firewalld结合IPSet动态黑名单是高效拦截恶意流量的实战方案。传统防火墙规则逐个添加IP效率低下,而IPSet能管理海量IP集合,配合动态更新机制,可自动封禁扫描器、爆破工具等攻击源。下面直接说明如何配置firewalld的IPSet,并集成动态黑名单脚本实现自动化防护。

一、firewalld与IPSet协同工作原理

firewalld作为CentOS默认防火墙工具,通过zone和service概念管理流量。其内置的IPSet支持允许创建IP地址、网络段、端口号的集合,并将集合作为整体应用到防火墙规则。例如,创建一个名为"blacklist"的IPSet存储恶意IP,再通过firewalld规则拒绝该集合所有访问,比逐条添加规则节省大量系统资源。IPSet集合类型可选hash:ip(单个IP)、hash:net(网段)等,firewalld通过direct接口直接调用底层iptables/ipset工具,确保高性能匹配。

二、创建并绑定IPSet到firewalld规则

首先通过firewall-cmd永久创建IPSet,类型设为hash:ip,并关联到public zone(根据实际网络zone调整)。以下为具体操作命令:

# 创建永久IPSet,命名为blacklist,存储IPv4地址
sudo firewall-cmd --permanent --new-ipset=blacklist --type=hash:ip --option=family=inet

# 加载IPSet到运行时配置
sudo firewall-cmd --reload

# 查看已创建IPSet
sudo firewall-cmd --info-ipset=blacklist

# 将IPSet关联到public zone的拒绝规则
sudo firewall-cmd --permanent --zone=public --add-rich-rule='rule source ipset=blacklist drop'

# 再次重载使规则生效
sudo firewall-cmd --reload

此时,添加到blacklist的IP将自动被丢弃。测试方法:手动添加一个测试IP到IPSet,并尝试访问验证拦截效果:

# 向IPSet添加测试IP(例如192.168.1.100)
sudo firewall-cmd --ipset=blacklist --add-entry=192.168.1.100

# 确认IP已加入集合
sudo firewall-cmd --ipset=blacklist --get-entries

# 清除测试IP(避免误封)
sudo firewall-cmd --ipset=blacklist --remove-entry=192.168.1.100

三、动态黑名单的自动化更新机制

手动管理黑名单不现实,需借助自动化脚本定期更新IPSet。常见动态黑名单来源包括:Fail2ban日志分析、公开威胁情报IP库(如AbuseIPDB)、实时入侵检测系统(IDS)警报。以下示例脚本通过解析/var/log/secure日志,提取失败登录次数超阈值的IP,自动加入firewalld的IPSet:

#!/bin/bash
# 动态黑名单更新脚本 dynamic_blacklist.sh
THRESHOLD=5  # 登录失败阈值
LOG_FILE="/var/log/secure"
IPSET_NAME="blacklist"

# 分析日志,获取失败次数超阈值的IP
BAD_IPS=$(grep "Failed password" $LOG_FILE | awk '{print $(NF-3)}' | sort | uniq -c | awk -v limit=$THRESHOLD '$1 > limit {print $2}')

# 将IP添加到IPSet
for ip in $BAD_IPS; do
    firewall-cmd --ipset=$IPSET_NAME --add-entry=$ip 2>/dev/null && echo "$(date) - 已封锁IP: $ip" >> /var/log/firewalld_blacklist.log
done

# 可选:清理超过7天的旧IP(避免IPSet过大)
# 需额外维护IP添加时间记录,此处省略简化

通过cron定时任务每5分钟执行脚本,实现动态封锁:

# 编辑cron任务
sudo crontab -e
# 添加行:
*/5 * * * * /root/dynamic_blacklist.sh

四、优化IPSet性能与维护策略

大规模黑名单需注意性能影响。IPSet默认hash表大小可能不足,可在创建时指定参数优化:

# 创建时设置hashsize为4096,maxelem为100000(支持10万条IP)
sudo firewall-cmd --permanent --new-ipset=large-blacklist --type=hash:ip --option=family=inet --option=hashsize=4096 --option=maxelem=100000

定期维护措施包括:

1. 每周备份IPSet列表(firewall-cmd --ipset=blacklist --get-entries > backup.txt);

2. 设置IP过期时间,可通过额外脚本结合时间戳记录自动移除旧IP;

3. 白名单豁免机制,创建whitelist集合并设置更高优先级规则:

# 创建白名单IPSet
sudo firewall-cmd --permanent --new-ipset=whitelist --type=hash:ip
# 添加白名单规则(允许访问)
sudo firewall-cmd --permanent --zone=public --add-rich-rule='rule source ipset=whitelist accept'
# 注意:firewalld规则顺序影响执行,通常白名单规则需在黑名单前

五、高级应用:集成外部威胁情报源

企业级防护可扩展脚本,从外部API获取威胁IP列表。例如,下载公开的恶意IP库并批量导入:

#!/bin/bash
# 从威胁情报源获取IP列表(示例使用静态文件URL)
THREAT_LIST_URL="https://example.com/threat-ips.txt"
IPSET_NAME="blacklist"
TEMP_FILE="/tmp/threat_ips.txt"

# 下载列表(实际环境应添加证书验证和错误处理)
curl -s $THREAT_LIST_URL -o $TEMP_FILE

# 清空现有IPSet(避免重复,根据需求选择)
# firewall-cmd --ipset=$IPSET_NAME --flush

# 批量导入IP(每行一个IP格式)
while read ip; do
    [[ $ip =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]] && firewall-cmd --ipset=$IPSET_NAME --add-entry=$ip 2>/dev/null
done < $TEMP_FILE

# 日志记录
echo "$(date) - 已更新威胁情报IP" >> /var/log/firewalld_threat.log

注意:直接清空IPSet可能导致短暂规则丢失,建议生产环境采用增量更新或维护两个IPSet交替使用。

六、故障排查与常见问题

1. 规则未生效:检查firewalld和IPSet状态(systemctl status firewalld;ipset list);

2. 添加IP失败:确认IPSet类型匹配(IPv4/IPv6);

3. 性能下降:查看IPSet大小(ipset list | grep size),过大时需调整hashsize;

4. 重启后丢失:确保所有命令带--permanent参数,或保存IPSet到文件(ipset save > /etc/ipset.conf)并设置开机加载。

此方案将静态防火墙升级为动态自适应防护层,特别适合暴露公网的服务。但需注意:过度依赖黑名单可能误封正常用户,建议结合行为分析、人机验证等多层安全策略。