十一,iptables详解(11):iptables之网络防火墙

  我们一起来回顾一下之前的知识,在第一篇介绍iptables的文章中,我们就描述过防火墙的概念,我们说过,防火墙从逻辑上讲,可以分为主机防火墙与网络防火墙。

  主机防火墙:针对于单个主机进行防护。

  网络防火墙: 往往处于网络入口或边缘,针对于网络入口进行防护,服务于防火墙背后的本地局域网。

  在前文的举例中,iptables都是作为主机防火墙的角色出现的,那么,iptables怎样作为网络防火墙呢?这就是我们今天要聊的话题。

  回到刚才的概念,网络防火墙往往处于网络的入口或者边缘,那么,如果想要使用iptables充当网络防火墙,iptables所在的主机则需要处于网络入口处,示意图如下。

 

 

   上图中,橘黄色主机为iptables所在主机,此时iptables充当的角色即为网络防火墙,上图中的浅蓝色圆形表示网络防火墙所防护的网络区域,圆形内的蓝色矩形表示网络内的主机。

  当外部网络中的主机与网络内部主机通讯时,不管是由外部主机发往内部主机的报文,还是由内部主机发往外部主机的报文,都需要经过iptables所在的主机,由iptables所在的主机进行"过滤并转发",所以,防火墙主机的主要工作就是"过滤并转发",那么,说到这里,我们则不得不再次回顾之前的iptables报文流程图了,如下:

 

 

   前文中,iptables都是作为"主机防火墙"的角色出现的,所以我们举例时,只用到了上图中的INPUT链与OUTPUT链,因为拥有"过滤功能"的链只有3条,INPUT、OUTPUT、FORWARD,当报文发往本机时,如果想要过滤,只能在INPUT链与OUTPUT链中实现,而此时,iptables的角色发生了转变,我们想要将iptables所在的主机打造成"网络防火墙",而刚才已经说过,网络防火墙的职责就是"过滤并转发",要想"过滤",只能在INPUT、OUTPUT、FORWARD三条链中实现,要想"转发",报文则只会经过FORWARD链(发往本机的报文才会经过INPUT链),所以,综上所述,iptables的角色变为"网络防火墙"时,规则只能定义在FORWARD链中。

  环境准备

  那么为了能够进行实验,我们来设置一下实验场景,如下图所示

 

 

   我们假设,上图中圆形所示的网络为内部网络

  注:此处所描述的内网、外网与我们平常所说的公网、私网不同。

  此处描述的内外部网络你可以理解成两个网段,A网络与B网络,为了方便描述,我们把圆形内的主机称为内部主机,把上图中圆形所表示的网络称为内部网络,把圆形外的网络称为外部网络。

   假设,内部网络的网段为172.16.0.0/16,此内部网络中存在主机C,主机C的IP地址为172.16.30.1。

  上图中的主机B充当了网络防火墙的角色,主机B也属于内部网络,同时主机B也能与外部网络进行通讯,如上图所示,主机B有两块网卡,网卡1与网卡2,网卡1的IP地址为172.16.30.3,网卡2的IP地址为192.168.1.146,所以,防火墙主机在内部网络中的IP地址为172.16.30.3,防火墙主机与外部网络通讯的IP地址为192.168.1.146。

  上图中的主机A充当了"外部网络主机"的角色,A主机的IP地址为192.168.1.147,我们使用主机A访问内部网络中的主机C,但是需要主机B进行转发,主机B在转发报文时会进行过滤,以实现网络防火墙的功能。

  我已经准备了3台虚拟机,A、B、C

  由于B主机现在的角色是172.16.0.0中的"网络防火墙",那么,我们直接将C主机的网关指向B主机的内部网络IP,如下图所示

 

 

   同时,为了尽量简化路由设置,我们直接将A主机访问172.16网络时的网关指向B主机的网卡2上的IP,如下图所示。

root@node1 html]# route add -net 172.16.0.0/16 gw 192.168.1.146

   查看路由

 

 

   保证AC主机是可以互通的,并且是走对应网关的

  A主机查看

 

 

   C主机查看

 

 

   环境准备完毕,下面开始测试

 

  网络防火墙测试

  之前说过,iptables作为网络防火墙时,主要负责"过滤与转发",既然要过滤,则需配置filter表,既然要转发,则需在FORWAED链中定义规则,所以,我们应该在filter表中的FORWARD链中配置规则。

  那么,我们先来看看主机B上的filter表中是否已经存在规则,如下

 

   从上图可以看出,FORWARD链中没有任何规则,默认策略为ACCEPT,我们可以使用"白名单机制"(如果忘了请回顾前文:黑白名单机制)

  在主机B中FORWARD链的末端添加一条默认拒绝的规则,然后将"放行规则"设置在这条"默认拒绝规则"之前即可。

  示例如下

[root@node2 ~]# iptables -A FORWARD -j REJECT
[root@node2 ~]# iptables -nvL
Chain INPUT (policy ACCEPT 20 packets, 3524 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
   32  2003 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable

Chain OUTPUT (policy ACCEPT 41 packets, 5794 bytes)
 pkts bytes target     prot opt in     out     source               destination         

   好了,配置完上述规则后,主机A与主机C已经无法通讯了,因为它们之间如果想要通讯,则需要靠主机B进行转发,而上述规则设置完成后,所有报文都无法通过FORWARD链了,所以任何经过转发的报文在经过FORWARD链时都会被拒绝,外部主机的报文无法转发到内部主机中,内部网主机的报文也无法转发到外部主机中,因为主机B已经拒绝转发所有报文。

  现在,我们同时将A主机与C主机中的web服务启动,以便进行测试。

  首先,我们启动A主机的httpd服务

 

  启动C主机的httpd服务

 

systemctl start httpd

   由于刚才已经在主机B中设置了默认拒绝的规则,所以此刻,A主机无法访问C主机的web服务,C主机同样无法访问A主机的web服务。

  那么,如果我们想要使内部的主机能够访问外部主机的web服务,我们应该怎样做呢?没错,我们需要在FORWARD链中放行内部主机对外部主机的web请求,只需如下配置即可。

[root@node2 ~]# iptables -I FORWARD -s 172.16.0.0/16 -p tcp --dport 80 -j ACCEPT
[root@node2 ~]# iptables -nvL
Chain INPUT (policy ACCEPT 24 packets, 3900 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    1    60 ACCEPT     tcp  --  *      *       172.16.0.0/16        0.0.0.0/0            tcp dpt:80
 2004  134K REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable

Chain OUTPUT (policy ACCEPT 47 packets, 6790 bytes)
 pkts bytes target     prot opt in     out     source               destination         

   如上图所示,防火墙放行了内部主机的web请求,因为我们将来自内部网络中目标端口为80的报文都放行了,那么此时,我们在C主机上访问A主机的web服务试试

  此时,在主机C上访问主机A的web服务,如下

 

   可以看到,主机C并无法访问到主机A上的web服务,这是为什么呢?

  聪明如你肯定已经想到了,我们只在主机B上放行了内部主机访问80端口的请求,但是并没有放行外部主机的回应报文,虽然内部主机的请求能够通过防火墙主机B转发出去,但是回应的报文则无法进入防火墙,所以,我们仍然需要在主机B上进行如下设置。

[root@node2 ~]# iptables -I FORWARD -d 172.16.0.0/16 -p tcp --sport 80 -j ACCEPT
[root@node2 ~]# iptables -nvL --line
Chain INPUT (policy ACCEPT 18 packets, 3278 bytes)
num   pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1        0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            172.16.0.0/16        tcp spt:80
2       40  2400 ACCEPT     tcp  --  *      *       172.16.0.0/16        0.0.0.0/0            tcp dpt:80
3     4636  309K REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable

   如上图所示,当外部主机中的web服务响应内部主机时,目标地址肯定为内部主机,所以,我们需要放行目标IP属于内部主机网段的报文,源端口为80,因为外部主机肯定会使用80端口进行回应。

  完成上述配置后,再次回到C主机上,访问A主机的web服务,可以看到,已经能够正常访问了。

 

   从上述示例可以看出,当iptables作为"网络防火墙"时,在配置规则时,往往需要考虑"双向性",也就是说,我们为了达成一个目的,往往需要两条规则才能完成。

  那么此时,A主机能够访问C主机中的web服务吗?我想你已经知道答案了,没错,A主机此时无法访问C主机中的web服务,因为B主机中并没有放行相关报文。

  结合之前的知识,我们可以将上述规则配置进行优化,比如,不管是由内而外,还是由外而内,只要是"响应报文",我们统统放行,配置如下

  注:如果你没有明白如下配置的含义,请回顾之前的文章

 

   如上图所示,先将"web响应报文放行规则"删除,同时增加了上图中的规则,只需要在网络防火墙主机的FORWARD链中添加如上一条规则,就可以将绝大多数响应报文放行了,不管是外部响应内部,还是内部响应外部,一条规则就能搞定,当iptables作为网络防火墙时,每次配置规则时都要考虑"双向"的问题,但是配置完上述规则后,我们只要考虑请求报文的方向就行了,而回应报文,上述一条规则就能搞定,这样配置,即使以后有更多服务的响应报文需要放行,我们也不用再去针对响应报文设置规则了(具体原因前文已经详细的总结过),应该会让我们省去不少规则吧。

  比如,我们除了想要让内部主机能够访问外部的web服务,还想让内部主机能够访问外部的sshd服务,那么,我们则可以进行如下设置。

[root@node2 ~]# iptables -I FORWARD -p tcp -s 172.16.0.0/16 --dport 22 -j ACCEPT
[root@node2 ~]# iptables -nvL FORWARD --line
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1       10  2213 ACCEPT     tcp  --  *      *       172.16.0.0/16        0.0.0.0/0            tcp dpt:22
2       10  2321 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
3       92  5557 ACCEPT     tcp  --  *      *       172.16.0.0/16        0.0.0.0/0            tcp dpt:80
4     9153  608K REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable

   此刻,使用C主机即可访问A主机的22端口。

 

   目前,我们只允许内部主机访问外部主机的web服务与sshd服务,但是外部主机还无法访问内部主机的服务

   可以使用如下配置

[root@node2 ~]# iptables -I FORWARD -p tcp -s 192.168.1.147 --dport 80 -j ACCEPT
[root@node2 ~]# iptables -nvL FORWARD --line
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1        6   395 ACCEPT     tcp  --  *      *       192.168.1.147        0.0.0.0/0            tcp dpt:80
2       11  2265 ACCEPT     tcp  --  *      *       172.16.0.0/16        0.0.0.0/0            tcp dpt:22
3       15  2848 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
4       97  5857 ACCEPT     tcp  --  *      *       172.16.0.0/16        0.0.0.0/0            tcp dpt:80
5    10321  685K REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable

   源主机为192.168.1.147目的端口是80 通过

  设置后使用A主机访问C主机

 

   小结

#如果想要iptables作为网络防火墙,iptables所在主机开启核心转发功能,以便能够转发报文。
#使用如下命令查看当前主机是否已经开启了核心转发,0表示为开启,1表示已开启
cat /proc/sys/net/ipv4/ip_forward
#使用如下两种方法均可临时开启核心转发,立即生效,但是重启网络配置后会失效。
方法一:echo 1 > /proc/sys/net/ipv4/ip_forward
方法二:sysctl -w net.ipv4.ip_forward=1
#使用如下方法开启核心转发功能,重启网络服务后永久生效。
配置/etc/sysctl.conf文件(centos7中配置/usr/lib/sysctl.d/00-system.conf文件),在配置文件中将 net.ipv4.ip_forward设置为1
 
#由于iptables此时的角色为"网络防火墙",所以需要在filter表中的FORWARD链中设置规则。
#可以使用"白名单机制",先添加一条默认拒绝的规则,然后再为需要放行的报文设置规则。
#配置规则时需要考虑"方向问题",针对请求报文与回应报文,考虑报文的源地址与目标地址,源端口与目标端口等。
#示例为允许网络内主机访问网络外主机的web服务与sshd服务。
iptables -A FORWARD -j REJECT
iptables -I FORWARD -s 10.1.0.0/16 -p tcp --dport 80 -j ACCEPT
iptables -I FORWARD -d 10.1.0.0/16 -p tcp --sport 80 -j ACCEPT
iptables -I FORWARD -s 10.1.0.0/16 -p tcp --dport 22 -j ACCEPT
iptables -I FORWARD -d 10.1.0.0/16 -p tcp --sport 22 -j ACCEPT
 
#可以使用state扩展模块,对上述规则进行优化,使用如下配置可以省略许多"回应报文放行规则"。
iptables -A FORWARD -j REJECT
iptables -I FORWARD -s 10.1.0.0/16 -p tcp --dport 80 -j ACCEPT
iptables -I FORWARD -s 10.1.0.0/16 -p tcp --dport 22 -j ACCEPT
iptables -I FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
 

   

  一些注意点:

  1、当测试网络防火墙时,默认前提为网络已经正确配置。

  2、当测试网络防火墙时,如果出现问题,请先确定主机防火墙规则的配置没有问题。

 

   



   

posted @ 2020-09-03 16:14  minseo  阅读(592)  评论(0编辑  收藏  举报