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的管理工具,并且
-
drop(丢弃),任何接受的网络数据包都被丢弃,没有任何回复。仅能有发送出去的网路连接。
-
block(限制),任何接收的网络连接都被IPv4的icmp-host-prohibited信息和IPv6的icmp6-adm-prohibited信息所拒绝。
-
public(公共),在公共区域内使用,不能相信网络内的其他计算机不会对你的计算机造成危害,只能接收经过选取的连接。
-
external(外部),特别是为路由器启动了伪装功能的外部网。你不能相信来自网络的其他计算机,不能相信他们不会对你的计算机造成危害,只能接收经过选择的连接。
-
dmz(非军事区),用于你的非军事区内的电脑,此区域内可公开访问,可以有限的进入你的内部网络,仅仅接收经过选择的连接。
-
work(工作),用于工作区。你可以基本相信网络内的其他计算机不会危害到你。仅仅接收经过选择的连接。
-
home(家庭),用于家庭网络。你可以基本相信网络内的其他计算机不会危害到你。仅仅接收经过选择的连接。
-
internal(内部),用于内部网络。你可以基本相信网络内的其他计算机不会危害到你。仅仅接收经过选择的连接。
-
首先,我们来看看一个规则集中都包含了什么:
[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 按下列顺序处理一个包:
- 相应的源区域。可以存在零个或一个这样的区域。如果这个包满足一个富规则rich rule、服务是白名单中的、或者目标没有定义,那么源区域处理这个包,并且在这里结束。否则,向上传递这个包。
- 相应的接口区域。肯定有一个这样的区域。如果接口处理这个包,那么到这里结束。否则,向上传递这个包。
- 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
区域的 mdns
、samba-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 ~]#
原因:
原因: