防火墙作为网络安全的第一道防线,其发展历程经历了从简单包过滤到状态检测的演变。传统防火墙采用黑名单机制,就像小区门卫手里拿着通缉犯名单逐个比对,这种方式效率低下且容易漏判。而现代防火墙普遍采用白名单机制,相当于只允许持有门禁卡的住户进出,其他人员一律拦截。
firewalld作为RHEL/CentOS 7+默认的动态防火墙管理器,采用zone(区域)和service(服务)的抽象概念来简化规则配置。想象一下大型商场的安全管理:不同区域(儿童乐园、餐饮区、影院)有各自的安全等级和出入规则,而服务则相当于商场内提供的具体设施(电梯、消防通道、收银台)。这种设计使得安全策略可以像搭积木一样灵活组合。
关键认知:firewalld并非传统iptables的替代品,而是位于iptables/nftables之上的配置前端。实际数据包过滤仍由底层netfilter框架处理,就像用图形界面操作和直接敲命令最终都会修改同一份系统配置。
firewalld预设了9个典型安全区域,按信任度降序排列:
每个网络接口必须绑定一个zone,就像给商场每个入口分配不同的安检级别。通过firewall-cmd --get-active-zones可查看当前分配情况。实际部署时,建议根据网络环境自定义zone属性:
bash复制# 创建VIP专用区域
firewall-cmd --permanent --new-zone=vip
firewall-cmd --permanent --zone=vip --add-source=192.168.1.0/24
firewall-cmd --permanent --zone=vip --add-service=https
服务定义文件存储在/usr/lib/firewalld/services/中,采用XML格式描述协议和端口组合。例如SSH服务的定义:
xml复制<?xml version="1.0" encoding="utf-8"?>
<service>
<short>SSH</short>
<description>Secure Shell...</description>
<port protocol="tcp" port="22"/>
</service>
自定义服务时建议复制模板修改而非直接编辑系统文件:
bash复制cp /usr/lib/firewalld/services/ssh.xml /etc/firewalld/services/myapp.xml
# 编辑后重载生效
firewall-cmd --reload
假设服务器配置:
bash复制# 查看默认zone
firewall-cmd --get-default-zone
# 修改网卡绑定zone
firewall-cmd --zone=home --change-interface=ens224 --permanent
# 设置默认zone(新接口自动归属)
firewall-cmd --set-default-zone=public --permanent
当预定义服务不满足需求时,可通过rich rule实现精细控制:
bash复制# 允许vip区域主机访问3306端口
firewall-cmd --zone=vip --add-rich-rule='rule family="ipv4" source address="192.168.1.100/32" port port="3306" protocol="tcp" accept'
# 限制某IP每秒连接数
firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="203.0.113.45" limit value="5/s" accept'
经验之谈:rich rule的执行顺序很重要,先添加的规则优先级更高。可通过
--list-rich-rules查看当前顺序。
组合使用nftables和conntrack工具:
bash复制# 查看当前连接追踪
conntrack -L
# 监控被拒绝的包
nft monitor trace | grep DROP
临时启用日志记录被拒包:
bash复制firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" reject log prefix="DENIED: " limit value="5/m"'
然后在/var/log/messages中查看触发记录。调试完成后记得移除日志规则避免磁盘爆满。
调整内核参数提升高并发性能:
bash复制# 增大连接跟踪表
echo 524288 > /proc/sys/net/netfilter/nf_conntrack_max
# 缩短超时时间
echo 600 > /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_established
启用隐蔽模式防止端口扫描:
bash复制firewall-cmd --zone=public --add-rich-rule='rule protocol value="icmp" reject'
firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="0.0.0.0/0" port port="1-1024" protocol="tcp" reject'
完整备份firewalld状态:
bash复制# 导出所有配置
firewall-cmd --runtime-to-permanent
cp -r /etc/firewalld /backup/firewalld_$(date +%F)
# 只导出服务定义
ls /etc/firewalld/services/*.xml | xargs tar czvf firewall_services.tar.gz
使用ansible批量部署相同规则:
yaml复制- name: Deploy firewall rules
hosts: webservers
tasks:
- name: Copy custom services
copy:
src: files/firewalld/services/
dest: /etc/firewalld/services/
- name: Reload firewall
command: firewall-cmd --reload
在实际运维中,我发现firewalld的临时规则(--permanent参数)设计是个双刃剑。测试时建议先不加--permanent,确认无误后再永久生效。曾经有次直接在生产环境添加永久规则导致SSH连接中断,最后只能通过控制台恢复。