AlmaLinux 10:direct 接口已废弃,该改用 policy
AlmaLinux 10.2 虚拟机,firewalld 2.4.0。三件事都在同一台机器上验证:
- 读
man firewalld.direct的废弃声明; - 加一条 direct 规则,看它落在哪条链;
- 用 policy 实现同样的放行,再看落点。
截图:public/evidence/firewalld/alma-direct-vs-policy.png。
手册里写得很直接
Section titled “手册里写得很直接”$ man firewalld.direct | head -14DEPRECATED The direct interface has been deprecated. It will be removed in a future release. It is superseded by policies, see firewalld.policies(5).--direct 不是「暂时不推荐」,而是已列入移除计划,官方给的替代物是 policy。
direct 规则落在哪里
Section titled “direct 规则落在哪里”$ firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 \ -p tcp --dport 9999 -j ACCEPTsuccess$ firewall-cmd --reload$ firewall-cmd --direct --get-all-rulesipv4 filter INPUT 0 -p tcp --dport 9999 -j ACCEPT它在 nft 侧落到一条名为 INPUT 的链:
$ nft list ruleset | grep -B4 "dport 9999" | grep chain chain INPUT {注意:这条链不属于任何 zone。也就是说 direct 规则绕过了 zone 语义——没有 zone 的默认策略、没有 logging、没有 rich rule 的条件表达能力,纯靠 iptables 语法和顺序。
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=labpolicylabpolicy (active) 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 描述的是「从哪个 zone 来、到哪个 zone 去、放行什么」,这就是它取代 direct 的原因:语义完整、可审计。

三种方式怎么选
Section titled “三种方式怎么选”| 方式 | 作用域 | 状态 | 适用 |
|---|---|---|---|
--direct | 无 zone,nft chain INPUT | 已废弃 | 仅维护存量、临时救火 |
| rich rule | 单个 zone 内 | 支持 | 条件放行(源地址、日志、限速) |
| policy | zone 对 zone / zone 对 HOST | 支持,官方推荐 | 主机整体策略、转发与容器场景 |
| direct 写法 | policy 写法 |
|---|---|
--direct --add-rule ipv4 filter INPUT 0 -p tcp --dport 9999 -j ACCEPT | --policy X --add-port 9997/tcp --set-target ACCEPT |
-s 10.0.0.0/24 -j ACCEPT | --add-source 10.0.0.0/24 |
-j DROP | --set-target DROP |
-m limit --limit 10/m | 用 rich rule 的 limit value="10/m" |
--add-ingress-zone any报错:实测返回INVALID_ZONE: Policy 'labpolicy': 'any' not among existing zones,ingress 必须写真实 zone 名(public等);- 只加
--permanent不 reload:nft 里看不到,--info-policy也可能是 inactive; - policy 与 zone 冲突:policy 的 target 是 ACCEPT 时相当于整段放行,写宽了会盖过 zone 的默认拒绝;
- 以为 direct 规则会被 reload 清掉:带
--permanent的会保留——这恰恰是遗留系统难清理的原因。
练习:把一条 direct 规则迁成 policy
Section titled “练习:把一条 direct 规则迁成 policy”sudo firewall-cmd --direct --get-all-rulessudo 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检查:
--info-policy里 ingress/egress/ports 与预期一致;nft list ruleset | grep 9997能找到放行;- 把原 direct 规则移除并 reload,行为不变;
- 收尾
--delete-policy=lab9997。
常见问题
direct 现在还能用吗?
能,EL10 的 firewalld 仍实现该接口,但 man 明确写了将来移除;新配置不要再用。
policy 和 zone 是什么关系?
zone 描述「接口属于哪类信任域」,policy 描述「zone 与 zone(或 HOST)之间允许什么」,两者配合使用。
容器转发场景该用哪个?
用 policy:可指定 ingress/egress zone 与 target,正好覆盖转发与 podman 网络需要的语义。
- nftables 后端:/firewall-backend-nftables/
- rich rule 精确匹配:/firewalld-rich-rules/
- zone 与放行:/firewalld-zones/