CentOS自带防火墙firewalld 规则配置手册
一、基础命令
查看 firewalld 服务状态
systemctl status firewalld查看 firewall 运行状态
firewall-cmd --state手动启停 firewalld 服务
systemctl start|stop|restart firewalld展示当前配置的 firewall 规则
firewall-cmd --list-all任何修改完成后,需重新装载或重启服务
firewall-cmd --reload注意:--reload不中断现有连接,--complete-reload会中断所有连接(含状态信息),慎用。
二、放行规则
端口查询、放行
查询端口是否开放:
firewall-cmd --query-port=8080/tcp新建规则,开放 8080 端口:
firewall-cmd --permanent --add-port=8080/tcp移除上述规则:
firewall-cmd --permanent --remove-port=8080/tcp批量开放端口(范围):
firewall-cmd --permanent --add-port=9001-9100/tcp临时放行(不持久化,加 --timeout 秒后自动失效):
firewall-cmd --add-port=8080/tcp --timeout=300IP 放行
开放单个源 IP:
firewall-cmd --permanent --add-source=192.168.1.1开放整个源 IP 段:
firewall-cmd --permanent --add-source=192.168.1.0/24移除上述规则:
firewall-cmd --permanent --remove-source=192.168.1.1系统服务的开放
开放 http 服务:
firewall-cmd --permanent --add-service=http移除上述规则:
firewall-cmd --permanent --remove-service=http查看所有预定义服务:
firewall-cmd --get-services自定义复杂规则(放行)
允许指定 IP 访问本机 8080 端口:
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.1" port protocol="tcp" port="8080" accept'允许指定 IP 段访问本机 8080-8090 端口:
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port protocol="tcp" port="8080-8090" accept'三、拦截规则
1. reject 与 drop 的区别
| 动作 | 行为 | 客户端感知 | 适用场景 |
|---|---|---|---|
reject | 拒绝并回送 ICMP/TCP RST | 立即收到"被拒绝",明确知道有防火墙 | 内部网络,希望对方快速失败 |
drop | 静默丢弃,不回应 | 对方只能等超时,无法探测端口是否存在 | 对公网/扫描者,隐藏自身存在 |
对不可信来源(公网 IP、扫描器)优先用 drop;对内网需要明确告知的用 reject。
2. 拦截指定 IP / IP 段
拒绝指定 IP 的所有访问(回送拒绝):
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.100" reject'静默丢弃指定 IP 的所有访问(推荐用于拉黑):
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.100" drop'丢弃整个网段:
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" drop'移除拦截规则(将 add 换成 remove):
firewall-cmd --permanent --remove-rich-rule='rule family="ipv4" source address="192.168.1.100" drop'3. 拦截指定 IP 访问指定端口
禁止指定 IP 访问本机 8080 端口(明确拒绝):
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.1" port protocol="tcp" port="8080" reject'同上,但静默丢弃:
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.1" port protocol="tcp" port="8080" drop'4. 用 drop / block 预定义 zone 快速拉黑
firewalld 内置两个专门用于拦截的 zone,比 rich rule 更简洁:
- drop zone:丢弃所有进入的包
- block zone:拒绝所有进入的包(回送 ICMP)
把某个 IP 整段拉黑:
firewall-cmd --permanent --zone=drop --add-source=203.0.113.50
firewall-cmd --reload验证:
firewall-cmd --zone=drop --list-all提示:绑定了 source 的 IP 会优先匹配对应 zone 的规则,不再走默认 zone。
5. 大规模黑名单:ipset(IP 多时必用)
逐条 rich rule 不适合成百上千个 IP,应使用 ipset:
# 创建 ipset
firewall-cmd --permanent --new-ipset=blacklist --type=hash:ip
# 添加条目(可批量)
firewall-cmd --permanent --ipset=blacklist --add-entry=203.0.113.50
firewall-cmd --permanent --ipset=blacklist --add-entry=203.0.113.51
# 从文件批量导入(每行一个 IP)
firewall-cmd --permanent --ipset=blacklist --add-entries-from-file=/root/blacklist.txt
# 将整个 ipset 丢进 drop zone
firewall-cmd --permanent --zone=drop --add-source=ipset:blacklist
firewall-cmd --reload6. 黑名单模式:默认放行所有,只拦截指定对象
firewalld 默认 zone(通常是 public)本身就是"默认放行已放行的、拒绝其余",要实现默认放行一切、只拦指定 IP/端口,需要两步:
第一步:把默认 zone 的 target 改为 ACCEPT(全部放行)
firewall-cmd --permanent --zone=public --set-target=ACCEPT
firewall-cmd --reload此时所有入站流量默认放行,无需再逐个 add-port / add-service。
第二步:叠加拦截规则(以下几种方式任选,都优先于默认放行生效)
拦截指定 IP 的所有访问:
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.50" drop'拦截指定 IP 段:
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="198.51.100.0/24" drop'只拦指定 IP 的指定端口,该 IP 其余端口照常放行:
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.50" port protocol="tcp" port="22" drop'拦截所有人访问某端口(其余全放):
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" port protocol="tcp" port="3306" drop'配合 ipset 维护大名单(见第 5 节),规则本体只有一条:
firewall-cmd --permanent --zone=drop --add-source=ipset:blacklist注意:ACCEPT target + drop zone/ipset 组合时,source 绑定到 drop zone 的 IP 会被 zone 拦截,不经过 public 的 ACCEPT,逻辑上是安全的。
何时用黑名单模式:内网测试环境、服务端口多且变动频繁、只想针对性封堵少量恶意来源。公网生产环境不建议,漏拦一个就是敞开的。
7. 默认策略收紧:白名单模式
把默认 zone 改为 drop(未放行的全部丢弃,相当于全局默认拒绝):
firewall-cmd --set-default-zone=drop危险操作:执行前确保 SSH(22 端口或实际端口)已通过 service/port/rich rule 放行,否则远程连接会立即断开。建议先在 console/IPMI 可用的环境演练。
8. 一键断开所有网络(应急)
firewall-cmd --panic-on # 丢弃所有流量
firewall-cmd --panic-off # 恢复
firewall-cmd --query-panic # 查询状态四、拦截日志
查看是否开启拦截日志
firewall-cmd --get-log-denied
# 或
grep -i LogDenied /etc/firewalld/firewalld.conf开启拦截日志记录
firewall-cmd --set-log-denied=all或修改配置文件 /etc/firewalld/firewalld.conf,将 LogDenied 设置为 all。
可选值:all(全部)、unicast、broadcast、multicast、off。
生产环境建议用 unicast 而非 all,避免广播/组播刷爆日志。
日志记录在 /var/log/messages:
grep FINAL_REJECT /var/log/messages
# 实时跟踪
tail -f /var/log/messages | grep -E 'FINAL_REJECT|DROP'对单条规则记录日志并限速(rich rule)
只对特定拦截打日志,且限制日志频率(防止日志洪泛):
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port protocol="tcp" port="8080" log prefix="BLOCK-8080 " level=warning limit value="10/m" drop'prefix:自定义日志前缀,便于 greplimit value="10/m":每分钟最多记 10 条
拦截日志示例
Aug 23 11:21:05 SSO-DATA-01 kernel: FINAL_REJECT: IN=ens192 OUT= MAC=00:50:56:a8:c5:f9:00:50:56:a8:13:39:08:00 SRC=10.15.2.61 DST=10.15.2.62 LEN=2620 TOS=0x00 PREC=0x00 TTL=64 ID=9222 DF PROTO=TCP SPT=34475 DPT=21001 WINDOW=1424 RES=0x00 ACK PSH URGP=0关键字段速查:
SRC/DST:源 / 目的 IPSPT/DPT:源 / 目的端口PROTO:协议(TCP/UDP)SYN:新建连接(典型扫描特征)ACK PSH:已有连接中的数据包被拦(多为放行后又被规则变更切断)
五、验证与排错清单
firewall-cmd --list-all # 当前 zone 全部规则
firewall-cmd --list-all-zones # 所有 zone(含 drop/block)
firewall-cmd --get-active-zones # 网卡/源 IP 与 zone 的绑定关系
firewall-cmd --get-log-denied # 拦截日志开关
firewall-cmd --permanent --list-all # 持久化配置(对比运行时配置是否一致)常见坑:
- 改了没生效:忘了
--reload,或只加了运行时规则(没带--permanent)重启后丢失。 - 放行了还是被拦:检查是否有更优先的 rich rule / drop zone 匹配了该 IP;rich rule 的 drop/reject 优先于端口放行。
- 规则互相冲突:先用
--permanent --list-all审计现有规则,再加新规则。 - 远程把自己锁外面:涉及默认 zone 变更前,先
firewall-cmd --add-port=22/tcp --timeout=300留个临时退路。