iptables防火墙这部分的内容,是为没有类似阿里云云服务器的安全组的其他厂商云服务器所准备的。是的,跟大家脑海里想的一样,安全组基本等价于iptables防火墙。只不过对大部分普通用户来说,阿里云所提供的安全组使用更方便一些。

14.1 准备

14.1.1

iptables防火墙介绍
iptables是一种用在Linux操作系统上面的防火墙,其作用与我们前面所说的安全组大致相同。我们可以去利用它去设置一些特定规则,来使得数据包经过网卡时都会被检查。我们的服务器的系统会根据我们所设置的防火墙的规则,来决定到底怎么处理这些要进来的、要出去的、要被转发到别处的数据包。在每条防火墙规则(规则的英文名称是rules)里面,我们可以使用一些特性,去描述一下这些经过网卡时被检查的数据包的特征。比如说数据包使用的网络协议的类型、数据包的来源和去向、以及数据包使用的端口号等。

如果到网卡上的数据包符合我们设置的某一条规则,系统就会去执行这条规则里指定的动作(动作的英文名称是target)。它可以接受(ACCEPT)这个数据包,也就是让这个数据包通过,让它去它想去的地方;它也可以丢弃(DROP)这个数据包,也就是直接把这个数据包丢掉。因为DROP这个动作不会向外回应,所以比如说有人想连接我们的服务器,那么如果我们把他发过来的数据包给扔了的话,他那边的连接会一直等着,直到连接超时;假如动作的回应是拒绝(REJECT)数据包,那么这个动作会给对方一个回应,告诉对方——你被我拒绝了。

14.1.2

Chain:防火墙规则的分组
Chain这个概念有点像是防火墙规则的分组,它里面比较重要的是本身规则的顺序。我们可以根据自己的需求去创建Chain,默认有三个Chain:INPUT、OUTPUT、FORWARD。INPUT表示输入,它处理的是进入到服务器里面的数据包;OUTPUT表示输出,它处理的是服务器向外发送的数据包。比如说我们想要安装或升级服务器上的某一个服务时,服务器本身就会向外发送一些数据包;FORWARD表示转发,这个分组的数据包会从一个地方被转移到另一个地方。

每一个分组都可以设置一个默认的动作,如果数据包不符合分组里面的所有防火墙规则的话,就会去执行这个默认的动作,这个动作可以是接受、丢弃或者是拒绝。

这些Chain也就是规则的分组里面,会包含很多条规则。在检查数据包的时候,分组里面的规则的顺序是很重要的,它的顺序意味着规则的优先级高低,在前面的规则优先级高,在后面的规则优先级低。数据包会被按照分组里的规则的顺序来进行检查,如果符合Chain里面的某一条规则的描述,就会执行相对应的动作,也就是我们上面所说的接受、丢弃、拒绝。

当执行过动作后,系统就不会继续去检查这个数据包是不是符合剩下的规则里的描述了,因此Chain里排在最前面的规则比后面的规则的优先级要高一些。由于这个系统机制的存在,所以我们需要在设计规则时去把一些比较通用的规则放到前面,然后把更具体的规则放到后面。比如我们想要禁用从某一个IP地址发过来的数据,那么我们应该在Chain里面设置一些比较具体的规则。

14.2 端口

14.2.1

端口扫描
传输协议就是传输数据用的方法,比如说TCP协议和UDP协议。

端口号就是数据的一个通道。比如说用户的浏览器会在用户的电脑上打开一个端口,然后去连接到我们服务器上的80端口,在这两个端口之间电脑和服务器可以相互交流数据;我们服务器上的一些服务会默认监听一些端口,用户可以连接到这些端口上面。譬如我们前面提到的Web服务会默认监听80端口,SSH服务会默认使用22端口。

在服务器本地或者其他的地方,我们都可以去查看服务器打开的这些端口。如图14-1所示,我们登录服务器,去安装EPEL仓库,输入命令yum install epel-release -y后回车,稍微等待即可。
2-5-1-1-550×110.png
图14-1 安装EPEL仓库

然后我们再输入命令yum install nginx -y,去安装Nginx服务。如果按照第十一章节中所讲述的内容安装过一整套的网站运行环境后,这里可以不用再进行重复安装。然后我们输入命令systemctl start nginx,来启动Nginx服务。

如果我们有多余的服务器,可以在它上面安装Nmap来进行端口扫描。我们登录这台服务器,输入命令yum install nmap -y,然后回车安装。

如图14-2所示,接下来我们输入命令nmap -sT 114.114.114.114,去扫描114公共DNS提供服务的IP地址。这里的命令中的“s”代表scan ,中文意思为扫描;大写的“T”代表TCP协议。综上所述,上面的意思即为使用Nmap去扫描114.114.114.114这个公共DNS使用的TCP协议的公开端口。当然,这个IP地址也可以替换成我们所拥有的主服务器的IP地址。从图14-2所示的结果可以看出,114.114.114.114开放了两个使用TCP协议的端口。
2-5-2-1-480×140.png
图14-2 使用Nmap扫描114公共DNS

当然,如果我们想要知道主服务器开放了哪些端口,我们也可以在主服务器上安装Nmap来扫描自己。我们使用上面的Nmap安装命令在主服务器上安装Nmap,然后执行命令nmap -sT localhost来扫描自己,如图14-3所示。这里的“localhost”,即为本地主机。从图14-3所示的结果可以看出,主服务器开放了四个使用TCP协议的端口。
2-5-3-1-480×180.png
图14-3 使用Nmap扫描本地主机

14.2.2

查看端口上的连接
如图14-3所示,其中列出的端口,可能会有少部分我们不知道它是做什么的,也不知道它属于哪一个服务。如果出现了不了解的服务和端口号,那么我们可以查询系统里面的一个ANSI编码文件,这个文件上面会列出大部分我们已经了解的服务和服务所对应的端口号。登录主服务器,我们可以输入命令cat /etc/services,来输出这个文件里的详细内容,详细信息如图14-4所示。如图14-4所示,第一列是服务的名字,第二列是服务的端口号和使用的协议类型,第三列是服务的简略描述。在某些情况下,第三列显示的信息可能是服务的别名,第四列才是与服务相关的简略描述。如果我们发现服务器所开放的端口既不在这个文件里面,又没有出现我们手工设置的端口,这种情况下我们就需要多加注意了,有可能是服务器被入侵了。
2-5-4-1-new-600×300.png
图14-4 查看系统中所有的服务和对应的端口等基本信息

在输出这个文件时,我们可以使用关键词,来搜索特定服务,比如我们可以输入命令cat /etc/services | grep 80,来查找端口号中有“80”字段的服务。如图14-5所示,其关键词会用红色来着重显示。
2-5-5-1-600×300.png
图14-5 使用关键词搜索系统中特定的服务

如果我们想知道某一个端口到底是哪个服务打开的,我们可以使用命令netstat -anp | grep 80,来查看使用该端口的服务。上面命令中的“a”代表all,意为所有;“n”代表numeric,意为直接使用数字显示;“p”代表programs,意为显示正在使用Socket的程序识别码和程序名称。如图14-6所示,我们从图中的结果了解到使用80端口的是Nginx服务,服务前面的数字则是进程的ID。
2-5-6-1-1212×88.png
图14-6 查看正在使用80端口的服务

我们还可以只列出当前使用TCP协议的服务的进程,输入命令netstat -ntp,可以得到如图14-7所示的反馈结果。如图14-7所示,图中的Local Address,代表主服务器的本机地址;Foreign Address代表正在连接主服务器的那台主机的地址。我们可以看到有两个地址,第一个地址是本地局域网地址,第二个地址则是我们当前使用的长城宽带的浮动公网IP地址;State表示状态,上面显示的ESTABLISHED意为连接已创建;后面的则是进程的ID和服务名称。如果这时有其他活动连接到我们的Web服务,本机地址等一些信息就会发生变化,再次输入上面的netstat -ntp命令,我们就可以看到其详细信息。
2-5-7-1-800×80.png
图14-7 查看正在使用TCP协议的服务的进程

14.3 基础

14.3.1

iptables基本命令
由于执行iptables命令需要root权限,所以我们可以使用root用户登录或者在命令前加sudo获得超级管理员权限。

比如我们想要查看系统现有的防火墙规则,我们可以输入命令iptables -L或iptables —list,这两个命令的意思相同,其作用是让系统列出所有的防火墙分组和里面的规则。如图14-8所示,一般情况下,我们会看到这三个Chain,它们就是iptables默认的防火墙的分组。大多数情况下,默认的iptables里面是没有规则的,而且policy的动作都是ACCEPT;当数据包不符合所有的规则后,系统才会去执行这个默认的policy。
2-5-8-1-666×393.png
图14-8 查看系统现有的防火墙规则

如果我们想要查看现有的规则是执行什么样的iptables命令生成的,我们可以使用iptables -S或iptables —list-rules命令。如图14-9所示,如果我们没有往里面添加具体的防火墙规则,我们会看到这三条默认的命令,它们就是设置分组默认动作的那些命令,且policy的默认动作应为ACCEPT。
2-5-9-1-360×60.png
图14-9 查看系统现有的防火墙规则的生成过程

如果我们想把FORWARD这个Chain的默认policy改成DROP,我们可以输入命令iptables -P FORWARD DROP来更改。如图14-10所示,更改后我们输入命令iptables —list-rules查看,从图中所示的反馈结果得知上面的更改命令生效了。如果我们想恢复原样,可以使用iptables -P FORWARD ACCEPT这个命令。命令中的“P”,是policy的缩写,后面的FORWARD和ACCEPT,可以根据实际需要灵活变通。
2-5-10-1-375×75.png
图14-10 将FORWARD默认策略改成DROP

14.3.2

禁止指定来源的访问
这里的指定来源,一般情况下是指某个具体的IP地址或者IP地址段。

在防火墙的规则里面,我们要指定一下规则应用的Chain,描述一下数据包的特征,然后再加上我们想要执行的具体动作。

如图14-11所示,我们在阿里云的云盾态势感知管理控制台上,得知有一些IP地址总是攻击我们的服务器,去请求一些它没有权限的资源,不断地向我们的服务器发出数据包,消耗了我们服务器的资源。
2-5-11-1-949×171.png
图14-11 阿里云的云盾态势感知管理控制台上显示的攻击服务器的IP地址

为了改善这种情况,我们可以添加一条防火墙规则去禁止这个IP地址的访问。我们登录服务器,输入命令iptables -A INPUT -s 120.52.18.49 -j DROP,回车执行即添加成功。命令中的“A”,即为Append,意思是向规则链中添加条目,后面的“INPUT”则是要添加的规则链的名字;“s”则是source,代表着数据包的来源,紧挨着的IP地址则是我们要禁止的指定来源;“j”则是jump,作用是指定要跳转的目标,后面紧挨着的动作则是我们想要执行的policy。这条规则的作用,就是扔掉120.52.18.49这个IP地址发来的所有的数据包。

14.3.3 禁止指定来源访问指定协议的端口号


我们继续在阿里云的云盾态势感知管理控制台上查看详细信息,发现攻击我们的IP地址与上面我们禁止掉的IP地址好像在同一个网段,即在120.52.18.0至120.52.18.255这一整个C类IP地址的范围内。如果想要了解更多关于IP地址子网的知识,我们可以去百度查找“IP CIDR”这个关键词,这里就不再多做阐述。

如图14-12所示,登录主服务器,我们输入命令iptables -A INPUT -s 120.52.18.0/24 -p tcp —dport 80 -j DROP,然后执行回车,防火墙规则就添加成功了。命令中的“p”,即为protocol,代表协议类型,后面紧挨着的“tcp”则是我们指定的协议;“dport”代表目标端口,后面的“80”则是我们指定的端口号。这条规则的作用,就是禁止120.52.18.1至120.52.18.254之间的IP地址使用TCP协议发送到80端口的数据包。虽然一整个C类IP地址有256个地址,但实际上可用的主机地址只有254个。
2-5-12-1-630×30.png
图14-12 禁止指定来源访问指定协议的端口号

14.4 管理规则

14.4.1

列出防火墙规则
查看现有的防火墙的规则,我们可以使用命令iptables -L,“L”代表List。在INPUT这个规则链里面,我们可以看到我们之前添加的两条规则。如果我们使用iptables -L —line-numbers这个命令,就会在这两条规则前面加上数字行号。如果我们想要查看这两条规则是执行什么样的iptables命令生成的,我们可以使用iptables -S或iptables —list-rules命令。

如果我们想要列出指定的规则链譬如INPUT这个Chain里面的规则,我们可以使用iptables -L INPUT这个命令去查看。如果我们想要得到更详细的信息,我们可以在这条命令后面加上-v,即使用iptables -L INPUT -v这个命令。如图14-13所示,我们发现系统所展示的信息里多了一些内容,比如pkts和bytes,它们分别是数据包的数量和数据包的大小。如果我们想要重置这里面的统计信息的话,我们可以使用iptables -Z这个命令,“Z”代表Zero;如果我们想要清除指定的规则链里的信息的话,我们可以加上这个Chain的名字。清除完成以后,我们执行命令iptables -L INPUT -v,会发现里面的pkts和bytes的数字都变成了零。
2-5-13-1-855×510.png
图14-13 列出防火墙规则

14.4.2

追加与插入规则
防火墙规则的顺序很重要,因为一个数据包进入以后,会被从第一条规则开始检查,遇到符合的规则就会执行对应的动作,执行以后就不会再继续使用后面的规则来检查这个数据包了。

之前我们在添加规则的时候,都使用了一个“-A”的选项,它全称为Append,中文意思为添加。使用这个选项后,我们新添加的规则会追加到现有的规则的底部,也就是新添加的规则会排列在原有规则的最后面。如果想避免这种情况发生,我们可以使用“-I”这个选项,把我们新添加的规则插入到指定的位置上。

我们可以输入命令iptables -L —line-numbers,先查看一下目前所有的规则链和它里面的所有规则。如图14-14所示,现在我们想添加一条规则,作为INPUT这个Chain里面的第一条规则,输入命令iptables -I INPUT 1 -i lo -j ACCEPT。我们可以在“-I”选项后加上我们想要插入的规则链的名字,以及想要插入的行号数字;“-i”的作用,是指定数据包进入本机的网络接口,后面的“lo”则是loopback的缩写。这条规则的作用是,可以允许本地流量自由进入,而且是最高优先级。再次执行iptables -L —line-numbers这个命令,我们可以看到我们新添加的命令已经被插入到了指定位置上。
2-5-14-1-660×110.png
图14-14 追加与插入规则

14.4.3

删除规则与清空所有规则
想要删除现有的规则,最简单的方法就是去使用规则的行号的数字来作为依据来删除。我们输入命令iptables -L —line-numbers,执行后发现我们的INPUT这个规则链里面,第一条规则和第二条规则重复了,于是我们需要删除一条多余的规则。

如图14-15所示,为了与前面添加的规则作出区别,我们删除掉INPUT这个Chain里面的第二条规则,输入并执行命令iptables -D INPUT 2;“D”是英文Delete的缩写,意为删除。完成后我们使用命令iptables -L —line-numbers再查看一下,会发现多余的规则已经被成功删除了。
2-5-15-1-690×106.png
图14-15 删除现有的规则

如果我们想要清空某个规则链比如INPUT这个规则链里面的所有规则,我们可以执行命令iptables -F INPUT来完成;这里的“F”是英文Flush的缩写,中文意思为冲洗。如果不在选项“-F”后面指定某个规则链,我们的iptables里面的所有规则都会被清空,使用的时候一定要观察清楚了解命令后再执行,以免意外情况发生。上面的命令执行后,我们再使用命令iptables -L —line-numbers去查看一下,会发现INPUT这个规则链里的所有规则已经被清空干净了。

14.4.4

CentOS:保存防火墙规则
我们前面添加的防火墙规则,如果不对它们进行保存,那么它们会在系统重新启动后消失,故我们必须找到一种方法把这些配置完成的规则保存下来。

CentOS 7这个系列的系统自带一个叫做FirewallD的防火墙,不过系统目前使用的还是iptables。我们可以先把系统自带的FirewallD防火墙关掉,然后再去安装一个叫做iptables-services的东西。

我们执行命令yum install iptables-services -y,完成以后使用命令systemctl start iptables去启动这个服务。如果我们之前使用了OneinStack这个一键开源工具,那么就有可能已经安装了这个服务;如果不确定自己是否已经安装,我们可以使用rpm -qa | grep iptables这个命令查看详细信息。启动服务以后,我们再使用systemctl enable iptables这个命令,让服务加入到开机自启动中。

防火墙规则会被保存到一个配置文件里面,我们可以使用命令cat /etc/sysconfig/iptables这个命令去查看文件里面的内容,内容里面列出的是一些比较常用的防火墙的规则。当然,我们自己新添加的规则,也会被保存到这个文件里面。重新启动iptables这个服务,我们可以立即应用这个配置文件里面的防火墙规则。执行命令systemctl restart iptables,可以达到我们重启服务的目的。我们输入iptables -L这个命令,系统会反馈给我们目前系统里面的防火墙规则的信息,这些规则保存在根目录下的etc/sysconfig的iptables配置文件里。

如图14-16所示,我们可以使用命令iptables -A INPUT -s 120.52.18.50 -j DROP,去新添加一条防火墙规则,禁止120.52.18.50这个IP地址的访问,然后我们输入service iptables save这个命令,去保存我们新添加的防火墙规则到iptables配置文件里面,完成后输入命令systemctl restart iptables,使得我们新添加的规则立即被重启生效。如图14-17所示,我们使用命令iptables -L —line-numbers查看,发现新添加的防火墙规则已经成功运行了。
2-5-16-1-525×60.png
图14-16 添加新的防火墙规则并保存防火墙规则

2-5-17-1-700×280.png
图14-17 查看新添加的防火墙规则是否成功生效

14.5 实施规则

14.5.1

默认的动作:Default Policy
每一个规则链都有一个默认的策略,也就是说一个数据包如果不符合所有的规则的描述的话,就会去执行这个默认的策略的指定动作。一般来说,这个默认的策略的指定动作是ACCEPT,意思就是允许通过,这个默认的策略有点像黑名单,我们需要添加我们不需要的所有的数据包的特征,让它们被扔掉或者被拒绝。实际上,这么做会让防火墙规则越来越庞大,以致于某一天拖累系统的运行。

为了解决这个潜在的麻烦,我们可以去更改默认的策略,设置为默认拒绝所有的数据包,然后在防火墙规则里面描述一些我们所需要的数据包的特征,以方便这些符合需要的数据包通过。我们可以把规则链默认的策略,设置为DROP或者REJECT。这样做会有许多好处,因为我们知道我们的服务器需要提供什么样的服务,只需要让这些服务发送或者接受的数据包正常通过就行了;同时,我们也可以去拒绝个别场景下的数据包,以让我们的服务器正常运行,比如禁止某一个想要干坏事的IP地址来访问我们的服务器。

14.5.2 把默认的Policy改成DROP


我们可以先执行命令iptables -L,查看一下防火墙规则的列表。我们会发现INPUT、OUTPUT、FORWARD这三个规则链默认的策略都是ACCEPT。

如果我们想把这些Chain的默认策略改成DROP,我们可以先执行iptables -F命令,把所有的防火墙规则都清洗掉,以便我们重新添加规则。然后我们执行命令service iptables save,保存一下配置文件。

接下来我们准备把INPUT这个Chain的默认的策略改成DROP,不过需要注意的是,我们不能把自己挡在外面,所以我们需要添加一个规则,允许当前已经建立的相关连接的数据包能够进入服务器。如图14-18所示,我们可以执行命令iptables -A INPUT -m conntrack —ctstate ESTABLISHED,RELATED -j ACCEPT,来达到我们上面描述的意图。这里的“m”,是英文module的缩写,意思是模块;后面的conntrack则是模块的名称,中文意为连接跟踪,它提供了一些功能,比如说ctstate。其中的“ESTABLISHED”,是允许已经创建的连接保持当前状态;紧接着在英文逗号后面,又加了一个“RELATED”,表示跟这个连接相关的数据包。
2-5-18-1-700×70.png
图14-18 允许当前已经建立的相关连接的数据包能够进入服务器

然后我们再为SSH服务打开需要的端口,一般情况下默认端口为22。我们输入命令iptables -A INPUT -p tcp —dport 22 -j ACCEPT进行回车执行,即可打开SSH服务默认的22端口,让SSH服务能够使用22端口传输数据包。

做完上面的操作以后,我们就可以把INPUT这个规则链的默认策略更改成DROP了。我们输入命令iptables -P INPUT DROP回车执行,然后输入命令service iptables save保存配置。

14.5.3 允许本地流量


有一些数据包会从本地主机发出,目的地也是本地主机。这些流量会用到一个虚拟网卡,名为loopback,它还有一个缩写“lo”。我们可以查看一下网络相关的配置,输入命令ifconfig,我们可以看到lo相关的设备信息,如图14-19所示。
2-5-19-1-550×360.png
图14-19 查看系统的网络配置

一般本地主机的服务与服务之间进行通信的时候,会用到这个虚拟网卡,比如说我们在服务器上安装数据库的服务、本地主机上的应用连接到本地主机上的数据库的时候,就会用到这个名叫lo的虚拟网卡。一般来说,数据库连接的端口就是给数据库服务的那个端口号,我们需要允许这样的流量通过虚拟网卡。

我们输入命令iptables -I INPUT 1 -i lo -j ACCEPT,把一条新规则插入到INPUT这个Chain的第一行;因为这种流量比较常见,所以我们需要把这条规则插入到第一行。这里的“i”,则是In.interface的缩写,作用是指定数据包进入的网络接口,后面的“lo”则是网络设备的缩写。设置好以后,我们使用service iptables save这个命令,来保存一下我们新添加的防火墙规则。

14.5.4 允许Web服务


Web服务的默认端口号是80,如果我们的网站使用了SSL安全证书加密,那么还需要一个额外的端口——443。

为了让潜在的用户可以访问到我们的网站,我们需要允许在这两个端口上传输的数据包通过。如图14-20所示,我们执行命令iptables -A INPUT -p tcp —dport 80 -j ACCEPT,然后再执行命令iptables -A INPUT -p tcp —dport 443 -j ACCEPT;最后我们输入命令service iptables save,保存一下配置文件。
2-5-20-1-555×55.png
图14-20 允许Web服务

在系统重启以后,我们就可以应用我们刚刚设置的规则;我们也可以选择立即重启服务,让这些规则马上生效。具体命令请大家翻阅本章节前面的文字后再进行操作,这里就不再多做阐述。

拓展知识:
iptables命令线上手册
http://man.linuxde.net/iptables