RHCE9学习指南 第24章防火墙
24.1 了解firewalld
在RHEL9中用的防火墙是firewalld,在firewalld中又涉及zone的概念。首先来了解一下什么是zone。
如在进地铁或高铁时需要安检,安检有不同的入口,如图24-1所示。
图24-1 以安检入口举例
不同的入口严格度不一样,有的入口大包小包都要检测,有的入口只要检测大包即可,背包或单肩包就不用检测了,有的入口是绿色通道不用检测直接通过。这里不同的安检入口指定了不同的规则。
同理,firewalld中的zone我们就理解为如上的安检入口,不同的zone中制定不同的规则。某网卡要和某一个zone进行关联,如图24-2所示,ens160和zone2进行关联,这样从网卡ens160进来的数据包都要使用zone2中的过滤规则。
图24-2 了解firewalld中的zone
网卡是不能同时和多个zone关联的,最多只能和一个zone关联。如果网卡没有和任何的zone关联,则使用默认的zone中的规则。
24.2 firewalld的基本配置
查看系统中有多少个zone,命令如下。
[root@server ~]# firewall-cmd --get-zones
block dmz drop external home internal libvirt nm-shared public trusted work
[root@server ~]#
在这许多的zone中,其中block这个zone中会拒绝所有的数据包通过,trusted允许所有的数据包通过。所以,如果把网卡和trusted关联,则来自这张网卡的数据包都能通过。
查看系统默认的zone,命令如下。
[root@server ~]# firewall-cmd --get-default-zone
public
[root@server ~]#
这里可以看到,默认的zone是public。
把默认的zone修改为trusted,命令如下。
[root@server ~]# firewall-cmd --set-default-zone=trusted
success
[root@server ~]# firewall-cmd --get-default-zone
trusted
[root@server ~]#
再次把默认的zone改成public,命令如下。
[root@server ~]# firewall-cmd --set-default-zone=public
success
[root@server ~]#
查看网卡ens160和哪个zone关联的,命令如下。
[root@server ~]# firewall-cmd --get-zone-of-interface=ens160
public
[root@server ~]#
这里可以看到,网卡ens160是和public关联的。
把网卡加入某个zone命令如下。firewall-cmd --add-interface=网卡名 --zone=zone名
如果不指定zone名则是默认的zone。
把ens160和home这个zone关联,命令如下。
[root@server ~]# firewall-cmd --add-interface=ens160 --zone=home
Error: ZONE_CONFLICT: 'ens160' already bound to a zone
[root@server ~]#
一张网卡只能在一个zone中,这里可以看到ens32已经属于一个zone了所以冲突。
可以先接口从public中删除,然后重新添加,这里把ens160从public中删除,命令如下。
[root@server ~]# firewall-cmd --remove-interface=ens160 --zone=public
success
[root@server ~]# firewall-cmd --get-zone-of-interface=ens160
no zone
[root@server ~]#
这样ens160不属于任何的zone了,如果不属于任何的zone,则使用默认zone中的规则。
然后把ens160加入home中,命令如下。
[root@server ~]# firewall-cmd --add-interface=ens160 --zone=home
success
[root@server ~]# firewall-cmd --get-zone-of-interface=ens160
home
[root@server ~]#
以后ens160会使用home中的规则,不再使用public中的规则。先从zone中删除,然后再添加到其他的zone中这个过程可以用一条命令替换,命令如下。
[root@server ~]# firewall-cmd --change-interface=ens160 --zone=public
success
[root@server ~]#
这句话的意思是把ens160切换到public这个zone中,如果不指定zone,则是默认的zone,命令如下。
[root@server ~]# firewall-cmd --get-zone-of-interface=ens160
public
[root@server ~]#
后面练习均是在public中做。
24.3 配置firewalld的规则
网卡在哪个zone中就使用那个zone中的规则,如果网卡不属于任何的zone,则使用默认zone中的规则。
一个zone中的规则可以通过如下命令查看。firewall-cmd --list-all--zone=zone名
如果不指定zone则是默认的zone。
现在查看public这个zone中的规则,命令如下。
[root@server ~]# firewall-cmd --list-all --zone=public
public (active)
target: default
icmp-block-inversion: no
interfaces: ens160
sources:
services: cockpit dhcpv6-client ssh
ports: 123/udp 323/udp 20-21/tcp 10010-10020/tcp
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
[root@server ~]#
因为默认的zone就是public,所以这里即使不加 --zone=public选项,显示的也是public这个zone中的规则。
我们看一下最常用的一些设置。
24.3.1 icmp-blocks
平时测试网络通或不通是用ping进行测试的,使用的是icmp协议,如图24-3所示。
图24-3 ping的过程
icmp有很多类型的数据包,ping的时候用的是以下两种。
(1)echo-request:我ping对方时发出去的包。
(2)echo-reply:对方回应我的包。
一共有多少种类型的icmp包,可以通过“firewall-cmd --get-icmptypes”查看。
在server上执行tcpdump命令进行抓包,命令如下。
[root@server ~]# tcpdump -i ens160 icmp
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens160, link-type EN10MB (Ethernet), capture size 262144 bytes
(此处等待数据包进来)
在server2上ping server的IP两次,命令如下。
[root@server2 ~]# ping 192.168.26.101 -c2
PING 192.168.26.101 (192.168.26.101) 56(84) bytes of data.
64 bytes from 192.168.26.101: icmp_seq=1 ttl=64 time=0.701 ms
64 bytes from 192.168.26.101: icmp_seq=2 ttl=64 time=0.427 ms
--- 192.168.26.101 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1006ms
rtt min/avg/max/mdev = 0.427/0.564/0.701/0.137 ms
[root@server2 ~]#
然后到server上查看,命令如下。
[root@server ~]# tcpdump -i ens160 icmp
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens160, link-type EN10MB (Ethernet), capture size 262144 bytes
... 192.168.26.102 > server.rhce.cc: ICMP echo request, id 21630, seq 1, length 64
... server.rhce.cc > 192.168.26.102: ICMP echo reply, id 21630, seq 1, length 64
... 192.168.26.102 > server.rhce.cc: ICMP echo request, id 21630, seq 2, length 64
... server.rhce.cc > 192.168.26.102: ICMP echo reply, id 21630, seq 2, length 64
^C这里按【Ctrl+C】组合键
4 packets captured
5 packets received by filter
0 packets dropped by kernel
[root@server ~]#
这里server2往server发送了两个echo-request的包,server均回应了echo reply包。
在server上用防火墙设置拒绝别人发过来的echo-request的包,命令如下。
[root@server ~]# firewall-cmd --add-icmp-block=echo-request
success
[root@server ~]# firewall-cmd --list-all
public (active)
...输出...
icmp-blocks: echo-request
rich rules:
[root@server ~]#
此时,server就不再接收别人发来的echo-requst包了,然后到server2再次ping,命令如下。
[root@server2 ~]# ping 192.168.26.101 -c2
PING 192.168.26.101 (192.168.26.101) 56(84) bytes of data.
From 192.168.26.101 icmp_seq=1 Packet filtered
From 192.168.26.101 icmp_seq=2 Packet filtered
--- 192.168.26.101 ping statistics ---
2 packets transmitted, 0 received, +2 errors, 100% packet loss, time 1016ms
[root@server2 ~]#
可以看到,在server2上已经ping不通server了。
如果要想继续ping操作,就取消对应的设置,命令如下。
[root@server ~]# firewall-cmd --remove-icmp-block=echo-request
success
[root@server ~]#
24.3.2 services
两台主机通信必须要使用某个协议,例如,浏览器访问网站用的是http,远程登录到Linux服务器用的是ssh协议等。
默认情况下,public这个zone中只允许很少的服务通过,如下所示。
[root@server ~]# firewall-cmd --list-all
public (active)
...输出...
services: cockpit dhcpv6-client ssh
...输出...
[root@server ~]#
可以看到,这里并有允许http通过,如果要查看防火墙是否开放了某个协议,也可以通过如下语法进行查看。firewall-cmd --query-service=服务名
要获取系统所支持的所有服务,可以通过如下命令进行查看。firewall-cmd --get-services
再次验证http协议是否被firewall允许,命令如下。
[root@server ~]# firewall-cmd --query-service=http
no
[root@server ~]#
在server上请通过yum install httpd -y 安装httpd包,启动服务并写一些测试数据,命令如下。
[root@server ~]# systemctl start httpd
[root@server ~]# echo "hello rhce" > /var/www/html/index.html
[root@server ~]# cat /var/www/html/index.html
hello rhce
[root@server ~]#
然后在宿主机上用浏览器访问server,如图24-4所示。
图24-4 测试宿主机能不能访问
可以看到,现在根本访问不了,这是因为server上的防火墙并不允许http协议的数据包通过,然后在防火墙中开放http协议,命令如下。
[root@server ~]# firewall-cmd --add-service=http
success
[root@server ~]# firewall-cmd --query-service=http
yes
[root@server ~]#
然后再次打开浏览器验证,结果如图24-5所示。
图24-5 放行之后就能访问到了
此时可以正常打开了。如果要从防火墙中把此服务删除,则可用remove-service,命令如下。
[root@server ~]# firewall-cmd --remove-service=http
success
[root@server ~]# firewall-cmd --query-service=http
no
[root@server ~]#
此时浏览器中是访问不了192.168.26.101的了。
24.3.3 ports
前面介绍了通过对服务进行过滤与放行,这些服务使用的都是标准端口,例如,http对应的是端口80,ssh对应的是22等。
但有时如果服务使用的是一个非标准端口,例如,把服务httpd的端口更改为8080。如果在防火墙中只是放行http这个服务,本质就是放行了端口80,此时用户肯定是访问不到web服务的,因为只能通过端口8080才能访问到web服务。下面做一下这个实验。
先临时关闭selinux,命令如下。
[root@server ~]# setenforce 0
[root@server ~]# getenforce
Permissive
[root@server ~]#
确保selinux是处在Permissive模式的。
敲如下命令把httpd的端口替换为8080,并重启httpd服务,命令如下。
[root@server ~]# sed -i '/^Listen/cListen 8080' /etc/httpd/conf/httpd.conf
[root@server ~]# systemctl restart httpd
[root@server ~]#
首先在防火墙中放行http,命令如下。
[root@server ~]# firewall-cmd --add-service=http
success
[root@server ~]#
在浏览器中访问192.168.26.101:8080,如图24-6所示。
图24-6 在宿主机中访问端口8080
可以看到,访问失败,因为放行http也只是允许端口80端口而非8080端口。
把http服务从防火墙删除,命令如下。
[root@server ~]# firewall-cmd --remove-service=http
success
[root@server ~]#
下面开始放行端口,常用的语句如下。
firewall-cmd --query-port=N/协议:查询是否开放了N端口。
firewall-cmd --add-port=N/协议:开放N端口。
firewall-cmd --remove-port=N/协议:删除N端口。
这里协议包括TCP/UDP等。
在防火墙中添加端口,也可以添加一个范围,例如,要在防火墙中开放1000~2000范围的端口,可以用如下命令。firewall-cmd --add-port=1000-2000/tcp
这里“-”表示到的意思。
下面把端口8080放行,命令如下。
[root@server ~]# firewall-cmd --add-port=8080/tcp
success
[root@server ~]# firewall-cmd --query-port=8080/tcp
yes
[root@server ~]#
然后再次在浏览器中访问,结果如图24-7所示。
图24-7 防火墙放行之后就能访问了
现在已经可以正常访问了。
在防火墙中删除此端口,命令如下。
[root@server ~]# firewall-cmd --remove-port=8080/tcp
success
[root@server ~]# firewall-cmd --query-port=8080/tcp
no
[root@server ~]#
下面把环境还原,再次开启selinux,确保状态为Enforcing模式,命令如下。
[root@server ~]# setenforce 1
[root@server ~]# getenforce
Enforcing
[root@server ~]#
再次把httpd的端口改为80,并重启服务,命令如下。
[root@server ~]# sed -i '/^Listen/cListen 80' /etc/httpd/conf/httpd.conf
[root@server ~]# systemctl restart httpd
[root@server ~]#
24.4 富规则
前面不管是对端口放行还是对服务放行,会遇到一个问题就是,如果允许则是允许所有的客户端,如果拒绝,则是拒绝所有的客户端,有些一刀切的感觉。
有时需要设置允许特定的客户端才能访问,其他客户端不能访问,此时就需要使用到富规则。
富规则可以对服务进行限制,也可以对端口进行限制。
放行服务的语法如下。
firewall-cmd --add-rich-rule='rule family=ipv4 source address=源网段 service name=服务名 accept'
这里用单引号或双引号均可,先查看现在是否有富规则。
[root@server ~]# firewall-cmd --list-rich-rules
[root@server ~]#
这里现在还没有任何的富规则,下面开始创建富规则。
练习1:
允许192.168.26.1访问本机的http服务,其他客户端不允许。
先确保在防火墙的services中没有添加http,否则所有的客户端都允许了。
[root@server ~]# firewall-cmd --query-service=http
no
[root@server ~]#
现在确定在service中是没有添加http的,所以现在所有客户端都是被拒绝的。下面开始添加富规则,命令如下。
[root@server ~]# firewall-cmd --add-rich-rule="rule family=ipv4 source address=192.168.26.1 service name=http accept"
success
[root@server ~]#
在192.168.26.1(即笔记本电脑)访问,如图24-8所示。
图24-8 宿主机能访问
可以看到,现在是正常的,然后在192.168.26.102(server2机器)上访问,结果如图24-9所示。
图24-9 在server上访问不了
可以看到,访问不了。查看现有富规则,命令如下。
[root@server ~]# firewall-cmd --list-rich-rules
rule family="ipv4" source address="192.168.26.1" service name="http" accept
[root@server ~]#
富规则的命令只要把添加时的add换成remove即可,命令如下。
[root@server ~]# firewall-cmd --remove-rich-rule="rule family=ipv4 source address=192.168.26.1 service name=http accept"
success
[root@server ~]#
放行端口的语法如下。
firewall-cmd --add-rich-rule 'rule family=ipv4 source address=源网段 port port=N protocol=协议 accept'
这里可以端口也可以写一个范围,如下所示。
firewall-cmd --add-rich-rule 'rule family=ipv4 source address=源网段 port port=M-N protocol=协议 accept'
这里是M-N的意思是从M端口到N端口。
练习2:
允许192.168.26.101访问本机的80端口。
[root@server ~]# firewall-cmd --add-rich-rule="rule family=ipv4 source address=192.168.26.102 port port=80 protocol=tcp accept"
success
[root@server ~]# firewall-cmd --list-rich-rules
rule family="ipv4" source address="192.168.26.102" port port="80" protocol="tcp" accept
[root@server ~]#
然后在192.168.26.1(即笔记本电脑)访问试试,如图24-10所示。
图24-10 在宿主机上访问不了
然后到机器192.168.26.102(workstation机器)上通过浏览器进行访问192.168.26.101,结果如图24-11所示。
图24-11 在server2上能访问
可以看到,能正常访问。
此时,防火墙的规则如下所示。
[root@server ~]# firewall-cmd --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: ens160
sources:
services: cockpit dhcpv6-client ssh
ports: 123/udp 323/udp 20-21/tcp 10010-10020/tcp
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
rule family="ipv4" source address="192.168.26.102" port port="80" protocol="tcp" accept
[root@server ~]#
删除此规则,命令如下。
[root@server ~****]# firewall-cmd --remove-rich-rule="rule family=ipv4 source address=192.168.26.102 port port=80 protocol=tcp accept"
success
[root@server ~]#
注意:前面讲的对这些规则的管理(包括服务、端口、富规则等),都只是临时生效,如果想希望能永久生效需要加上--permanent选项。
不加--permanent 当前生效,重启系统或firewalld之后不再生效。
加--permanent选项,当前不生效,重启系统或firewalld之后生效。
所以,写的时候可以写两条,一条不包含--permanent,一条包含--permanent的。
作业
作业题在server2上完成。
作业1:查看当前firewalld默认的zone。
作业2:把firewalld默认的zone改为home。
作业3:查看网卡ens160绑定到哪个zone的。
作业4:再次把firewalld默认的zone改为public。
作业5:设置只允许192.168.26.0/24网段的主机访问server2的端口80,其他客户端都不允许访问。
作业6:设置除192.168.26.0/24网段的主机外,其他客户端都可以访问server2的端口808端口。