FreeBSD上用IPFilter进行桥过滤
几年以前,我以前的一个大学老师准备利用Microsoft的一台大型赠品设备来组建一个实验室。希望把这个实验室建成某种供学生和职工使用的地方,让他们拥有学院系统(Faculty System)的系统管理员所给予他们的更高的权限。Internet编程(Web,分布式操作系统等)教学也计划在这里进行。这个老师的一个愿望就是不用防火墙将这个实验室进行隔离,从而使学生们可以访问全世界的站点。很明显 ,他不懂Internet安全。在那段时间中,这个实验室简直就变成了一些学生(他们中的大多数已经离开学校,有的去了Redmond)的游乐场,他们玩虚拟竞技场(Unreal Tournament),播放吵人的音乐。学院对此十分不满,希望能够对其重新进行控制。因此他们叫我接管这里。毕竟,我是Unix/Linux的忠实拥护者,因此我必须知道我要谈论些什么。我接下了这个任务,不料竟然会见到一个烂摊子。一些机器被用来做warez,或者被病毒或其他乱七八糟的东西感染。还有一台机器被人在很多年前就取得了root权限。(讽刺的是,那是一台Linux机器,而不是Microsoft的,这台机器从来都没有采取过安全措施,实验室管理员的弟弟在上面放了一个rootkit。当我们发现之后,将它换成了FreeBSD,而root密码由我们自己保管,从此以后那台机器再也没有被入侵过。)
现在,这个实验室里由10台Windows XP机器和一台FreeBSD机器,而且对Internet完全开放。没有任何备份(有一台磁带机,但是通常里面都是同一盘磁带),没有统一的登录口令,Unix和Windows之间没有共享的Home目录,没有任何安全措施。我的任务就是:将它变得安全,并且将这个实验室变成研究生为自己的项目工作的地方,在这些机器中安装一些Linux,Mac OS X和FreeBSD。
我首先想到的是安装某种防火墙,使实验室远离那些外界的潜在威胁,而又不对实验室的用户进行过多的限制。几个星期以前,我安装了我的第一个ipfilter防火墙,并且设置了NAT和其他东西,总共只花费了几个小时的时间。虽然我很清楚的知道荷兰的Unix社区是Linux的狂热支持者,但是我觉得FreeBSD加ipfilter(或者OpenBSD加packetfileter)比Linux防火墙更容易配置。Linux防火墙的规则与ipfilter的规则比起来过于复杂和模糊,因此FreeBSD加ipfilter成为我的首选。
或许正如你所知道的那样,ipfilter支持防火墙和NAT功能,因此我的第一个选择就是使用外部IP地址,给所有机器一个私有网段的IP地址(比如10.0.0.x),NAT和过滤所有东西,并且我在一个小时内完成了这项工作。不幸的是,学院管理员不希望那样做。他们的理由是,如果有人从Internet上入侵到我们实验室的某台机器,那么我们将NAT到整个实验室,这样会对寻找被攻击的机器增加难度。所以所有机器必须保留他们所分配的IP地址。
但是,你如何象那样设置?很明显,你可以使用普通的NAT。那么,你怎么为你的防火墙分配IP地址和网络标志(Netmask)呢?解决的办法就是网桥。网桥将两个网段链接在一起,并且使他们看上去象一个网络。因此,最基本的,你可以把数据包从一个网段复制到另外一个网段。那么,为什么不在他们之间放置一个过滤器,从而构建一个带有过滤功能的网桥呢?带有过滤功能的网桥使在不改变网络设置的情况下对数据包进行过滤变成可能,还可以避免重新铺设线路。带过滤功能的网桥也被认为是一个透明的过滤器。
FreeBSD通过ipfw对构建带有过滤功能的网桥提供了很好的支持,并且已经有很多很好的关于这方面的指南。但是,我对ipfilter十分着迷。FreeBSD 4-STABLE分支并不正式支持ipfilter上带过滤功能的网桥(但在5-CURRENT中是标准设置)。但是已经有4-STABLE上的补丁,并且我认为比我见过的稳定发行版更好。
我在一台老PC上安装了FreeBSD 4.6(包含kernel代码),下载了补丁,将它们进行了应用,并且编译了一个新内核。我在内核配置中添加了如下选项:
options BRIDGE
options IPFILTER
我去掉了其他大多数选项。在重建一个新内核之后,我重启了机器。在启动前,我输入了下面的sysctl命令(当然,也把它们放进了/etc/sysctl.conf):
sysctl net.link.ether.bridge_cfg=xl0:0,xl1:0
sysctl net.link.ether.bridge_ipf=1
sysctl net.link.ether.bridge=1
现在,我已经拥有了一个带ipfilter过滤功能的网桥(在xl0和xl1之间进行设置),但是它还没有被配置来进行任何过滤。
接着就是设置过滤规则。第一步是在/etc/rc.conf中激活ipfilter:
ipfilter_enable="YES"
我把ipfilter的规则放到/etc/ipf.rules,因此我只需要进行这一点点更改。
我将xl0作为对外连接界面,把xl1作为内部连接界面。我的规则很简单:禁止所有从外部访问工作站的操作,允许一部分外部服务的对内访问(SSH,HTTP,MS Terminal Server connections),但是不对实验室的内部用户进行限制。
pass in quick on xl0 proto tcp from any to 131.211.83.40 port = 22 flags S keep state
pass in quick on xl0 proto tcp from any to 131.211.83.40 port = 80 flags S keep state
pass in quick on xl1 proto tcp from any to any keep state
pass in quick on xl1 proto udp from any to any keep state
pass in quick on xl1 proto icmp from any to any keep state
block in on xl0 from any to 131.211.83.40
[more hosts go here]
所有来自内网的通信都被允许通过(保持原有状态不变)。除了很少的几种连接(SSH和HTTP)以外,其他来自外部的通信都被禁止掉。我只允许那些带有SYN标记或者是已获允许的回话的一部分的数据包通过。
除了我忘记把FTP放到允许回话的行列以外,几乎所有机制都运行得很好。FTP是一种十分危险的协议。FTP(至少变量被称作“active”)总是尝试在20端口(ftp-data)建立一个从服务器到客户端的连接。在上面的规则当中,开启FTP是不可能的。我们必须加入下面的规则:
pass in quick on xl0 proto tcp from any to 131.211.83.40 port = 20 flags S keep state
在一个“普通”的NAT设置中,你可以为FTP建立一个代理。但因为这不是NAT设置,因此,不可能使用代理。现在,除了WinAmp外,所有东西都工作得很好。
应该考虑的问题
在你开始使用ipfilter的带有过滤功能的网桥之前,必须考虑下面的问题:
4-STABLE的补丁被作者标识为“风险自负”(Use At Your Own Risk)。我在FreeBSD 4.6上成功使用了,但是它可能在新版本上无法工作。
不能进行NAT。请记住,这个网桥无论如何都没有自己的IP,因此它不能进行NAT。这也意味着你不能使用端口映射(Redirection of Ports)和代理(比如FTP代理)。
我使用的“out”关键字并没有起作用。
return-rst选项(它拒绝一个连接,而不是使它超时)也不起作用,return-icmp-as-dest也一样(这两个选项在ipfilter HOWTO 3.6节中有描述)
结论
我发现在FreeBSD和ipfilter上建立一个带有过滤功能的网桥。操作系统和过滤系统都被证实是十分稳定和通用的,并且带过滤功能的网桥是非常有用的增加安全性,或者临时堵住安全漏洞的方法。