CentOS 7 防火墙的黄金法则是:用 firewalld 取代 iptables,用 zone 思维取代链规则思维。 对于绝大多数业务场景,只需掌握 zone(区域)、service(服务)、port(端口)三者的组合配置,即可覆盖 90% 以上的安全需求,下面从原理到实战,层层拆解。
先搞懂 firewalld 的底层逻辑
firewalld 是 CentOS 7 默认的动态防火墙管理工具,它并非取代 netfilter,而是在 iptables 之上封装了更人性化的管理接口。核心区别在于两点:动态生效(无需重启服务)与区域化管理(Zone),传统 iptables 每次修改必须重启才能干净应用,而 firewalld 支持运行时配置与永久配置分离,修改即时生效,无需中断业务。
Zone 是理解 firewalld 的第一把钥匙
系统预设了 9 个区域,从 trust(完全信任)到 drop(丢弃一切),安全级别依次递增。默认区域是 public,这是所有未特殊指定流量的“收容所”,理解 Zone 的关键在于:网卡绑定区域,区域决定规则,一块网卡同一时间只能属于一个区域,但一个区域可以包含多块网卡。
基础命令是日常运维的必修课
查询与状态检查的四个高频命令,务必备忘:
systemctl status firewalld查看服务运行状态firewall-cmd --state快速判断防火墙是否在运行firewall-cmd --get-default-zone确认当前默认区域firewall-cmd --list-all查看当前区域的完整规则
日常开放端口的正确姿势,永久 + 重载”的固定搭配:
firewall-cmd --permanent --add-port=8080/tcp firewall-cmd --reload
这里的 --permanent 决定规则写入永久配置,--reload 让永久配置覆盖运行时配置。常见的坑是:只加 --permanent 不执行 reload,导致规则未生效;或者不加 --permanent,服务器重启后规则丢失。

服务与端口的差异化管理
firewalld 内置了常见服务的预定义规则,能用服务名就不用端口号,这是保持配置可读性的关键。
# 推荐:使用服务名(底层自动映射端口) firewall-cmd --permanent --add-service=http firewall-cmd --permanent --add-service=https # 不推荐:直接暴露端口段(难以维护且不够安全) firewall-cmd --permanent --add-port=30000-40000/tcp
对于自定义应用,建议先在 /etc/firewalld/services/ 目录下创建 XML 服务定义文件,然后在 zone 中引用。这样做的收益是:所有规则一目了然,且可在多个 zone 间复用。
实战:多区域配置的安全隔离
一个典型的生产环境架构:Web 前端暴露公网,数据库仅内网访问。 这样的场景必须拆分为多区域,而不是在同一个区域里叠加规则。
# 1. 将 eth0(公网网卡)绑定到 public 区域 firewall-cmd --permanent --zone=public --change-interface=eth0 # 2. 将 eth1(内网网卡)绑定到 internal 区域 firewall-cmd --permanent --zone=internal --change-interface=eth1 # 3. 公网区域仅开放 80/443 firewall-cmd --permanent --zone=public --add-service=http firewall-cmd --permanent --zone=public --add-service=https # 4. 内网区域开放 MySQL 端口(仅限内网 IP 段) firewall-cmd --permanent --zone=internal --add-service=mysql firewall-cmd --permanent --zone=internal --add-source=192.168.1.0/24 # 5. 移除 public 区域不该有的 SSH 暴露(改为内网管理) firewall-cmd --permanent --zone=public --remove-service=ssh
关键点在于:--add-source 按来源 IP 匹配,--change-interface 按网卡绑定。 当数据包到达时,firewalld 优先匹配 source 规则,其次匹配 interface 规则,这为精细化访问控制提供了极大灵活性。
端口转发与富规则:进阶必杀技
端口转发是生产环境中最常用的需求之一,比如把 80 端口转发到 8080 应用端口:

firewall-cmd --permanent --zone=public --add-forward-port=port=80:proto=tcp:toport=8080 firewall-cmd --reload
这里的关键是必须开启内核 IP 转发:
sysctl -w net.ipv4.ip_forward=1 echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
富规则(Rich Rule)是 firewalld 的终极武器,能够表达复杂的组合逻辑。 例如限制某个 IP 对 SSH 的访问频率:
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.100" service name="ssh" reject' firewall-cmd --reload
富规则按照 rule -> source -> service/port -> action 的顺序解读,支持 log、accept、reject、drop 四种动作,几乎可以替代 iptables 的绝大多数场景。
酷番云独家经验案例:一次防火墙误操作的事故复盘
在酷番云云服务器运维中,我们曾遇到一位客户反馈:执行 firewall-cmd --complete-reload 后所有规则丢失,业务全部中断。 排查发现,客户此前修改规则时全部只用了 --runtime 模式(未加 --permanent),而 --complete-reload 会用永久配置覆盖运行时配置,导致全部临时规则被清空。
这暴露了两个核心运维认知盲区:
- 运行时配置与永久配置是两套独立体系,只有同时写入永久配置才具备持久性。
- 执行 reload 类操作前,务必先执行
firewall-cmd --list-all确认当前生效规则,再决定是否重载。
酷番云的建议是:在变更防火墙前,先执行 firewall-cmd --runtime-to-permanent 将当前运行时规则固化到永久配置中,再进行 reload 操作。 这是最稳妥的习惯,也是我们用代价换来的最佳实践。

性能调优与安全加固的五个建议
- 规则数量控制在 100 条以内,firewalld 规则过多会显著增加内核 netfilter 的匹配开销,高并发场景下直接影响网络吞吐。
- 使用 ipset 管理大批量 IP 封禁,避免逐条添加富规则导致性能劣化,先创建 ipset 集合,再在富规则中引用。
- 默认区域选择 drop 而非 public,对于仅需极少数开放端口的业务场景,
--set-default-zone=drop比手动移除 public 区域的默认放行更安全。 - 禁 ping 是双刃剑,建议用富规则实现限速而非完全丢弃,这样既不影响监控可用性探测,又能防 ICMP 洪水。
- 所有规则变更必须走变更流程:先在测试机验证,再写入生产,最后执行 reload,这是避免事故的底线。
高频问题解答
firewalld 和 iptables 到底用哪个?
优先使用 firewalld。 尽管 iptables 仍然存在且底层功能一致,但 firewalld 提供区域化管理、动态加载、服务抽象三层优势,大幅降低配置错误率,只有涉及 DNAT 到内网其他主机的复杂 NAT 规则时,才需要直接操作 iptables,且建议在 firewalld 中通过富规则实现,避免双栈管理混乱。
规则配好后服务器重启就失效,如何排查?
99% 的原因是未加 --permanent。 注意 firewall-cmd --add-port=80/tcp 默认只修改运行时配置,必须加上 --permanent 才会写入永久配置,若确认已加 --permanent,检查 /etc/firewalld/zones/ 下对应区域 XML 文件是否生成,以及 firewall-cmd --permanent --list-all 输出是否包含预期规则。
你在生产环境中是否遇到过防火墙配置引发的诡异故障?遇到过规则明明加了却不生效,或者 reload 后业务中断的情况吗? 欢迎在评论区分享你的经历,我们一起探讨更健壮的防火墙管理方案。
图片来源于AI模型,如侵权请联系管理员。作者:酷小编,如若转载,请注明出处:https://www.kufanyun.com/ask/750683.html

