Rocky 10:direct 规则为什么该换成 policy
Rocky Linux 10.2 虚拟机 + firewalld 2.4.0。同一次会话里做三件事:读 man 的废弃段落、加一条 direct 规则、用 policy 做等价放行,然后对比 nft 里的落点。
截图:public/evidence/firewalld/rocky-direct-vs-policy.png。
先看官方态度
Section titled “先看官方态度”$ man firewalld.directDEPRECATED The direct interface has been deprecated. It will be removed in a future release. It is superseded by policies, see firewalld.policies(5).「will be removed」+「superseded by policies」两句,基本决定了新配置不该再写 --direct。
direct 规则换成 nft 看是什么样
Section titled “direct 规则换成 nft 看是什么样”$ firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 \ -p tcp --dport 9999 -j ACCEPTsuccess$ firewall-cmd --reload$ nft list ruleset | grep -B4 "dport 9999" | grep chain chain INPUT {direct 规则进的是 chain INPUT——一条没有 zone 归属的链。后果有三:
- zone 的默认策略、日志、rich rule 条件都用不上;
- 规则顺序完全靠
priority数字手工安排,容易压住别的规则; - 排查时
firewall-cmd --list-all看不到它,只出现在--direct --get-all-rules里。
等价写法:policy
Section titled “等价写法:policy”# firewall-cmd --permanent --new-policy labpolicy# firewall-cmd --permanent --policy labpolicy --add-ingress-zone public# firewall-cmd --permanent --policy labpolicy --add-egress-zone HOST# firewall-cmd --permanent --policy labpolicy --add-port 9997/tcp# firewall-cmd --permanent --policy labpolicy --set-target ACCEPT# firewall-cmd --reload$ firewall-cmd --info-policy=labpolicy target: ACCEPT ingress-zones: public egress-zones: HOST ports: 9997/tcp$ nft list ruleset | grep -B3 "dport 9997" | grep chain chain filter_IN_policy_labpolicy_allow {policy 有独立的链(filter_IN_policy_<name>_allow),与 zone 规则互不覆盖,语义也写进了配置本身:谁进来(ingress)、去哪(egress)、做什么(target)。

- 单机开个端口:优先
firewall-cmd --add-port(zone 内); - 需要源地址/日志/限速:rich rule;
- 与转发、容器、整体策略相关:policy;
--direct:只用于兼容既有脚本,不作为新方案。
迁移时容易踩的三点
Section titled “迁移时容易踩的三点”- ingress zone 不能用
any:实测报INVALID_ZONE: 'any' not among existing zones,必须写真实 zone(如public); - policy 的 target 要慎用 ACCEPT:整段放行会盖过 zone 的默认拒绝,先确认意图;
--permanent与 runtime 要同步:只改 runtime,reload 后立刻丢失。
--list-all里找不到某条放行 → 它可能在 direct 或 policy 里,分别用--direct --get-all-rules、--list-policies查;- 删除 direct 规则必须逐字一致,写错不报错(见 rich rule 那篇的同类问题);
- policy 建了但
disable: yes或未生效,--info-policy会显示状态,别只看nft有没有链。
练习:direct → policy 迁移
Section titled “练习:direct → policy 迁移”sudo firewall-cmd --list-policiessudo firewall-cmd --permanent --new-policy lab9997sudo firewall-cmd --permanent --policy lab9997 --add-ingress-zone publicsudo firewall-cmd --permanent --policy lab9997 --add-egress-zone HOSTsudo firewall-cmd --permanent --policy lab9997 --add-port 9997/tcpsudo firewall-cmd --permanent --policy lab9997 --set-target ACCEPTsudo firewall-cmd --reloadsudo firewall-cmd --info-policy=lab9997检查:
- 策略状态为 active,ingress/egress 与预期一致;
nft list ruleset | grep 9997能匹配到放行;- 移除原 direct 规则后行为不变;
- 收尾删除策略。
常见问题
policy 会不会和 zone 规则冲突?
不会互相覆盖:它们在 nft 里是不同的链,按 hook 顺序执行;冲突一般来自 target 设得太宽。
direct 的优先级参数还要保留吗?
不需要。policy 通过 zone 对与 target 表达意图,不再依赖手工优先级数字。
旧系统里的 direct.xml 怎么办?
先导出 --direct --get-all-rules,逐条映射成 policy 或 rich rule,验证后清空 direct.xml。
- nftables 后端:/firewall-backend-nftables/
- rich rule:/firewalld-rich-rules/
- zone 概念:/firewalld-zones/