firewall详解与操作

firewall是什么:

  先声明一点,不知道iptables的,可以先去了解下。

  firewalld的底层是通过iptables来实现的,,firewalld 和 iptables 都不是防火墙,它们只是防火墙的管理程序,真正的防火墙是内核的netfilter。CentOs 6 中使用iptables来管理防火墙,到了CentOs 7 默认使用firewalld来管理防火墙, firewalld 的底层还是调用 iptables 的,firewalld在iptables的基础上加了许多很好用的功能。总的来说,firewalld 是系统服务,有守护进程。iptables 也只是一个工具,不是服务。firewall的包过滤机制也是通过iptables来实现的,

  firewalld 的设计者认识到大多数的 iptables 使用案例仅涉及到几个单播源 IP,仅让每个符合白名单的服务通过,而其它的会被拒绝。这种模式的好处是,firewalld 可以通过定义的源 IP 和/或网络接口将入站流量分类到不同区域zone。每个区域基于指定的准则按自己配置去通过或拒绝包。

firewall对比iptables有什么变化:

firewall基于iptables 进行语法简化。firewalld 通过使用服务名而不是它的端口和协议去指定服务,使它更易于使用,例如,是使用 samba 而不是使用 UDP 端口 137 和 138 和 TCP 端口 139 和 445。它进一步简化语法,消除了 iptables 中对语句顺序的依赖。可以认为firewall就是iptables的管理工具,并且firewall中加入了防火墙的“zone”的概念 ,zone可以理解为 firewalld 的单位、规则集:

默认的规则集有:

  • drop(丢弃),任何接受的网络数据包都被丢弃,没有任何回复。仅能有发送出去的网路连接。

  • block(限制),任何接收的网络连接都被IPv4的icmp-host-prohibited信息和IPv6的icmp6-adm-prohibited信息所拒绝。

  • public(公共),在公共区域内使用,不能相信网络内的其他计算机不会对你的计算机造成危害,只能接收经过选取的连接。  

  • external(外部),特别是为路由器启动了伪装功能的外部网。你不能相信来自网络的其他计算机,不能相信他们不会对你的计算机造成危害,只能接收经过选择的连接。

  • dmz(非军事区),用于你的非军事区内的电脑,此区域内可公开访问,可以有限的进入你的内部网络,仅仅接收经过选择的连接。

  • work(工作),用于工作区。你可以基本相信网络内的其他计算机不会危害到你。仅仅接收经过选择的连接。

  • home(家庭),用于家庭网络。你可以基本相信网络内的其他计算机不会危害到你。仅仅接收经过选择的连接。

  • internal(内部),用于内部网络。你可以基本相信网络内的其他计算机不会危害到你。仅仅接收经过选择的连接。

  • trusted(信任),可接受所有的网络连接。

firewall的默认zone是public,默认只开放ssh服务和ipv6-client服务

firewall规则集使用详解:

首先,我们来看看一个规则集中都包含了什么:

[root@localhost opt]# firewall-cmd --zone=public --list-all
public
target: default
icmp-block-inversion: no
interfaces: 
sources: 
services: ssh dhcpv6-client
ports: 
protocols: 
masquerade: no
forward-ports: 
source-ports: 
icmp-blocks: 
rich rules:

public  表示 public 区域
target: default

默认可以取四个值:default、ACCEPT、%%REJECT%%、DROP

  • ACCEPT:通过这个包。
  • %%REJECT%%:拒绝这个包,并返回一个拒绝的回复。
  • DROP:丢弃这个包,不回复任何信息。
  • default:不做任何事情。

icmp-block-inversion: no
interfaces:   划归本规则集管理的硬件设备,如网卡等
sources:   信任区域的源ip
services: ssh dhcpv6-client  开放的服务
ports:   开放的端口
protocols: 
masquerade:   no表示这个区域是否允许 IP 伪装。如果允许,它将允许 IP 转发,它可以让你的计算机作为一个路由器。
forward-ports:   列出转发的端口。
source-ports:   信任区域的源ip及端口
icmp-blocks:   阻塞的 icmp 流量的黑名单。
rich rules:  在一个区域中优先处理的高级配置。

firewall的使用:

活动区域中扮演两个不同的角色。关联接口行为的区域作为接口区域,并且,关联源行为的区域作为源区域(一个区域能够扮演两个角色)。firewalld 按下列顺序处理一个包:

  1. 相应的源区域。可以存在零个或一个这样的区域。如果这个包满足一个富规则rich rule、服务是白名单中的、或者目标没有定义,那么源区域处理这个包,并且在这里结束。否则,向上传递这个包。
  2. 相应的接口区域。肯定有一个这样的区域。如果接口处理这个包,那么到这里结束。否则,向上传递这个包。
  3. firewalld 默认动作。接受 icmp 包并拒绝其它的一切。

这里的关键信息是,源区域优先于接口区域。因此,对于多区域的 firewalld 配置的一般设计模式是,创建一个优先源区域来允许指定的 IP 对系统服务的提升访问,并在一个限制性接口区域限制其它访问。

 

一个简单的多区域示例

为演示优先权,让我们在 public 区域中将 http 替换成 ssh,并且为我们喜欢的 IP 地址,如 1.1.1.1,设置一个默认的 internal 区域。以下的命令完成这个任务:

# firewall-cmd --permanent --zone=public--remove-service=ssh
# firewall-cmd --permanent --zone=public--add-service=http
# firewall-cmd --permanent --zone=internal --add-source=1.1.1.1
# firewall-cmd --reload

 

这些命令的结果是生成如下的配置:

# firewall-cmd --zone=public--list-all

public(default, active)

interfaces: eno1 eno2

sources:

services: dhcpv6-client http

ports:

masquerade:no

forward-ports:

icmp-blocks:

rich rules:

# firewall-cmd --permanent --zone=public--get-target

default

# firewall-cmd --zone=internal --list-all

internal (active)

interfaces:

sources:1.1.1.1

services: dhcpv6-client mdns samba-client ssh

ports:

masquerade:no

forward-ports:

icmp-blocks:

rich rules:

# firewall-cmd --permanent --zone=internal --get-target

default

 

 

在上面的配置中,如果有人尝试从 1.1.1.1 去 ssh,这个请求将会成功,因为这个源区域(internal)被首先应用,并且它允许 ssh 访问。

如果有人尝试从其它的地址,如 2.2.2.2,去访问 ssh,它不是这个源区域的,因为和这个源区域不匹配。因此,这个请求被直接转到接口区域(public),它没有显式处理 ssh,因为,public 的目标是 default,这个请求被传递到默认动作,它将被拒绝。

如果 1.1.1.1 尝试进行 http 访问会怎样?源区域(internal)不允许它,但是,目标是 default,因此,请求将传递到接口区域(public),它被允许访问。

现在,让我们假设有人从 3.3.3.3 拖你的网站。要限制从那个 IP 的访问,简单地增加它到预定义的 drop 区域,正如其名,它将丢弃所有的连接:

# firewall-cmd --permanent --zone=drop --add-source=3.3.3.3

# firewall-cmd --reload

 

 

下一次 3.3.3.3 尝试去访问你的网站,firewalld 将转发请求到源区域(drop)。因为目标是 DROP,请求将被拒绝,并且它不会被转发到接口区域(public)。

 

一个实用的多区域示例

假设你为你的组织的一台服务器配置防火墙。你希望允许全世界使用 http 和 https 的访问,你的组织(1.1.0.0/16)和工作组(1.1.1.0/8)使用 ssh 访问,并且你的工作组可以访问 samba 服务。使用 firewalld 中的区域,你可以用一个很直观的方式去实现这个配置。

public 这个命名,它的逻辑似乎是把全世界访问指定为公共区域,而 internal 区域用于为本地使用。从在 public 区域内设置使用 http 和 https 替换 dhcpv6-client 和 ssh 服务来开始:

# firewall-cmd --permanent --zone=public--remove-service=dhcpv6-client
# firewall-cmd --permanent --zone=public--remove-service=ssh
# firewall-cmd --permanent --zone=public--add-service=http
# firewall-cmd --permanent --zone=public--add-service=https

 

然后,取消 internal 区域的 mdnssamba-client 和 dhcpv6-client 服务(仅保留 ssh),并增加你的组织为源:

# firewall-cmd --permanent --zone=internal --remove-service=mdns
# firewall-cmd --permanent --zone=internal --remove-service=samba-client
# firewall-cmd --permanent --zone=internal --remove-service=dhcpv6-client
# firewall-cmd --permanent --zone=internal --add-source=1.1.0.0/16

 

为容纳你提升的 samba 的权限,增加一个富规则:

# 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

 

 

仅剩下少数的细节了。从一个 internal 区域以外的 IP 去尝试通过 ssh 到你的服务器,结果是回复一个拒绝的消息。它是 firewalld 默认的。更为安全的作法是去显示不活跃的 IP 行为并丢弃该连接。改变 public 区域的目标为 DROP,而不是 default 来实现它:

# firewall-cmd --permanent --zone=public--set-target=DROP
# firewall-cmd --reload

 

但是,等等,你不再可以 ping 了,甚至是从内部区域!并且 icmp (ping 使用的协议)并不在 firewalld 可以列入白名单的服务列表中。那是因为,icmp 是第 3 层的 IP 协议,它没有端口的概念,不像那些捆绑了端口的服务。在设置公共区域为 DROP 之前,ping 能够通过防火墙是因为你的 default 目标通过它到达防火墙的默认动作(default),即允许它通过。但现在它已经被删除了。

为恢复内部网络的 ping,使用一个富规则:

# firewall-cmd --permanent --zone=internal --add-rich-rule='rule protocol value="icmp" accept'
# firewall-cmd --reload

 

结果如下,这里是两个活动区域的配置:

# firewall-cmd --zone=public--list-all
public(default, active)
interfaces: eno1 eno2
sources:
services: http https
ports:
masquerade:no
forward-ports:
icmp-blocks:
rich rules:
# firewall-cmd --permanent --zone=public--get-target
DROP
# firewall-cmd --zone=internal --list-all
internal (active)
interfaces:
sources:1.1.0.0/16
services:ssh
ports:
masquerade:no
forward-ports:
icmp-blocks:
rich rules:
rule family=ipv4 source address="1.1.1.0/8" service name="samba" accept
rule protocol value="icmp" accept
# firewall-cmd --permanent --zone=internal --get-target
default

 

这个设置演示了一个三层嵌套的防火墙。最外层,public,是一个接口区域,包含全世界的访问。紧接着的一层,internal,是一个源区域,包含你的组织,它是 public 的一个子集。最后,一个富规则增加到最内层,包含了你的工作组,它是 internal 的一个子集。

这里的关键信息是,当在一个场景中可以突破到嵌套层,最外层将使用接口区域,接下来的将使用一个源区域,并且在源区域中额外使用富规则。

firewall常用的配置命令:

修改firewall防护等级
firewall-cmd --set-default-zone=block

查看当前zone的详细规则
firewall-cmd --list-all

放开22tcp端口
firewall-cmd --zone=public --add-port=22/tcp --permanent 限制ip的同时限制端口

firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.74.129" port protocol="tcp" port="28088" accept"
systemctl restart firewalld


添加单个ip为信任
firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='192.168.1.128' accept"
添加IP段为信任
firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='192.168.1.0/24' accept"
删除信任的ip段
firewall-cmd --permanent --remove-rich-rule="rule family='ipv4' source address='192.168.1.128' accept"

还有更多的富规则配置方法可以使用man firewalld.richlanguage来查看

在添加信任的时候,我们除了可以在当前的规则集中添加信任,还可以将需要信任的ip或ip段添加到更受信任的规则集中来实现

如:firewall-cmd --permanent --zone=trusted --add-source=192.168.74.1
效果与在当前zone中添加信任的效果是一样的,不过,最好在当前zone中添加富规则,这样的话,相对易管理

 这里仅列出几个常用的,更多的写法可以参考man,使用man firewalld.richlanguage来查看

在日常维护中,我们可能用的比较多的就是使用防火墙来对ip进行封禁等操作:

永久封禁单个ip的所有请求
firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='222.222.222.222' reject"

当然,我们平时或许不需要这样来做,因为这样做的话,还需要重启下firewall,firewall还提供timeout参数
即时生效,一定时间内对服务/ip等等的需求来进行开放或者封禁,比如我们可以写个自动化脚本,当发现有异常的连接时就可以添加一条rule将其相应的地址drop掉
而且还可以使用--timeout给设置个时间段,过时之后自动删除!所以--timeout和--permanent是不可以一起使用的。
如:firewall-cmd --add-service=ssh --timeout=10s

 

在实际的应用中发现:

1.安装并运行docker的主机,在打开firewall服务后,创建新容器会报如下错误,且旧容器的服务无法访问:

[root@localhost ~]# docker run -d -p 8080:80 --name="nginx-8080" docker.io/nginx
e0243020be093c04c3c6de16692839156655f489631077693f2cb3cdab7ebb4c
/usr/bin/docker-current: Error response from daemon: driver failed programming external connectivity on endpoint nginx-8080 (cebe58ea6558cf6a5eb2b39d7eae5520ef365538e1cc5f39f50ee83aacc8862b):  (iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 8080 -j DNAT --to-destination 172.17.0.3:80 ! -i docker0: iptables: No chain/target/match by that name.
 (exit status 1)).
[root@localhost ~]# 

解决办法是重启docker,重启后问题不再出现,且之后对每次对firewall服务的操作都会影响docker提供的服务,所以每次修改firewall之后都要重启docker

原因:

docker 使用iptables 来实现网络隔离。docker 默认使用 bridge 网桥模式来实现容器的网络。dockerd 会在 iptables 建立 docker 链来设置所有的规则。firewalld 启动或重启时,会将iptables的规则清空。导致docker启动新容器出错。旧容器服务无法访问,这时就需要重启docker。

2.测试发现,在限制192.168.74.129只能访问28088端口的同时,docker启动的其他端口的服务也可以被访问。而系统本地的服务正常被限制。

原因: docker会将一些映射规则自动的加载到iptables的DOCKER chain中。docker配置后的转发规则允许ip对这个docker下所有的服务端口进行访问。

 

posted @ 2020-06-30 14:12  小雨淅淅o0  阅读(1672)  评论(0编辑  收藏  举报