一、基础命令

查看 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=300

IP 放行

开放单个源 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 --reload

6. 黑名单模式:默认放行所有,只拦截指定对象

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(全部)、unicastbroadcastmulticastoff
生产环境建议用 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:自定义日志前缀,便于 grep
  • limit 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:源 / 目的 IP
  • SPT / 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  # 持久化配置(对比运行时配置是否一致)

常见坑:

  1. 改了没生效:忘了 --reload,或只加了运行时规则(没带 --permanent)重启后丢失。
  2. 放行了还是被拦:检查是否有更优先的 rich rule / drop zone 匹配了该 IP;rich rule 的 drop/reject 优先于端口放行。
  3. 规则互相冲突:先用 --permanent --list-all 审计现有规则,再加新规则。
  4. 远程把自己锁外面:涉及默认 zone 变更前,先 firewall-cmd --add-port=22/tcp --timeout=300 留个临时退路。

标签: none