简介
direct
是 firewalld
服务的一个功能,它允许用户以更直接的方式配置防火墙规则,绕过通常的 firewalld
区域(zone)和服务的抽象层。然而,这个功能已经被弃用(deprecated),并将在未来的版本中移除。
弃用原因:直接配置可能导致与 firewalld
的其他功能(如区域和服务)发生冲突或混淆。因此,推荐使用 firewalld
的策略(policies)和区域(zones)来配置防火墙。
替代方案:可以通过policies来替代direct
direct命令结构
文件结构
<?xml version="1.0" encoding="utf-8"?>
<direct>[ <chain ipv="ipv4|ipv6|eb" table="table" chain="chain"/> ][ <rule ipv="ipv4|ipv6|eb" table="table" chain="chain" priority="priority"> args </rule> ][ <passthrough ipv="ipv4|ipv6|eb"> args </passthrough> ]
</direct>
chain
它用于定义额外链的名称。一个链条条目具有三个属性:
-
ipv="ipv4|ipv6|eb"
:将创建链的 IP 家族。可以是 ipv4、ipv6 或 eb。 -
table="table"
:链将被创建的表名。这可以是 iptables、ip6tables 或 ebtables 可用的表之一。 -
chain="chain"
:将被创建的链的名称。请确保没有其他同名链存在。
请记得添加一条规则或者带有 --jump
或 --goto
选项的穿透规则,将该链与另一个链连接起来。这个与我们iptables中的自定义链和关联自定义链到对应的表是一样的。
rule
它用于向内置或添加的链中添加规则。一个规则条目具有四个属性:
-
ipv="ipv4|ipv6|eb"
:将添加规则的 IP 家族。可以是 ipv4、ipv6 或 eb。 -
table="table"
:规则将被添加到的表的名称。这可以是 iptables、ip6tables 或 ebtables 可用的表之一。 -
chain="chain"
:将添加规则的链的名称。这可以是内置链或使用chain
标签创建的链。如果链名称是内置链,则规则将被添加到chain_direct
,否则使用提供的链名称。chain_direct
在所有内置链中内部创建,以确保添加的规则不会与 firewalld 创建的规则发生冲突。 -
priority="priority"
:优先级用于排序规则。优先级为 0 表示在链的顶部添加规则。具有相同优先级的规则处于同一级别,这些规则的顺序不固定且可能更改。如果想确保一个规则在另一个规则之后添加,为第一个规则使用较低的优先级,为后续规则使用较高的优先级。
passthrough
passthrough
是 firewalld
中 direct.xml
文件的一个可选元素标签,用于向内置或添加的链中添加规则。。当你使用 passthrough
时,你需要确保添加的规则与 firewalld
自动创建的其他规则没有冲突。
注意事项:
当使用firewalld
时,根据配置的FirewallBackend
(在firewalld.conf
中设置),直接规则的行为会有所不同。主要的后端有两个:iptables
和nftables
数据包接受/丢弃优先级
- 如果使用了
FirewallBackend=nftables
,直接规则中ACCEPT数据包并不会立即导致数据包被系统接受。这些数据包仍然需要遵守firewalld
的nftables规则集。这基本上意味着有两个独立的防火墙,数据包必须同时被两者接受(iptables和nftables)。 - 对于DROP规则,数据包会立即被丢弃,无论
FirewallBackend
的值是什么。 - 为了解决nftables中ACCEPT数据包的问题,用户可以:
- 使用富规则(Rich Rules),它们会被转换成启用的后端规则。
- 在nftables规则集中明确接受数据包,这可以通过将接口或源添加到受信任的区域来实现。注意,这意味着
firewalld
将不会对这些数据包进行任何过滤。 - 在适当的区域中仅启用相关的服务、端口、地址等。
- 可以通过设置
FirewallBackend=iptables
来回退到iptables后端。但是,应该意识到firewalld
的开发重点是nftables后端。
配置直接规则
命令参考
irect Options--direct --指定将要使用直接规则--get-all-chains --获取所有的链--get-chains {ipv4|ipv6|eb} <table> --获取表中的链--add-chain {ipv4|ipv6|eb} <table> <chain> --添加链到表中(自定义的)--remove-chain {ipv4|ipv6|eb} <table> <chain> --移除表中的某条链--query-chain {ipv4|ipv6|eb} <table> <chain> --返回链是否已被添加到表--get-all-rules --获取所有的策略规则--get-rules {ipv4|ipv6|eb} <table> <chain> --获取指定表中指定链中的规则--add-rule {ipv4|ipv6|eb} <table> <chain> <priority> <arg>... --在指定表中的指定链添加规则--remove-rule {ipv4|ipv6|eb} <table> <chain> <priority> <arg>... --优先从指定表中的指定链删除规则条目--remove-rules {ipv4|ipv6|eb} <table> <chain> --从表中删除规则条目--query-rule {ipv4|ipv6|eb} <table> <chain> <priority> <arg>... --返回是否优先的规则已被添加到链表中--passthrough {ipv4|ipv6|eb} <arg>... --直接传递iptables的命令--get-all-passthroughs --获取所有直接传递的规则--get-passthroughs {ipv4|ipv6|eb} <arg>... --获取跟踪直通规则--add-passthrough {ipv4|ipv6|eb} <arg>... --添加一个直接规则--remove-passthrough {ipv4|ipv6|eb} <arg>... --移除一个直接规则--query-passthrough {ipv4|ipv6|eb} <arg>... --查询直接规则是否添加
增加直接规则
firewall-cmd --direct --add-chain { ipv4 | ipv6 | eb } <table> [自定义链表名] <args>firewall-cmd --direct --add-rule { ipv4 | ipv6 | eb } <table> <chain> <priority> <args>
删除直接规则
firewall-cmd --direct --remove-chain { ipv4 | ipv6 | eb } <table> [自定义链表名] <args>firewall-cmd --direct --remove-rule { ipv4 | ipv6 | eb } <table> <chain> <priority> <args>
firewalld与iptables表对比
修改firewall的后端为iptables
编辑/etc/firewalld/firewalld.conf,将FirewallBackend=修改为iptables,默认为nftables
此时查看我们的firewalld zone
查看iptables
此时会发现我们的iptables有非常多的规则,我这里只列出与我们前面配置的trusted zone相关的规则。
测试1
配置直接规则,允许192.168.140.248访问140.250的80端口,在firewalld中,我们已经配置了2条规则,第一条禁止第二条放行,但是禁止的优先级高,所以禁止优先。
测试2
我们现在要限制192.168.140.248对250的icmp访问,每5秒放行一个数据包。这个在我们上篇文章介绍rich rule的时候是没有实现的,那么我们这里通过--direct来实现
上面配置的详细原理可以参考iptables常用扩展模块和iptables自定义链的配置方式。配置完成后通过--runtime-to-permanent从runtime永久化然后重新加载。
此时在192.168.140.248上ping可以实现我们想要的功能吗?
查看iptables
总结:
当我们使用--direct参数后,并且将后端改为iptables后,那么数据包的处理方式就和iptables是一样的。我们可以直接修改iptables也可以通过firewalld-cmd进行配置。这个时候如果使用--direct命令去配置的话,需要我们对iptables有一定程度的了解。更多的iptables的使用大家可以看我前面与iptables有关的文章。