3.4. 配置安全策略

ipfilter有两个模块:网络地址翻译(network address translator,简称NAT)器与数据包过滤器(packet filter,简称IPF)。NAT用于地址伪装(隐藏单个外部IP地址后面的内部IP地址),还用于重定向主机和端口之间的数据包。包过滤器则按照规则集检查NAT或未NAT过的数据包,以决定丢弃或放行。

由于NAT首先处理数据包,因此我们先配置NAT。网络地址翻译及数据包重定向的规则一律存放在/etc/ipnat.rules文件中。

# 内网NAT规则
map tun0 192.168.1.0/24 -> x.x.x.x/32 portmap tcp/udp 10000:20000
map tun0 192.168.1.0/24 -> x.x.x.x/32
# DMZ NAT规则
map tun0 192.168.2.0/24 -> x.x.x.x/32 portmap tcp/udp 20001:30000
map tun0 192.168.2.0/24 -> x.x.x.x/32

这里"x.x.x.x"代表ISP分配外网接口的实际IP。tun0则是外网接口设备名。如果外部接口未使用串行端口,将tun0替换实际网络接口设备名即可。

这些规则的作用是让NAT模块映像所有在端口为10000-20000,从内网到地址"x.x.x.x"的连接。并映射所有端口为20001-30000,从DMZ到地址"x.x.x.x"的连接。

现在我们可以把内网和DMZ连接到Internet上了,但外网还不能访问DMZ中的服务。我们需要做一个重定向,下面仅仅是一个简单的重定向HTTP数据包的NAT规则:

# 重定向外网的HTTP服务请求
rdr tun0 x.x.x.x/32 port 80 -> 192.168.2.254 port 8080 tcp
rdr tun0 x.x.x.x/32 port 80 -> 192.168.2.254 port 8080 udp
# 重定向内网的HTTP服务请求
rdr fxp1 x.x.x.x/32 port 80 -> 192.168.2.254 port 8080 tcp
rdr fxp1 x.x.x.x/32 port 80 -> 192.168.2.254 port 8080 udp
# 重定向DMZ的HTTP服务请求
rdr fxp2 x.x.x.x/32 port 80 -> 192.168.2.254 port 8080 tcp
rdr fxp2 x.x.x.x/32 port 80 -> 192.168.2.254 port 8080 udp

这里192.168.2.254是DMZ区HTTP服务器的IP地址。出于安全考虑,服务器监听于一个高端口8080。这些规则的作用是将各个接口接收的数据包重定向到"x.x.x.x"的80端口上,那儿才是真正的目的地。

其它服务的NAT规则以此类推,只要更改端口号与服务器的地址就行了。如邮件服务器的重定向规则如下:

# 重定向外网的SMTP服务请求
rdr tun0 x.x.x.x/32 port 25 -> 192.168.2.253 port 25 tcp
rdr tun0 x.x.x.x/32 port 25 -> 192.168.2.253 port 25 udp
# 重定向内网的SMTP服务请求
rdr fxp1 x.x.x.x/32 port 25 -> 192.168.2.253 port 25 tcp
rdr fxp1 x.x.x.x/32 port 25 -> 192.168.2.253 port 25 udp
# 重定向DMZ的SMTP服务请求
rdr fxp2 x.x.x.x/32 port 25 -> 192.168.2.253 port 25 tcp
rdr fxp2 x.x.x.x/32 port 25 -> 192.168.2.253 port 25 udp

照此将设置好所有服务的重定向NAT规则。

下面可以开始考虑包过滤规则了。所有的包过滤规则都放在/etc/ipf.rules文件中。

先考虑lo0接口:lo0 是软件环路接口,在这里阻挡数据包会浪费大量的处理器周期,pass all吧!

pass out quick on lo0 all
pass in quick on lo0 all

关键字quick指示过滤核心一旦数据包匹配上本条规则,立刻中止规则匹配,这样可加快处理速度,并简化了规则的书写。

接着考虑接口tun0。按照预先的设计,我们要在这里阻截所有目的地址不合法的数据包:

block out quick on tun0 from any to 192.168.0.0/16
block out quick on tun0 from any to 172.16.0.0/12
block out quick on tun0 from any to 127.0.0.0/8
block out quick on tun0 from any to 10.0.0.0/8
block out quick on tun0 from any to 0.0.0.0/8
block out quick on tun0 from any to 169.254.0.0/16
block out quick on tun0 from any to 192.0.2.0/24
block out quick on tun0 from any to 204.152.64.0/23
block out quick on tun0 from any to 224.0.0.0/3

这样就防止了有害数据包进入外网。

下面来添加让合法的数据包输出的规则。下面这三条规则允许所有从内网合法地址发往外网的数据流:

pass out quick on tun0 proto tcp from 192.168.1.0/24 to any keep state
pass out quick on tun0 proto udp from 192.168.1.0/24 to any keep state
pass out quick on tun0 proto icmp from 192.168.1.0/24 to any keep state

关键字keep state指示ipfilter记住连接状态,这样可以使此连接的后续数据包不再进行规则检查。关键字proto定义规则所使用的协议。

我们还需要将所有来自DMZ合法地址的数据包能顺利地发送到外网。这很容易做到:只需复制内网规则,更换一下网络地址即可(用192.168.2.0/24 代替192.168.1.0/24):

pass out quick on tun0 proto tcp from 192.168.2.0/24 to any keep state
pass out quick on tun0 proto udp from 192.168.2.0/24 to any keep state
pass out quick on tun0 proto icmp from 192.168.2.0/24 to any keep state

所有其它想通过tun0出外网的数据包均应阻断:

block out quick on tun0 all

以上规则定义了什么样的数据包可以由我们的网络连接外网。下面我们将定义阻断那些想进入防火墙内部的不受欢迎的数据包:

block in     quick on tun0 from 192.168.0.0/16 to any
block in     quick on tun0 from 172.16.0.0/12 to any
block in     quick on tun0 from 10.0.0.0/8 to any
block in     quick on tun0 from 127.0.0.0/8 to any
block in     quick on tun0 from 0.0.0.0/8 to any
block in     quick on tun0 from 169.254.0.0/16 to any
block in     quick on tun0 from 192.0.2.0/24 to any
block in     quick on tun0 from 204.152.64.0/23 to any
block in     quick on tun0 from 224.0.0.0/3 to any
block in log quick on tun0 from x.x.x.x/32 to any
block in log quick on tun0 from any to x.x.x.0/32
block in log quick on tun0 from any to x.x.x.255/32

关键字log将使ipfilter记录所有匹配本条规则的数据包。

这样,所有非法数据包都将被丢弃。但去往DMZ的合法端口的数据包必须让行。以下规则过滤目的端口为80的数据包。

pass in quick on tun0 proto tcp/udp from any to x.x.x.x/32 port = 80 keep state
pass in quick on tun0 proto tcp/udp from any to 192.168.2.254/32 port = 8080 keep state

注意ipf.rules中的地址/端口一定要与ipnat.rules一致。对其余服务如法炮制。

丢弃所有其它外网接口上的数据包:

block in quick on tun0 all 

外网接口规则基本上差不多了。接着考虑内网与DMZ接口。

假设内网接口为fxp1上,先丢弃所有想连接内网的数据包:

block out quick on fxp1 all

再限制对内网DNS的访问(即列在/etc/resolv.conf 文件中的DNS服务器):

pass out quick on fxp1 proto tcp from 192.168.1.1 to 192.168.1.2/32 port = 53 keep state
pass out quick on fxp1 proto udp from 192.168.1.1 to 192.168.1.2/32 port = 53 keep state

或者干脆用外部DNS服务器"y.y.y.y" 和 "z.z.z.z"来代替内部DNS服务器。在/etc/resolv.conf文件中:

lookup file bind
nameserver y.y.y.y
nameserver z.z.z.z

注意,关键字"out"定义了数据包的一种流向:从防火墙的上层协议进入底层协议,由接口输出(如流向外网的数据包);"in"定义了数据包的另一种流向:由接口输入,并从防火墙的底层协议进入上层协议(如流向内网的数据包)。

下列规则定义了什么样的数据包可以进入防火墙:

block in     quick on fxp1 from 172.16.0.0/12 to any
block in     quick on fxp1 from 10.0.0.0/8 to any
block in     quick on fxp1 from 127.0.0.0/8 to any
block in     quick on fxp1 from 0.0.0.0/8 to any
block in     quick on fxp1 from 169.254.0.0/16 to any
block in     quick on fxp1 from 192.0.2.0/24 to any
block in     quick on fxp1 from 204.152.64.0/23 to any
block in     quick on fxp1 from 224.0.0.0/3 to any
block in log quick on fxp1 from x.x.x.x/32 to any
block in log quick on fxp1 from any to x.x.x.0/32
block in log quick on fxp1 from any to x.x.x.255/32
pass in quick on fxp1 proto tcp from 192.168.1.0/24 to any keep state
pass in quick on fxp1 proto udp from 192.168.1.0/24 to any keep state
pass in quick on fxp1 proto icmp from 192.168.1.0/24 to any keep state
block in quick on fxp1 all

DMZ区与内网不同,它主要是一些对外开放的服务。首先,我们不限制内网到DMZ的通信:

pass out quick on fxp2 proto tcp from 192.168.1.0/24 to 192.168.2.0/24 keep state
pass out quick on fxp2 proto udp from 192.168.1.0/24 to 192.168.2.0/24 keep state
pass out quick on fxp2 proto icmp from 192.168.1.0/24 to 192.168.2.0/24 keep state

接下来,阻断所有其余的数据包:

block out quick on fxp2 from any to 192.168.0.0/16
block out quick on fxp2 from any to 172.16.0.0/12
block out quick on fxp2 from any to 127.0.0.0/8
block out quick on fxp2 from any to 10.0.0.0/8
block out quick on fxp2 from any to 0.0.0.0/8
block out quick on fxp2 from any to 169.254.0.0/16
block out quick on fxp2 from any to 192.0.2.0/24
block out quick on fxp2 from any to 204.152.64.0/23
block out quick on fxp2 from any to 224.0.0.0/3

然后,对来自外网的访问公开地址的数据包放行:

pass out quick on fxp2 proto tcp from any to 192.168.2.254/32 port = 8080 keep state
pass out quick on fxp2 proto udp from any to 192.168.2.254/32 port = 8080 keep state
pass out quick on fxp2 proto tcp from any to 192.168.2.253/32 port = 25 keep state
pass out quick on fxp2 proto udp from any to 192.168.2.253/32 port = 25 keep state

最后,阻断其余的数据包:

block out quick on fxp2 all

到目前为止,我们还未设置由DMZ到外网的过滤规则,Internet上的数据包,我们将让所有从合法地址发送的数据包通过:

block in   quick on fxp2 from 172.16.0.0/12 to any
block in     quick on fxp2 from 10.0.0.0/8 to any
block in     quick on fxp2 from 127.0.0.0/8 to any
block in     quick on fxp2 from 0.0.0.0/8 to any
block in     quick on fxp2 from 169.254.0.0/16 to any
block in     quick on fxp2 from 192.0.2.0/24 to any
block in     quick on fxp2 from 204.152.64.0/23 to any
block in     quick on fxp2 from 224.0.0.0/3 to any
block in log quick on fxp2 from x.x.x.x/32 to any
block in log quick on fxp2 from any to x.x.x.0/32
block in log quick on fxp2 from any to x.x.x.255/32
pass in quick on fxp2 proto tcp from 192.168.2.0/24 to any keep state
pass in quick on fxp2 proto udp from 192.168.2.0/24 to any keep state
pass in quick on fxp2 proto icmp from 192.168.2.0/24 to any keep state
block in quick on fxp2 all

规则写完了,该加载生效了。

ipfilter规则文件的加载方式是:

ipf -Fa -f /etc/ipf.rules
ipnat -FC -f /etc/ipnat.rules

如果想清空规则,则请运行:

ipf -Fa
ipnat -FC

还可以用ipfstat、ipftest等工具进行简单的调试。