本文是一份面向 Debian / Ubuntu 的 firewalld 实战指南,重点讲清楚 zone、service、runtime 与 permanent 配置、端口和服务放行、接口绑定、NAT、富规则以及常见排障。它适合希望用更高层、更动态方式管理防火墙的系统。
适用场景
- 服务器防火墙管理
- 需要按 zone 管理不同网卡或来源
- 需要动态修改防火墙规则
- 需要统一管理端口、服务、转发和 NAT
- 希望比手写 iptables 更好维护
firewalld 是什么
firewalld 是一个动态防火墙管理器,核心特性是:
- 基于 zone 的信任分级
- runtime 与 permanent 分离
- 提供 firewall-cmd 命令行工具
- 可与 NetworkManager 配合自动绑定接口
它底层可以和 nftables / iptables 兼容层一起工作,但对使用者来说,最重要的是它把防火墙抽象成了 zone 和服务。
基本概念
Zone
Zone 表示一类网络信任级别。一个接口或来源地址通常只属于一个 zone。
常见预定义 zone:
- drop
- block
- public
- external
- dmz
- work
- home
- internal
- trusted
Service
Service 是预定义或自定义的服务定义,例如:
- ssh
- http
- https
它本质上是端口、协议和相关规则的集合。
Runtime 和 Permanent
- runtime:当前运行中的临时配置
- permanent:持久化配置,重启后仍保留
这是 firewalld 最容易混淆的地方。
安装 firewalld
在 Debian / Ubuntu 上通常可以安装:
sudo apt update
sudo apt install -y firewalld启动并设置自启:
sudo systemctl enable firewalld
sudo systemctl start firewalld查看状态:
sudo systemctl status firewalld验证命令:
firewall-cmd --state常用命令
查看版本
firewall-cmd --version查看默认 zone
firewall-cmd --get-default-zone查看活动 zone
firewall-cmd --get-active-zones查看当前 zone 的规则
firewall-cmd --list-all查看所有可用 zone
firewall-cmd --get-zones查看支持的服务
firewall-cmd --get-serviceszone 的使用
firewalld 的核心是把接口、来源或连接绑定到 zone。
查看某个接口属于哪个 zone
firewall-cmd --get-zone-of-interface=eth0设置默认 zone
sudo firewall-cmd --set-default-zone=public给接口绑定 zone
sudo firewall-cmd --zone=public --add-interface=eth0如果要永久生效:
sudo firewall-cmd --permanent --zone=public --add-interface=eth0注意:
- runtime 修改只对当前生效
- permanent 修改需要 --reload 或重启后才会进入 runtime
放行端口
runtime 放行端口
sudo firewall-cmd --zone=public --add-port=80/tcppermanent 放行端口
sudo firewall-cmd --permanent --zone=public --add-port=80/tcp
sudo firewall-cmd --reload放行多个端口
sudo firewall-cmd --permanent --zone=public --add-port=80/tcp
sudo firewall-cmd --permanent --zone=public --add-port=443/tcp
sudo firewall-cmd --reload放行服务
firewalld 更推荐使用 service 而不是直接写端口。
放行 SSH
sudo firewall-cmd --permanent --zone=public --add-service=ssh
sudo firewall-cmd --reload放行 HTTP / HTTPS
sudo firewall-cmd --permanent --zone=public --add-service=http
sudo firewall-cmd --permanent --zone=public --add-service=https
sudo firewall-cmd --reload查看某个 zone 已放行的服务
firewall-cmd --zone=public --list-services删除规则
删除端口
sudo firewall-cmd --permanent --zone=public --remove-port=80/tcp
sudo firewall-cmd --reload删除服务
sudo firewall-cmd --permanent --zone=public --remove-service=http
sudo firewall-cmd --reloadrich rule
rich rule 适合表达更复杂的条件,例如来源 IP、端口、协议、日志和动作。
允许某个来源访问 SSH
sudo firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="1.2.3.4" service name="ssh" accept'
sudo firewall-cmd --reload拒绝某个网段
sudo firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="10.0.0.0/8" drop'
sudo firewall-cmd --reload添加日志
sudo firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="1.2.3.4" log prefix="firewalld-deny " level="warning" drop'
sudo firewall-cmd --reload直接规则与高级规则
firewalld 也支持更底层的直接规则接口,但一般不建议优先使用,除非你明确知道自己在做什么。
建议优先级:
- zone
- service
- port
- rich rule
- direct rule
配置目录
用户自定义 zone 通常放在:
/etc/firewalld/zones默认和回退配置通常在:
/usr/lib/firewalld/zones如果你需要长期维护自己的 zone 文件,建议放到 /etc/firewalld/zones。
重新加载与重启
重新加载
sudo firewall-cmd --reload重新启动服务
sudo systemctl restart firewalld建议:
- 修改 permanent 后优先 --reload
- 如果配置异常,再考虑重启 firewalld
查看完整规则
firewall-cmd --list-all
firewall-cmd --list-all-zones如果你想看某个 zone:
firewall-cmd --zone=public --list-all转发与 NAT
firewalld 也可以管理转发和 NAT 场景。
允许伪装
sudo firewall-cmd --permanent --zone=external --add-masquerade
sudo firewall-cmd --reload查看伪装状态
firewall-cmd --zone=external --query-masquerade典型服务器模板
一个常见服务器思路是:
- public zone 绑定外网接口
- 放行 SSH
- 放行 HTTP / HTTPS
- 关闭不需要的服务
示例:
sudo firewall-cmd --permanent --zone=public --add-service=ssh
sudo firewall-cmd --permanent --zone=public --add-service=http
sudo firewall-cmd --permanent --zone=public --add-service=https
sudo firewall-cmd --reload常见问题
1. 改完规则后不生效
检查:
- 你改的是 runtime 还是 permanent
- 有没有执行 --reload
- 接口是否绑定到你预期的 zone
2. SSH 连接被断开
通常是没有先放行 SSH 就改了默认规则。建议始终保留一个回滚会话。
3. 接口在错误的 zone
检查:
firewall-cmd --get-active-zones4. 端口放行了还是访问不到
检查:
- 服务本身是否监听
- 目标端口是否正确
- 云安全组是否放行
- 是否还有其他防火墙策略
5. 配置重启后丢失
说明你只改了 runtime,没有写 permanent。
与 iptables / nftables 的关系
firewalld 是更高层的防火墙管理器,它可以管理底层的 nftables 或 iptables 规则实现。
建议:
- 想要 zone 化、动态管理,用 firewalld
- 想要完全手写规则、精确控制,考虑 iptables 或 nftables
- 不要在没有理解的情况下混用多套策略
最小可用流程
如果你想快速把一台机器配成 firewalld 防火墙,顺序如下:
sudo apt update
sudo apt install -y firewalld
sudo systemctl enable firewalld
sudo systemctl start firewalld
sudo firewall-cmd --permanent --zone=public --add-service=ssh
sudo firewall-cmd --permanent --zone=public --add-service=http
sudo firewall-cmd --permanent --zone=public --add-service=https
sudo firewall-cmd --reload然后检查:
firewall-cmd --get-active-zones
firewall-cmd --zone=public --list-all结论
firewalld 的核心是:
- zone 管信任级别
- service 管服务级放行
- runtime / permanent 区分临时和持久配置
- firewall-cmd 是主要操作入口
- reload 是把永久配置落到运行态