在firewalld使用时候过程中,定义的多条rich规则,或者和direct规则混用,导致firewalld的过滤的数据包的规则,在某些情况下不会按照我们定义的规则顺序去执行,之所以造成这种问题的原因,是因为不了解firewalld对区域和其规则的设定在底层发生了什么!例如
我在《第3篇:Linux防火墙-firewalld与ICMP控制》已经探讨过这个问题。
我们在深入探讨firewalld基于它的后端iptables的内部机制,需要了解iptables过滤数据表的原理,下图是一个很好的总结。
![](https://img.haomeiwen.com/i16148197/8124659cbaf3523f.png)
firewalld作为iptables的前端,它在iptables的 PREROUTING / FORWARD / INPUT/OUTPUT链内部为其活动区域都预设了的不同区域名称的链,这些链的执行尤其固定的顺序,下图是firewalld的external和internal为活动区域的规则集执行流程,读者可以通过iptables命令来验证上图,不过这个图我做了一些精简。
![](https://img.haomeiwen.com/i16148197/599fb3582c0e0b41.png)
下图的流程是承接上图的路由系统
![](https://img.haomeiwen.com/i16148197/d8e88b6a84d71c73.png)
从上图可知,firewalld的internal/external区域会映射到iptables内部的对应区域链的规则集,例如,在PREROUTING链中firewalld在iptables中加载了三个chain,并且这三个chain的优先级依次是
- PREROUTING_direct:用于装载通过firewalld定义的direct规则。
- PREROUTING_ZONES_SOURCE:这个链在CentOS8的firewalld中已经取消。
- PREROUTING_ZONES:用于装载firewalld活动区域相关的chain
我们通过iptables命令查看PREROUTING链来证实我们的说法
![](https://img.haomeiwen.com/i16148197/305039a65553579d.png)
此时,我们通过firewalld定义下面一条direct规则,来继续印证上面提到的PREROUTING_direct链的作用。
firewall-cmd --permanent --direct --add-rule \
ipv4 mangle PREROUTING 0 -p icmp -i ens33 -j DROP
首先从下图演示中,我们定义了上面的direct规则,在重装firewalld后我们通过iptables命令来查看通过direct命令选项定义的规则会在装载到PREROUTING_direct链当中。
![](https://img.haomeiwen.com/i16148197/f2571a3004cfcec4.png)
我们因此知道PREROUTING_direct是用于装载direct选项定义iptables规则。
区域的原理
我们继续通过iptables查看另外一个PREROUTING_Zones链,如下命令
iptables -t mangle -L PREROUTING_ZONES -nv
![](https://img.haomeiwen.com/i16148197/0217044012e9667d.png)
在上图输出中,我们得知PREROUTING_direct链中装载着三条规则,这三条规则分别指向着下面三个chain,它们是firewalld为其活动区域相关的。其匹配顺序如下
PRE_internal ➤ PRE_external ➤ PRE_public
没错,我们通过firewall-cmd --get-active-zones的演示来验证我们的想法。
![](https://img.haomeiwen.com/i16148197/4eb3e1cbe153e357.png)
其中的public区域对于的PRE_public链在0.63版本的firewalld中是默认存在的,而在centOS8中的0.70版本,除非显式定义public为活动区域,否则会默认取消了PRE_public
那么,我们继续在这里提出一个问题,firewall-cmd设定默认区域会否对- PRE_internal和PRE_external的先后次序有所影响?
我们按照如下图,首先查看firewalld的默认区域和活动区域,并且查看PREROUTING_ZONES链中三条链的顺序。根前文是一致的。
![](https://img.haomeiwen.com/i16148197/e6b6d01a17759d78.png)
之后,firewalld的默认区域由public区域替换为external区域,其顺序变更为
PRE_internal ➤ PRE_external ➤ PRE_externl
然后,再将默认区域由external区域替换为internal区域,如下图所示
![](https://img.haomeiwen.com/i16148197/380b41f7d0d332fb.png)
在iptables的PREROUTING链中,顺序如下PRE_internal ➤ PRE_external ➤ PRE_internal
在firewalld中,通过前后对比,我们得出如下几个基本的结论
- firewall设定默认区域的链会追加到iptables对应链(这里是PREROUTING)中的最后位置。
- internal区域的链(例如:PRE_internal)的优先于external区域的链被匹配
注意:
我们通过上面的操作,读者你们会否发现?如果firewalld已经存在两个活动区域,而将其中一个活动区域设定为默认区域,这种配置是错误的。因为internal区域内的规则会被优先匹配,而internal区域又被设置为默认的区域,同一个链的上下文中,internal作为最后一条默认规则并不会被执行。
因此,当我们的防火墙存在两个区域internal/trust/work和external时,这些区域是用于安全地相互传递信息,而对于一些不可信任的连接请求是会被拒之防火墙之外的,我们可以交由默认规则来处理,而firewalld中有一个区域叫drop非常适合作为iptables规则列表中的默认规则。
区域设定的本质
从上文的我们已经知道firewalld的特定区域会在iptables规则列表存在与该区域名称对应的链。例如在PREROUTING链中
internal区域会被映射为 pre_interanl链
external区域会被映射为pre_external链
在FORWARD链中,即更为复杂的映射关系,你们可以自行使用iptables命令去查看,这里不一一举例。
我们知道firewalld中引入了区域这个概念后,可以在区域中进行类似如下操作
- 开放目标端口,例如
firewall-cmd --zone=external --add-port=3389/tcp --permanent
firewall-cmd --reload
我们用iptables查看external相关的规则集,会发现在iptables的filter表-->INPUT链-->IN_external_allow链,会存在这样的一条规则。
![](https://img.haomeiwen.com/i16148197/28775c03d6ddb3be.png)
- 开放源网络,例如执行下面命令后
firewall-cmd --zone=external --add-source=172.42.38.128
firewall-cmd --runtime-to-permanent
iptables的INPUT_ZONES_SOURCE链多了一条放行主机172.42.38.128的规则,其实就是由上面的命令执行后,添加到预设这个链中的。
![](https://img.haomeiwen.com/i16148197/68c633acd41e9656.png)
- 定义rich规则,例如定义下面这样的一条规则
firewall-cmd --zone=internal --add-rich-rule='rule
family=ipv4 source address=10.10.10.0/24 \
service name=ssh drop'
那么上面设定rich规则会被内化为iptables的filter表-->INPUT链-->INPUT_ZONES链-->IN_internal_deny链内的一条iptables规则,如下图
![](https://img.haomeiwen.com/i16148197/3d1aaf149c0d444e.png)
我们再看看定义下面的一条带有日志规则的rich规则,这次的rich规则是运行10.10.10.4的一台主机访问防火墙的ssh端口
firewall-cmd --zone=internal --add-rich-rule="rule \
family=ipv4 source address=10.10.10.4/32 \
service name=ssh log prefix=\"ssh connect:\"
level=\"notice\" accept"
上面的rich规则首选会分成两个部分,如下图所示
-
首先会由iptables的LOG链来做日志处理,即内化为filter表-->INPUT链-->INPUT_ZONES链-->IN_internal_log链内的一条iptables规则。
-
然后内化为在filter表-->INPUT链-->INPUT_ZONES链-->IN_internal_allow链内的一条iptables规则
-
设定区域的target
以上这些区域的操作会最终内化成firewalld在该区域的预设链内,并且带有固有顺序的规则列表。
后续更新。。。。
网友评论