FirewallD 是 CentOS 7 服务器上默认可用的防火墙管理工具。基本上,它是 iptables 的封装,有图形配置工具firewall-config和命令行工具firewall-cmd。使用 iptables 服务,每次改动都要求刷新旧规则,并且从/etc/sysconfig/iptables读取新规则,然而 firewalld 只应用改动了的不同部分。

你真的理解防火墙吗

“防火墙”到底是什么

“防火墙”在我国最早是一种建筑,他又叫“封火墙”,其主要作用就是防火,因为那时候的建筑都是以木质结构为主,而且又非常密集,所以一个住宅着火就很容易传播到邻近的住宅,最初的防火墙就是在这种木质结构上涂上灰泥从而达到将火源隔断的目的。

网络中的防火墙来源于英文单词“firewall”的翻译,有时候也叫“网络防火墙”,不过这个词使用的并不是非常准确,这也就导致了对防火墙的普遍误解。

一想到防火墙大家的第一印象大概就是“隔离”,而且很多防火墙的资料也是这么介绍的,比如“将内网和外网进行隔离”、“将本地电脑和外部网络隔离”等等, 而且有时候还会配一张示意图,图中的防火墙就是一堵墙。以前学生在刚接触防火墙的时候心里就产生了一些疑问:既然防火墙已经将网络给隔断了,那么正常的通信是怎么进行的呢?是可以穿墙而过还是需要从其他通道进入呢?而且,当时学生甚至认为防火墙是用来防病毒的!

其实这一切的根源都来自对“防火墙”这个词本身的理解,实际上“网络防火墙”所起的并不是墙的作用,而是门卫的作用,如果按门卫去理解很多问题就迎刃而解了。

墙和门卫有哪些区别呢?这个问题虽然看起来有些可笑,不过对于理解网络防火墙还是有好处的。首先,墙所起的作用是隔断,无论谁都过不去,但是门卫就不一样 了,他的职能是检查和判断是否可以通过,只要符合条件就可以通过;其次,墙是死的,而门卫是活的,所以门卫还可以完成很多更加灵活的功能,比如有人要到A部门办事,但A部门搬到新的办公地址去了,这时门卫就可以告诉来人“你要去的部门换地方了,你到XXX去吧”,再比如有的人并不是要进去办事,只是想从里边穿过去抄近道,这种情况门 卫也能处理,但是墙是无论如何都办不到的。

理解防火墙本质的好处

可能有的读者会想:你这是在咬文嚼字,不就是个名词吗,理解不理解又有什么关系呢?会用不就行了?而且这么多年大家用的不也挺好的嘛!

其实并不是这样,我们以前如果要使用一个防火墙一般都是先看他都具有哪些功能,其中我们能用到哪些,怎么去用,然后再去找文档、找例子。。。。。。这其实是一 种被动的用法,因为这里我们其实是将防火墙当做一个新事物来学习和使用的(虽然我们一般刚开始都会将其理解为墙,但是慢慢会发现他跟墙的模型并不相符,所以就会将其当做一个新的事物来学习),但是理解了防火墙的本质就是门卫之后就不一样了,这时我们在使用防火墙的时候首先就要想:我要给我的服务器(或者自 己的PC)找个门卫,这个门卫需要做什么,然后再去找防火墙、查具体某功能的配置方法等等,这样就主动了。

不仅如此,在理解了其本质之后还有更大的好处,比如你想好了想找的“门卫”都需要有哪些功能之后又去找防火墙,然而却发现没有一款防火墙可以满足你的需求,这时候创新的机会就来了!也就是说通过防火墙和门卫功能的类别更容易设计出更加合理和易用的防火墙。我们来看个例子,比如一个门卫应该可以有按时间段放行的功能,但是现有防火墙却很少有这个功能,其实这个功能很多地方都是可以用得到的,比如每天要定时远程备份一下日志,那么只要在每天在特定的时间段开放端口就行了,而不需要一直开着,当然这种需求可以通过定时任务很容易地解决,不过只要从“门卫”的角度去思考,这样的需求还有很多。

真正好的创意其实是建立在扎实的基本功和对事物本质的深层次理解上的,而不是为了创新而创新出来的。

防火墙与杀毒软件

对于不了解防火墙的用户来说很多时候都分不清防火墙和杀毒软件之间的关系,而且往往会认为防火墙就是用来防病毒的,其实这是对防火墙非常大的误解,这也许跟大家心目中防火墙的“墙”、“保护”、“安全”等特征有关系,但是防火墙其实并不能防病毒。

我们上面说了,防火墙所起的是门卫的作用,不过这个门卫的逻辑非常简单,他主要关心的只有两样东西:1、从哪来的2、到哪里去,别的东西他一概不管(实际上还 有一些东西,比如是有预约的——TCP,还是无预约的——UDP,如果是有预约的还会判断是刚要去预约还是已经预约好了等内容)。而病毒是属于所携带的内容方面的东西,这部分并不是门卫的职责范围,而是应该有专人去负责,这就好像有人跟门卫说要去市场部,而且门卫所接到的指令是“所有到市场部的全部放行”,所以门卫就放行了,但是没想到此人是到市场部去吵架的!不过这就不是门卫应该管的事情,而是保安所应该管的事情了。其实不仅如此,我们的防火墙这个“门 卫”即使见到来的人拿着刀、拿着枪,也一样会放行,因为他只关心两样东西:从哪里来和到哪里去。

这种结构虽然“分工明确”,但是我们总会觉得这种门卫有点不近人情,至少算不上一个好门卫。那么能不能让他包含查毒、防毒甚至杀毒的功能呢?当然没问题,因为防火墙就是一个软件,软件都是人写的, 只要我们把相应的功能给加进去就可以了,非常简单!不过事实上并非如此,我们还拿门卫的例子来给大家解释,因为门卫需要负责检查所有进出的人,而要想知 道某个人是否携带了违禁物品(病毒)就需要对其进行收身,如果门卫要对所有人都进行收身,那么大家可以想象一下在上下班这种人流高峰期会是一种什么场景!而 且对于服务器来说一秒钟就可能会有成千上万的访问,所以哪怕每次检查多用一点点时间,累计起来就非常可怕了!而且以我们现在这种特征码的检查方式来说检查病毒所用的并不是“一点点时间”,所以这种想法虽然技术上没有问题,但是并不可行,至少从现在的技术来看是不可行的。

我们来总结一下,防火墙就像一个门卫,他的职能是负责让不让进出,而进去之后干什么那就不是他需要管的事情了,这应该是保安(杀毒软件)或者其他相关部门的人所需要负责的。

 

理解了防火墙的本质之后再来学习、使用防火墙就容易了,不过对于Centos7新的防火墙firewalld来说还有一个很多人没有真正理解透的概念,那就是zone,学生下节再给大家详细介绍。

Firewalld的结构

firewalld简介

Centos7中默认将原来的防火墙iptables升级为了firewalld,firewalld跟iptables比起来至少有两大好处:

1、firewalld可以动态修改单条规则,而不需要像iptables那样,在修改了规则后必须得全部刷新才可以生效;

2、firewalld在使用上要比iptables人性化很多,即使不明白“五张表五条链”而且对TCP/IP协议也不理解也可以实现大部分功能。

 

多知道点

iptables实际包含五张表

大部分iptables的资料都介绍说iptables包含四张表、五条链,不过实际上iptables还有第五张表——security表,但是这张表需要和selinux结合使用,而selinux虽然已经发布了十多年了但是直到现在还有很多人对他的理解不够透彻,甚至有很多人会将其关闭!

其实selinux的设计理念在安全上来说是非常优秀的,而且理解了其设计理念之后再去使用也没那么复杂,只不过其内置的规则是非常复杂的,等有机会学生专门给大家介绍一下selinux,现在还回到iptables的五张表,他们分别是filter、nat、mangle、raw和security。

filter表就是我们最常使用的过滤表;nat表主要用于数据包转发,比如局域网的电脑如果想连接互联网,那么就可以使用nat给转发一下;mangle表的规则可以对数据包进行修改,比如修改ttl值等;raw表主要是为了提高效率使用的,raw本身的含义是指“原生的”、“未经过加工的”,符合raw表所对应规则的数据包将会跳过一些检查,这样就可以提高效率,当然,raw表的优先级也是最高的;security是跟selinux相关的MAC模式的安全过滤。

当然,这些内容大家了解一下就行,即使不理解也可以使用将firewalld使用的很好。

 

firewalld和iptables的关系

firewalld自身并不具备防火墙的功能,而是和iptables一样需要通过内核的netfilter来实现,也就是说firewalld和iptables一样,他们的作用都是用于维护规则,而真正使用规则干活的是内核的netfilter,只不过firewalld和iptables的结构以及使用方法不一样罢了。

 

  • 规则生效的方式不同:使用 iptables service,每一个单独更改意味着清除所有旧有的规则和从 /etc/sysconfig/iptables里读取所有新的规则(静态防火墙),然而使用 firewalld 时却不会再清除所有规则,仅仅运行与原先不同的新的规则。因此,firewalld 可以在运行时改变设置而不丢失现行连接(动态防火墙)。

防火墙 docker重启 防火墙重启是什么意思_xml

从上图可以看到,iptables服务和firewalld都是通过iptables命令与内核的netfilter进行交互的。在centos7中,我们仍然可以使用iptables命令来管理我们的防火墙。唯一不同的是当我们重启服务器或重启firewalld时,iptables命令管理的规则不会自动加载,反而会被firewalld的规则代替。

 

firewalld的结构

我们这里所说的结构并不是firewalld软件的结构,而是配置文件的结构。

在具体介绍firewalld配置文件结构之前学生先来给大家介绍一下firewalld的配置模式,firewalld的配置模式设计的非常巧妙,而且这种设计思路也非常值得我们借鉴和学习。

firewalld的配置模式

firewalld的配置文件以xml格式为主(主配置文件firewalld.conf例外),他们有两个存储位置

/etc/firewalld/
/usr/lib/firewalld/

使用时的规则是这样的:当需要一个文件时firewalld会首先到第一个目录中去查找,如果可以找到,那么就直接使用,否则会继续到第二个目录中查找。换而言之,/etc/firewalld/中的配置会覆盖/usr/lib/firewalld/中的配置。

 

firewalld的这种配置文件结构的主要作用是这样的:在第二个目录中存放的是firewalld给提供的通用配置文件,如果我们想修改配置,那么可以copy一份到第一个目录中,然后再进行修改。这么做有两个好处:首先我们日后可以非常清晰地看到都有哪些文件是我们自己创建或者修改过的,其次,如果想恢复firewalld给提供的默认配置,只需要将自己在第一个目录中的配置文件删除即可,非常简单,而不需要像其他很多软件那样在修改之前还得先备份一下,而且时间长了还有可能忘掉之前备份的是什么版本。

当然,这种配置模式也并不是firewalld的首创,在其他很多地方也都有用到,比如java中用于记录日志的logback也是这种模式,他在查找配置文件时会首先在根目录下找logback-test.xml文件,如果可以找到就直接使用,如果找不到就会接着找logback.xml文件,如果还找不到就会使用自己包里边自带的配置文件,这样使用起来就非常方便了,比如我们可以把logback-test.xml和logback.xml两个文件都创建出来,在开发机上使用logback-test.xml文件,然后在往服务器部署的时候直接将其删掉就可以了!当然还有很多产品也使用了这种配置模式,spring的很多子框架也使用的是这种模式,比如spring MVC中的组件配置也是这样,如果没有配置的话就会使用默认的配置,当然,我们这里不是在讲Spring MVC所以就不展开了,如果想了解更多细节大家可以参考学生编写的《看透Spring MVC:源代码分析与实践》一书。

配置文件结构

firewalld的配置文件结构非常简单,主要有两个文件和三个目录:

文件:firewalld.conf、lockdown-whitelist.xml

目录:zones、services、icmptypes

另外,如果使用到direct,还会有一个direct.xml文件。我们要注意,在保存默认配置的目录“/usr/lib/firewalld/”中只有我们这里所说的目录,而没有firewalld.conf、lockdown-whitelist.xml和direct.xml这三个文件,也就是说这三个文件只存在于“/etc/firewalld/”目录中。

下面学生分别来给大家介绍一下这些文件和目录的作用

  • firewalld.conf:firewalld的主配置文件,是键值对的格式,不过非常简单,只有五个配置项
  • DefaultZone:默认使用的zone,关于zone学生稍后给大家详细介绍,默认值为public;
  • MinimalMark: 标记的最小值,linux内核会对每个进入的数据包都进行标记,目的当然是为了对他们进行区分,比如学生在前面给大家补充iptables五张表相关的内容时候介绍说符合raw表规则的数据包可以跳过一些检查,那么是怎么跳过的呢?这里其实就是使用的标记,当然对数据包的标记还有很多作用。这里所设置的 MinimalMark值就是标记的最小值,默认值为100,一般情况下我们不需要对其进行修改,但是如果我们有特殊需要的时候就可以通过对其进行修改来告诉linux所使用标记的最小值了,比如我们需要给符合某条件的数据包标记为123,这时候为了防止混淆就需要将MinimalMark设置为一个大于123的值了;
  • CleanupOnExit:这个配置项非常容易理解,他表示当退出firewalld后是否清除防火墙规则,默认值为yes;
  • Lockdown: 这个选项跟D-BUS接口操作firewalld有关,firewalld可以让别的程序通过D-BUS接口直接操作,当Lockdown设置为yes的时候就可以通过lockdown-whitelist.xml文件来限制都有哪些程序可以对firewalld进行操作,而当设置为no的时候就没有限制了,默认值为 no;
  • IPv6_rpfilter:其功能类似于rp_filter,只不过是针对ipv6版的,其作用是判断所接受到的包是否是伪造的,检查方式主要是通过路由表中的路由条目实现的,更多详细的信息大家可以搜索uRPF相关的资料,这里的默认值为yes。
  • lockdown-whitelist.xml:当Lockdown为yes的时候用来限制可以通过D-BUS接口操作firewalld的程序
  • direct.xml:通过这个文件可以直接使用防火墙的过滤规则,这对于熟悉iptables的用户来说会非常顺手,另外也对从原来的iptables到firewalld的迁移提供了一条绿色通道
  • zones:保存zone配置文件
  • services:保存service配置文件
  • icmptypes:保存和icmp类型相关的配置文件

 

在firewalld的使用中最基础也是最重要的就是对zone的理解,不过现在还普遍理解的不是很透彻,下面学生就来给大家详细介绍一下zone到底是什么。

zone

firewalld默认提供了九个zone配置文件:block.xml、dmz.xml、drop.xml、external.xml、home.xml、internal.xml、public.xml、trusted.xml、work.xml,他们都保存在“/usr/lib/firewalld/zones/”目录下。这些zone之间是什么关系?他们分别适用用哪些场景呢?

为了弄明白这些问题大家需要先明白zone的本质含义。学生在上一节给大家介绍防火墙时说过防火墙就相当于一个门卫,门卫对具体某个来访的人判断是否应该放行是依靠规则来判断的,而我们这里的zone其实就是一套规则集,或者说是一套判断的方案。

理解了这层含义firewalld就容易了,比如上面的九个zone其实就是九种方案,而且起决定作用的其实是每个xml文件所包含的内容,而不是文件名,所以大家不需要对每种zone(每个文件名)的含义花费过多的精力,比如trusted这个zone会信任所有的数据包,也就是说所有数据包都会放行,但是public这个zone只会放行其中所配置的服务,其他的一律不予放行,其实我们如果将这两个文件中的内容互换一下他们的规则就换过来了,也就是public这个zone会放行所有的数据包,下面我们来看一下这两个文件的内容

public.xml

<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>Public</short>
  <description>For use in public areas. You do not trust the other computers on networks to not harm your computer.
 Only selected incoming connections are accepted.</description>
  <service name="ssh"/>
  <service name="dhcpv6-client"/>
</zone>

trusted.xml

<?xml version="1.0" encoding="utf-8"?>
<zone target="ACCEPT">
  <short>Trusted</short>
  <description>All network connections are accepted.</description>
</zone>

我们要特别注意trusted.xml中zone的target,就是因为他设置为了ACCEPT,所以才会放行所有的数据包,而public.xml中的zone没有target属性,这样就会默认拒绝(reject)通过,所以public这个zone(这种方案)只有其中配置过的服务才可以通过。

其他的zone大家可以自己打开xml文件来看一下,这里学生就不一一介绍了,关于zone配置文件的详细结构及含义后面学生再给大家进行讲解,下面学生再给大家介绍一下firewalld中的service。

附录:9个区域配置文件

drop.xml

 

<?xml version="1.0" encoding="utf-8"?>
<zone target="DROP">
  <short>Drop</short>
  <description>Unsolicited incoming network packets are dropped. Incoming packets that are related to outgoing network connections are accepted. Outgoing network connections are allowed.</description>
</zone>

 

block.xml

<?xml version="1.0" encoding="utf-8"?>
<zone target="%%REJECT%%">
  <short>Block</short>
  <description>Unsolicited incoming network packets are rejected. Incoming packets that are related to outgoing network connections are accepted. Outgoing network connections are allowed.</description>
</zone>

public.xml

<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>Public</short>
  <description>For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description>
  <service name="ssh"/>
  <service name="dhcpv6-client"/>
</zone>

external.xml

<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>External</short>
  <description>For use on external networks. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description>
  <service name="ssh"/>
  <masquerade/>
</zone>

dmz.xml

<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>DMZ</short>
  <description>For computers in your demilitarized zone that are publicly-accessible with limited access to your internal network. Only selected incoming connections are accepted.</description>
  <service name="ssh"/>
</zone>

work.xml

<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>Work</short>
  <description>For use in work areas. You mostly trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description>
  <service name="ssh"/>
  <service name="dhcpv6-client"/>
</zone>

home.xml

<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>Home</short>
  <description>For use in home areas. You mostly trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description>
  <service name="ssh"/>
  <service name="mdns"/>
  <service name="samba-client"/>
  <service name="dhcpv6-client"/>
</zone>

internal.xml

<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>Internal</short>
  <description>For use on internal networks. You mostly trust the other computers on the networks to not harm your computer. Only selected incoming connections are accepted.</description>
  <service name="ssh"/>
  <service name="mdns"/>
  <service name="samba-client"/>
  <service name="dhcpv6-client"/>
</zone>

trusted.xml

<?xml version="1.0" encoding="utf-8"?>
<zone target="ACCEPT">
  <short>Trusted</short>
  <description>All network connections are accepted.</description>
</zone>

 

service

service是firewalld中另外一个非常重要的概念,不过其含义是非常简单的。学生还是拿门卫的例子来给大家做解释,在iptables的时代我们给门卫下达规则时需要告诉他“所有到22号楼的人全部予以放行”、“所有到80号楼的人全部予以放行”等等,不过到了firewalld的时代就不需要这样了,而是可以直接下达像“到销售部的全部予以放行”这样的命令,然后门卫再一查发现销售部在80号楼,那么所有到80号楼的人门卫就都会放行了。我们这里的楼牌号和端口号相对应,部门名和服务名相对应,这样大家应该就可以理解service的作用了。

从端口号改为服务名主要有两个好处:首先是使用服务名配置的语义清晰,不容易出错;其次在对某个服务的端口号进行修改的时候只需要修改相应的service文件就可以了,而不需要再修改防火墙方案——zone。这其实跟DNS将ip地址和域名关联了起来是一样的道理。下面学生再来给大家介绍一下service的配置文件。

service配置文件的命名规则是<服务名>.xml,比如ssh的配置文件是ssh.xml,http的配置文件是http.xml等,他们默认保存在“/usr/lib/firewalld/services/”目录下,常见的服务其中都可以找到,如果我们想修改某个服务的配置,那么可以复制一份到“/etc/firewalld/services/”目录下然后进行修改就可以了,要想恢复默认配置直接将我们自己的配置文件删除就可以了。我们来看一下ssh服务的ssh.xml文件

<?xml version="1.0" encoding="utf-8"?>
<service>
  <short>SSH</short>
  <description>Secure Shell (SSH) is a protocol for logging into and executing commands on remote machines. It provides secure encrypted communications. If you plan on accessing your machine remotely via SSH over a firewalled interface, enable this option. You need the openssh-server package installed for this option to be useful.</description>
  <port protocol="tcp" port="22"/>
</service>

可以看到这里配置了tcp的22号端口,所以将ssh服务配置到所使用的zone(默认public)中后tcp的22号端口就开放了。如果我们想将ssh的端口修改为222,那么只需要将ssh.xml复制一份到“/firewalld/services/”中,然后将端口号修改为222就可以了。当然直接修改“/usr/lib/firewalld/services/”中的配置文件也可以实现,但是强烈建议不要那么做,原因相信大家都明白。 

明白原理之后使用起来就可以非常灵活了,比如我们将“/etc/firewalld/services/ssh.xml”文件复制一份到“/etc/firewalld/services/”中,然后将名字改为abc.xml,并且将abc这个服务配置到所使用的zone中,这时22端口就会开放。也就是说在zone中所配置的服务其实跟实际的服务并不存在直接联系,而是和相应配置文件中配置的内容有关系。

配置方法

firewalld的配置方法主要有三种:firewall-config、firewall-cmd和直接编辑xml文件,其中firewall-config是图形化工具,firewall-cmd是命令行工具,而对于linux来说大家应该更习惯使用命令行方式的操作,所以firewall-config我们就不给大家介绍了。具体的配置方法学生在下一节给大家进行介绍。

Firewalld常用命令

Firewalld防火墙中所使用到的命令可以分为三大类:安装卸载、维护和策略操作。

安装

在Centos7中默认已经安装了firewalld,如果需要自行安装,可以直接使用yum安装

[root@excelib.com ~]# yum install firewalld

如果需要使用图形化配置工具还需要安装firewall-config

[root@excelib.com ~]# yum install firewall-config

这样firewalld就安装完成了,不过要注意firewalld跟iptables不能同时使用,所以在使用firewalld之前首先需要将iptables停用。

维护命令

firewalld的维护相对来说是非常简单的,其命令主要分为三大类:启动停止和查询状态、设置开机自动启动以及更新规则。

启动停止和查询状态

在Centos7中默认将原来的服务管理工具service升级为了systemctl,其实原来的service只是一个脚本执行工具,而systemctl的功能非常强大,关于systemctl的详细用法大家可以阅读linux中国的一篇文章,地址是:https://linux.cn/article-5926-1.html,这篇文章写的非常详细,所以学生就不再给大家做补充了,下面来说一说怎么用它来操作firewalld。

启动

[root@excelib.com ~]# systemctl start firewalld

停止

[root@excelib.com ~]# systemctl stop firewalld

重启

[root@excelib.com ~]# systemctl restart firewalld

查询状态

[root@excelib.com ~]$ systemctl status firewalld

另外,对于firewalld来说还可以使用自身的firewall-cmd工具来查询运行状态

[root@excelib.com ~]$ firewall-cmd --state

 

设置开机自动启动

设置开机自动启动也是使用systemctl来操作的,命令如下

启用开机自动启动

[root@excelib.com ~]$ systemctl enable firewalld

禁用开机自动启动

[root@excelib.com ~]$ systemctl disable firewalld

查看自动启动状态

[root@excelib.com ~]$ systemctl is-enabled firewalld

当然,systemctl的这些命令不只适用于firewalld,也适用于其他服务,使用时只要将firewalld换成相应服务的名称就可以了。

 

更新规则

直接使用firewall-cmd修改的规则是不需要更新就可以直接生效的,但是如果加了--permanent参数,或者直接编辑xml文件之后就需要我们手动reload了,firewall-cmd提供了两个更新规则的参数:--reload和--complete-reload,前者只是更新需要更新规则,而且更新的过程中不会影响现有的连接,而后者在更新时会将所有的规则清除掉然后重建,而且为了安全考虑,在更新之前首先会将策略设置为DROP,等更新完成之后再恢复为ACCEPT,这样就会对现有连接造成影响,所以如果没有特殊需求我们应该尽量使用前者。具体命令如下

[root@excelib.com ~]# firewall-cmd --reload
[root@excelib.com ~]# firewall-cmd --complete-reload

策略操作

对于firewalld来说最重要的就是策略操作了,策略操作主要有三种方法:使用firewall-config操作、使用firewall-cmd操作和直接编辑xml文件,学生在上节已经给大家介绍过了,firewall-config是图形化工具,firewall-cmd是命令行工具,我们这里主要以命令行工具为主来给大家介绍。

firewall-cmd中关于规则的命令非常多,如果在这里全部列出来再给大家解释一遍应该效果也不会太好,所以学生在后面讲到具体相关内容时再给大家讲相应的命令,比如讲到zone的时候给大家介绍跟zone相关的命令,这样大家更容易理解和记忆。

firewall-cmd中的命令虽然非常多,但是有四大类使用频率非常高的命令:

  --add-xxx

  --remove-xxx

  --query-xxx

  --get-xxx

  --list-xxx

这里前两个非常容易理解,一个是添加一个是删除,而后三个从名字上就不太容易区分了,下面学生给大家解释一下。

  • --query-xxx主要用于布尔值的查询,比如
[root@excelib.com ~]$ firewall-cmd --zone=public --query-service=ssh
  • --get-xxx主要用于获取特定的内容,比如这个命令用于查询在public这个zone中是否包含ssh这个服务。
[root@excelib.com ~]$ firewall-cmd --get-zones

这样就可以获取到预设的zones,默认情况下返回结果为

block dmz drop external home internal public trusted work
  • --list-xxx主要用于按一定条件进行查询(不过有的list命名也不需要条件),比如 
[root@excelib.com ~]$ firewall-cmd --zone=public --list-services

 这个命令可以返回public这个zone中所包含的services。

query还是比较容易理解的,但是get和list从字面上并不容易区分,刚开始学生以为get命令用于获取单个结果,list用于获取多个结果,但后来发现并不是这样。当然,我们在使用的时候按照文档中的说明来使用就可以了。

 

另外,在firewall-cmd中有一个比较特殊的参数:--permanent,他表示是否将修改后的规则保存下来,如果不加这个参数,那么所做的修改当时会立即生效,但是在firewalld重启之后就会丢失,而加上这个参数后所做的修改就会永久保存下来,不过这时的修改不会立即生效而是需要reload后才可以生效。其实这个也非常容易理解,当不加--permanent修改规则时firewalld会实际修改运行时的规则,而如果加了这个参数firewalld其实是去修改的xml配置文件,和我们直接编辑xml文件一样,所以就需要reload才可以生效。

Firewalld的panic模式

Firewalld有一种Panic模式,Panic的单词含义为“恐慌”、“惊慌”,在firewalld中他表示当发生紧急情况(比如遭到攻击)时启用的一种“禁行模式”,启用这种模式后所有的进包和出包都会被丢弃,和panic模式相关的有三个命令

[root@excelib.com ~]# firewall-cmd --panic-on
[root@excelib.com ~]# firewall-cmd --panic-off
[root@excelib.com ~]# firewall-cmd --query-panic

这三个命令很容易理解,第一个是启用panic模式,也就是“禁行模式”,第二个是禁用panic模式,第三个是查询是否已启用panic模式。

当启用了panic模式后所有的进包和出包都会被丢弃,不过如果对于原来已经建立的连接并不会马上断开,只是双方不能进行通信了而已,当达到设置的最长不活动(inactivity)周期后才会断开,而如果在断开前将panic模式关闭的话连接就不会受影响。

因为启用panic模式后会丢弃所有进包和出包,所以使用时要格外谨慎,另外,如果是使用的ssh连接的话,启动panic模式后ssh的连接也会被断开(准确来说是不可通信了),这时更加需要注意。

多知道点

firewall-cmd的本质

大家现在应该对firewall-cmd命令已经比较熟悉的,但是他的本质到底是什么呢?学生在这里给大家介绍一下。

firewall-cmd其实是一个位于/usr/bin目录下的Python脚本,大家如果想了解firewall-cmd命令的具体的细节而且又熟悉Python语言的话就可以直接打开这个文件进行代码阅读。

另外,这个命令有一个对于安全来说非常重要但是又很不容易引起注意的问题,首先我们来看一下这个脚本文件的属性


[root@excelib.com~]# ll /usr/bin/firewall-cmd
-rwxr-xr-w. 1 root root 62012 Nov 20 20:35 /usr/bin/firewall-cmd


大家可以看到这里的权限是755,也就是说所有用户都可以执行该命令,当然,这么设计主要是为了学生后面要给大家介绍的使用其他程序通过D-BUS接口来操作firewalld有关,而且在前面给大家说过可以通过whitelist来设置,不过只有将Lockdown配置为yes后whitelist才会生效,而且默认配置为no,也就是说默认情况下所有程序(用户)都可以执行firewall-cmd命令,这当然是不安全的,如果大家不需要使用其他程序对其进行操作的话可以直接将其权限改为750,这样更加安全


[root@excelib.com~]# chmod 750 /usr/bin/firewall-cmd


用活firewalld防火墙中的zone

firewalld中zone的含义学生前面已经给大家介绍过了,说白了一个zone就是一套规则集。可是什么时候该用哪个zone、每个zone中的规则具体是怎么设置呢?下面学生就来给大家详细讲解。

名词解释

在具体介绍zone之前学生先给大家介绍几个相关的名词,因为如果不理解这几个名词zone就无从入手。

  • target:目标,这个前面学生也已经给大家介绍过了,可以理解为默认行为。即当某个zone被设定为默认zone时,进入此zone中未匹配到任何规则到的报文将应用此target行为。有3个可选值:default、ACCEPT、%%REJECT%%、DROP,如果缺省则为%%REJECT%%。
  • service:这个在前面学生已经给大家解释过了,他表示一个服务
  • port:端口,使用port可以不通过service而直接对端口进行设置
  • interface:接口,可以理解为网卡
  • source:源地址,可以是ip地址也可以是ip地址段
  • icmp-block:icmp报文阻塞,可以按照icmp类型进行设置
  • masquerade:ip地址伪装,也就是按照源网卡地址进行NAT转发
  • forward-port:端口转发
  • rule:自定义规则

哪个zone在起作用

我们知道每个zone就是一套规则集,但是有那么多zone,对于一个具体的请求来说应该使用哪个zone(哪套规则)来处理呢?这个问题至关重要,如果这点不弄明白其他的都是空中楼阁,即使规则设置的再好,不知道怎样用、在哪里用也不行。

对于一个接受到的请求具体使用哪个zone,firewalld是通过三种方法来判断的:

1、source,也就是报文的源地址(如果某个zone中定义了source,那么这个zone会被优先启用)

2、interface,接收请求的网卡(如果某个zone中定义了interface,那么这个zone会被第二优先启用)

3、firewalld.conf中配置的默认zone(如果没有以上两种情况或者以上两个情况都未匹配到的报文,会被默认zone处理)

这三个的优先级按顺序依次降低,也就是说如果按照source可以找到就不会再按interface去查找,如果前两个都找不到才会使用第三个,也就是学生在前面给大家讲过的在firewalld.conf中配置的默认zone。此外,我们可以通过firewall-cmd --get-active-zones命令来 查看所有生效的zone(注意不会显示默认zone),后面我们会介绍到。

好了,我们现在知道其原理了,下面学生就给大家介绍每一种方式所对应的配置方法。

配置source

source是在zone的xml文件中配置的,其格式为

<zone>
    <source address="address[/mask]"/>
</zone>

只要我们将source节点放入相应的zone配置文件中就可以了,节点的address属性就是源地址,不过我们要注意相同的source节点只能在一个zone中进行配置,不能同时在多个zone中配置,也就是说同一个源地址只能对应于一个zone,另外,直接编辑xml文件之后还需要reload才可以起作用,这些学生前面已经给大家讲过,这里就不再重述了。

另外,我们当然也可以使用firewall-cmd命令进行配置,这里主要有五个相关命令(参数)

firewall-cmd [--permanent] [--zone=zone] --list-sources
firewall-cmd [--permanent] [--zone=zone] --query-source=source[/mask]
firewall-cmd [--permanent] [--zone=zone] --add-source=source[/mask]
firewall-cmd               [--zone=zone] --change-source=source[/mask]
firewall-cmd [--permanent] [--zone=zone] --remove-source=source[/mask]

我们分别来介绍一下

  • --list-sources:用于列出指定zone的所有绑定的source地址
  • --query-source:用于查询指定zone是否跟指定source地址进行了绑定
  • --add-source:用于将一个source地址绑定到指定的zone(只可绑定一次,第二次绑定到不同的zone会报错)
  • --change-source:用于改变source地址所绑定的zone,如果原来没有绑定则进行绑定,这样就跟--add-source的作用一样了
  • --remove-source:用于删除source地址跟zone的绑定

 另外,大家可以看到上面的命令中有两个可选参数:--permanent和--zone,--permanent学生在前面已经给大家介绍过了,表示是否存储到配置文件中(如果存储到配置文件中这不会立即生效),--zone用于指定所要设置的zone,如果不指定则使用默认zone。

我们来看个例子

[root@excelib.com ~]# firewall-cmd --zone=drop --change-source=1.2.3.4

这样就可以将1.2.3.4绑定到drop这个zone中了,如果没有修改过drop规则的话所有来自1.2.3.4这个ip的连接将会被drop。

至于什么时候使用add什么时候使用change,如果我们就是想将某源地址(已经绑定在其他zone时)绑定到指定的zone那么最好使用change;而如果想在源地址没绑定的时候进行绑定,如果已经绑定过则不绑定那么就使用add。

换而言之:

如果源地址没有在任何zone中绑定,此时change和add的作用是一样的,都是绑定到指定zone中;如果源地址已经在其他zone中绑定了,想把该源地址从这个zone中删除然后再绑定到指定的zone中,此时使用change;如果使用add,该源地址已经绑定在某个zone的情况下是不重新绑定到指定zone中。

 

配置interface

interface有两个可以配置的位置:1、zone所对应的xml配置文件2、网卡配置文件(也就是ifcfg-*文件)。

第一种配置跟source大同小异,学生这里就不再细述了,interface在zone配置文件中的节点为

<zone>
    <interface name="string"/>
</zone>

相关的firewall-cmd命令为

firewall-cmd [--permanent] [--zone=zone] --list-interfaces
firewall-cmd [--permanent] [--zone=zone] --add-interface=interface
firewall-cmd        [--zone=zone] --change-interface=interface
firewall-cmd [--permanent] [--zone=zone] --query-interface=interface
firewall-cmd [--permanent] [--zone=zone] --remove-interface=interface

另外,我们还可以在网卡配置文件中进行配置,比如可以在ifcfg-em1文件中添加下面的配置

ZONE=public

这行配置就相当于下面的命令

[root@excelib.com ~]# firewall-cmd --zone=public --change-interface=em1

这样配置之后来自em1的连接就会使用public这个zone进行管理(如果source匹配了其他的zone除外)。

配置默认zone

默认zone的配置学生前面已经给大家介绍过了,他是通过firewalld.conf配置文件的DefaultZone配置项来配置的,当然也可以使用firewall-cmd命令来配置

firewall-cmd --set-default-zone=zone

另外还可以通过--get-default-zone来获取默认zone的值。

查看当前起作用的zone

我们可以使用下面的命令来查看当前所有起作用的zone

firewall-cmd --get-active-zones

这个命令会返回所有绑定了source、interface以及默认的zone,并会说明在什么情况下使用。

反向查询

firewalld还给我们提供了反向查询的命令,也就是根据source或者interface查询所对应的zone,其命令如下

firewall-cmd --get-zone-of-interface=interface
firewall-cmd --get-zone-of-source=source[/mask]

有了这两个命令我们就可以检查我们的设置是否正确了。

 

好了,现在大家就明白了一个接收到的请求具体使用哪个zone了,那么zone具体的规则怎么配置呢?下面学生就来给大家详细介绍。

zone规则配置

target

zone规则中首先最重要的是target的设置,他默认可以取四个值:default、ACCEPT、%%REJECT%%、DROP,其含义很容易理解,这里学生就不介绍了,需要说明的是,缺省时默认的target为DROP,下面来说怎么配置。

在xml文件中target是zone节点的一个属性,比如drop.xml中为

<zone target="DROP">

block.xml中为

<zone target="%%REJECT%%">

如果使用firewall-cmd命令来操作,命令如下

firewall-cmd --permanent [--zone=zone] --get-target
firewall-cmd --permanent [--zone=zone] --set-target=target

我们要特别注意,这里的--permanent不是可选的,也就是说使用firewall-cmd命令也不可以让他直接生效,也需要reload才可以。

service

service学生在前面也已经给大家介绍过了,他的配置和我们上面所介绍的source基本相同,只不过同一个service可以配置到多个不同的zone中,当然也就不需要--change命令了,他在zone配置文件中的节点为

<zone>
    <service name="string"/>
</zone>

相应的配置命令为

 

firewall-cmd [--permanent] [--zone=zone] --list-services
firewall-cmd [--permanent] [--zone=zone] --add-service=service [--timeout=seconds]
firewall-cmd [--permanent] [--zone=zone] --remove-service=service
firewall-cmd [--permanent] [--zone=zone] --query-service=service

 

具体每个命令的含义大家对照上面的source很容易就理解了,不过这里的--add命令中多了一个--timeout选项,学生这里给大家介绍一下。

--add-service中的--timeout的含义是这样的:添加一个服务,但是不是一直生效而是生效一段时间,过期之后自动删除。

这个选项非常有用,比如我们想暂时开放一个端口进行一些特殊的操作(比如远程调试),等处理完成后再关闭,不过有时候我们处理完之后就忘记关闭了,而现在的--timeout选项就可以帮我们很好地解决这个问题,我们在打开的时候就可以直接设置一个时间,到时间之后他自动就可以关闭了。另外,这个参数还有更有用的用法,学生会在下面给大家讲到。当然--timeout和--permanent是不可以一起使用的。

另外,这里我们主要讲的是怎么在zone中使用service,而service自己的配置学生下节再给大家详细介绍。

port

port是直接对端口的操作,他和service非常相似,所以这里也不详细介绍了,port在zone中的配置节点为

<zone>
    <port port="portid[-portid]" protocol="tcp|udp"/>
</zone>

相应命令为

firewall-cmd [--permanent] [--zone=zone] --list-ports
firewall-cmd [--permanent] [--zone=zone] --add-port=portid[-portid]/protocol [--timeout=seconds]
firewall-cmd [--permanent] [--zone=zone] --remove-port=portid[-portid]/protocol
firewall-cmd [--permanent] [--zone=zone] --query-port=portid[-portid]/protocol

icmp-block

icmp-block是按照icmp的类型进行设置阻塞,比如我们不想接受ping报文就可以使用下面的命令来设置

[root@excelib.com ~]# firewall-cmd --add-icmp-block=echo-request

当然,如果需要长久保存就需要加--permanent选项,不过那样就需要reload才能生效。

icmp-block在zone配置文件中的节点为

<zone>
    <icmp-block name="string"/>
</zone>

相应操作命令为

firewall-cmd [--permanent] [--zone=zone] --list-icmp-blocks
firewall-cmd [--permanent] [--zone=zone] --add-icmp-block=icmptype [--timeout=seconds]
firewall-cmd [--permanent] [--zone=zone] --remove-icmp-block=icmptype
firewall-cmd [--permanent] [--zone=zone] --query-icmp-block=icmptype

masquerade

masquerade大家应该都比较熟悉,其作用就是ip地址伪装,也就是NAT转发中的一种,具体处理方式是将接收到的请求的源地址设置为转发请求网卡的地址,这在路由器等相关设备中非常重要,比如大家很多都使用的是路由器连接的局域网,而想上互联网就得将我们的ip地址给修改一下,要不大家都是192.168.1.XXX的内网地址,那请求怎么能正确返回呢?所以在路由器中将请求实际发送到互联网的时候就会将请求的源地址设置为路由器的外网地址,这样请求就能正确地返回给路由器了,然后路由器再根据记录返回给我们发送请求的主机了,这就是masquerade。

其设置非常简单,masquerade在zone中是一个没有参数(属性)的节点

<zone>
    <masquerade/>
</zone>

操作命令为

firewall-cmd [--permanent] [--zone=zone] --add-masquerade [--timeout=seconds]
firewall-cmd [--permanent] [--zone=zone] --remove-masquerade
firewall-cmd [--permanent] [--zone=zone] --query-masquerade

forward-port

这项也非常容易理解,他是进行端口转发的,比如我们要将在80端口接收到tcp请求转发到8080端口可以使用下面的命令

[root@excelib.com ~]# firewall-cmd --add-forward-port=port=80:proto=tcp:toport=8080

forward-port还支持范围转发,比如我们还可以将80到85端口的所有请求都转发到8080端口,这时只需要将上面命令中的port修改为80-85即可。

在zone配置文件中节点如下

<zone>
    <forward-port port="portid[-portid]" protocol="tcp|udp" [to-port="portid[-portid]"] [to-addr="ipv4address"]/>
</zone>

相关操作命令如下

firewall-cmd [--permanent] [--zone=zone] --list-forward-ports
firewall-cmd [--permanent] [--zone=zone] --add-forward-port=port=portid[-portid]:proto=protocol[:toport=portid[-portid]][:toaddr=address[/mask]][--timeout=seconds]
firewall-cmd [--permanent] [--zone=zone] --remove-forward-port=port=portid[-portid]:proto=protocol[:toport=portid[-portid]][:toaddr=address[/mask]]
firewall-cmd [--permanent] [--zone=zone] --query-forward-port=port=portid[-portid]:proto=protocol[:toport=portid[-portid]][:toaddr=address[/mask]]

rule

rule可以用来定义一条复杂的规则,其在zone配置文件中的节点定义如下

<zone>
    <rule [family="ipv4|ipv6"]>
               [ <source address="address[/mask]" [invert="bool"]/> ]
               [ <destination address="address[/mask]" [invert="bool"]/> ]
               [
                 <service name="string"/> |
                 <port port="portid[-portid]" protocol="tcp|udp"/> |
                 <protocol value="protocol"/> |
                 <icmp-block name="icmptype"/> |
                 <masquerade/> |
                 <forward-port port="portid[-portid]" protocol="tcp|udp" [to-port="portid[-portid]"] [to-addr="address"]/>
               ]
               [ <log [prefix="prefixtext"] [level="emerg|alert|crit|err|warn|notice|info|debug"]/> [<limit value="rate/duration"/>] </log> ]
               [ <audit> [<limit value="rate/duration"/>] </audit> ]
               [ <accept/> | <reject [type="rejecttype"]/> | <drop/> ]
     </rule>
</zone>

可以看到这里一条rule的配置的配置项非常多,比zone本身还多出了destination、log、audit等配置项。其实这里的rule就相当于使用iptables时的一条规则。rule的操作命令如下

firewall-cmd [--permanent] [--zone=zone] --list-rich-rules
firewall-cmd [--permanent] [--zone=zone] --add-rich-rule='rule' [--timeout=seconds]
firewall-cmd [--permanent] [--zone=zone] --remove-rich-rule='rule'
firewall-cmd [--permanent] [--zone=zone] --query-rich-rule='rule'

这里的参数'rule'代表一条规则语句,语句结构就是直接按照上面学生给大家的节点结构去掉尖括号来书写就可以了,比如要设置地址为1.2.3.4的source就可以写成source address="1.2.3.4",也就是直接写标签名,然后跟着写属性就可以了,我们来看个例子

[root@excelib.com ~]# firewall-cmd --add-rich-rule='rule family="ipv4" source address="1.2.3.4" drop'

这条规则就会将1.2.3.4这个源地址的连接全部给drop掉。

使用rule结合--timeout我们可以实现一些非常好玩和有用的功能,比如我们可以写个自动化脚本,当发现有异常的连接时就可以添加一条rule将其相应的地址drop掉,而且还可以使用--timeout给设置个时间段,过了之后再自动开放!

用活firewalld防火墙之service

前面学生已经给大家介绍了在firewalld中service的概念以及在zone中怎么使用service,但是service本身怎么配置我们还没讲,本节学生就来给大家介绍service本身的配置。

service配置文件

service相对于zone来说结构要简单的多,其整体配置文件结构如下

<service [version="string"]>
     [<short>short description</short>]
     [<description>description</description>]
     [<port [port="portid[-portid]"] protocol="protocol"/>]
     [<module name="helper"/>]
     [<destination ipv4="address[/mask]" ipv6="address[/mask]"/>]
</service>

firewall-cmd分别提供了两个命令来创建和删除service

firewall-cmd --permanent --new-service='service'
firewall-cmd --permanent --delete-service='service'

不过我们如果直接编辑xml文件应该更简单,前面学生给大家介绍service概念的时候已经给大家介绍过了操作service配置文件的方法了,大部分服务在“/usr/lib/firewalld/services/”目录下都可以找到,不过我们不要直接修改而要复制一份到“/etc/firewalld/services/”中然后再进行修改,当然如果想自己创建一个服务也可以直接在“/etc/firewalld/services/”目录中创建,另外,更好的做法是在“/usr/lib/firewalld/services/”中找一个类似的服务复制一份到“/etc/firewalld/services/”目录中,然后修改文件名和其中的内容。

下面学生对service中的每个配置项给大家解释一下

version

version是service节点的一个可选属性,用于表示service的版本。

short

short在zone、icmptype等配置文件中也存在,其作用是简介,主要是让我们对所配置的内容有所了解,类似于注释的作用。

description

作用跟short相同,不过描述信息更加详细。

port

服务所对应的端口,这项是service中非常重要的一个配置项,大部分service主要就是对port进行绑定的,当一个service绑定了指定端口之后,该端口接收到的连接就会当成这个service,然后到所对应的zone中去查询规则,从而判断是否可以放行。

一个service中可以配置多个port节点,这在有的时候是非常有用的,比如

port节点有两可个配置的属性:port和protocol

port属性

port用来配置所使用的端口号,可以是单个端口也可以是一个端口段,比如port=100-105表示100到105之间的端口号,另外,port属性是个可选属性,可以不进行设置。

protocol属性

protocol属性用于指定所对应的协议,如果port属性不为空,那么protocol应该设置为tcp或者udp,如果port属性为空(没设置),那么protocol可以设置为/etc/protocols中所包含的任意协议。

module

module用于设置netfilter的helper。学生前面给大家介绍过,firewalld其实是基于netfilter进行工作的,netfilter中的helper主要用于连接的跟踪,这样就可以实现“有状态的防火墙”,也就是将相关的连接管理到一起。一个典型的例子就是ftp的连接,我们知道一般来说ftp使用的是21号端口,不过21号端口主要是用来传输命令的,实际传输文件又会使用一个其他的端口,不过这两个连接还有内在的联系,这种情况就可以使用netfilter中的helper来处理,在我们这里service中就是module节点。我们看一下firewalld默认给我们提供的ftp的service配置文件ftp.xml

<?xml version="1.0" encoding="utf-8"?>
<service>
  <short>FTP</short>
  <description>FTP is a protocol used for remote file transfer. If you plan to make your FTP server publicly available, enable this option. You need the vsftpd package installed for this option to be useful.</description>
  <port protocol="tcp" port="21"/>
  <module name="nf_conntrack_ftp"/>
</service>

destination

destination非常简单,他就表示目标地址,也就是根据目标地址来绑定服务,他有两个属性:ipv4和ipv6,分别用于绑定ipv4和ipv6的地址,可以使用单个地址也可以使用掩码。

另外,在一个service中destination最多只能出现一次。

使用service

编辑完service配置文件后我们就可以在zone中使用了,具体使用方法学生在前面已经给大家介绍过,这里就不再重述了。

Firewalld中的whitelist并不是规则白名单

whitelist的含义

白名单跟防火墙结合在一起大家很容易将其理解为规则白名单,不过在Firewalld中whitelist却并不是规则白名单的含义。

对于一个防火墙来说,最重要的当然就是规则了,Firewalld当然也不例外,学生前面也给大家介绍了很多规则相关的配置方法,不过大家有没有意识到一个潜在的问题呢?当我们服务器中的某个服务(比如http)出现漏洞时,攻击者如果可以执行命令那么是不是就可以使用firewall-cmd工具来修改我们防火墙的规则呢?如果真是这样那么后果可想而知,攻击者不但可以开放我们原来没有开放的端口,甚至还可以搞恶作剧——将我们正常服务的端口给关闭!

Firewalld中whitelist就是来解决这个问题的,他可以限制谁能对防火墙规则进行修改,也就是说这里的whitelist其实使用用来配置可以修改防火墙规则的主体的白名单。

使用条件

在默认配置下whitelist是不启用的,我们需要将Lockdown设置为yes才可以启用,这些内容前面学生已经给大家介绍过了,另外,firewall-cmd工具也可以直接对其进行设置和查询,命令如下

firewall-cmd --lockdown-on
firewall-cmd --lockdown-off
firewall-cmd --query-lockdown

第一个是开启Lockdown,也就是让whitelist起作用,第二个是关闭Lockdown,第三个是查询当前Lockdown的状态。

这三个命令非常容易理解,不过他们跟学生前面给大家介绍过的其他命令有一些使用上的区别,我们看到这三个命令都没有--permanent选项,不过这并不表示他们不可以持久化保存,其实恰恰相反,在我们对Lockdown进行修改时配置文件和运行时环境会同时进行修改,也就是说当我们使用firewall-cmd命令对Lockdown的状态进行修改后首先可以立即生效、其次在重启后也不会失效。

另外,在使用--lockdown-on的时候大家要特别小心,要先看自己在不在whitelist范围内,如果不在,启用之后我们自己也不可以对防火墙进行操作了!

配置文件

whitelist的配置文件是位于/etc/firewalld目录下的lockdown-whitelist.xml文件,其结构如下

<whitelist>
    [<selinux context="selinuxcontext"/>]
    [<command name="commandline[*]"/>]
    [<user {name="username"|id="userid"}/>]
</whitelist>

我们看到这里面有三个可选的配置节点:selinux、command和user,每个配置节点都可以配置多个,配置进来的就表示可以修改防火墙规则,下面学生分别来给大家介绍一下这三个配置项。

selinux

一说到selinux可能有的人就会产生畏惧心,不过这里用到的非常简单,只需要将某进程的content给设置进去就行了,具体某个进程的content大家可以使用“ps -e --context”命令来查找,找出来之后设置到context属性中就可以了。

我们可以直接编辑xml配置文件,另外也可以使用firewall-cmd命令来操作,相关命令如下

firewall-cmd [--permanent] --add-lockdown-whitelist-context=context
firewall-cmd [--permanent] --remove-lockdown-whitelist-context=context
firewall-cmd [--permanent] --query-lockdown-whitelist-context=context
firewall-cmd [--permanent] --list-lockdown-whitelist-contexts

这四个命令也非常容易理解,他们分别表示添加、删除、查询一个具体的selinuxcontenxt以及罗列出所有白名单中配置了的selinuxcontenxt,使用--permanent可以持久化保存,不使用可以立即生效。

command

通过command节点可以针对具体的command命令进行配置,配置之后此命令就可以被一般用户执行了。比如我们想将之前讲过的panic模式的开启和关闭命令开放,这样当遇到紧急情况时一般用户也可以启动panic模式,这种需求我们使用下面的配置即可

<whitelist>
    <command name="/usr/bin/python /bin/firewall-cmd --panic-on"/>
    <command name="/usr/bin/python /bin/firewall-cmd --panic-off"/>
</whitelist>

另外,command还可以使用通配符“*”,所以上面的配置还可以简化为

<whitelist>
    <command name="/usr/bin/python /bin/firewall-cmd --panic-*"/>
</whitelist>

当然,command也可以使用firewall-cmd命令来操作,相关命令如下

firewall-cmd [--permanent] --add-lockdown-whitelist-command=command
firewall-cmd [--permanent] --remove-lockdown-whitelist-command=command
firewall-cmd [--permanent] --query-lockdown-whitelist-command=command
firewall-cmd [--permanent] --list-lockdown-whitelist-commands

命令的含义跟上面的selinux差不多,大家可以很容易理解,学生就不再解释了。

user

这里的user指的就是linux中的用户,通过这项可以对指定的用户开放配置权限,指定用户的方法有两种:通过userId和通过userName都可以,在默认的lockdown-whitelist.xml配置文件中就设置了id为0的user,也就是root用户

<whitelist>
  ...
  <user id="0"/>
</whitelist>

当然,通过name属性设置用户名也是可以的,非常简单,学生这里就不给大家举例了。user也可以使用firewall-cmd命令来操作,而且uid和name是分开操作的,所以user相关的命令一共有八个

firewall-cmd [--permanent] --add-lockdown-whitelist-uid=uid
firewall-cmd [--permanent] --remove-lockdown-whitelist-uid=uid
firewall-cmd [--permanent] --query-lockdown-whitelist-uid=uid
firewall-cmd [--permanent] --list-lockdown-whitelist-uids
 
firewall-cmd [--permanent] --add-lockdown-whitelist-user=user
firewall-cmd [--permanent] --remove-lockdown-whitelist-user=user
firewall-cmd [--permanent] --query-lockdown-whitelist-user=user
firewall-cmd [--permanent] --list-lockdown-whitelist-users

前四个是对uid进行操作,后四个是对username进行操作,具体含义大家应该很容易理解。

特别注意

在使用whitelist的时候我们要特别注意一点,那就是whitelist只是针对规则的修改(包括添加和删除)起作用,但是不会限制查询。如果大家是使用root配置好防火墙后一般很少修改,也没有使用脚本动态修改等特殊需求的话可以直接将/bin/firewall-cmd的权限设置为750或者更低。

 Firewalld防火墙与ICMP攻击

提到ICMP大家应该都很熟悉,可能有人会说:不就是ping吗?但是说到ICMP攻击以及相关防御措施可能就有的人不是非常清楚了。

ICMP的概念

要想理解ICMP攻击以及防范我们还得从ICMP的概念说起,ICMP是“Internet Control Message Protocol”的缩写,意思是“Internet控制消息协议”,他主要用于在不同主机、路由器等设备之间传递控制消息,比如网络是否可以联通、路由设备地址的发现、路由路径是否合理等内容。

ICMP攻击

ICMP协议被攻击的方法有很多种,比如的“Ping of Death”、使用ICMP数据包发起DDOS攻击、redirect攻击等等,下面学生简单给大家介绍一下。

“Ping of Death”的原理是当发送的数据包大小超过64KB(规定最大64KB)后接收信息的主机就会出现内存分配错误,进一步会导致TCP/IP堆栈崩溃,甚至主机死机!不过这一漏洞在新版的操作系统中已经解决了。

ICMP 的DDOS简单来说就是一直不停地发送ICMP数据包从而占满被攻击主机的带宽,当然,更进一步还可以使用一些手段将流量进行放大,比如将源地址设置为被 攻击主机的“echo-request”类型报文广播给很多第三方主机,这时这些接收到报文的主机就会给被攻击目标主机返回“echo-replay”报 文,这样流量就被放大了。

要理解redirect攻击,首先要明白redirect的作用,学生给大家举个例子大家就明白了,比如有个快递 需要从北京发往广州,结果北京发到沈阳的中转站了,这时候沈阳就觉得不对呀,要往广州发应该往南边发才对怎么能往北边发呢?所以沈阳站就会跟北京站联系, 告诉他:你发的不对,你应该往南边的XXX站发送才对。ICMP中的redirect就是起这个作用的,当路由设备发现某个数据包经过自己不是最优路径时 就会给源地址发一个redirect数据包,告诉对方发的路径不合适,并且指出应该发往的地址。这个功能是很有用的,不过如果被攻击者使用情况就完全不一 样了,他们可以使用这一功能将正常(合理)的路由地址给修改为一个不合理的甚至不存在的地址,这样就会给通讯造成问题,另外,有一些还会将目标地址设置为 他们自己可以控制的主机的地址,这样就可以截获数据了!跟redirect相关的还有router-advertisement、router- solicitation等类型的ICMP数据包。

当然,除了这三种还有很多攻击的类型,比如我们下面会说到的destination-unreachable、source-quench、time-exceeded等类型的攻击。

可能看到这里有的读者就觉得不容易理解了:echo-request、redirect、destination-unreachable等等到底是什么东西呢?其实这都是ICMP的类型,下面学生就来给大家介绍ICMP的类型。

ICMP的类型

ICMP 数据包主要包含三部分内容:类型、代码和附加数据,其中的类型和代码属于包头,代码(code)相当于类型(type)下的细分子类型,我们也可以理解为 他们共同来决定一个ICMP包的类型,比如学生上面给大家讲的redirect的type为5,不过5这个type下面还有4个code——0,、1、 2、3,他们所表示的含义如下表所示

表1:ICMP包Redirect类型表

type

code

描述

5

0

Redirect for network——对网络重定向

5

1

Redirect for host——对主机重定向

5

2

Redirect for TOS and network——对服务类型和网络重定向

5

3

Redirect for TOS and host——对服务类型和主机重定向

具体更多的代码学生就不在这里罗列了,大家很容易就可以找到。在ICMP数据包中type和code就像excel中的两个单元格,只要将相应的数据填入,主机就可以知道这个ICMP包的类型了。

这里的type和code我们当然是不需要记的,在使用的时候只需要用名字就可以了,比如type为8的数据包我们直接写Echo request、type为0的数据包我们直接写Echo Reply就行了,下面学生简单地给大家介绍几个常见的类型

  • Echo request:需要回应的请求,也就是我们常说的ping请求
  • Echo Reply:对ping的回应报文(pong)
  • Destination Unreachable:目标不可达
  • Source Quench:源地址资源紧张,正常情况下当我们要发送数据的路由设备请求过多时就会发出这种ICMP包
  • Time Exceeded:超时,比如TTL用完后就会产生这种类型的数据包

Firewalld针对ICMP攻击的防御方法

firewalld中有专门针对icmp报文的配置方法,而且使用起来也非常简单,我们只需要将firewalld所支持的icmp类型配置到所使用的zone中就可以了,要查看firewalld所支持的icmp类型可以使用下面的命令

firewall-cmd [--permanent] --get-icmptypes

默认的返回结果如下

destination-unreachable echo-reply echo-request parameter-problem redirect 
router-advertisement router-solicitation source-quench time-exceeded

这里的类型前面学生基本都给大家介绍过了,下面来学生来给大家讲怎么使用。跟icmptype相关的命令主要有四个

firewall-cmd [--permanent] [--zone=zone] --list-icmp-blocks
firewall-cmd [--permanent] [--zone=zone] --add-icmp-block=<icmptype>
firewall-cmd [--permanent] [--zone=zone] --remove-icmp-block=<icmptype>
firewall-cmd [--permanent] [--zone=zone] --query-icmp-block=<icmptype>

他们分别用于列出zone中所阻止的所有icmp类型、添加、删除和查询某个具体的icmp类型,如果指定zone则对具体zone进行操作,否则对当前活动的zone进行操作。

icmp配置文件的结构也非常简单,除了short和description外只有一个destination节点,可以设置对ipv4和ipv6的支持与否。

补充与建议

对于firewalld中的icmp设置大家要特别注意下面三点

1、firewalld只可以阻止指定类型的icmp包,没有其他更多的配置选项

2、如果使用drop、reject这些zone的话,默认所有icmp类型都会阻塞

3、默认情况下firewalld中所配置的icmp类型主要是针对入包的,而对于主机发出的包是不会拦截的。另外,在前面学生跟大家说过firewalld是一款有状态的防火墙,也就是说不同连接之间的关系firewalld在内部是有记录的,所以即使我们将echo-reply设置到zone中之后再去使用本机ping其他主机也是可以收到回复的,这是因为firewalld底层可以识别出那个echo-reply是我们发生去请求的回应。

对于具体哪个类型应该阻止,哪个应该放行大家需要根据自己的实际情况来设定,学生下面给大家提供一些思考的方向和建议。

  • destination-unreachable:当收到这种类型数据包之后相应地址的连接将会被断开,如果是攻击者伪造的数据包,那么会将我们的很多正常连接断开。当将其设置到zone中后我们本机发送的请求还是可以收到destination-unreachable类型回复的,只是直接发给我们的destination-unreachable数据包进不来了,所以建议大家可以阻止。
  • echo-request:主要用于接收ping请求,阻塞之后我们的主机将不可被ping,不过打开后又有可能被攻击,有种惯用的做法是设置开通的频率,比如1秒钟只可以被ping一次,不过这种功能直接使用学生上面给大家介绍的方法是无法设置的,不过没关系,当学习了学生下一节将要给大家介绍的firewalld中的direct之后就可以设置了。
  • echo-reply:这是回应ping信息的包,一般来说我们应该将其阻止,因为他跟destination-unreachable一样,如果是我们本机发出的即使设置了阻止也还是可以接收到的。
  • parameter-problem:当接收到的报文参数错误,无法解析时会返回这种类型的报文。
  • redirect:这种报文学生在前面已经给大家详细介绍过,这里就不再重述了。
  • router-advertisement和router-solicitation:这是一对报文,他们的作用是用来发现路由设备的地址,主机发出router-solicitation类型数据包来查找路由设备,路由设备可以发出router-advertisement类型ICMP数据包来告诉主机自己是路由设备
  • source-quench:这个学生也给大家介绍过了,当源地址设备(比如路由设备)资源紧张时就会发出这种数据包
  • time-exceeded:数据包超时。

 

最后还是那句话,没有最优配置方法(否则就不需要配置了),大家需要根据自己的实际情况进行配置。

用活Firewalld防火墙之direct

学生在前面已经给大家介绍过了Firewalld中direct的作用,使用他可以直接使用iptables、ip6tables中的规则进行配置,下面学生就给大家介绍direct的具体用法。

direct结构

我们还是先从配置文件入手,direct的配置文件为/etc/firewalld/direct.xml文件,结构如下

<?xml version="1.0" encoding="utf-8"?>
<direct>
   [ <chain ipv="ipv4|ipv6" table="table" chain="chain"/> ]
   [ <rule ipv="ipv4|ipv6" table="table" chain="chain" priority="priority"> args </rule> ]
   [ <passthrough ipv="ipv4|ipv6"> args </passthrough> ]
</direct>

大家可以看到这里的direct一共有三种节点:chain、rule和passthrough,他们都是可选的,而且都可以出现多次。

属性

  • ipv:这个属性非常简单,表示ip的版本
  • table:chain和rule节点中的table属性就是iptables/ip6tables中的table
  • chain:chain中的chain属性用于指定一个自定义链的名字,注意,不可与已有链重名;rule中的chain属性既可以是内建的(也就是iptables/ip6tables中的五条链),也可以是在direct中自定义的chain
  • priority:优先级,用于设置不同rule的优先级,就像iptables中规则的前后顺序,数字越小优先级越高
  • args:rule和passthrough中的args就是iptables/ip6tables中的一条具体的规则,不过他们可以使用我们自定义的chain。
     

 

使用

因为direct的使用跟iptables/ip6tables非常相似,换句话说,想用好direct需要有iptables/ip6tables的基础,而iptables/ip6tables并不是我们这套教程的重点,所以这里学生就不给大家详细讲解了。

direct中自定义chain跟iptables/ip6tables中使用-N新建chain类似,创建完之后就可以在规则中使用-j或者-g来使用了。

Firewalld中跟direct相关的命令如下

firewall-cmd [--permanent] --direct --get-all-chains
firewall-cmd [--permanent] --direct --get-chains { ipv4 | ipv6 | eb } table
firewall-cmd [--permanent] --direct --add-chain { ipv4 | ipv6 | eb } table chain
firewall-cmd [--permanent] --direct --remove-chain { ipv4 | ipv6 | eb } table chain
firewall-cmd [--permanent] --direct --query-chain { ipv4 | ipv6 | eb } table chain
 
firewall-cmd [--permanent] --direct --get-all-rules
firewall-cmd [--permanent] --direct --get-rules { ipv4 | ipv6 | eb } table chain
firewall-cmd [--permanent] --direct --add-rule { ipv4 | ipv6 | eb } table chain priority args
firewall-cmd [--permanent] --direct --remove-rule { ipv4 | ipv6 | eb } table chain priority args
firewall-cmd [--permanent] --direct --remove-rules { ipv4 | ipv6 | eb } table chain
firewall-cmd [--permanent] --direct --query-rule { ipv4 | ipv6 | eb } table chain priority args
 
firewall-cmd --direct --passthrough { ipv4 | ipv6 | eb } args
firewall-cmd --permanent --direct --get-all-passthroughs
firewall-cmd --permanent --direct --get-passthroughs { ipv4 | ipv6 | eb }
firewall-cmd --permanent --direct --add-passthrough { ipv4 | ipv6 | eb } args
firewall-cmd --permanent --direct --remove-passthrough { ipv4 | ipv6 | eb } args
firewall-cmd --permanent --direct --query-passthrough { ipv4 | ipv6 | eb } args

下面我们来看个文档(firewalld.direct(5))中提供的例子

<?xml version="1.0" encoding="utf-8"?>
<direct>
    <chain ipv="ipv4" table="raw" chain="blacklist"/>
    <rule ipv="ipv4" table="raw" chain="PREROUTING" priority="0">-s 192.168.1.0/24 -j blacklist</rule>
    <rule ipv="ipv4" table="raw" chain="PREROUTING" priority="1">-s 192.168.5.0/24 -j blacklist</rule>
    <rule ipv="ipv4" table="raw" chain="blacklist" priority="0">-m limit --limit 1/min -j LOG --log-prefix "blacklisted: "</rule>
    <rule ipv="ipv4" table="raw" chain="blacklist" priority="1">-j DROP</rule>
</direct>

在这个例子中首先自定义了一个叫blacklist的链,然后将所有来自192.168.1.0/24和192.168.5.0/24的数据包都指向了这个链,最后定义了这个链的规则:首先进行记录,然后drop,记录的方法是使用“blacklisted: ”前缀并且限制1分钟记录一次。

当然,使用相似的方法大家也可以写出来上一节学生给大家留下的那个问题:对ping请求进行限制。

实战练习

1、允许访问本机的redis服务(端口6379)

 

[root@www zones]# firewall-cmd --get-services  #查看是否有定义好的redis服务
RH-Satellite-6 amanda-client amanda-k5-client bacula bacula-client ceph ceph-mon dhcp dhcpv6 dhcpv6-client dns docker-registry dropbox-lansync freeipa-ldap freeipa-ldaps freeipa-replication ftp high-availability http https imap imaps ipp ipp-client ipsec iscsi-target kadmin kerberos kpasswd ldap ldaps libvirt libvirt-tls mdns mosh mountd ms-wbt mysql nfs ntp openvpn pmcd pmproxy pmwebapi pmwebapis pop3 pop3s postgresql privoxy proxy-dhcp ptp pulseaudio puppetmaster radius rpc-bind rsyncd samba samba-client sane smtp smtps snmp snmptrap squid ssh synergy syslog syslog-tls telnet tftp tftp-client tinc tor-socks transmission-client vdsm vnc-server wbem-https xmpp-bosh xmpp-client xmpp-local xmpp-server
[root@www zones]# firewall-cmd --get-services|grep redis  #redis服务器未定义

方法一:通过端口,特点:直接快捷

[root@www zones]# firewall-cmd --zone=public --add-port=6379/tcp
success
[root@www zones]# firewall-cmd --zone=public --add-port=6379/tcp --permanent
success
[root@www zones]# cat public.xml
<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>Public</short>
  <description>For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description>
  <service name="dhcpv6-client"/>
  <service name="http"/>
  <service name="ssh"/>
  <port protocol="tcp" port="6379"/>
</zone>

方法二:通过服务

创建服务:(创建服务通过复制并修改配置文件的方法更加简单)

[root@www zones]# cp /usr/lib/firewalld/services/mysql.xml /etc/firewalld/services/redis.xml
[root@www zones]# vim /etc/firewalld/services/redis.xml
[root@www zones]# cat /etc/firewalld/services/redis.xml
<?xml version="1.0" encoding="utf-8"?>
<service>
  <short>Redis</short>
  <description>Redis Database Server</description>
  <port protocol="tcp" port="6379"/>
</service>

 [root@www zones]# firewall-cmd --zone=public --add-service=redis

 success

2、取消(禁止)访问本机的redis服务(端口6379)

[root@www zones]# firewall-cmd --zone=public --remove-port=6379/tcp
success
或者
[root@www zones]# firewall-cmd --zone=public --remove-service=redis
success

3、允许访问本机的http服务,但是禁止58.56.88.22访问。

[root@www zones]# firewall-cmd --add-service=http
success
[root@www zones]# firewall-cmd --zone=drop --change-source=58.56.88.22 --permanent  #永久生效,但是不实时生效
success
[root@www zones]# firewall-cmd --zone=drop --change-source=58.56.88.22
success     #实时生效。
或者使用firewall-cmd --reload来重读规则

4、查看当前生效的区域(接上题)

[root@www zones]# firewall-cmd --get-active-zones
drop
  sources: 58.56.88.22

5、只允许某个ip访问指定端口

设置规则:
firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.142.166" port protocol="tcp" port="5432" accept"

查看配置结果

firewall-cmd --list-all

删除规则

firewall-cmd --permanent --remove-rich-rule="rule family="ipv4" source address="192.168.142.166" port protocol="tcp" port="5432" accept"

 

参考内容: 

http://www.firewalld.org/documentation/