CentOS服务器默认的firewalld策略在很多生产环境里其实偏宽松,尤其是对入站流量的区域划分和端口开放逻辑。真正有效的安全配置不是简单地开几个端口、关几个服务,而是结合访问行为、来源IP信誉、连接频率和协议特征做分层拦截。下面直接讲如何利用firewalld、内核参数和日志联动,把恶意访问在到达业务层之前就精准阻断。
先确认防火墙运行状态和默认区域
登录服务器后先检查firewalld是否在运行,以及当前激活区域绑定了哪些网卡。很多恶意扫描能成功,是因为管理员误以为防火墙已经生效,实际上默认区域是public,但业务网卡被分配到了trusted区域。
systemctl status firewalld firewall-cmd --get-active-zones firewall-cmd --list-all
如果发现网卡不在public区域,需要立即调整。trusted区域默认放行所有流量,这是非常危险的状态。用下面的命令把网卡重新绑定到public区域,并移除多余的区域绑定。
firewall-cmd --zone=public --change-interface=eth0 --permanent firewall-cmd --reload
基于来源IP的精准封禁
恶意访问往往来自固定的IP段或已知的扫描源。firewalld支持rich rule和ipset两种方式做来源限制。对于少量IP,直接使用rich rule封禁即可;对于大量IP或动态更新的黑名单,建议使用ipset配合firewalld。
先创建一个自定义ipset,命名为blacklist,类型为hash:ip,超时时间设置为24小时,这样临时封禁的IP不会永久占用内存。
firewall-cmd --permanent --new-ipset=blacklist --type=hash:ip --option=timeout=86400 firewall-cmd --reload
然后添加一条rich rule,让来自blacklist这个ipset的所有流量直接丢弃,并且不返回任何响应。这样扫描器无法判断端口是否开放,增加其探测成本。
firewall-cmd --permanent --zone=public --add-rich-rule='rule source ipset=blacklist drop' firewall-cmd --reload
当发现某个IP在暴力破解SSH或持续扫描端口时,一条命令就能将其加入黑名单。
firewall-cmd --permanent --ipset=blacklist --add-entry=203.0.113.45 firewall-cmd --reload
如果攻击源来自整个C段,可以改用hash:net类型的ipset,或者直接在rich rule中写网段。但要注意不要误伤正常用户,尤其是CDN回源IP段。
限制SSH登录来源和连接频率
SSH是CentOS服务器被暴力破解的重灾区。仅修改默认端口22并不能解决根本问题,因为端口扫描可以快速发现新端口。更有效的做法是限制来源IP范围,并对新建连接做频率控制。
如果运维团队有固定办公IP,可以直接用rich rule只允许这些IP访问SSH端口。
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="198.51.100.0/24" port port="22" protocol="tcp" accept' firewall-cmd --permanent --zone=public --remove-service=ssh firewall-cmd --reload
注意这里先添加允许规则,再移除默认的ssh服务放行,顺序不能反。否则可能把自己锁在服务器外面。
如果无法固定来源IP,可以使用firewalld的direct规则配合iptables的limit模块做连接频率限制。下面这条规则限制每个IP在60秒内只能新建3个SSH连接,超过的丢弃。
firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -p tcp --dport 22 -m state --state NEW -m recent --set --name ssh_attack firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 1 -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 --name ssh_attack -j DROP firewall-cmd --reload
这两条direct规则比rich rule更底层,执行效率更高,适合高并发场景。但要注意direct规则的顺序和位置,避免与其他规则冲突。
针对Web服务的恶意请求拦截
如果服务器上运行Nginx或Apache,防火墙层面只能拦截到IP和端口级别,无法识别具体的恶意HTTP请求。但可以通过日志分析工具实时提取攻击源IP,自动加入firewalld黑名单。
例如使用fail2ban监控Nginx的错误日志和访问日志,当某个IP在短时间内产生大量404、502或匹配到SQL注入特征时,自动调用firewall-cmd封禁该IP。安装和基础配置如下。
yum install -y fail2ban cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
在jail.local中添加针对Nginx的监控规则,设置最大失败次数和封禁时间。这里的action要指定为firewallcmd-ipset,这样fail2ban会直接操作firewalld的ipset,而不是iptables。
[nginx-404] enabled = true port = http,https filter = nginx-404 logpath = /var/log/nginx/access.log maxretry = 30 findtime = 10 bantime = 3600 action = firewallcmd-ipset[name=blacklist, port=all, protocol=all]
同时需要在filter.d目录下创建对应的正则匹配文件,用来识别恶意请求特征。例如匹配包含union select、sleep(、../等字符串的请求。
# /etc/fail2ban/filter.d/nginx-404.conf [Definition] failregex = ^<HOST> -.*"(GET|POST).*(union select|sleep\(|\.\./).*" ignoreregex =
这样配置后,fail2ban会在检测到恶意请求时自动将攻击源IP加入blacklist这个ipset,firewalld随即在入站方向丢弃该IP的所有流量。整个过程无需人工干预,响应时间在秒级。
利用内核参数增强网络层防御
防火墙规则只能过滤已经到达网卡的流量,但有些攻击类型需要在TCP/IP协议栈层面进行抑制。通过sysctl调整内核参数,可以减少SYN Flood、ICMP Flood和IP欺骗的影响。
编辑/etc/sysctl.conf文件,加入以下参数。
net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_max_syn_backlog = 4096 net.ipv4.tcp_synack_retries = 2 net.ipv4.tcp_syn_retries = 2 net.ipv4.icmp_echo_ignore_all = 1 net.ipv4.conf.all.rp_filter = 1 net.ipv4.conf.default.rp_filter = 1 net.ipv4.conf.all.accept_redirects = 0 net.ipv4.conf.default.accept_redirects = 0 net.ipv4.conf.all.secure_redirects = 0 net.ipv4.conf.default.secure_redirects = 0 net.ipv4.conf.all.log_martians = 1 net.ipv4.conf.default.log_martians = 1
执行sysctl -p让配置生效。其中tcp_syncookies开启后,服务器在SYN队列满时不再直接丢弃新连接,而是返回带有cookie的SYN-ACK,只有完成三次握手的连接才会进入队列。这能有效缓解SYN Flood攻击。rp_filter开启反向路径过滤,可以丢弃源地址明显伪造的数据包。
定期审计防火墙规则和日志
防火墙配置不是一劳永逸的。业务变更、临时加白、测试规则都可能留下安全漏洞。建议每周检查一次firewalld的完整规则列表,重点看是否有过于宽泛的放行规则,以及direct规则是否与rich rule存在冲突。
firewall-cmd --list-all firewall-cmd --direct --get-all-rules firewall-cmd --get-ipset-blacklist
同时要关注/var/log/firewalld和/var/log/messages中的拒绝记录。如果发现某个正常业务IP被频繁拦截,需要及时调整规则;如果发现某个IP段持续尝试连接多个端口,应该考虑将其整个网段加入黑名单。
对于日志量较大的服务器,可以使用logwatch或自定义脚本每天汇总firewalld的drop记录,按来源IP和目的端口排序,快速发现异常访问模式。
grep "FINAL_REJECT" /var/log/firewalld | awk '{print $10}' | sort | uniq -c | sort -rn | head -20
这条命令可以统计被拒绝次数最多的20个来源IP,帮助管理员识别需要重点关注的攻击源。
结合地理位置和ASN进行粗粒度拦截
如果业务只面向特定国家或地区,可以在防火墙层面直接丢弃来自其他地区的流量。CentOS可以通过安装GeoIP数据库和ipset来实现。先下载国家IP段数据,然后转换成ipset可识别的格式,最后在firewalld中创建对应的ipset并添加drop规则。
这种做法的好处是能大幅减少攻击面,尤其是来自海外的扫描和爆破流量。但要注意GeoIP数据库需要定期更新,否则可能误伤正常用户。另外对于使用CDN的网站,需要在CDN层面做地理位置限制,而不是在源站防火墙上做,因为源站看到的都是CDN节点IP。
总结
CentOS服务器防火墙的精准拦截,核心在于把来源IP信誉、连接频率、协议特征和地理位置结合起来,形成多层过滤机制。firewalld的rich rule和ipset提供了灵活的规则表达能力,fail2ban实现了从日志到防火墙的自动化联动,内核参数则在更底层抑制攻击流量。这些措施配合定期审计,可以显著降低服务器被恶意访问和入侵的风险。安全配置没有终点,持续监控和动态调整才是关键。
