13.2.4 自定义规则
当然,iptbales不只可以设置默认规则,还可以手动加入很多规则。首先我们来看一下路由器的网卡配置:
结合之前的实验图,可知主机A连接到ens33网卡,主机B连接到ens34网卡。
再运行如下命令(为了演示清晰,我们一条命令一次清空规则):
iptables -A INPUT -j DROP ---给INPUT链增加规则,拒绝所有通信
以上命令后,ApingR或BpingR都不通,但ApingB可通。PS:思考一下原因。
iptables -F
iptables -A INPUT -i ens33 -j DROP ---给INPUT链增加规则
注:-i 指定in-interface,即接收数据的网卡,则ens33网卡拒绝接收任何数据。则ApingR不通,但是BpingR通(因为BpingR走的是ens34),ApingB也通(因为路由器转发时审核FORWARD链)。
iptables -F
iptables -A FORWARD -i ens33 -s 202.0.0.0/24 -j DROP
注:-s 指定源地址 也可用202.0.0.1 指定ip,本命令实现ens33网卡拒绝转发源地址是202.0.0.1的数据包,则ApingB不通,ApingR或BpingR通。
iptables -F
iptables -A FORWARD -i ens33 -d 192.168.10.2 -j DROP
注:-d 指定目的地址, 本命令实现ens33网卡拒绝转发目的地址是192.168.10.2的数据包,则ApingB不通,ApingR或BpingR通,但如果10.0网段内还有10.3、10.4等主机的话,A是可以ping通它们的,因为规则中只拒绝了目的是10.1的通信。
好了,有了以上的案例,我们来做一个小的总结,分析如下命令:
iptables -F
iptables -A FORWARD -i ens33 -s 202.0.0.10 -d 192.168.10.2 -j DROP
命令功能是拒绝202.0.0.10到192.168.10.2的通信(若有202.0.0.10的主机,ping B一定不通),那么202.0.0.1ping主机B通吗?答案是通的,因为FORWARD链中这条规则只拒绝了202.0.0.10到192.168.10.2,并未明确拒绝202.0.0.1到192.168.10.2,则该条规则,并不匹配202.0.0.1到192.168.10.2的通信,按照iptables原理,不匹配这条规则,则去审核下一条规则,但又没有下一条规则了,则按照默认规则(即policy)执行,policy是ACCEPT允许的,则202.0.0.1到192.168.10.2可通。
所以总结:当链中一条规则审核某个通信时,该通信的数据包,必须符合规则中的所有条件(即所有参数设置),才被视为匹配这条规则,否则,即使有一个条件不符合,也会被视为不匹配规则,那么将转去审核下一条规则。若链中所有规则与该通信都不匹配,则按照默认规则执行。PS:我们现在只讲了-i –s –d三个参数,还好理解,但以后一条规则中可能会有更多的参数,则都按照此总结执行,切记切记。
tips:以上两段文字读者可以多读即便,理解清楚原理。
再看下面的案例:
iptables -F
iptables -A FORWARD -i ens33 -s 202.0.0.0/24 -j DROP
iptables -A FORWARD -i ens33 -d 192.168.10.2 -j DROP
iptables -A FORWARD -i ens33 -s 202.0.0.1 -d 192.168.10.2 -j ACCEPT
iptables -L ---查看一下
以上几条命令给FORWARD链中增加了三条规则,其中最后一条规则是允许202.0.0.1到10.2(即主机B)的通信,那么我们可以尝试一下,ApingB通吗?会发现还是不通的。这是因为链中规则在审核时,是按照从上到下的顺序依次审核的,遇到一条匹配的,则会立即执行了,就不再审核之后的规则,所以以上案例中,ApingB时审核到第一条规则,拒绝202.0.0.0/24网段到任何地址,是匹配的,则立即被拒绝了,后面的负责根本没有被审核,所以ApingB不同。
所以,链中规则是有严格的逻辑排列顺序的,我们在制定规则时需要设计清楚规则的顺序。但是,我们在输入命令时,一旦有失误遗漏了某条命令,难道还需要清除所有,重新写入吗?当然Linux是没有这么low的,iptables也是可以做插入或删除规则的。命令如下:
iptables -I FORWARD 1 -iens33 -s 202.0.0.1 -d 192.168.10.2 -j ACCEPT
注:-I插入规则,链名后设定插入到的序号,即1表示插入到第一条位置
这样,ApingB可通了。
iptables -D FORWARD 1 --- -D 删除链中指定序号的规则
然后,ApingB又不通了。
之上,我们介绍了对数据包中目的ip及源ip的限制,属于第三层网络层的审核,下面来对第四层的信息做审核:
iptables -F
iptables -A FORWARD –i ens33 -p tcp -j DROP --- -p 指定协议
注:-p后可指定的协议只有:tcp udp icmp
以上命令,实现拒绝公网的主机访问内网的所有tcp请求,举例来说就是如果内网有一台web服务器,公网主机是无法访问的(读者可自行在主机B上部署web服务以验证)。但是ApingB是通的,因为规则中我们只拒绝了tcp通信,并未拒绝icmp协议(ping命令是属于ICMP协议中的命令)。
tips:在这里,如果对网络通信基础(即TCP/IP协议)了解比较清楚的读者,可能会问了,ICMP协议是属于网络层的协议,tcp、udp是属于传输层的协议,且ICMP协议也是借助于tcp协议的7号端口通信的,为什么拒绝tcp时,icmp会通呢?原因要从通信的封装上来讲。
我们知道,按照OSI七层结构(TCP/IP协议是由OSI协议发展而来的)的封装原理,软件要发送的原始数据会由7、6、5、4、3、2、1的顺序逐层封装的。正常的数据通信,当封装到第四层时,第四层会使用TCP或UDP协议的格式进行封装,然后交给第三层。第三层网络层的功能是实现网络寻址,使用的寻址方式是ip,所以第三层会按照IP协议封装,如下图:
第三层网络层共有四个常用协议:IP、ICMP、ARP、RARP。其中IP协议实现网络寻址、ICMP协议可实现网络连接探测。ping命令就是ICMP协议规定的命令之一。所以当我们使用ping命令时,实际上走的是ICMP协议。但是ping命令的格式是ping后面写目标主机的ip(如:ping 192.168.10.2),所以可知,ping命令也是要借助于ip地址寻址的,也就是说,ICMP也是要借助IP协议工作的。从封装的角度来说,第四层传输层封装完毕交给第三层后,会由ICMP协议封装,再由IP协议封装,如下图:
图中可见:ICMP协议是被IP协议封装的。
所以从封装的角度来看,可以被IP协议封装在内的协议有TCP、UDP、ICMP三种,所以iptables的-p参数后可以指定这三个参数。而且基于如此也把ICMP视为一种独立的协议了。
到此,我们可知道 –p tcp的话会拒绝所有tcp通信,包括:web、ftp、ssh、NFS等等的所有tcp服务。如果我们要只拒绝某个特定服务呢?iptbales是通过服务的端口做限制的,命令如下:
iptables -F
iptables -A FORWARD -i ens33 -p tcp --dport 22 -j DROP
注:--dport 指定目的端口
如上命令,就可以仅屏蔽公网访问内网的ssh服务了,但仍然可以访问web服务。
按照以上思路可知,加参数--sport参数是设定源端口的,来看命令:
iptables -F
iptables -A FORWARD -o ens33 -p tcp --sport 22 -j DROP
功能:拒绝ens33向外发出源端口是22的数据
解释一下:为了通过设置源端口验证拒绝公网主机访问内网主机的ssh服务,我们先来分析一下访问原理,当公网客户端请求访问内网主机的ssh服务时,客户端会开启一个动态端口(TCP 1024以上的某个端口),请求访问服务器的TCP 22端口,那么从封装的角度看,第四层封装的目的端口是22,源端口是1024以上的某个端口。服务器收到后,会以22端口回复给客户端,那么回复时,从ens33网卡发出的数据源端口是22。所以我们在以上命令中设定参数 –o ens33,-o表示out-interface,即指定发出数据的端口审核本规则,--sport参数设定源端口。
以上针对端口做了限制,iptables还可以针对传输层标记位做限制。我们知道,传输层的TCP连接需要经过三次握手,即双方的三次通信,控制标记位分别是:syn、syn ack、ack。iptables也可以针对这些标记位做限制。
先来介绍一下案例需求:如果我们想让内网主机可以正常访问公网,但是公网主机无法访问内网服务,实现对内网的保护。这该如何设置呢?如果我们在ens33网卡上拒绝tcp访问进入,那么正常内网访问公网时,公网回复的数据也是走tcp通信的,则也会被屏蔽掉。所以,需要在ens33网卡上设置拒绝公网主动访问内网的数据进入,但是允许公网回复给内网的数据进入,也就是说ens33网卡上拒绝标记位是syn的请求类数据进入,允许syn ack相应、回复类数据进入,具体命令如下:
iptables -F
iptables -A FORWARD -i ens33 -p tcp --syn -j DROP
注: --syn 指定传输层标记位,但iptables中仅支持设置syn标记位,设置别的标记位会报错。
读者可以在主机A上也部署web服务,尝试A访问B的web服务不同,但B访问A的web服务可通。
借助于以上思想,我们还可设计iptbales允许内网主动ping公网,但拒绝公网主动ping内网。我们知道,ping命令是一去一回的过程,即向对方发送ping请求,并收到对方回复后才视为可通,在ping中,请求数据称为echo-request请求数据(又称为ping操作),回复数据称为echo-replay数据(又称为pong操作),为了便于识别,给echo-request数据设定的标记数字为0 ,echo-rely数据设定的标记数字为8(IP协议的封装格式中有对内部所封装协议的标记区域,通过填如0或8以区别request或reply,6表示TCP协议,17表示UDP协议。对网络基础比较熟悉的读者可以回忆一下,若不太熟,可以只记数字就好了)。
所以,在iptables上可以通过对标记数字做设置:
iptables -A FORWARD -i ens33 -p icmp --icmp-type 8 -j DROP
这样就可以实现上述效果了。