firewalld是CentOS 7之后默认的防火墙管理工具,日常用得最多的是--add-port这种简单端口放行。但这种写法只能控制端口本身,没法限定来源IP、没法做条件判断,更没法记录日志。真要实现这些精细化的访问控制,就得靠rich rule(富规则)。富规则提供了一套接近自然语言的语法,可以组合来源地址、目的地址、端口、协议、动作和日志等多个条件,是firewalld里功能最完整的一层规则体系。

富规则的基本语法结构
一条富规则由若干个元素按固定顺序组合而成,基本骨架是这样的:
rule [family="ipv4|ipv6"]
[source address="地址[/掩码]" [invert="true"]]
[destination address="地址[/掩码]" [invert="true"]]
[service name="服务名" | port port="端口号" protocol="tcp|udp"]
[protocol value="icmp" ]
[icmp-block name="类型"]
[forward-port port="端口" protocol="tcp" to-port="目标端口" to-addr="目标IP"]
[log [prefix="前缀" level="级别"] [limit value="速率"]]
[audit]
[accept | reject | drop | mark]几个要点需要先弄明白。family指定规则适用的协议族,写ipv4还是ipv6要与source中的地址类型匹配,否则规则会添加失败。source里的invert="true"表示取反,比如source是192.168.1.0/24且取反,含义就是"来源不是这个网段"。最后的动作三选一:accept允许通过,reject拒绝并回送一个拒绝报文,drop直接丢弃不给任何回应。从安全角度讲,drop更隐蔽,reject对客户端更友好,按业务需求选即可。
添加富规则使用firewall-cmd --add-rich-rule,查询用--query-rich-rule,删除用--remove-rich-rule。要注意这些操作默认只对运行时生效,重启后失效。想永久生效必须加--permanent参数,而且加完之后要执行firewall-cmd --reload才会加载到运行时。这个双模式设计坑过不少人,调试时建议先用runtime模式试,确认没问题再补permanent版本。
常见场景的富规则配置实例
场景一:只允许指定IP访问SSH
服务器暴露在公网上,22端口天天被扫是常态。用富规则把SSH限制到运维网段,是最常见的用法:
# 只允许192.168.10.0/24网段访问SSH firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.10.0/24" service name="ssh" accept' # 其他来源一律拒绝访问22端口 firewall-cmd --permanent --add-rich-rule='rule family="ipv4" port port="22" protocol="tcp" drop' firewall-cmd --reload
这里有个容易被忽视的点:zone里如果已经通过--add-service=ssh放行了SSH,那条规则对所有人生效,后面的drop规则未必能挡住。firewalld内部规则有优先级,直接写在命令行的富规则优先级高于zone基础配置,但为了逻辑清晰,建议限制SSH时先执行--remove-service=ssh,把基础放行去掉,再靠富规则精确控制。改SSH规则前务必先确认受限网段能连上,否则很容易把自己锁在外面,只能靠控制台救援。
场景二:拒绝特定IP并记录日志
排查恶意访问时,往往既要拦截又想留下证据,富规则可以把动作和日志写在同一条里:
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.45" log prefix="BAD-GUY:" level="warning" limit value="3/m" drop' firewall-cmd --reload
limit value="3/m"表示每分钟最多记录3条,防止攻击者用高频请求把日志刷爆。日志会进入系统日志(可通过journalctl或/var/log/messages查看),前缀BAD-GUY方便grep筛选。如果没有limit限制,一次端口扫描就可能产生上万条内核日志,严重时影响性能,所以生产环境凡是带log的规则都建议加上限速。
场景三:端口转发
把外部访问的8080端口转发到内网另一台机器的80端口,富规则同样能办到:
# 先开启伪装 firewall-cmd --permanent --add-masquerade # 将本机8080转发到192.168.20.15的80端口 firewall-cmd --permanent --add-rich-rule='rule family="ipv4" forward-port port="8080" protocol="tcp" to-port="80" to-addr="192.168.20.15" accept' firewall-cmd --reload
forward-port必须配合masquerade(地址伪装)才能对外的转发正常工作,缺少这一步是端口转发不生效的最常见原因。另外转发目标端口本身不需要在本机放行,因为流量根本不经过本机的服务进程,直接由内核转发走了。
规则查看、排错与注意事项
配置完成后,查看当前zone的所有富规则用:
# 查看运行时富规则 firewall-cmd --list-rich-rules # 查看永久配置中的富规则 firewall-cmd --permanent --list-rich-rules # 查看指定zone的富规则 firewall-cmd --zone=public --list-rich-rules # 检查单条规则是否存在 firewall-cmd --query-rich-rule='rule family="ipv4" source address="192.168.10.0/24" accept'
排查规则不生效的问题,可以按这个思路走。第一步用firewall-cmd --list-all确认规则确实加进了目标zone,很多问题是规则加到了默认zone而服务跑在别的zone上。第二步检查permanent和runtime是否一致,改了永久配置忘了reload,或者只在runtime加了规则重启后丢失,都属于高频失误。第三步如果firewalld本身正常但仍不通,要看底层iptables:firewall-cmd --direct --get-all-rules和iptables -L -n能帮你看是否有别的直通规则冲突。
还有两点经验值得记下。一是富规则里引号的使用,整条规则外层用单引号包裹,内部的address、port等参数值用双引号,混用或漏掉都会导致解析报错。二是删除规则时,--remove-rich-rule后面跟的规则文本必须与添加时完全一致,多一个空格都可能匹配不上,稳妥的做法是先从--list-rich-rules的输出里复制原文再执行删除。掌握这些细节后,富规则基本能覆盖日常防火墙的绝大部分精细化控制需求。
firewalldrich ruleCentOS防火墙配置修改时间:2026-09-13 09:40:30