Linux防火墙由netfilter处理,这是一个内核级框架。十多年来,iptables为netfilter提供了用户级抽象层。iptables使数据包接受一系列规则,并且如果规则的IP /端口/协议组合与数据包相匹配,则应用规则,数据包被接受,拒绝或丢弃。
Firewalld是netfilter的一个新的用户级抽象层。不幸的是,由于缺乏描述多区域配置的文档,其功能和灵活性受到了低估。本文提供了一些示例来纠正这种情况。
Firewalld默认Zone及其默认Target
firewalld |
|
Zone Name | Zone target |
block | REJECT |
dmz | default |
drop | DROP |
external | default |
home | default |
internal | default |
public | default |
trusted | ACCEPT |
work | default |
Zone
firewalld中最高层的组织是区域。如果一个数据包与该区域的相关network interface or IP/mask source相匹配,则该数据包与该区域匹配,按照该区域规则处理。
## 获取所有可用区域
# firewall-cmd --get-zones
## 获取激活的区域
# firewall-cmd --get-active-zones
public (active) 表示公共区域是默认区域(interfacesdefault to it when they come up),并且它是活动的,因为它至少有一个与之关联的接口或源。
interfaces: eno1 eno2 列出与区域相关的接口。
sources:列出了该区域的来源。现在没有,但如果有的话,它们的格式为xxx.xxx.xxx.xxx/xx。
services: dhcpv6-client ssh列出了通过防火墙允许的服务。你可以通过执行命令:firewall-cmd --get-services,得到一份完整的Firewalld定义服务列表,以方便我们在这里配置。如果没有找到对应的服务,只能使用下面的ports进行配置。
ports:80/tcp列出允许通过防火墙的端口目的地。有些服务并没有在firewalld中定义。
masquerade: no表示该区域的IP伪装功能已被禁用。如果启用,这将允许IP转发,您的计算机充当路由器。
forward-ports: 列出转发的端口。
icmp-blocks: 被阻止的icmp流量的黑名单。
rich rules: 高级配置,首先在区域中进行处理。
default 是该区域的目标,通过上面匹配,到最后数据包仍然没有被处理,按照default进行处理:按照优先级pass on。
## 设置某服务的有效时间:The timeout option takes time values in seconds(s), minutes (m) or hours (h).
# firewall-cmd --zone=public --add-service=ssh--timeout=5m
Targets
当Packages在Zone中通过source ip地址或者interface被匹配,而又没有被处理(例如:匹配到service白名单、端口白名单处理动作是ACCEPT),那么按照Target定义的动作处理相应的数据包。
ACCEPT: accept the packet.
REJECT: reject the packet, returning a rejectreply.
DROP: drop the packet, returning no reply.
default: don't do anything. The zone washes itshands of the problem, and kicks it ""upstairs"".
default:不做任何事情,处理完手头问题,上报给上层Zone。
Zone的类型及其优先级
Zone Type | Zone Precedence | Zone description |
interface zones | 低 | 域中interfaces有值 |
source zones | 高 | 域中sources有值 |
mixed zones | 高 | 域中interfaces和sources均有值 |
Firewalld handles a packet in the following order:
The source zone. Zero or one such zones may exist.If the source zone deals with the packet because the service is whitelisted(the packet satisfies a rich rule), or thetarget is not default, we end here. Otherwise, we pass the packet on.
1、源Zone,0个或者多个 源Zone存在。如果在源Zone中数据包被白名单化(如:数据包满足rich rule),或者黑名单化(如:icmp-blocks),或者Target不是default,数据包均会在本Zone中被处理,否则,将数据包发给下一个Zone。
The interface zone. Exactly one such zone willalways exist. If the interface zone deals with the packet, we end here.Otherwise, we pass the packet on.
2、接口Zone,至少1个接口Zone总是存在的。如果数据包在此域被处理,流程终止。否则,数据包发送给firewalld default action。
The firewalld default action. Accept icmp packetsand reject everything else.
3、firewalld默认动作。
总而言之:数据包先匹配源地址,在源地址域中,如果匹配,如匹配rich roles,如果匹配到则按照该role处理;如果没有匹配rich roles,则按照该域的target处理;如果没有匹配源地址域,那么去匹配接口域,接口域中也可以配置rich roles,那么就按照target处理。都没处理按照默认处理走。
调试
Firewalld的设置并没有iptables平铺的格式那么直观,如果出现问题,可以通过
# iptables -S
将firewalld配置转化为iptables格式;这样也有利于理解firewalld的工作模式。
新的Chain以-N开头被首先声明出来;其余的规则以-A开头。
已建立的连接和本地流量是被允许的。
进来的数据包,首先进入INPUT_ZONES_SOURCE chain;如果源地址ZONE存在,那么转发到相应的ZONE。此后,转发给NPUT_ZONES chain,在这里被路由到一个interfaceZONE
## 声明新的Chain
-N INPUT_ZONES
-N INPUT_ZONES_SOURCE
## ESTABLISHED和 local的数据流量是ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED-j ACCEPT
-A INPUT -i lo -j ACCEPT
## 数据包先到INPUT_ZONES_SOURCE链流转
(因为INPUT_ZONES_SOURCE在INPUT_ZONES前面)
-A INPUT -j INPUT_ZONES_SOURCE
-A INPUT -j INPUT_ZONES
## 发送到IN_internal链,匹配IN_internal链规则
-A INPUT_ZONES_SOURCE -s 1.1.0.0/16 -g IN_internal
-A IN_internal_allow -p tcp -m tcp --dport 22 -mconntrack --ctstate NEW -j ACCEPT
## 如果源ZONE没匹配到,那么在INPUT_ZONES中流转
-A INPUT_ZONES -i ens192 -g IN_public
-A INPUT_ZONES -i ens160 -g IN_public
-A INPUT_ZONES -g IN_public
-A IN_public_allow -p tcp -m tcp --dport 22 -mconntrack --ctstate NEW -j ACCEPT
其他操作
## 添加rich rule
# firewall-cmd --permanent --zone=internal--add-rich-rule='rule protocol value="icmp" accept'
# firewall-cmd –reload
# firewall-cmd --permanent --zone=internal--add-rich-rule='rule /
family=ipv4 source address="1.1.1.0/8"service name="samba" accept'
# firewall-cmd --reload
## 修改public的target为DROP
# firewall-cmd --permanent --zone=public--set-target=DROP