admin管理员组

文章数量:1647839

摘要:本文将向读者介绍IP Filter防火墙,同时也将介绍一些防火墙设计的基本原理。
一.引言
1. IP Filter是一款很棒的小型防火墙。与其他一些免费防火墙相比(ipfwadm, ipchains, ipfw),它更加小巧并且设计优雅。本文将系统地向读者介绍IP Filter防火墙。本文还将在使用规则方面介绍各种包过滤防火墙的相同点和不同点。如果你在以前对包过滤防火墙有一点认识的话你会发现那是非常有用的。当然如果你对此非常熟悉的话,你反而会觉得这篇文章在浪费你的时间。对此,我们强烈建议你阅读Chap-man与Zwicky O’Reilly合著的《Building Internet Firewalls》以及Stevens与Addison-Wesley合著的《TCP/IP Illustrated》第一卷.
2. 注意:本文旨在介绍如何构建基于IP-Filter的防火墙,作者对因此引起的各种损坏不负责任。如果你不同意,你可以去聘请一位经验丰富的安全专家为你构建防火墙。
3. 本文的版权归本文作者所有,任何复制与翻译请保留此版权声明。
IP-Filter的官方主页:
http://coombs.anu.edu.au/~avalon/
BSD平台下的IP-Filter:
http://www.benzedrine.cx/pf.html
本文的最新版本可在如下网址找到
http://www.obfuscation/ipf/
二.的防火墙都具备的,本章的基础知识对后续章节的阅读很有帮助,但必须明白的是仅仅防火墙基础知识
本章将使你对IP Filter的规则与防火墙理论有个总体认识,文中涉及到的所有功能是所有设计优秀阅读本章还是不够的,要想构建一个高效安全的系统,你还需要认真阅读后续章节。
1. 配置文件
IP-Filter有一个配置文件(与那些逐条执行命令的不同),在Unix下配置文件每条规则为一行,有“#”标志的表明是注释,规则与注释可以在同一行,并且允许空格存在,以增强可读性。
2. 基本规则的处理
所有规则都将被由上至下而执行。这意味着如果你的配置文件如下:
block in all
pass in all

计算机将这样处理:
block in all
pass in all

也就是说当有一个包进来,IP-Filter所做的第一件事是:
block in all

如果IP-Filter认为有必要,它会移向下一条规则并执行它:
pass in all

此时你可能要问:“IP-Filter会移向下一条规则吗?”
如果你对ipfwadm和ipfw熟悉的话,可能你就不会问了,并被搞得晕头转向,因为有的包不该通过却通过了而不该禁止的却被禁止了。
许多包过滤防火墙都是在执行到与规则匹配时就不再继续将包与规则进行比较了,但IP-Filter不是这样。除非你强行中断,否则它会将包与所有规则进行比较,是否允许包通过取决于最后一条匹配的规则。在上例中,IP-Filter先看看包,再看看第一条规则:
block in all

IP-Filter想:“到目前为止,我想应该禁止这个包,”然后它又看看第二条规则:
Pass in all

“到目前为止,我想应该让这个包通过,”IP-Filter又看看第三条规则,已经没有规则了,所以它让这个包通过了。应该指出,即使规则如下包仍能通过:
block in all
block in all
block in all
block in all
pass in all

也就是说,没有累积效应,最后匹配的规则拥有优先权。
3. 特殊规则的处理
如果你对其它包过滤防火墙熟悉的话,你会觉得这种设计令人头晕,不够简洁并且处理速度不高。设想,你有100条规则,其中常用的是前10条,如果每个包到来时都让它全部比较的话会令事情变得很糟糕。幸运的是有一个关键词quick可以避免这种情况发生。如果有如下规则:
block in quick all
pass in all

这种情况下IP-Filter先看看第一条规则:
block in quick all

数据包与规则匹配,检查结束,包将被毫无疑问的丢掉,没有记录,没有警告,什么都没有,下一条规则:
pass in all

计算机根本就没遇到,它就如同不在配置文件里一样,前面规则中的终止关键词quick使得后面的规则失效。在这里IP-Filter虽然干得不错,但所有包都被丢掉了,为了使一些包通过,我们得做些修改。
4. IP控制
有很多标准可用于包过滤,最常用的是基于IP的,有很多IP地址是在公共网络传输时永远都不会遇到的,比如:192.168.0.0/16(16是子网掩码,如果以十进制并带点的形式写出也许你会更熟悉255.255.0.0,两种方式IP-Filter都接受)。如果你想禁止192.168.0.0/16,你可以这样:
block in quick from 192.168.0.0/16 to any
pass in all

现在我们有了一条实用的规则了,想象一下,如果有一个包从1.2.3.4来,检查第一条规则:
block in quick from 192.168.0.0/16 to any

包是从1.2.3.4来的而非192.168.*.*,不匹配,检查第二条规则:
pass in all

1.2.3.4当然是all的一部分,匹配,所以此包通过。
不久,又有一个包从192.168.1.2来,先检查第一条规则:
block in quick from 162.168.0.0/16 to any

匹配,包被丢弃,防火墙不再检查后面的规则,因为此处条件满足且有关键词quick,既然我们打算禁止私有地址通过防火墙,让我们把其它的也添上:
block in quick from 192.168.0.0/16 to any
block in quick from 172.16.0.0/12 to any
block in quick from 10.0.0.0/8 to any
pass in all


三个IP地址都是一些私有IP地址。
5. 接口控制
现在的公司在连接Internet前一般都会有内部的局域网,这也是很多公司考虑使用防火墙的一个主要原因。将内网与外网连接起来的机器叫路由。路由与一般机器的区别在于路由拥有多于一个的网络接口。你接受到的每一个包都是从网络接口上传来,你发送的每一个包都是从网络接口上传出的。如果你有三个接口:lo(回受),x10(3com网卡),tun0(FreeBSD下PPP协议的通用接口),你想禁止从tun0上传来的包通过,你可以这样:
block in quick on tun0 all
pass in all


这样,如果包从tun0上传来,第一条规则将禁止它通过,当包从lo或x10上传来,第一条规则不匹配而第二条匹配,所以包被允许通过。
6. 同时控制IP和接口
很少有人会将tun0激活却不用于数据传输,更多的规则能使防火墙更符合我们的要求,让我们允许除192.168.0.0/16外的所有数据通过tun0,你可以这样构建你的防火墙:
block in quick on tun0 from 192.168.0.0/16 to any
pass in all


与我们以前的规则:
block in quick from 192.168.0.0/16 to any
pass in all


相比,老的规则将所有网络接口上到来的192.168.0.0/16的包都丢弃了,而新的规则只丢弃了tun0上192.168.0.0/16的包。如果在x10上有来自于192.168.0.0/16的包,将被允许通过。
至此,我们已经能定制出功能丰富的防火墙:
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
pass in all


前面三项我们已经见过,第四项的IP是用于回受(loopback)的A类地址,许多软件通过127.0.0.1与自身进行通讯,所以将其禁止是个不错的主意。第五项的0.0.0.0/8在Internet上是绝不会出现的。许多IP堆栈将0.0.0.0/32视为默认的网关,而其余的网络地址0.*.*.*被各种不同的系统用作路由决定。169.254.0.0/16被Internet分址机构 (IANA)指派用于当系统不能由动态主机分配协议(DHCP)获得IP时自动分配的IP。最明显的例子便是当Microsoft操作系统不能找到DHCP主机时就会使用这个IP范围内的某个IP。
192.0.2.0/24在文件中已被作为保留地址。而204.152.64.0/23已被Sun公司作为私有地址保留了,是否要将其禁止完全由你自己决定。而最后的一条规则将用于组播的D类和E类地址禁止。关于E类地址更详细的资料可在RFC 1166上找到。
总的说来,进行包过滤有一条重要的原则:
当你确定某个接口只应该有特定的包到来时,建立系统时,就只允许这些特定的包通过。
比如因为任何从10.0.0.0/8来到tun0的包都是无法应答,无法路由的非法包,所以应禁止它通过。同理,127.0.0.0/8也应禁止。同时,如果你有一个20.20.20.0/24的内网,那么从PPP上将其禁止是比较明智的决定:
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 quick on tun0 from 20.20.20.0/24 to any
pass in all

7.关键词out的使用
到目前为止,我们都只对入站连接进行审核,同理,对出站连接进行审核是一个不错的习惯,比如我们有内网20.20.20.0/24,可以这样使用关键词out:
pass out quick on tun0 from 20.20.20.0/24 to any
block out quick on tun0 from any to any

这样做有两个好处:
这样可以为你的网络节省不少带宽;
可以防止内网的ip欺骗,使别人的电脑更安全,同时也使你的网络对***缺乏诱惑力,你也会更安全.
现在规则变成了:
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 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 127.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
block out quick on tun0 from !20.20.20.0/24 to any

8.关键词log的使用
到目前为止,所有数据都是被无声无息的拦截或悄悄地通过了,难道你不想看看它们都是些什么吗?当然一般情况下你是不会记录下所有的数据,我们只会对特殊的数据感兴趣,比如,也许你对从202.202.202.0/24传来并被拦截的感兴趣,你可以这样(注意关键词log的使用):
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 20.20.20.0/24 to any
pass in all


看起来我们的防火墙干得还不错,不过为防止smurf***(一种以最初发动这种***的程序名来命名的***方法。这种***方法结合使用了IP欺骗和ICMP回复方法使大量网络传输充斥目标系统,引起目标系统拒绝为正常系统进行服务。),我们应该加入以下两行:
block in log quick on tun0 from any to 20.20.20.0/32
block in log quick on tun0 from any to 20.20.20.255/32


所以总的规则变成了这样:
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 20.20.20.0/24 to any
block in log quick on tun0 from any to 20.20.20.0/32
block in log quick on tun0 from any to 20.20.20.255/32
pass in all


9.进一步的完善
让我们来把每个接口都制定好规则,首先是lo0,由于系统的一些软件依赖lo0进行相互间的通讯,就让它疯狂自由的通讯吧:
pass out quick on lo0
pass in quick on lo0

接下来是x10,我们暂且对内部网络充分信任,所以如同lo0一样:
pass out quick on xl0
pass in quick on xl0


最后是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 from 20.20.20.0/24 to any
block out quick on tun0 from any to any
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 20.20.20.0/24 to any
block in log quick on tun0 from any to 20.20.20.0/32
block in log quick on tun0 from any to 20.20.20.255/32
pass in all


好了,整个看起来还不错,20.20.20.0/24既可以防止被ip欺骗,也可以防止被用做ip欺骗。记着,对你自己的网络,要根据你自己的要求制定规则。

10.关键词proto的使用
如今拒绝服务***就象缓冲区溢出***一样普遍,很多拒绝服务******系统的TCP/IP堆栈,使得TCP/IP堆栈被破坏,ICMP包***便是其中的一种,那为何我们不禁止ICMP协议呢:
block in log quick on tun0 proto icmp from any to any

现在,任何从tun0上来的ICMP包都将被记录并丢弃。

11.关键词icmp-type的使用
禁止所有的ICMP在安全角度上是可行的,但安全性和易用性的平衡是永远的话题,比如你想使ping和traceroute命令仍能使用,你不得不启用ICMP Type 0和ICMP Type 11:
pass in quick on tun0 proto icmp from any to 20.20.20.0/24 icmp-type 0
pass in quick on tun0 proto icmp from any to 20.20.20.0/24 icmp-type 11


规则的先后顺序很重要,既然我们在每一条规则里都有quick,所以pass的规则应在block规则前面,所以规则最好是这样:
pass in quick on tun0 proto icmp from any to 20.20.20.0/24 icmp-type 0
pass in quick on tun0 proto icmp from any to 20.20.20.0/24 icmp-type 11
block in log quick on tun0 proto icmp from any to any


将这三条规则与我们上面的规则进行合并。不过合并时应该小心,如果将这三条规则放在前面,就像这样:
pass in quick on tun0 proto icmp from any to 20.20.20.0/24 icmp-type 0
pass in quick on tun0 proto icmp from any to 20.20.20.0/24 icmp-type 11
block in log quick on tun0 proto icmp from any to any
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 20.20.20.0/24 to any
block in log quick on tun0 from any to 20.20.20.0/32
block in log quick on tun0 from any to 20.20.20.255/32
pass in all

那么有一个问题:我们将允许任何目的地址为20.202.20.0/24的ICMP Type 0/11通过,这样等于又陷于smurf***威胁之下,我们可以这样:
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 20.20.20.0/24 to any
block in log quick on tun0 from any to 20.20.20.0/32
block in log quick on tun0 from any to 20.20.20.255/32
pass in quick on tun0 proto icmp from any to 20.20.20.0/24 icmp-type 0
pass in quick on tun0 proto icmp from any to 20.20.20.0/24 icmp-type 11
block in log quick on tun0 proto icmp from any to any
pass in all

将这三条规则放后面,我们先将可疑的包丢弃后再进行ICMP的审核。注意:在进行规则合并时一定要小心。

12.关键词port的使用
许多服务,如rsh,relogin,telnet等使用起来非常方便,但也非常的不安全,到处都充满了嗅探和欺骗,一个折中的办法是只在受信任的内部网络中使用,不在外网中使用。这一点很容易作到,因为它们都使用特定的TCP端口(513,514,23),因此我们创建这样的规则:
block in log quick on tun0 proto tcp from any to 20.20.20.0/24 port = 513
block in log quick on tun0 proto tcp from any to 20.20.20.0/24 port = 514
block in log quick on tun0 proto tcp from any to 20.20.20.0/24 port = 23

把这三条放在pass in all前面就可以抵御危险。也许你还想禁止514/udp(syslog),111/tcp&111/udp(portmap),515/tcp(lpd),2049/tcp&2049/udp(NFS),6000/tcp(X11)等等,你完全可以通过netstat –a查看自己开放的端口并列出想禁用的。要想禁用udp端口只需将上面的tcp换为udp即可,比如要禁用514/udp(syslog),你可以这样:
block in log quick on tun0 proto udp from any to 20.20.20.0/24 port = 514

IP-Filter提供一种同时禁用TCP和UDP的简便方法,比如对Portmap:
block in log quick on tun0 proto tcp/udp from any to 20.20.20.0/24 port = 111


三.防火墙高级知识
以下内容延续上面的基础知识,针对高级防火墙的设计以及IP-Filter的特点作详细讲解,如果你对此能够非常熟悉,你将能够构建起一个强壮的防火墙。
1. 安全的开始
依靠端口对服务进行审核有个大问题,很多服务不是总使用固定的端口,尤其是那些依赖于RPC的服务,如lockd, statd,甚至nfsd有时也不在2049上。与其时刻监视端口与服务的关系,我们还不如这样来得干净:
block in all

对,就是禁止所有,虽然不实用但很安全。假如我们是一个web服务器呢?因为它要做的很少,连DNS查询都不用,只在80/TCP上等待连接,所以我们只需简单的加一条规则:
block in on tun0 all
pass in quick on tun0 proto tcp from any to 20.20.20.1/32 port = 80


当然,作为web服务器,为了作出一定的回应,再加一条规则是必要的:
block in on tun0 all
pass in quick on tun0 proto tcp from any to 20.20.20.1/32 port = 80
pass out quick on tun0 proto tcp from 20.20.20.1/32 port = 80 to any


我们用基本的防火墙知识解决了这个问题,其实在IP-Filter中,有个更简洁的方法。

2. 关键词keep state的使用
防火墙的任务就是阻止那些恶意的数据。我们心里想:这个包是到我23/tcp端口的,应该没问题或者这个包带有FIN标志位,可以通过……。但是我们的防火墙并不清楚TCP/UDP/ICMP会话的开始,进行和终止,它仅有一些含糊的规则可供使用,我们只能默默地祈祷这次带有FIN标志位的数据不是针对我们端口和服务的FIN扫描;那次发到23/tcp的数据不是一次telnet的会话劫持。这儿到底有没有一个方法用以鉴别是TCP/UDP/ICMP会话还是端口扫描,或者DoS拒绝服务呢?有,IP-Filter为我们提供了keep state。
大多数人都想在得到安全的同时又获得方便,这也是为什么Cisco有“established”,以便使已经建立会话的数据顺利通过,Ipfw也有“established”,Ipfwadmin有setup/established。使用established很容易引起误会,粗看起来,仿佛这些防火墙时刻都监视着每个连接的建立与释放,事实上它们的判断仍然依赖于这些包中人人都可伪造的部分。它们读取的是TCP包中的标志位部分,这也正是它们对UDP/ICMP无效的原因(UDP/ICMP没有标志位)。任何人只要能伪造标志位便能骗过这些防火墙。
IP-Filter在这种情况下表现如何呢?与其它防火墙不同,在IP-Filter中使用关键词keep state开启状态保持功能(keeping state)能够真正监视会话,它不仅对TCP有效,对UDP/ICMP也同样有效。在前面我们讲的都是当数据包到来时,防火墙根据规则进行检查,当数据包要发送时,防火墙也根据规则进行检查,然而,事实上是当数据包到来时,先根据状态表进行检查,如果必要的话再根据规则进行检查,同理,当数据包要发送时,先根据状态表进行检查,如果必要,再根据规则进行检查。状态表列有所有可以直接通过的TCP/UDP/ICMP会话。直接通过?不安全吧?没事,你的防火墙绝对没问题。
所有的TCP/IP会话都有开始和结束(即便有时它们在同一个包里),没有开始部分就没有结束部分,这意味着我们真正需要关注的是TCP/UDP/ICMP会话的开始部分,如果我们允许会话的开始部分通过,就没有理由不让其后面的部分通过,除非你想让系统的IP堆栈崩溃。状态保持功能允许你将精力集中在审核会话的开始部分而忽略后续的部分,如果开始部分被允许了,后续部分也将被允许,而如果开始部分就被禁止了则后续部分不能通过。我们以一个ssh服务器为例(记着:仅仅运行着ssh服务):
block out quick on tun0 all
pass in quick on tun0 proto tcp from any to 20.20.20.1/32 port = 22 keep state


你可能一眼就发现这里没有“pass out”,这儿只有一个“block out”,尽管如此,这儿仍然没有问题,因为使用了“keep state”,一旦有一个SYN先生来敲ssh的家门,这儿就建立了一个“状态”(state),这样对于后面由SYN先生带来的客人们就没有必要再拒之门外了。这儿有另一个例子:
block in quick on tun0 all
pass out quick on tun0 proto tcp from 20.20.20.1/32 to any keep state

在这里这个服务器没有运行任何服务,准确地说,这是一个客户端,这个客户端不想让任何未经授权的包进站,同时又想完全自由的与外面进行通讯,这里使用“keep state”以便为每个访问外面的会话创建一个“状态”(state),一旦“状态”被创建,后续的通讯大门将打开,这个会话的数据将自由出入。我们曾提到“keep state”对于UDP和ICMP仍然有效:
block in quick on tun0 all
pass out quick on tun0 proto tcp from 20.20.20.1/32 to any keep state
pass out quick on tun0 proto udp from 20.20.20.1/32 to any keep state
pass out quick on tun0 proto icmp from 20.20.20.1/32 to any keep state


哦,上帝啊,我们现在能使用ping了,我们在TCP,UDP,ICMP上使用了状态保持功能后能够自由的访问外面,如同防火墙不存在一样,但防火墙确实在那儿,它正在那儿阻挡着外面所有非法的访问,对于***,它又是存在的。简直太令人不可思议了!我们再看看下面这个怎么样:
pass in quick on tun0 proto tcp from any to 20.20.20.1/32 port = 23
pass out quick on tun0 proto tcp from any to any keep state
block in quick all
block out quick all


也许你会认为这是一个不错的设置:我们既允许外面对23/tcp的访问,又能自由地访问外面。不幸的是,事实上这个设置有问题。让我们考虑一下这样一种情况:从A点向我们的防火墙B点发送了一个对23/tcp的SYN请求,根据第一条规则它顺利通过了,注意,这儿没有关键词“keep state”,也就没有创建一个“状态”,所以当我们准备发送一个SYN/Ack回应包时,我们遇到麻烦了。如果是一个向外的SYN请求,IP-Filter可以顺利地创建一个“状态”并使数据通过,但SYN/Ack不行,用于握手第二阶段的SYN/Ack不能被IP-Filter用于创建“状态”。所以我们需要稍加修改:
pass in quick on tun0 proto tcp from any to 20.20.20.1/32 port = 23 keep state
pass out quick on tun0 proto tcp from any to any keep state
block in quick all
block out quick all


这样当SYN请求进来时就为自己出去创建好了通路(“状态”),一旦三次握手的会话建立,IP-Filter就为会话做上4/4模式的记号,意味着这个会话将用于长时间的数据传输直到超时,如果你想看看IP-Filter为会话做的是什么标记,你可以用ipfstat –s命令查看状态表。


3. UDP的状态处理
UDP没有三次握手的会话,所以使用状态保持会有一点麻烦,但IP-Filter仍然有办法。现在假设从地址A的端口X向地址B的端口Y发送了一个UDP包,A的IP-Filter将只允许从B的Y端口发向A的X端口的UDP回应包通过。不过这是一个短时“状态”通道,大约60秒。例如我们用nslookup命令查询
www.3com
的ip,地址,
$nslookup
www.3com

这时我们创建了这样一个UDP包:
17:54:25.499852 20.20.20.1.2111 > 198.41.0.5.53: 51979+

这个包的源地址是20.20.20.1,源端口是2111,目的地址是198.41.0.5,目的端口是53,20.20.20.1上的IP-Filter把一个时限60秒的状态通道打开了,如果在此期间有从198.41.0.5的53端口回到我们20.20.20.1的2111端口的UDP包,IP-Filter将允许它通过。正如所料,数毫秒后它回来了:
17:54:25.501209 198.41.0.5.53 > 20.20.20.1.2111: 51979 q:
www.3com


IP-Filter看了看表:“哼,这么快就回来了,进去吧。”
然后关闭了状态通道,以后再有类似的包也进不去了。
4. ICMP的状态处理
IP-Filter使用类似处理TCP和UDP的方法来处理ICMP。大体上有两种ICMP包:
请求,回应。当你的规则如下时:
pass out on tun0 proto icmp from any to any icmp-type 8 keep state

为使出站的ping(典型的ICMP)能收到回应,回来的icmp-type0包应该被允许进入。通道开放的时间为默认的60秒,在状态表里IP-Filter同样给它打上了标记:0/0
所以如果你正期待着ICMP应答包的到来,请加上类似于proto icmp [...] keep state的字样。
大多数ICMP都是在TCP/UDP传输异常时产生的(如icmp-type 3 code 3代表端口是关闭的, icmp-type 11代表超时),在3.4.x或更高版本的IP-Filter中,当ICMP的类型可能为状态表中的会话产生时,IP-Filter就让它通过。比如在老版本的IP-Filter下你想使用traceroute命令的话就得这样:
pass out on tun0 proto udp from any to any port 33434>

现在你只需这样:
pass out on tun0 proto udp from any to any port 33434>

为了防止在进行通讯时某些卑鄙的ICMP包利用状态表穿透防火墙,IP-Filter不仅仅利用源地址,源端口,目的地址,目的端口进行辨别,还对数据包的有效负载(payload)进行审核。

5.关键词flags和keep frags的使用
让我们回到前面设好的地方:
pass in quick on tun0 proto tcp from any to 20.20.20.1/32 port = 23 keep state
pass out quick on tun0 proto tcp from any to any keep state
block in quick all
block out quick all


为了防范FIN扫描,我们还要这样修改一下:
pass in quick on tun0 proto tcp from any to 20.20.20.1/32 port = 23 flags S keep state
pass out quick on tun0 proto tcp from any to any flags S keep state
block in quick all
block out quick all


这样就只有目的地为20.20.20.1/32,目的端口为23且带有SYN标志位的数据才被允许通过,记入状态表,这样做可防范FIN扫描和XMAS扫描,防止无礼的数据把堆栈搞得乱七八糟。因为现在只允许带有SYN标志位的数据通过,有些正常数据是分片传输的,它们将无法通过,对于这一点,IP-Filter也考虑到了,使用关键词keep frags后,IP-Filter将允许它们通过。还有一点就是有的地方用flags S/SA代替flags S,flags S其实是和flags S/AUPRFS严格等同的,它们对应的是只带SYN标志位的数据,而flags S/SA则允许数据除SYN外,还可以带有URG, PSH, FIN, 或RST标志位,因为有些协议需要这些标志位的存在,但看起来有点不安全,是否使用它完全由你自己决定。
pass in quick on tun0 proto tcp from any to 20.20.20.1/32 port = 23 flags S keep state keep frags
pass out quick on tun0 proto tcp from any to any keep state flags S keep frags
block in log quick all
block out log quick all

这样一来,唯一不能防范的端口扫描反而是SYN扫描了,如果你很对此很敏感的话,可以对所有入站的SYN包作记录。
6. 关键词return-rst的使用
到目前为止,我们的防火墙都只是悄悄地丢弃了非法的包,没有向远端主机作出任何回应,其实这样不妥,因为这样就等于告诉了***者防火墙的存在,如果我们发送回一个重置信号(RST)的话,***者会误以为没有防火墙存在,没有需要的端口开放,也就是没有可利用的服务存在,也许只有疯子才会继续下去。IP-Filter使用关键词return-rst向远端主机发送重置信号(RST),我们曾经这样写过:
block in log on tun0 proto tcp from any to 20.20.20.0/24 port = 23
pass in all


现在我们改成:
block return-rst in log proto tcp from any to 20.20.20.0/24 port = 23
block in log quick on tun0
pass in all


我们还需要一条规则,因为return-rst只对TCP有效,我们想使UDP,ICMP以及其它的也有同样的效果:
block return-icmp(port-unr) in log quick on tun0 proto udp from any to 20.20.20.0/24 port = 111

这里我们使用了关键词return-icmp(port-unr表示端口不可到达),这样远端主机收到的将是“请求被拒绝”(connection refused)而不是“超时”(connection timed out)。根据《TCP/IP Illustrated》,当被质询的服务不存在时,应该发送回一个“端口不可到达”(port-unreachable)的ICMP包,当然,你也可以使用其它类型的ICMP包,但最好是port-unreachable,IP-Filter默认的也是这样。但老版本的IP-Filter有个问题,就是发送回去的ICMP包使用的ip地址是防火墙的ip地址而不是被质询的主机地址,这样的话,骗局很容易被戳穿,所以在3.3版本以上的IP-Filter(包括3.3版)中增加了一个新的关键词return-icmp-as-dest来弥补这个缺陷。新版IP-Filter中应该这样:
block return-icmp-as-dest(port-unr) in log on tun0 proto udp from any to 20.20.20.0/24 port = 111

7. 日志记录
IP-Filter软件本身将日志发送到/dev/ipl,无法直接读取,但是管理员可以通过ipmon命令来对日志进行实时观察,调整ipmon参数可以将可读的日志发送到屏幕,文件或者传给syslog,在3.3版中甚至可以通过使用关键词log level来控制输出格式:
block in log level auth.info quick on tun0 from 20.20.20.0/24 to any
block in log level auth.alert quick on tun0 proto tcp from any to 20.20.20.0/24 port = 21


有了log level我们就可以为自己定制出合适的规则。比如,如果有人对你的telnet服务进行一次试探,你可能有耐心看看日志,但如果他进行了500次试探呢,你还有耐心看完吗?这里我们可以使用关键词log first让防火墙只记录相同类型试探中的第一次,再配合其它一些关键词我们可以构建出功能完善的防火墙。
另一个有用的用法是使用log body,它能记录下包的前128字节,在某些特定条件下将非常有用。需要注意的是不要过于频繁地使用log body,因为它会是你的日志变得非常冗长。
8. 综合
我们去掉冗余的,加入前面我们设置的用来防范ip欺骗的规则,一个防火墙初步产生了:
block in on tun0
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 20.20.20.0/24 to any
block in log quick on tun0 from any to 20.20.20.0/32
block in log quick on tun0 from any to 20.20.20.255/32
pass out quick on tun0 proto tcp/udp from 20.20.20.1/32 to any keep state
pass out quick on tun0 proto icmp from 20.20.20.1/32 to any keep state
pass in quick on tun0 proto tcp from any to 20.20.20.1/32 port = 80 flags S keep state

9. 使用组策略提高性能
让我们继续扩展我们的防火墙,现在要考虑在实际的应用环境了。假定我们有三个网络接口x10,x11和x12:
x10连接到外部的网络20.20.20.0/26
x11连接到隔离区(DMZ)20.20.20.64/26
x12连接到内网20.20.20.128/25
让我们看看以下规则:
block in quick on xl0 from 192.168.0.0/16 to any
block in quick on xl0 from 172.16.0.0/12 to any
block in quick on xl0 from 10.0.0.0/8 to any
block in quick on xl0 from 127.0.0.0/8 to any
block in quick on xl0 from 0.0.0.0/8 to any
block in quick on xl0 from 169.254.0.0/16 to any
block in quick on xl0 from 192.0.2.0/24 to any
block in quick on xl0 from 204.152.64.0/23 to any
block in quick on xl0 from 224.0.0.0/3 to any
block in log quick on xl0 from 20.20.20.0/24 to any
block in log quick on xl0 from any to 20.20.20.0/32
block in log quick on xl0 from any to 20.20.20.63/32
block in log quick on xl0 from any to 20.20.20.64/32
block in log quick on xl0 from any to 20.20.20.127/32
block in log quick on xl0 from any to 20.20.20.128/32

block in log quick on xl0 from any to 20.20.20.255/32
pass out on xl0 all

pass out quick on xl1 proto tcp from any to 20.20.20.64/26 port = 80 flags S keep state
pass out quick on xl1 proto tcp from any to 20.20.20.64/26 port = 21 flags S keep state
pass out quick on xl1 proto tcp from any to 20.20.20.64/26 port = 20 flags S keep state
pass out quick on xl1 proto tcp from any to 20.20.20.65/32 port = 53 flags S keep state
pass out quick on xl1 proto udp from any to 20.20.20.65/32 port = 53 keep state
pass out quick on xl1 proto tcp from any to 20.20.20.66/32 port = 53 flags S keep state
pass out quick on xl1 proto udp from any to 20.20.20.66/32 port = 53 keep state
block out on xl1 all
pass in quick on xl1 proto tcp/udp from 20.20.20.64/26 to any keep state

block out on xl2 all
pass in quick on xl2 proto tcp/udp from 20.20.20.128/25 to any keep state


从这个例子中我们可以看出我们的防火墙并没有预计的那么好,由于我们在x11上作了很多检测,所以每个包都将被严格的检测,这将严重影响x10与x12之间通讯的性能。如果你真的这样建起你的防火墙的话,在x12的人一定会来拧掉你的脑袋,为了保住你的脑袋,你最好使用组策略优化防火墙的性能。组策略允许你建立起一个树状的规则表而不是这样的线性的规则表。这样如果到来的包与一些规则无关(比如这儿的x11规则组),将永远不会与那些规则相遇。看起来就象一个主机上装了几个防火墙一样。下面有一个简单的例子:
block out quick on xl1 all head 10
pass out quick proto tcp from any to 20.20.20.64/26 port = 80 flags S keep state group 10
block out on xl2 all


从这个精简的例子可以看出组策略的思路,如果数据的目的地址不是x11,那它与group 10不匹配,跳过它检查后面的规则。如果数据目的地址是x11,将检查group 10,即检查SYN/80。为了提高性能,我们把前面的防火墙规则重写一遍:
block in quick on xl0 all head 1
block in quick on xl0 from 192.168.0.0/16 to any group 1
block in quick on xl0 from 172.16.0.0/12 to any group 1
block in quick on xl0 from 10.0.0.0/8 to any group 1
block in quick on xl0 from 127.0.0.0/8 to any group 1
block in quick on xl0 from 0.0.0.0/8 to any group 1
block in quick on xl0 from 169.254.0.0/16 to any group 1
block in quick on xl0 from 192.0.2.0/24 to any group 1
block in quick on xl0 from 204.152.64.0/23 to any group 1
block in quick on xl0 from 224.0.0.0/3 to any group 1
block in log quick on xl0 from 20.20.20.0/24 to any group 1
block in log quick on xl0 from any to 20.20.20.0/32 group 1
block in log quick on xl0 from any to 20.20.20.63/32 group 1
block in log quick on xl0 from any to 20.20.20.64/32 group 1
block in log quick on xl0 from any to 20.20.20.127/32 group 1
block in log quick on xl0 from any to 20.20.20.128/32 group 1
block in log quick on xl0 from any to 20.20.20.255/32 group 1
pass in on xl0 all group 1
pass out on xl0 all
block out quick on xl1 all head 10
pass out quick on xl1 proto tcp from any to 20.20.20.64/26 port = 80 flags S keep state group 10
pass out quick on xl1 proto tcp from any to 20.20.20.64/26 port = 21 flags S keep state group 10
pass out quick on xl1 proto tcp from any to 20.20.20.64/26 port = 20 flags S keep state group 10
pass out quick on xl1 proto tcp from any to 20.20.20.65/32 port = 53 flags S keep state group 10
pass out quick on xl1 proto udp from any to 20.20.20.65/32 port = 53 keep state group 10
pass out quick on xl1 proto tcp from any to 20.20.20.66/32 port = 53 flags S keep state
pass out quick on xl1 proto udp from any to 20.20.20.66/32 port = 53 keep state group 10
pass in quick on xl1 proto tcp/udp from 20.20.20.64/26 to any keep state
block out on xl2 all
pass in quick on xl2 proto tcp/udp from 20.20.20.128/25 to any keep state


应用此规则之后会使防火墙完成如下的功能:
l xl0口上阻止从192.168.0.0/16、172.16.0.0/12、10.0.0.0/8、127.0.0.0/8、0.0.0.0/8、169.254.0.0/16 、192.0.2.0/24、204.152.64.0/231、224.0.0.0/3、20.20.20.0/24、20.20.20.0/32、20.20.20.63/32 、20.20.20.64/32 、20.20.20.127/32、20.20.20.128/32、20.20.20.255/32、等网段的数据包的进入,此规则的编写是通过将这些规则绑定为一个组的方式来进行的(从head 1到最后一个group 1为一组,从head 10到最后一个group 10为另一组)。同时对所有从Xl0口通过的外出包不作限制。
l 在DMZ区的20.20.20.64/26网段内的机器被允许提供www及ftp服务,对于IP地址为20.20.20.65/32机器,允许其对外提供DNS服务。
l 对于内网安全区则应用了更为严格的安全规则,只允许20.20.20.128/25网段的机器对内网进行访问,同时阻止所有其他网段的机器对内网的访问。
10.关键词fastrout的使用
我们现在做的工作就是传送数据或者拦截数据,正如路由一样,要消耗包上的TTL值,对外表明一个节点的存在。许多扫描利用发送不同TTL值的UDP包来判断两点之间的拓扑结构,如果我们既想开启路由跟踪(traceroute),又不想暴露自己,我们可以使用关键词fastrout:
block in quick on xl0 fastroute proto udp from any to any port 33434 >
关键词fastroute将告诉IP-Filter在转发数据时不要消耗TTL值,IP-Filter使用系统的路由表将数据悄悄地发送出去.有一点需要注意,如果我们把系统的IP转发功能打开了,这儿将形成两个通道,由于防火墙的处理这种事务的效率远不及系统的内核,所以使用fastroute只是增强隐蔽性,而不能提高效率.
四.NAT和Proxy
对于个人用户来说,使用防火墙最大的好处莫过于可以使用NAT(网络地址转换Network Address Translation),用行话来说是IP伪装(IP Masquerading).
1.将几个地址映射成一个地址
依靠一个简单的命令可以使NAT具有类似Linux的IP伪装功能:
map tun0 192.168.1.0/24 -> 20.20.20.1/32
这样,任何将要从tun0上发出的来自192.168.1.0/24的包,源地址都将被改为20.20.20.1/32,然后发往目的地.系统记录着正在进行的转发过程,以便实现其逆过程,即把发向20.20.20.1/32的数据再转发回正确的主机.准确地说,IP-Filter的作用应该叫NPAT(网络地址与端口转发Network and Port Address Translation),因为IP-Filter可以改变网络地址和端口,而单纯意义上的NAT只能改变网络地址.在实际应用中往往会遇到这样一种情况:你的ISP商并没有给你分配一个固定的IP,这给我们的设置带来了点麻烦,幸好IP-Filter还够聪明,你可以只指定为0/32就行了,查询IP的事将由IP-Filter自己去做,所以我们可以这样写:
map tun0 192.168.1.0/24 -> 0/32
现在你可以将防火墙连接到网络使用了,如果你重新拨号了或者你的ISP商提供的IP变更了,你可以通过ipf –y命令对你的地址进行更新.有人也许会对IP-Filter的端口转发感兴趣,因为如果有几个主机在对同一IP连接时使用了相同的端口,将造成冲突,这时需要使用端口转发,比如我们想把源端口映射到20000:30000之间:
map tun0 192.168.1.0/24 -> 0/32 portmap tcp/udp 20000:30000
你也可以更省事,让IP-Filter自己决定使用合适的端口,使用关键词auto:
map tun0 192.168.1.0/24 -> 0/32 portmap tcp/udp auto
由于端口映射只对TCP或UDP有效,所以对于其它协议如ICMP,IPSec ESP/AH需要额外指定规则:
map tun0 192.168.1.0/24 -> 0/32 portmap tcp/udp 20000:30000
map tun0 192.168.1.0/24 -> 0/32

2.将很多地址映射成几个地址
与上面的类似,要将很多个地址映射为几个地址可以使用端口转发:
map tun0 192.168.0.0/16 -> 20.20.20.0/24 portmap tcp/udp 20000:60000
有些远端主机要求建立多重连接时使用静态的IP地址,这时可以使用关键词map-block告诉NAT对于这种会话静态地映射为固定的IP和端口:
map-block tun0 192.168.1.0/24 -> 20.20.20.0/24
与map一样,map-block也可以使用auto让IP-Filter自己决定使用什么端口:
map-block tun0 192.168.1.0/24 -> 20.20.20.0/24 auto
当然你也可以指定一个所有IP都使用的端口:
map-block tun0 192.168.1.0/24 -> 20.20.20.0/24 ports 64
3.一对一的映射
有时某个主机要求将自己的地址固定地映射为另一个地址,这时可以使用关键词Bimap:
bimap tun0 192.168.1.1/32 -> 20.20.20.1/32
4.Map的高级用法
我们经常会根据源地址,目的地址的不同作出截然不同的操作,比如我们现在要求在同C网段5.0.0.0/20通讯时不使用NAT:
map tun0 from 192.168.1.0/24 ! to 5.0.0.0/20 -> 20.20.20.1/32


另一个例子:
map tun0 from 192.168.1.5/32 port = 5555 to 1.2.3.4/32 -> 20.20.20.2/32
map tun0 from 192.168.1.0/24 to 5.0.0.0/20 -> 20.20.20.2/32 portmap auto

5.关键词rdr的使用
假如我们在20.20.20.5上运行着一个web服务,由于对网络安全越来越不信任,我们决定不再在80端口运行web服务而改为8000端口。问题是修改端口后别人如何才能照常访问我们呢?我们可以使用NAT的重定向功能来实现。这儿需要使用关键词rdr。
rdr tun0 20.20.20.5/32 port 80 -> 192.168.0.5 port 8000
由于NAT默认的协议是TCP,如果你想对UDP进行重定向,可以指定协议。比如我们要在防火墙上建一个Windows下Back Orifice蜜罐:
rdr tun0 20.20.20.0/24 port 31337 -> 127.0.0.1 port 31337 udp
我们也可以根据源地址及目的地址的不同使用不同的重定向:
rdr tun0 from 10.1.1.1/32 to 20.20.20.5/32 port = 80 -> 192.168.0.5 port 8001
rdr tun0 from 10.1.1.1/32 port = 12345 to 20.20.20.5/32 port = 80 -> 192.168.0.5 port 8002

有一点要十分注意,不能将防火墙当作反射服务器使用,比如:
rdr tun0 20.20.20.5/32 port 80 -> 20.20.20.6 port 80 tcp
当tun0上从20.20.20.5来了一个包时,防火墙先将目的地址更改再进行过滤,然后交给系统作路由处理,由于20.20.20.5与20.20.20.6处于同一网段,现在20.20.20.5的数据仍在入站,又要求出站,系统将不会允许。其实还是有办法实现你的目的,但那种方法是如此的烦琐以至于很多人都不用。聪明的人能写出TIS plug-gw(一组由Trusted Information Systems写的构造防火墙的工具包,又叫firewall toolkit,这个工具箱里的软件适当的安装并配置以一定的安全策略就可以构成基本的防火墙),而晕头的人会写出一重又一重的死循环。所以一定要记着源地址与转发的目的地址不能使用同一个网络接口。
6.利用rdr实现透明代理
既然你都考虑到使用防火墙了,也许你也会考虑使用代理,当你的NAT有点问题时,你可以通过如下重定向解决问题:
rdr xl0 0.0.0.0/0 port 21 -> 127.0.0.1 port 21
这样,来自x10(内部网络),对任何地址(0.0.0.0/0)的ftp请求都将通过代理进行连接。这个简单的例子可以引导我们完成其它(如web浏览)类似的要求。有很多补丁包都可以使防火墙具备透明代理的功能,TIS Firewall Toolkit’s ftp-gw,Squid(
http://squid.nlanr
)等,但使用关键词rdr的手工定制往往更适合要求。
7.NAT与过滤功能同时使用
很多用户希望同时使用NAT与过滤功能以便只为受信任的主机提供特定的服务。比如,你只想在20.20.20.5上(实际上是你内部的主机192.168.0.5)为172.16.8.2提供web服务,你可以在你的ipnat.rules上这样写:
rdr tun0 20.20.20.5/32 port 80 -> 192.168.0.5 port 8000
在你的ipf.rules上这样写:
pass in on tun0 proto tcp from 172.16.8.2/32 to 192.168.0.5/32 port = 8000 flags S keep state
从这里我们还可以看出,NAT先对数据进行处理,然后再进行过滤检查。
8.利用NAT实现透明代理
由于防火墙的NAT功能使得数据通过防火墙时可以被改写,所以通过NAT可以在应用程序的水平上轻易地实现透明代理,比如ftp:
map tun0 192.168.1.0/24 -> 20.20.20.1/32 proxy port ftp ftp/tcp
需要牢记的是代理的规则一定要放在端口映射规则之前,否则端口映射将改变端口而使得代理规则根本没有机会被执行。与此类似的,在使用NAT 实现其它类型的代理时,也应将代理规则放在端口映射规则之前,如“rcmd”(不知道的人还以为是伯克利开发的r-系列服务),“raudio”(Real Audio公司开发的脉冲调制音频数字流技术)等。
9.利用NAT实现负载平衡
既然ipnat可以对通过的数据进行改写,那我们何不利用它来代替那些昂贵的系统以实现负载平衡呢?我们只需要使用关键词round-robin便可以为多个地址指派会话,实现负载平衡:
rdr tun0 20.20.20.5/32 port 80 -> 192.168.0.5, 192.168.0.6, 192.168.0.7 port 8000


五.过滤规则的维护
过滤规则依靠ipf utility来装载,规则允许以文件形式储存在任何地方,默认情况下储存在/etc/ipf.rules, /usr/local/etc/ipf.rules或/etc/opt/ipf/ipf.rules,IP-Filter有两份配置文件,一份叫active set,另一份叫inactive set,,默认使用的规则是active set,你可以在inactive set命令行中添加-I参数使inactive set生效,使用-S参数可以把两份文件联接起来,这对于想修改配置十分方便,你不用将原文件删掉,只需要使用这些参数就可对改动进行测试。在命令行中使用-r参数还可以将规则暂时从配置中挪开。如果你的已经改变了规则,最好使用-F参数重新载入。
总之,更新ipf配置文件最方便的方法是ipf -Fa -f /etc/ipf.rules,更多的操作请看ipf(1)帮助文件。
六.NAT规则的维护
NAT规则的载入依靠ipnat utility。与过滤规则类似,NAT规则允许以文件形式存放在任何地方,默认存放在/etc/ipnat.rules, /usr/local/etc/ipnat.rules, or /etc/opt/ipf/ipnat.rules。在命令行中添加-r参数将使规则失效,但最好使用-C参数使其完全更新,由于-C不能使活动中的规则更新,这时你可以使用-F。
总之,更新ipnat配置文件最方便的方法是ipnat -CF -f /etc/ipnat.rules。更多的请看帮助文件。
七.监控与调试
对防火墙进行必要的跟踪调试可以让我们及时发现其中的问题,提高运行效率。下面介绍一些常用工具。
1. Ipfstat
Ipfstat将各种你感兴趣的数据罗列出来,这些数据代表了防火墙的工作状态,比如,有多少包通过或被禁止了,是否被记录了,有多少通道被打开了等等。以下是一个例子:
#ipfstat
input packets: blocked 99286 passed 1255609 nomatch 14686 counted 0
output packets: blocked 4200 passed 1284345 nomatch 14687 counted 0
input packets logged: blocked 99286 passed 0
output packets logged: blocked 0 passed 0
packets logged: input 0 output 0
log failures: input 3898 output 0
fragment state(in): kept 0 lost 0
fragment state(out): kept 0 lost 0
packet state(in): kept 169364 lost 0
packet state(out): kept 431395 lost 0
ICMP replies: 0 TCP RSTs sent: 0
Result cache hits(in): 1215208 (out): 1098963
IN Pullups succeeded: 2 failed: 0
OUT Pullups succeeded: 0 failed: 0
Fastroute successes: 0 failures: 0
TCP cksum fails(in): 0 (out): 0
Packet log flags set: (0)
None
Ipfstat还可以显示当前防火墙使用的规则,使用-i和-o参数将分别显示入站和出站的规则,使用-h参数后将显示更详细的信息(如规则被命中的次数):
#ipfstat -ho
2451423 pass out on xl0 from any to any
354727 block out on ppp0 from any to any
430918 pass out quick on ppp0 proto tcp/udp from 20.20.20.0/24 to any keep state keep frags
从这里我们可以发现有点不对劲,因为有太多的block了,ipfstat并不能告诉你你的规则是对还是错,但它会详细的告诉你你的规则造成的结果。要想看看你现在具体的规则可以使用-n参数,它将逐行显示出来:
#ipfstat -on
@1 pass out on xl0 from any to any
@2 block out on ppp0 from any to any
@3 pass out quick on ppp0 proto tcp/udp from 20.20.20.0/24 to any keep state keep frags
使用-s参数会有更多关于防火墙的信息:
#ipfstat -s
281458 TCP
319349 UDP
0 ICMP
19780145 hits
5723648 misses
0 maximum
0 nomemory
1 active
319349 expired
281419 closed
100.100.100.1 -> 20.20.20.1 ttl 864000 pass 20490 pr 6 state 4/4
pkts 196 bytes 17394 987 -> 22 585538471:2213225493 16592:16500
pass in log quick keep state
pkt_flags & b = 2, pkt_options & ffffffff = 0
pkt_security & ffff = 0, pkt_auth & ffff = 0
虽然输出的信息会不断变化,但基本的信息不会变。让我们来看看防火墙都告诉了我们些什么。从这里可以看到有一个TCP连接的通道打开了,因为是4/4模式(state 4/4),所以这个连接已经完全建立。我们可以看到这个通道的超时时间为240小时,因为防火墙把TTL计数器设为默认的864000,每一秒计数器减一,直到为0,会话超时,通道关闭。我们还可以看出目前这个连接共传送了196个包(pkts 196),17kB(bytes 17394),连接从100.100.100.1到20.20.20.1(100.100.100.1 -> 20.20.20.1),端口为从987到22(987 -> 22),后面的长串数字是TCP序列号(TCP sequence numbers),这些数字可以防止别人伪造数据进行会话劫持。后面还给出了TCP窗口的大小。“pass in log quick keep state”这句表明这是一个入站连接。
2. Ipmon
Ipfstat虽然是一个不错的工具,但看到的是防火墙状态的快照,要想看防火墙的日志,需要使用ipmon。Ipmon可以查看packet log,state log和nat log。ipmon既可以在前台运行也可以作为守护进程转储到syslog或其它形式的文件。如果你想查看日志,请使用ipmon -o S:
#ipmon -o S
01/08/1999 15:58:57.836053 STATE:NEW 100.100.100.1,53 -> 20.20.20.15,53 PR udp
01/08/1999 15:58:58.030815 STATE:NEW 20.20.20.15,123 -> 128.167.1.69,123 PR udp
01/08/1999 15:59:18.032174 STATE:NEW 20.20.20.15,123 -> 128.173.14.71,123 PR udp
01/08/1999 15:59:24.570107 STATE:EXPIRE 100.100.100.1,53 -> 20.20.20.15,53 PR udp Pkts 4 Bytes 356
01/08/1999 16:03:51.754867 STATE:NEW 20.20.20.13,1019 -> 100.100.100.10,22 PR tcp
01/08/1999 16:04:03.070127 STATE:EXPIRE 20.20.20.13,1019 -> 100.100.100.10,22 PR tcp Pkts 63 Bytes 4604
从这里可以看到有一个来自外部的DNS查询请求,两个对外的时间服务查询请求,另有一个短暂的SSH出站连接.Ipmon也可以告诉我们关于包的日志记录,如:
#ipmon -o I
15:57:33.803147 ppp0 @0:2 b 100.100.100.103,443 -> 20.20.20.10,4923 PR tcp len 20 1488 –A
这句话是什么意思呢?第一部分意思很明显,是事件发生的时间,第二部分说明事件发生的接口(ppp0),第三部分很多人容易错过,它表示造成事件的原因,还记得ipfstat –in吗?此处你可以查看第0组规则的第二条,它便是造成这条记录的原因.第四部分的“b”代表防火墙的操作(block),表明数据被禁止了。第五,六部分很清楚的表明数据的来源和目的地。第七部分("PR")和第八部分表明协议的类型(tcp)和数据包包头长度(20),然后是包的大小(1488)和包的标志位(-A),这儿是一个ACK数据包。
由于互联网的不稳定,经常发生包超时及重发,有时候你会一下子得到两份相同的数据包,防火墙会认为其中一份是属于另一个会话,最后只能将其丢弃。有时防火墙又在会话的最后阶段提前关闭了通道,使得最后的数据包无法通过,并被记录在案。所以不必为一些日志过于操心。
我们再来看看另一段记录:
12:46:12.470951 xl0 @0:1 S 20.20.20.254 -> 255.255.255.255 PR icmp len 20 9216 icmp 9/0
icmp 9/0我们可以看出这是一个路由广播。
最后让我们用ipmon查看一下NAT的日志:
#ipmon -o N
01/08/1999 05:30:02.466114 @2 NAT:RDR 20.20.20.253,113 20.20.20.253,113 [100.100.100.13,45816]
01/08/1999 05:30:31.990037 @2 NAT:EXPIRE 20.20.20.253,113 20.20.20.253,113 [100.100.100.13,45816] Pkts 10 Bytes 455
八.关于IP-Filter的其它说明
1. 关于keep state
状态保持(keep state)是一个十分有用的命令,但很多人会在这个问题上纠缠不清,下面是我们列举过的一个例子:
block in all
pass in quick proto tcp from any to 20.20.20.20/32 port = 23 flags S
pass out all keep state

虽然带有SYN的包可以进站但SYN/ACK包却无法出站,所以会话无法建立,对于不完全的会话,防火墙默认的是60秒后放弃等待。为了能正常使用我们有两种修改方式:
1)
block in all
pass in quick proto tcp from any to 20.20.20.20/32 port = 23 keep state
block out all

2)
block in all
pass in quick proto tcp from any to 20.20.20.20/32 port = 23 flags S keep state
pass out all keep state
更多关于IP-Filter的状态保持(keep state)的使用可以参见Guido van Rooij写的《Real Stateful TCP PacketFiltering in IP Filter》。在以下网址可以找到:
http://www.iae.nl/users/guido/papers/tcp_filtering.ps.gz
2. 关于FTP
设置FTP对很多防火墙管理员来说是很头疼的事,因为对于FTP服务端和FTP客户端,设置是不同的。
在FTP协议中,有两种数据传输方式,一种叫主动模式(active),一种叫被动模式(passive)。在主动模式下,服务端主动连接客户端的一个端口并向客户端发送数据。在被动模式下,客户端主动连接服务端并接收数据。
如果你的防火墙后面运行的是服务端,要建立主动模式将十分简单,而要建立被动模式却是一个大问题。我们先来处理主动模式。一般情况下,对主动模式的FTP服务我们可以像HTTP及SMTP服务一样处理:打开FTP的端口,使用状态保持(keep state)等待请求:
pass in quick proto tcp from any to 20.20.20.20/32 port = 21 flags S keep state
pass out proto tcp all keep state

这几条规则将允许外部与你的FTP服务器20.20.20.20建立主动模式的FTP连接。
轮到被动模式了。利用浏览器进行的FTP连接就属于这种模式,所以这种模式非常常见,防火墙不得不支持它.对于被动模式,每一个新的请求都将在服务端打开一个新的端口(一般高于1023)进行连接,对防火墙来说,这相当于产生了一个新的服务,由于任何设置合理的防火墙都不会允许对未知服务的连接,所以防火墙会将其阻断.
有的人第一反应是允许1023以上的所有端口连接:
pass in quick proto tcp from any to 20.20.20.20/32 port > 1023 flags S keep state
pass out proto tcp all keep state

虽然可行,但显然这不是一个完美的主意,至少从安全性角度看不是.较好的办法是只打开一段端口(比如15001-19999),然后找到wu-ftpd的ftpaccess,在passive ports option上作必要的设置.相应的,防火墙应该设为:
pass in quick proto tcp from any to 20.20.20.20/32 port 15000 >
如果这样还不能令你满意,我想你只能在FTP服务与防火墙之间作一个折中了。
如果你的防火墙后面是FTP客户端,那么各种问题在3.3.3版以后都得到了较好地解决。如果是被动模式,可以这样:
pass out proto tcp all keep state
如果是主动模式,服务端会反向主动向客户端连接,一般情况下,如果两者之间有防火墙的话会导致失败,为解决这个问题,IP-Filter使用了ipnat代理以便为服务端反向连接临时打开一个通道,即便你没有使用ipnat的NAT功能,ipnat的代理功能仍然有效.下面是一个精简的例子,你可以把它加入到ipnat的配置文件里(这儿的ep0是你的网络接口名):
map ep0 0/0 -> 0/32 proxy port 21 ftp/tcp
更多的信息可以参见本文的第三章第六节.如果你的服务器仍不能工作,可以考虑使用NAT功能.但从安全角度考虑不推荐使用,原因见:
http://www.false/ipfilter/2001_11/0273.html
3.调整内核性能
要想使IP-Filter更好的运行,有几个有用的参数需要调节.首先应将IP转发功能打开,否则底层的ip堆栈将不能发送数据.
IP转发(IP Forwarding):
openbsd: net.inet.ip.forwarding=1
freebsd: net.inet.ip.forwarding=1
netbsd: net.inet.ip.forwarding=1
solaris:
ndd -set /dev/ip ip_forwarding 1
短暂端口调节(Ephemeral Port Adjustment,主要为UDP所用):
openbsd: net.inet.ip.portfirst = 25000
freebsd: net.inet.ip.portrange.first = 25000 net.inet.ip.portrange.last = 49151
netbsd: net.inet.ip.anonportmin = 25000 net.inet.ip.anonportmax = 49151
solaris:
ndd -set /dev/tcp tcp_smallest_anon_port 25000
ndd -set /dev/tcp tcp_largest_anon_port 65535
其它有用的地方:
openbsd:
net.inet.ip.sourceroute = 0
net.inet.ip.directed-broadcast = 0
freebsd:
net.inet.ip.sourceroute=0
net.ip.accept_sourceroute=0
netbsd:
net.inet.ip.allowsrcrt=0
net.inet.ip.forwsrcrt=0
net.inet.ip.directed-broadcast=0
net.inet.ip.redirect=0
solaris:
ndd -set /dev/ip ip_forward_directed_broadcasts 0
ndd -set /dev/ip ip_forward_src_routed 0
ndd -set /dev/ip ip_respond_to_echo_broadcast 0

另外,FreeBSD还有一些特别的选项:
net.inet.ipf.fr_flags: 0
net.inet.ipf.fr_pass: 514
net.inet.ipf.fr_active: 0
net.inet.ipf.fr_tcpidletimeout: 864000
net.inet.ipf.fr_tcpclosewait: 60
net.inet.ipf.fr_tcplastack: 20
net.inet.ipf.fr_tcptimeout: 120
net.inet.ipf.fr_tcpclosed: 1
net.inet.ipf.fr_udptimeout: 120
net.inet.ipf.fr_icmptimeout: 120
net.inet.ipf.fr_defnatage: 1200
net.inet.ipf.fr_ipfrttl: 120
net.inet.ipf.ipl_unreach: 13
net.inet.ipf.ipl_inited: 1
net.inet.ipf.fr_authsize: 32
net.inet.ipf.fr_authused: 0
net.inet.ipf.fr_defaultauthage: 600


九.有趣的地方
这一章并不打算再讲述任何关于IP-Filter的新东西,本章的目的在于讲述一些或许你未曾想过的东西,希望能对你有所启发,想出更多关于IP-Filter的有趣的地方。
1. 在个人主机上使用IP-Filter
很久很久以前,在遥远的荷兰Eubdhoven工业大学,Wietse Venama发布了tcp-wrapper,从那时起,它被全世界用来为网络服务提供安全保护。但是美中不足的是,正如它的名字一样,它只能为TCP服务提供保护,并且你的服务需要以inetd守护进程的形式运行,除非你对其重新编译,这是一个很大的安全问题。如果你使用IP-Filter就不再有这些烦恼。比如我的笔记本电脑经常需要连接一些不×××全的网络,我就这样使用IP-Filter:
pass in quick on lo0 all
pass out quick on lo0 all
block in log all
block out all
pass in quick proto tcp from any to any port = 113 flags S keep state
pass in quick proto tcp from any to any port = 22 flags S keep state
pass in quick proto tcp from any port = 20 to any port 39999 >
pass out quick proto icmp from any to any keep state
pass out quick proto tcp/udp from any to any keep state keep frags
我已经这样使用了很久了,从未出过问题。如果我对安全要求更高,我还可以使用NAT,proxy,加入防欺骗功能等。IP-Filter对于多人使用的公共计算机也非常有用,虽然它不能阻止一个具有root权限的***者为所欲为,但如果善良的人不小心打开了不该打开的服务,它仍然能保障计算机的安全。
在我看来,在本地个人机上使用IP-Filter是一个明智的决定,谁说安全和方便不能兼得?
2. 防火墙,透明的过滤器
许多网络管理员对以太网络桥接器都非常熟悉。以太网络桥接器能将两个不同的网段连接到一起,通常用于几个建筑物之间的网络连接,改变网络速度,扩展网线的连接距离。集线器和交换机是两种常见的以太网络桥接器,有时它们仅有两个网络接口,叫做中集器。最新版本的Linux,OpenBSD,NetBSD和FreeBSD都支持将1000台主机连接到10台桥接器。一般情况下,网桥都介于两个主机的连接之间,且对于这两台主机来说是不可见的,IP-Filter和OpenBSD可以做到这一点。以太网络桥接器工作在ISO参考模型的第二层,IP协议处于ISO参考模型的第三层,IP-Filter处于第二层与第三层之间,因为它的工作会涉及到IP和网络接口。将IP-Filter与OpenBSD结合起来就可以成为一个看不见摸不着的防火墙,没有IP地址,没有物理地址,唯一可能暴露防火墙的是数据在IP-Filter上的延时要比在超五类线上要长。
规则的设置也是出奇的简单,在OpenBSD下,第一个桥接器叫bridge0,假如在我们有两块网卡,x10和x11,要把它变成一个网桥只需使用以下命令:
brconfig bridge0 add xl0 add xl1 up
ifconfig xl0 up
ifconfig xl1 up

从这儿可以看到,所有从x10来的数据都从x11发送出去了,所有来自x11的数据都从x10发送出去了,还应看到这儿我们没有为防火墙指定ip地址,其实也没必要指定。让我们把它放到具体的网络环境中,假如我们的网络是这样的:
20.20.20.1 20.20.20.0/24 集线器
这表示我们在20.20.20.1上有一个连接到子网20.20.20.0/24的路由,所有来自子网20.20.20.0/24的数据都通过路由20.20.20.1传送给外面的世界。让我们把IP-Filter网桥连接进去:
20.20.20.1 20.20.20.0/24集线器
我们在IpfBridge上使用的规则为:
pass in quick all
pass out quick all

虽然我们加入了IpfBridge,但网络的结构和功能仍然没有改变,让我们再加入几条规则:
block in quick on xl0 proto icmp
pass in quick all
pass out quick all

这次,虽然20.20.20.1和20.20.20.0/24仍然以为与以前一样,但如果20.20.20.1想使用ping命令查看202.20.20.2是否在线,它将永远别想得到答案。同理,20.20.20.2也别想能收到来自20.20.20.1的ICMP包,IP-Filter已将数据阻截。利用这个办法,只要有足够的网卡,我们可以将每个主机都分割开来,使安全性空前提高。
如果你想在你的网络上使用ping,traceroute,调整最大传输单元(MTU)的大小,禁用ICMP不是个好办法。让我们用IP-Filter的keep state来构建一个更好的防火墙:
pass in quick on xl1 proto tcp keep state
pass in quick on xl1 proto udp keep state
pass in quick on xl1 proto icmp keep state
block in quick on xl0

这样一来,我们的20.20.20.0/24网段(或许更确切的应该称为x11网段)能够自由地访问外部网络,但外部却不能访问x11网段。从外面看,路由是可见的,x11网段的主机也是活动的,但就是不能进入,即便路由被攻陷。到目前为止,我们还只是依赖网络接口和协议进行过滤,虽然网桥工作在ISO第二层,但是IP-Filter仍然可以以ip为标准进行过滤。一般情况下我们都开放了几个服务,所以规则应该看起来是这样:
pass in quick on xl1 proto tcp keep state
pass in quick on xl1 proto udp keep state
pass in quick on xl1 proto icmp keep state
block in quick on xl1 # nuh-uh, we’re only passing tcp/udp/icmp sir.
pass in quick on xl0 proto udp from any to 20.20.20.2/32 port=53 keep state
pass in quick on xl0 proto tcp from any to 20.20.20.2/32 port=53 flags S keep state
pass in quick on xl0 proto tcp from any to 20.20.20.3/32 port=25 flags S keep state
pass in quick on xl0 proto tcp from any to 20.20.20.7/32 port=80 flags S keep state
block in quick on xl0

现在我们可以在20.20.20.2上提供DNS服务,在20.20.20.3上提供SMTP服务,在20.20.20.7上提供Web服务。
不得不承认,我们的防火墙还并不完美。
首先,也许你已发现所有的规则都建立在入站连接上而不是入站和出站都有。这是因为对出站连接进行过滤在带有桥接功能的OpenBSD上还不能实现。最初是为了防止引起防火墙性能的急剧下降,虽然现在的防火墙已能支撑这种资源消耗了,但问题仍没有得到解决,如果你真的想使用这项功能,你只能自己编写代码或向OpenBSD维护人员求助了。
其次,带有桥接功能的IP-Filter给IP-Filter的NAT功能带来很多麻烦。使用NAT会向外泄露关于IP-Filter的信息;由于网桥没有ip可伪装,所以往往会引起混乱甚至引起内核在引导时出现问题。当然你也可以为出站的网络接口指定ip以使NAT能正常工作,但桥接器的优点就不复存在了。
3.使用IP-Filter修补设计错误的网络
很多机构往往是先考虑使用ip,再考虑安全。到最后,一个C网段被搞的乱七八糟,服务器,工作站,路由器……全搞到一块儿了,下面是一个例子:
20.20.20.1
router
20.20.20.6
unix server
20.20.20.2
unix server
20.20.20.7
nt workstation
20.20.20.3
unix server
20.20.20.8
nt server
20.20.20.4
win98 workstation
20.20.20.9
unix workstation
20.20.20.5
intelligent switch
20.20.20.10
win95 workstation
修补的原则大体上是将受信任的服务器放在一个网段,所有的工作站放在一个网段,交换机放在另一个网段。然后把路由器放在各子网之间用于包过滤。工作站在服务器上只有一般用户权限,在交换机上没有权力,只有网络管理员的工作站才对所有主机享有特权。要这样划分,我们需要两个集线器(或交换机),和一台装有IP-Filter,3块网卡的主机。我们打算把所有服务器用一个集线器连接起来,用另一个集线器把所有工作站连接起来。通常的做法是将两个集线器彼此连接起来,再连接到路由,但这次我们不打算这样干,我们要把IP-Filter放在网络的中央:
路由
X10
IPF
X12
X11
工作站群
服务器群




我们把路由器接到IPF的x10,工作站群接到IPF的x12,服务器群接到IPF的x11,接下来建立IPF的规则使整个网络运行起来:
pass in quick on xl0 proto udp from any to 20.20.20.2/32 port=53 keep state
pass in quick on xl0 proto tcp from any to 20.20.20.2/32 port=53 flags S keep state
pass in quick on xl0 proto tcp from any to 20.20.20.3/32 port=25 flags S keep state
pass in quick on xl0 proto tcp from any to 20.20.20.7/32 port=80 flags S keep state
block in quick on xl0
pass in quick on xl1 proto tcp keep state
pass in quick on xl1 proto udp keep state
pass in quick on xl1 proto icmp keep state
block in quick on xl1 # nuh-uh, we’re only passing tcp/udp/icmp sir.
pass in quick on xl2 proto tcp keep state
pass in quick on xl2 proto udp keep state
pass in quick on xl2 proto icmp keep state
block in quick on xl2 # nuh-uh, we’re only passing tcp/udp/icmp sir.

来自路由的对服务器的访问将受到限制(DNS,SMTP,HTTP),工作站也不能在服务器上为所欲为,根据你部门的具体情况也可作适当的调整,比如你根本不想让工作站访问服务器,你可以修改在x12上的规则:
pass in quick on xl2 proto tcp keep state
pass in quick on xl2 proto udp keep state
pass in quick on xl2 proto icmp keep state
block in quick on xl2 # nuh-uh, we’re only passing tcp/udp/icmp sir.

改为:
block in quick on xl2 from any to 20.20.20.0/24
pass in quick on xl2 proto tcp keep state
pass in quick on xl2 proto udp keep state
pass in quick on xl2 proto icmp keep state
block in quick on xl2 # nuh-uh, we’re only passing tcp/udp/icmp sir.

或许你想让它们仅仅能使用服务器上的IMAP功能发邮件,好办:
pass in quick on xl2 proto tcp from any to 20.20.20.3/32 port=25
pass in quick on xl2 proto tcp from any to 20.20.20.3/32 port=143
block in quick on xl2 from any to 20.20.20.0/24
pass in quick on xl2 proto tcp keep state
pass in quick on xl2 proto udp keep state
pass in quick on xl2 proto icmp keep state
block in quick on xl2 # nuh-uh, we’re only passing tcp/udp/icmp sir.

或许你的想法刚好相反:只允许工作站访问服务器,而不许访问外网。你可以这样:
pass in quick on xl2 from any to 20.20.20.0/24
block in quick on xl2

如果你的要求更严厉,你还可以将x11上规则改为:
pass in quick on xl1 from any to 20.20.20.0/24
block in quick on xl1

把修改后的规则完整列出来:
pass in quick on xl0 proto udp from any to 20.20.20.2/32 port=53 keep state
pass in quick on xl0 proto tcp from any to 20.20.20.2/32 port=53
pass in quick on xl0 proto tcp from any to 20.20.20.3/32 port=25
pass in quick on xl0 proto tcp from any to 20.20.20.7/32 port=80
block in quick on xl0
pass in quick on xl1 from any to 20.20.20.0/24
block in quick on xl1
pass in quick on xl2 from any to 20.20.20.0/24
block in quick on xl2

现在服务器和工作站之间能够相互访问,但它们都不能访问外网,外网也只能使用服务器提供的有限的服务。
利用IP-Filter,我们将凌乱的网络清理了一番,现在看起来比原来好多了。

4.构建***检测系统
到现在为止,我们都只是将数据简单地丢弃,没做更多处理,其实我们可以考虑将它们传到另一台主机以收集很多有用的信息而不是简单地用ipmon看看日志。一个较好的做法是利用***检测系统对这些数据进行分析。这样一来,就可以将我们的***检测系统隐藏起来不被发现。如果你只是想收集分析应该被丢弃的数据,你可以使用关键词to或者fastroute(我们后面会谈到两者之间的区别)。如果你想收集分析所有通过的数据,你需要使用关键词dup-to来获得每一份数据的拷贝。
A. 使用关键词dup-to
比如我们想把所有通过x13发送出去的数据复制一份,从网络接口ed0发送到我们的收集分析系统,需要在x13上作这样的设置:
pass out on xl3 dup-to ed0 from any to any
也许你打算直接把拷贝发送给一个有特定IP主机,需要作小小的改动:
pass out on xl3 dup-to ed0:192.168.254.2 from any to any
但有一点需要注意,这种方法会改变数据原始的目的地址,所以你一定要搞清楚它真实的目的地址。如果你使用主机192.168.254.2同时收集本应发给Web服务和Mail服务的数据,瞬间你就会发现要区分出数据的原始目的地是件痛苦的事情。如果你使用一组主机分别进行收集分析,收集的信息将会非常有用(比如你用192.168.254.2收集分析Http服务器的数据,用20.20.20.20收集分析SMTP服务器的数据,用20.20.20.16收集分析telnet会话的数据,……等等)。一般情况下,IP-Filter需要使用ARP协议来寻找主机物理地址,出于安全考虑,我们可以使用静态的ARP表。
B.使用关键词to
使用关键dup-to有一个不足之处:由于所有数据都需要复制一份并发送出去,所以防火墙的性能会受到很大的影响,如果无必要,我们可以仅对本应丢弃的数据进行收集分析而不是所有的数据,我们可以使用关键词to强迫数据忽略路由表直接从一个不同的接口发送出去:
block in quick on xl0 to ed0 proto tcp from any to any port
这里我们使用了block quick,因为与fastroute类似,如果使用pass,IP-Filter将形成两条数据传输路径,很容易引起系统崩溃。


十.过滤伪造的IP地址
前面我们已经多多少少地提到了关于伪造IP的事。由于很多IP地址已经被Internet分址机构 (IANA)作为保留地址,有的IP地址在写本文时仍然没被使用,所以它们既不应该以源地址的身份出现,也不应该以目的地址的身份出现,看起来,我们应该毫不犹豫地将其禁止:
#s/OUTSIDE/outside-interface (eg: fxp0)
#s/MYNET/network-cidr-address (eg: 1.2.3.0/24)
#
block in on OUTSIDE all
block in quick on OUTSIDE from 0.0.0.0/7 to any
block in quick on OUTSIDE from 2.0.0.0/8 to any
block in quick on OUTSIDE from 5.0.0.0/8 to any
block in quick on OUTSIDE from 10.0.0.0/8 to any
block in quick on OUTSIDE from 23.0.0.0/8 to any
block in quick on OUTSIDE from 27.0.0.0/8 to any
block in quick on OUTSIDE from 31.0.0.0/8 to any
block in quick on OUTSIDE from 69.0.0.0/8 to any
block in quick on OUTSIDE from 70.0.0.0/7 to any
block in quick on OUTSIDE from 72.0.0.0/5 to any
block in quick on OUTSIDE from 82.0.0.0/7 to any
block in quick on OUTSIDE from 84.0.0.0/6 to any
block in quick on OUTSIDE from 88.0.0.0/5 to any
block in quick on OUTSIDE from 96.0.0.0/3 to any
block in quick on OUTSIDE from 127.0.0.0/8 to any
block in quick on OUTSIDE from 128.0.0.0/16 to any
block in quick on OUTSIDE from 128.66.0.0/16 to any
block in quick on OUTSIDE from 169.254.0.0/16 to any
block in quick on OUTSIDE from 172.16.0.0/12 to any
block in quick on OUTSIDE from 191.255.0.0/16 to any
block in quick on OUTSIDE from 192.0.0.0/19 to any
block in quick on OUTSIDE from 192.0.48.0/20 to any
block in quick on OUTSIDE from 192.0.64.0/18 to any
block in quick on OUTSIDE from 192.0.128.0/17 to any
block in quick on OUTSIDE from 192.168.0.0/16 to any
block in quick on OUTSIDE from 197.0.0.0/8 to any
block in quick on OUTSIDE from 201.0.0.0/8 to any
block in quick on OUTSIDE from 204.152.64.0/23 to any
block in quick on OUTSIDE from 219.0.0.0/8 to any
block in quick on OUTSIDE from 220.0.0.0/6 to any
block in quick on OUTSIDE from 224.0.0.0/3 to any
block in quick on OUTSIDE from MYNET to any
#Your pass rules come here...

block out on OUTSIDE all
block out quick on OUTSIDE from !MYNET to any
block out quick on OUTSIDE from MYNET to 0.0.0.0/7
block out quick on OUTSIDE from MYNET to 2.0.0.0/8
block out quick on OUTSIDE from MYNET to 5.0.0.0/8
block out quick on OUTSIDE from MYNET to 10.0.0.0/8
block out quick on OUTSIDE from MYNET to 23.0.0.0/8
block out quick on OUTSIDE from MYNET to 27.0.0.0/8
block out quick on OUTSIDE from MYNET to 31.0.0.0/8
block out quick on OUTSIDE from MYNET to 69.0.0.0/8
block out quick on OUTSIDE from MYNET to 70.0.0.0/7
block out quick on OUTSIDE from MYNET to 72.0.0.0/5
block out quick on OUTSIDE from MYNET to 82.0.0.0/7
block out quick on OUTSIDE from MYNET to 84.0.0.0/6
block out quick on OUTSIDE from MYNET to 88.0.0.0/5
block out quick on OUTSIDE from MYNET to 96.0.0.0/3
block out quick on OUTSIDE from MYNET to 127.0.0.0/8
block out quick on OUTSIDE from MYNET to 128.0.0.0/16
block out quick on OUTSIDE from MYNET to 128.66.0.0/16
block out quick on OUTSIDE from MYNET to 169.254.0.0/16
block out quick on OUTSIDE from MYNET to 172.16.0.0/12
block out quick on OUTSIDE from MYNET to 191.255.0.0/16
block out quick on OUTSIDE from MYNET to 192.0.0.0/19
block out quick on OUTSIDE from MYNET to 192.0.48.0/20
block out quick on OUTSIDE from MYNET to 192.0.64.0/18
block out quick on OUTSIDE from MYNET to 192.0.128.0/17
block out quick on OUTSIDE from MYNET to 192.168.0.0/16
block out quick on OUTSIDE from MYNET to 197.0.0.0/8
block out quick on OUTSIDE from MYNET to 201.0.0.0/8
block out quick on OUTSIDE from MYNET to 204.152.64.0/23
block out quick on OUTSIDE from MYNET to 219.0.0.0/8
block out quick on OUTSIDE from MYNET to 220.0.0.0/6
block out quick on OUTSIDE from MYNET to 224.0.0.0/3
#Your pass rules come here...
为了更好的使用这项功能,建议你偶尔到whois.arin上去看看,因为说不定哪天Internet分址机构 (IANA)又将其中一段分配给了一个公司或其他什么的,到时候可不要怪我没提醒过你啊。

转自:http://blog.chinaunix/u/11335/showart_72382.html

转载于:https://blog.51cto/daedalus/703889

本文标签: 防火墙pf