Firewalld 企业运维实战:从入门到防DDoS
# Firewalld 企业运维实战
# 前言
Firewalld(Fire Wall Daemon)是 Linux 系统中功能强大的动态防火墙管理工具,广泛应用于生产环境。本文整合了 Firewalld 的日常操作命令与 DDoS 防护实战技巧,帮助运维人员快速搭建企业级网络安全防护。
版本说明
本文基于 CentOS/RHEL 7+ 和 Ubuntu 18.04+ 测试。
Firewalld 核心命令在各发行版间保持一致,部分路径差异已标注。
# 1. Firewalld 概述与安装
# 1.1 为什么选择 Firewalld
与传统的 iptables 相比,Firewalld 具有以下优势:
- 动态管理:规则修改无需重启服务,即时生效
- 区域(Zone)概念:按网络环境(home、work、public 等)快速切换安全策略
- 服务管理:内置常用服务(HTTP、SSH 等)简化配置
- Rich Rules:支持复杂的规则语法,满足企业级需求
# 1.2 安装与启动
# CentOS/RHEL
sudo yum install firewalld
sudo systemctl start firewalld
sudo systemctl enable firewalld
# Ubuntu/Debian
sudo apt-get install firewalld
sudo systemctl start firewalld
sudo systemctl enable firewalld
2
3
4
5
6
7
8
9
# 1.3 验证安装
# 检查防火墙状态
sudo firewall-cmd --state
# 预期输出
# running
2
3
4
5
# 2. 核心概念:区域与服务
# 2.1 区域(Zone)管理
Firewalld 的核心概念是区域,每个区域对应不同的信任级别:
| 区域 | 适用场景 | 默认策略 |
|---|---|---|
| drop | 最低信任,丢弃所有入站 | 拒绝所有入站,允许出站 |
| block | 拒绝入站,明确通知客户端 | 拒绝并返回 ICMP 消息 |
| public | 公共网络,不信任任何入站 | 仅允许选中的入站连接 |
| external | 外部网络,伪装已启用 | 仅允许选中的入站,启用 NAT |
| dmz | 非军事区,开放部分服务 | 仅允许特定服务 |
| work | 工作网络,基本信任 | 仅允许特定服务 |
| home | 家庭网络,高度信任 | 仅允许特定服务 |
| internal | 内部网络,高度信任 | 仅允许特定服务 |
| trusted | 完全信任,允许所有 | 允许所有 |
# 2.2 区域操作命令
# 查看所有可用区域
firewall-cmd --get-zones
# 查看当前激活的区域
firewall-cmd --get-active-zones
# 查看特定区域的配置
firewall-cmd --zone=public --list-all
# 将网卡绑定到指定区域
firewall-cmd --permanent --zone=public --change-interface=eth0
# 设置默认区域
firewall-cmd --set-default-zone=public
2
3
4
5
6
7
8
9
10
11
12
13
14
# 2.3 服务管理
Firewalld 内置了常见服务定义,简化配置:
# 查看所有可用服务
firewall-cmd --get-services
# 查看特定服务详情
firewall-cmd --service=ssh --get-description
firewall-cmd --service=ssh --get-ports
# 允许服务通过防火墙(临时生效)
firewall-cmd --zone=public --add-service=http
# 允许服务通过防火墙(永久生效)
firewall-cmd --zone=public --permanent --add-service=http
# 移除服务
firewall-cmd --zone=public --permanent --remove-service=http
# 查看已允许的服务
firewall-cmd --zone=public --list-services
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 3. 端口与规则管理
# 3.1 端口操作
# 开放指定端口(临时)
firewall-cmd --zone=public --add-port=8080/tcp
# 开放指定端口(永久)
firewall-cmd --zone=public --permanent --add-port=8080/tcp
# 开放连续端口范围
firewall-cmd --zone=public --permanent --add-port=8000-9000/tcp
# 移除端口
firewall-cmd --zone=public --permanent --remove-port=8080/tcp
# 查看已开放的端口
firewall-cmd --zone=public --list-ports
2
3
4
5
6
7
8
9
10
11
12
13
14
# 3.2 Rich Rules 高级规则
Rich Rules 支持复杂的规则匹配条件:
# 基础语法
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" port port="22" protocol="tcp" accept'
# 限制连接速率(每秒最多 10 次 SSH 连接)
firewall-cmd --permanent --add-rich-rule='rule service name="ssh" limit value="10/s" accept'
# 限制每分钟最大连接数
firewall-cmd --permanent --add-rich-rule='rule service name="http" limit value="50/m" accept'
# 禁止特定 IP 访问
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="<INTERNAL_IP_1>0" reject'
# 允许特定 IP 段访问
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="<INTERNAL_NETWORK>" accept'
# 端口转发(将 80 端口流量转发到内部服务器)
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" forward-port port="80" protocol="tcp" to-port="8080" to-addr="<INTERNAL_IP_1>"'
# 查看所有 Rich Rules
firewall-cmd --list-rich-rules
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 4. NAT 与端口转发
# 4.1 SNAT(源地址转换)
# 配置 SNAT(内网访问外网时使用)
firewall-cmd --permanent --direct --add-rule ipv4 nat POSTROUTING 0 -s <LAN_SUBNET> -o eth0 -j MASQUERADE
# 验证 SNAT 规则
iptables -t nat -L -n -v
2
3
4
5
# 4.2 DNAT(目的地址转换)
# 端口转发:将外部 3306 端口转发到内部 MySQL 服务器
firewall-cmd --permanent --direct --add-rule ipv4 nat PREROUTING 0 -p tcp --dport 3306 -j DNAT --to-destination <GATEWAY_IP>0:3306
# 转发所有流量到内部服务器
firewall-cmd --permanent --add-forward-port=port=80:proto=tcp:toaddr=<GATEWAY_IP>:toport=8080
2
3
4
5
# 4.3 动态伪装
# 启用 IP 伪装(自动 SNAT)
firewall-cmd --zone=external --add-masquerade
# 禁用 IP 伪装
firewall-cmd --zone=external --remove-masquerade
# 查看伪装状态
firewall-cmd --zone=external --query-masquerade
2
3
4
5
6
7
8
# 5. DDoS 防护实战
# 5.1 连接速率限制
DDoS 攻击通常表现为大量短时间内的连接请求。通过限制每个 IP 的连接速率,可以有效缓解:
# 限制 SSH 连接:每分钟最多 10 次
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" service name="ssh" limit value="10/m" accept'
# 限制 HTTP 连接:每秒最多 50 次
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" service name="http" limit value="50/s" accept'
# 限制 HTTPS 连接:每秒最多 50 次
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" service name="https" limit value="50/s" accept'
# 重载规则使生效
firewall-cmd --reload
2
3
4
5
6
7
8
9
10
11
# 5.2 SYN Flood 防护
SYN Flood 是最常见的 DDoS 攻击方式,通过限制 SYN 包的速率来防御:
# 限制 SYN 包速率:每秒最多 1 个,突发最多 3 个
firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -p tcp --syn -m limit --limit 1/s --limit-burst 3 -j ACCEPT
firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 1 -p tcp --syn -j DROP
# 验证规则
firewall-cmd --direct --get-all-rules
2
3
4
5
6
# 5.3 基于连接数的限流
限制单个 IP 在一定时间内的最大连接数:
# 限制每 IP 60 秒内最多 10 个新连接
firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -m conntrack --ctstate NEW -m recent --set
firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 1 -m conntrack --ctstate NEW -m recent --update --seconds 60 --hitcount 10 -j DROP
# 查看被 DROP 的 IP(调试用)
cat /proc/net/nf_conntrack | grep recent
2
3
4
5
6
# 5.4 ICMP Rate Limiting
防止 Ping Flood 攻击:
# 限制 ICMP 响应速率
firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT
firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 1 -p icmp --icmp-type echo-request -j DROP
2
3
# 5.5 禁用 Ping 响应(可选)
在极高安全要求的环境下,可以完全禁用 ICMP 响应:
# 禁用 ping 响应
firewall-cmd --permanent --add-icmp-block=echo-reply
firewall-cmd --permanent --add-icmp-block=echo-request
firewall-cmd --reload
2
3
4
# 6. 日志记录与监控
# 6.1 启用日志记录
记录被丢弃的连接,便于分析与溯源:
# 记录被拒绝的连接,每分钟最多 5 条
firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 2 -m limit --limit 5/min -j LOG --log-prefix "Firewalld-Dropped: "
# 查看系统日志
journalctl -xe | grep -i firewalld
# 或
tail -f /var/log/messages | grep -i firewalld
2
3
4
5
6
7
# 6.2 实时监控命令
# 查看当前所有规则
firewall-cmd --list-all
# 查看直接规则
firewall-cmd --direct --get-all-rules
# 查看连接跟踪表
conntrack -L
# 查看各 zone 的规则数量
for zone in $(firewall-cmd --get-zones); do
echo "$zone: $(firewall-cmd --zone=$zone --list-rules | wc -l) rules"
done
2
3
4
5
6
7
8
9
10
11
12
13
# 7. 自定义服务
创建可复用的服务定义,简化常用端口管理:
# 创建自定义服务文件
sudo cp /usr/lib/firewalld/services/ssh.xml /etc/firewalld/services/myapp.xml
sudo nano /etc/firewalld/services/myapp.xml
2
3
自定义服务 XML 示例:
<?xml version="1.0" encoding="utf-8"?>
<service>
<short>MyApp</short>
<description>My Custom Application Service</description>
<port protocol="tcp" port="8080"/>
<port protocol="tcp" port="8443"/>
</service>
2
3
4
5
6
7
# 重载后使用自定义服务
firewall-cmd --reload
firewall-cmd --zone=public --permanent --add-service=myapp
2
3
# 8. 常见问题排查
# 8.1 规则不生效
# 确认是临时生效还是永久生效
# 临时规则重启服务后失效
firewall-cmd --list-all
# 永久规则需要重载
firewall-cmd --reload
# 检查规则冲突
firewall-cmd --permanent --direct --get-all-rules
2
3
4
5
6
7
8
9
# 8.2 无法连接
# 1. 确认服务/端口已开放
firewall-cmd --zone=public --list-ports
# 2. 检查服务是否运行
systemctl status firewalld
# 3. 查看日志
journalctl -u firewalld -n 50
# 4. 测试连通性
telnet <server-ip> <port>
2
3
4
5
6
7
8
9
10
11
# 8.3 性能问题
# 限制规则数量,避免过度复杂化
# 合并相似规则,使用 IP 段而非单独 IP
# 定期清理不再使用的规则
# 检查规则数量
iptables -L -n | wc -l
2
3
4
5
6
# 9. 坑与边界
临时规则 vs 永久规则:未加
--permanent的规则在重启或重载后会丢失。务必确认规则是否需要持久化。规则顺序:Rich Rules 按顺序匹配,第一条匹配的规则生效。需要限制的规则要放在允许规则之前。
默认区域陷阱:未指定 zone 的规则会应用到默认区域,确认默认区域符合安全策略后再操作。
direct rules 优先级:通过
--direct添加的 iptables 规则优先级高于 Firewalld 的原生规则,可能导致冲突。IPv4 与 IPv6:大部分企业场景仅配置 IPv4,IPv6 规则需要单独处理。在禁用 IPv6 前确认无相关业务。
NAT 伪装与端口转发:端口转发依赖 DNAT,启用前确保源端口未被占用。SNAT 需要确认网关已开启转发 (
sysctl -w net.ipv4.ip_forward=1)。服务名与端口号:使用服务名(如
ssh)时,Firewalld 会查找对应端口定义。若自定义服务,需确保 XML 配置正确。
# 10. 可复用要点
生产环境建议:默认区域设为
block或drop,仅显式开放必要的端口和服务。生产服务器的网卡应绑定到高风险区域(如 public 或 block),内网管理平面网卡绑定到低风险区域(如 work 或 internal)。快速排查口诀:
firewalld-cmd --state确认运行--list-all查看生效规则--reload重载使永久规则生效journalctl -xe查看详细日志
安全基线配置:
# 基础安全加固 firewall-cmd --set-default-zone=public firewall-cmd --zone=public --remove-service=cockpit # 禁用不必要服务 firewall-cmd --zone=public --add-service=ssh firewall-cmd --zone=public --add-service=https firewall-cmd --zone=public --add-service=https1
2
3
4
5
6备份与回滚:
# 导出当前配置 firewalld-cmd --export > /root/firewalld-backup.rules # 恢复配置 firewalld-cmd --import < /root/firewalld-backup.rules1
2
3
4
5与 iptables 关系:Firewalld 本质上是 iptables 的前端管理器,两者不能同时运行。生产环境建议选择其一,避免冲突。如果从 iptables 迁移到 Firewalld,记得先清理已有 iptables 规则:
iptables -F; iptables -X; systemctl enable iptables; systemctl stop iptables。
# 11. 进阶:与其他安全组件集成
# 11.1 与 Fail2Ban 联动
Fail2Ban 可以读取 Firewalld 日志并动态封禁攻击源:
# 安装 Fail2Ban
yum install fail2ban
# 配置 jail.local
cat > /etc/fail2ban/jail.local <<EOF
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 5
[firewalld]
enabled = true
filter = firewalld
action = firewalld[permanent]
port = ssh
logpath = /var/log/firewalld
EOF
# 启动服务
systemctl enable fail2ban
systemctl start fail2ban
# 查看封禁状态
fail2ban-client status
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 11.2 与 Cloudflare 联动
如果业务前端有 Cloudflare CDN,可以结合 Cloudflare 的 Firewalld 功能:
# 限定只有 Cloudflare IP 可访问 80/443 端口
for ip in $(curl -s https://www.cloudflare.com/ips-v4); do
firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='$ip' accept"
done
firewall-cmd --reload
2
3
4
5
# 11.3 入侵检测集成
结合 OSSEC 等 HIDS 工具可以实现自动响应:
# 当 OSSEC 检测到异常时,调用 firewall-cmd 封禁
# 示例:自动封禁检测到的攻击源
#!/bin/bash
ATTACKER_IP=$1
firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='$ATTACKER_IP' reject"
firewall-cmd --reload
2
3
4
5
6
# 12. 性能基准与容量规划
# 12.1 规则数量建议
Firewalld 的规则数量直接影响转发性能:
| 场景 | 推荐规则数 | 最大限制 |
|---|---|---|
| 简单 Web 服务 | < 50 | 500 |
| 多服务混合 | 50-200 | 1000 |
| 复杂企业环境 | 200-500 | 2000 |
# 12.2 连接跟踪容量
# 查看当前连接跟踪数
cat /proc/net/nf_conntrack | wc -l
# 连接跟踪最大值
sysctl net.netfilter.nf_conntrack_max
# 建议值:每GB内存支持约 100k 连接
# 4GB 内存机器建议设置:
sysctl -w net.netfilter.nf_conntrack_max=400000
2
3
4
5
6
7
8
9
# 12.3 监控指标
# 将以下指标加入监控告警
# 1. 规则数量
firewall-cmd --list-all | grep -c "rule "
# 2. 连接跟踪使用率
echo "$(cat /proc/net/nf_conntrack | wc -l) / $(sysctl net.netfilter.nf_conntrack_max)"
# 3. 每秒通过包数
iptables -L -n -v | grep "Chain INPUT"
2
3
4
5
6
7
8
9
# 13. 实际使用场景
# 13.1 Web 服务器的防火墙配置
最常见的使用场景是用 Firewalld 保护一台对外提供 HTTP/HTTPS 服务的 Web 服务器。
典型需求:只开放 80(HTTP)、443(HTTPS)和 22(SSH)端口,其他端口一律关闭。服务器需要主动访问外部服务(如调用第三方 API、yum update),所以 OUTPUT 方向基本放行。
推荐配置:
# 设置默认 zone 为 public
firewall-cmd --set-default-zone=public
# 开放必要服务
firewall-cmd --zone=public --add-service=ssh
firewall-cmd --zone=public --add-service=http
firewall-cmd --zone=public --add-service=https
# 开放非标准端口(如 8080)
firewall-cmd --zone=public --add-port=8080/tcp
# 永久化
firewall-cmd --runtime-to-permanent
2
3
4
5
6
7
8
9
10
11
12
13
进阶需求:如果希望防护 SYN Flood 攻击,可以添加连接速率限制:
firewall-cmd --permanent --add-rich-rule='rule service name="http" limit value="100/s" accept'
firewall-cmd --permanent --add-rich-rule='rule service name="https" limit value="100/s" accept'
2
# 13.2 数据库服务器的防火墙配置
数据库服务器(如 MySQL、Redis)更加敏感,通常只对应用服务器开放访问,对公网完全关闭。
典型需求:只允许特定应用服务器的 IP 访问 3306(或数据库对应端口),SSH 只允许运维人员 IP 访问。
推荐配置:
# 开放特定 IP 的数据库端口
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="<APP_SERVER_IP>" port port="3306" protocol="tcp" accept'
# SSH 只允许运维 IP
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="<OFFICE_IP>" service name="ssh" accept'
# 其他 IP 的 SSH 一律拒绝
firewall-cmd --permanent --add-rich-rule='rule service name="ssh" reject'
2
3
4
5
6
7
8
坑点提醒:如果数据库服务器需要被多台应用服务器访问,记得把每个应用服务器的 IP 都加入白名单。建议建立应用服务器 IP 列表,定期维护。
# 13.3 开发测试环境的防火墙配置
开发测试环境的服务器安全要求比生产环境低,但仍然需要基本的防护。
典型需求:开放更多端口供开发测试使用,但仍需防止意外暴露到公网。允许研发人员从办公网络访问。
推荐配置:
# 宽松模式:开发环境
firewall-cmd --set-default-zone=work
# 开放常用服务
firewall-cmd --zone=work --add-service=ssh
firewall-cmd --zone=work --add-service=http
firewall-cmd --zone=work --add-service=https
firewall-cmd --zone=work --add-service=mysql
# 允许整个办公网络段
firewall-cmd --zone=work --add-source=<OFFICE_NETWORK>
2
3
4
5
6
7
8
9
10
11
建议:开发环境和生产环境严格隔离,网络层面使用不同的安全组或 VLAN。开发环境即使被攻破,也不影响生产。
# 13.4 有 NAT 需求的场景
有些服务器需要做网络地址转换(NAT),比如让内网机器通过公网 IP 访问互联网,或者做端口映射。
典型场景 A:内网服务器共享上网
# 开启 IP 伪装
firewall-cmd --zone=external --add-masquerade
# 允许内网流量转发
firewall-cmd --permanent --direct --add-rule ipv4 nat POSTROUTING -s <INTERNAL_NETWORK> -o eth0 -j MASQUERADE
2
3
4
5
典型场景 B:端口映射
# 将公网 IP 的 8080 端口映射到内网服务器的 80
firewall-cmd --permanent --add-forward-port=port=8080:proto=tcp:toaddr=<INTERNAL_WEB_IP>:toport=80
2
注意事项:NAT 功能会修改数据包的源或目的 IP,可能影响某些基于 IP 的访问控制策略。开启前评估业务影响。
# 13.5 多网卡服务器的 Zone 绑定
生产服务器通常有多块网卡(管理网口、业务网口、存储网口),不同网卡应该绑定到不同的 Zone。
典型场景:eth0 绑定 public(对公网),eth1 绑定 work(对内网应用),eth2 绑定 trusted(对存储网络)。
推荐配置:
# 绑定网卡到 zone
firewall-cmd --zone=public --change-interface=eth0
firewall-cmd --zone=work --change-interface=eth1
firewall-cmd --zone=trusted --change-interface=eth2
# 各 zone 配置不同的服务
firewall-cmd --zone=public --add-service=ssh
firewall-cmd --zone=work --add-service=http
firewall-cmd --zone=trusted --add-service=nfs
2
3
4
5
6
7
8
9
好处:不同网络平面的流量天然隔离。即使公网网卡被攻破,攻击者也无法直接访问存储网络。
# 13.6 为什么要使用 Zone
对于刚接触 Firewalld 的人,可能会觉得 Zone 多此一举——直接用规则不就行了?
Zone 的价值在于快速切换安全策略。当你需要把一台服务器从"公共网络"移动到"内网"时,只需更改网卡的 Zone,所有规则自动切换,无需逐条修改规则。
举例:一台服务器最初部署在 DMZ 区域,使用 public Zone。后来需要迁移到内网,只需改为 work Zone,自动应用内网的安全策略。这比重新配置 iptables 要安全和快捷得多。
# 13.7 常见误区与反模式
误区一:规则写得越多越安全。实际上,规则越多,维护成本越高,漏配的风险也越大。建议只开放必要的端口,用白名单而非黑名单。
误区二:默认 zone 设为 trusted。这是最危险的做法。trusted Zone 放行所有流量,相当于没有防火墙。
误区三:只配临时规则不持久化。很多人为了测试方便只用 --add-port,忘记加 --permanent,重启后规则丢失。最佳实践是每次添加规则时同时加上 --permanent,最后 firewall-cmd --reload 统一生效。
误区四:把 Firewalld 和 iptables 混用。两者都管理 netfilter,混用会导致规则冲突。生产环境选择其一,不要同时启用。
误区五:忽视 IPv6。现在 IPv6 越来越普及,如果服务器有公网 IPv6 地址但只配置了 IPv4 防火墙,IPv6 方向可能完全暴露。务必确认业务是否需要 IPv6,如不需要可以明确禁用。