CentOS服务器防火墙的精细化配置,核心不是“全封”或“全放”,而是基于服务端口、来源IP、协议状态和流量特征四个维度建立最小权限规则。很多运维人员习惯用firewalld默认的public区域,只加几条端口放行就上线,这在生产环境里等于把安全交给默认策略。真正有效的防护,是从默认拒绝所有入站流量开始,再逐条放行业务必需端口,同时对SSH、Web、数据库等关键服务做来源限制和连接频率控制。
先确定防火墙管理工具与运行模式CentOS 7及之后版本默认使用firewalld,CentOS 6及更早版本使用iptables。本文以firewalld为主,因为它是当前CentOS服务器的主流选择。firewalld的核心概念是区域(zone)和服务(service),但精细化配置不能只依赖预定义服务,需要直接操作富规则(rich rule)和直接规则(direct rule)。先检查firewalld状态:
systemctl status firewalld firewall-cmd --state firewall-cmd --get-active-zones
如果服务器有多块网卡,建议为不同网卡绑定不同区域。例如公网网卡绑定drop或public区域,内网网卡绑定internal或trusted区域。这样内网服务之间的通信不受公网策略影响,公网只暴露必要端口。修改网卡所属区域:
firewall-cmd --permanent --zone=public --change-interface=eth0 firewall-cmd --permanent --zone=internal --change-interface=eth1 firewall-cmd --reload默认拒绝策略与端口放行的正确顺序
精细化配置的第一步是把默认区域的入站策略改为拒绝。firewalld的public区域默认入站策略是拒绝,但很多人会误加--add-service或--add-port导致放行范围过大。建议明确设置目标为DROP而非REJECT,DROP直接丢弃数据包,减少服务器响应暴露的信息。执行:
firewall-cmd --permanent --zone=public --set-target=DROP firewall-cmd --reload
然后只放行业务端口。例如Web服务器只放行80和443:
firewall-cmd --permanent --zone=public --add-port=80/tcp firewall-cmd --permanent --zone=public --add-port=443/tcp firewall-cmd --reload
注意,--add-port不加来源限制时,等于对全网开放该端口。对于数据库端口3306、Redis端口6379、SSH端口22,绝不能这样放行。正确做法是使用富规则指定来源IP或IP段。
SSH端口的精细化防护策略SSH是服务器被暴力破解的首要目标。即使修改了默认端口,也应对来源做严格限制。如果运维人员有固定办公IP,直接只允许该IP访问SSH:
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="203.0.113.50/32" port protocol="tcp" port="22" accept' firewall-cmd --reload
如果运维IP不固定,但属于某个运营商IP段,可以放行该IP段。例如放行某省电信的IP段:
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="203.0.113.0/24" port protocol="tcp" port="22" accept'
同时限制SSH连接频率,防止单IP暴力尝试。使用firewalld的direct规则配合iptables的recent模块:
firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH_BRUTE firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 1 -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 5 --name SSH_BRUTE -j DROP firewall-cmd --reload
这段规则的含义是:60秒内同一IP对SSH端口发起超过5次新连接,第6次及以后的连接直接丢弃。这能有效阻断自动化暴力破解工具,同时不影响正常运维登录。
Web服务的访问控制与CC攻击缓解Web服务通常需要对全网开放80和443端口,但这不代表防火墙层面无事可做。对于HTTP,可以限制单个IP的并发连接数,防止单IP占用过多连接资源。使用direct规则配合connlimit模块:
firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -p tcp --dport 80 -m connlimit --connlimit-above 30 --connlimit-mask 32 -j DROP firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 1 -p tcp --dport 443 -m connlimit --connlimit-above 30 --connlimit-mask 32 -j DROP firewall-cmd --reload
这条规则限制单IP对80和443端口的并发连接数不超过30。对于正常浏览器访问,30个并发连接足够;对于CC攻击或爬虫,会触发限制。如果Web服务器前面有CDN或反向代理,需要放行CDN节点IP段,同时限制真实来源IP。此时应使用X-Forwarded-For头在应用层处理,防火墙层放行CDN回源IP即可。
数据库与缓存服务的隔离策略MySQL、Redis、Memcached等组件不应暴露在公网。如果业务架构要求应用服务器与数据库服务器分离,应通过内网通信。在数据库服务器的防火墙配置中,只允许应用服务器的内网IP访问数据库端口:
firewall-cmd --permanent --zone=internal --add-rich-rule='rule family="ipv4" source address="10.0.0.10/32" port protocol="tcp" port="3306" accept' firewall-cmd --permanent --zone=internal --add-rich-rule='rule family="ipv4" source address="10.0.0.11/32" port protocol="tcp" port="3306" accept' firewall-cmd --reload
对于Redis,除了来源限制,还应在配置文件中设置requirepass和bind内网IP。防火墙层面再叠加一层访问控制:
firewall-cmd --permanent --zone=internal --add-rich-rule='rule family="ipv4" source address="10.0.0.0/24" port protocol="tcp" port="6379" accept' firewall-cmd --reload
如果Redis必须对公网提供只读服务,建议使用stunnel或spiped做加密代理,防火墙只放行代理端口,不直接暴露Redis端口。
ICMP与碎片包的处理精细化配置不能忽略ICMP协议。完全禁止ICMP会导致网络诊断困难,但完全放行又可能被用于Smurf攻击或探测。建议放行必要的ICMP类型,丢弃其他类型:
firewall-cmd --permanent --zone=public --add-icmp-block=echo-request firewall-cmd --permanent --zone=public --add-icmp-block=timestamp-request firewall-cmd --permanent --zone=public --add-icmp-block=address-mask-request firewall-cmd --reload
这里放行echo-request(ping),但阻止timestamp和address-mask请求,这两种ICMP类型常被用于主机探测。对于分片包,可以在direct规则中丢弃所有分片包,防止分片攻击:
firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -f -j DROP firewall-cmd --reload
注意,这条规则会丢弃所有分片包,如果业务依赖大包传输且路径MTU较小,可能影响正常通信。建议在确认业务不依赖分片后再启用。
出站流量的控制多数防火墙配置只关注入站流量,但出站流量同样需要控制。如果服务器被植入后门,攻击者通常会从服务器向外发起连接。限制出站流量可以阻断反弹Shell和木马回连。firewalld默认允许所有出站流量,需要手动设置出站策略:
firewall-cmd --permanent --direct --add-rule ipv4 filter OUTPUT 0 -m state --state ESTABLISHED,RELATED -j ACCEPT firewall-cmd --permanent --direct --add-rule ipv4 filter OUTPUT 1 -p tcp --dport 80 -j ACCEPT firewall-cmd --permanent --direct --add-rule ipv4 filter OUTPUT 2 -p tcp --dport 443 -j ACCEPT firewall-cmd --permanent --direct --add-rule ipv4 filter OUTPUT 3 -p udp --dport 53 -j ACCEPT firewall-cmd --permanent --direct --add-rule ipv4 filter OUTPUT 4 -j DROP firewall-cmd --reload
这段规则只允许出站的HTTP、HTTPS和DNS查询,其余出站流量全部丢弃。如果服务器需要调用第三方API、发送邮件或使用NTP时间同步,需要额外放行对应端口。例如放行SMTP的25端口和NTP的123端口:
firewall-cmd --permanent --direct --add-rule ipv4 filter OUTPUT 5 -p tcp --dport 25 -j ACCEPT firewall-cmd --permanent --direct --add-rule ipv4 filter OUTPUT 6 -p udp --dport 123 -j ACCEPT日志记录与审计
精细化配置的最后一步是记录被拒绝的连接。没有日志,出了问题无法追溯。firewalld默认会记录被拒绝的包,但日志级别和频率需要调整,避免日志刷屏。可以在direct规则中为DROP动作添加日志前缀:
firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -m limit --limit 5/min -j LOG --log-prefix "FIREWALL_DROP: " --log-level 4 firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 1 -j DROP
这条规则每分钟最多记录5条被丢弃的入站连接日志,日志前缀为FIREWALL_DROP,方便用grep过滤。同时建议将防火墙日志单独输出到/var/log/firewalld.log,避免与系统日志混在一起。在rsyslog配置中添加:
echo ':msg, contains, "FIREWALL_DROP" /var/log/firewalld.log' >> /etc/rsyslog.conf systemctl restart rsyslog规则持久化与回滚方案
所有firewall-cmd命令都必须加--permanent参数才能持久化,否则重启后失效。但直接修改永久规则有风险,一旦配置错误可能导致服务器失联。建议先在运行时添加规则测试,确认无误后再写入永久配置。如果配置过程中出现误操作导致无法连接,可以通过控制台或带外管理执行:
firewall-cmd --panic-on # 紧急情况下阻断所有流量 firewall-cmd --panic-off # 恢复流量
更稳妥的做法是定期备份防火墙配置。firewalld的配置文件位于/etc/firewalld/,直接打包备份:
tar czf firewalld-backup-$(date +%Y%m%d).tar.gz /etc/firewalld/
恢复时解压覆盖并执行firewall-cmd --reload即可。对于使用iptables的CentOS 6系统,使用iptables-save和iptables-restore进行备份恢复。
精细化防火墙配置不是一次性工作,而是需要根据业务变化持续调整。每次新增服务、变更IP、调整架构后,都要重新审查防火墙规则。建议每季度做一次规则审计,删除不再使用的放行条目,收紧过于宽泛的来源限制。防火墙是服务器安全的第一道门,门缝开得越小,攻击者能钻进来的机会就越少。
