Linux防火墙firewalld Rich规则的优先级

目录 Linux

一、实验示例

如图1,我们希望只有192.168.10.102的主机可以远程ssh到192.168.10.253的服务器,而同一网段内192.168.10.0/24的其他主机禁止访问。

Linux防火墙firewalld Rich规则的优先级-下一朵云
图1 网络拓扑图

在写rich规则时,往往会遇到两条冲突的规则。例如,为了只允许来自192.168.10.0/24网络的一台主机192.168.10.102允许通过ssh访问防火墙,显然下面的规则是不可取的

规则1:-拒绝来自192.168.10.0/24网络的所有主机(drop/reject)
规则2:-允许来自192.168.10.102的主机(accept)

由于192.168.10.102主机也属于192.168.10.0/24这个网络号,因此这两个规则都将应用于该主机,如果你对iptables规则熟悉的话,可能会去如下这样理解防火墙匹配规则的行为

1.仅处理入站的数据包。
2.数据包始终以从上到下的方向进行处理。

然后可能就许就这样定义防火墙的规则:

1:一旦数据包与规则匹配,将立即对该数据包执行关联操作(允许或拒绝)。
2:数据包将不可用于进一步处理。

规则1:允许来自192.168.10.102的主机(accept)
规则2:拒绝来自192.168.10.0/24网络的所有主机(drop/reject)

规则精确度越高的放在规则列表的最前,逻辑上应该是先设定accept行为的规则,然后再设定drop/reject行为的规则,这样的逻辑在iptables是正确,甚至其他传统的防火墙也是这样行为逻辑的。但你要搞清楚,到了firewalld的rich规则就不适用了。

为了证实这一说法,我么参考了http://firewalld.org的技术文档。请好好理解图2中划黄线的一段话

Linux防火墙firewalld Rich规则的优先级-下一朵云
图2 技术文档

中文的翻译:
当前的rich规则的一个问题是,它们是基于规则操作来组织的。 日志规则始终在拒绝规则之前发生。 拒绝规则总是发生在允许规则之前。 这导致用户感到困惑,因为它隐式地对规则进行了重新排序。 这也使得不可能添加全面的rich规则来拒绝流量。

因此firewalld的rich规则执行逻辑如下:

1.日志规则
2.drop/reject规则
3.accept规则

实验验证:

允许192.168.10.102的主机通过ssh访问服务器

firewall-cmd --zone=external --add-rich-rule="rule \ 
family="ipv4" \ 
source address="192.168.10.102" \ 
service name="ssh" \ 
log prefix=\"ssh connect from:\" \
level="notice" \
accept" 

拒绝192.168.10.0/24的其他主机通过ssh访问服务器

firewall-cmd  --zone=external --add-rich-rule="rule \
family="ipv4" \ 
source address="192.168.10.0/24" \ 
service name="ssh" \ 
log prefix=\"ssh reject from:\" \
level="notice" \
drop" 

实验的重点:就是要验证第一条rich的规则是否会被优先执行,还是第二条drop规则会先于第一条accept规则执行?

我们在192.168.10.102的主机上测试一下能否ssh到服务器?结果ssh请求无响应且没有错误提示返回,这里至少已经证实

即便在规则列表中accept规则位置先于drop规则,但是drop规则总是会优先于accept规则被匹配Rich规则的priority字段

二、Rich规则的priority字段

新版的firewalld添加了新的priority字段。它可以是-32768到32767之间的任何数字,其中数字越小,优先级越高。此范围足够大,以允许从脚本或其他实体自动生成规则。

那么就非常简单:只需在你想优先执行的rich规则中给priority字段定义一个足够小的负数,就能确保能优先于其他drop/reject规则被firewalld匹配。

firewall-cmd --zone=external --add-rich-rule="rule \ 
priority="-100" \
family="ipv4" \ 
source address="192.168.10.102" \ 
service name="ssh" \ 
log prefix=\"ssh connect from:\" \
level="notice" \
accept" 

此时,accept的规则优先于其他drop/reject规则被匹配,这正是我们所希望的

按照我上面的实验步骤,应该没什么问题,能达到预期实验的目地,结束本篇之前,要记得将上面的运行时配置转化为持久配置,执行下面命令

firewall-cmd --runtime-to-permanent

目前,rich规则的定义,至少来说已经解说地很清楚了,但rich规则的语法是非常复杂让人难以理解。