摘 要:防火墙是现代网站必不可少的一份子,本文是作者自身经验的总结,讲述利用Linux操作系统自己构筑企业的防火墙的基本概念、原理和步骤,并且作者还提出了一种灵活实用的防火墙设计方案作为配置实例供读者参考。
引 言
防火墙是一种非常有效的网络安全模型。在逻辑上它是一个分离器,一个限制器,一个分析器,有效的监控了内部网和Internet之间的活动,保证了内部网的安全。可以把防火墙比作机场的安检人员,它是外部进出企业内部网的必经之路,每个进出的数据包都要经过它的检查,并把那些有恶意的数据包隔离在外。
防火墙的种类很多,不过我认为大致可分为代理型防火墙和包过滤型防火墙两大类,包过滤型防火墙对每一个经过的数据包进行协议层过滤,只放行满足过滤规则的包,从而达到保护内部网的目的。代理型防火墙从应用层对数据包进行监控,对每一种应用使用一种代理程序,每一个代理程序设置一套规则,只对满足规则的请求进行处理。两种防火墙类型各有优缺点,可以单独使用,也可以组合起来使用。
以前有些人对使用因特网上的免费软件感到不舒服,现在随着Linux的发展壮大,这种现象有所缓解。可是在使用网络安全软件方面,大多数人仍然认为自由软件没有安全保障,其实这是一种偏见,特别是在现在安全软件价格不斐的情况下,你可能没有代理商给予的“保证”,但是你可以检查并修改源代码,并且与帮助维护软件的团体共享消息。实际上,代理商来来去去,团体却没有变。许多自由软件有着和因特网相伴数年的经验积累,这一点自由软件比商业软件有过之而无不及。
就Linux操作系统来说,一直对防火墙有很好的支持,利用它可很容易的实现各种类型的防火墙。并且Linux内核支持的IP伪装(IP MASQUERADE)技术,可使局域网用户和Internet之间实现透明的互访问,而不需为每个局域网用户申请一个合法的Internet地址。应用这种技术,可使局域网的用户可以共享一个或几个IP接入Internet。这一技术应用起来比起很多商业防火墙采用的NAT技术更为方便,安全性也没有降低。
基本概念
IP伪装(IP MASQUERADE)
IP伪装允许很多机器通过IP伪装防火墙隐蔽的访问Internet。对于Internet上的机器来说,所有这些往外的访问都像是从防火墙上发出的。加上它的其他附加功能,IP伪装提供了一个建立非常安全的网络环境的基础。攻破一个配置良好的IP伪装防火墙是极其困难的。
IP伪装与很多商业防火墙和路由器支持的NAT功能有些相似,是在Linux内核中支持的一项网络功能。比如,如果一个Linux主机与Internet连接,那么IP伪装使其他与该主机相连的内部主机也可以访问Internet而不不需有合法的Internet地址。
端口转发(Port Forward):
自动把发向某一主机某一端口的数据包转发到预先定义好的某主机的某一端口。它也是Linux内核支持的功能,与IP伪装配合使用可大大增强Linux防火墙的灵活性和安全性。
如何配置Linux防火墙
(1) 首先明确自己的需求
安装防火墙首先要弄清自己的需求,可以从下面两个方面考虑:
1. 对防火墙外的用户提供什么。
2. 防火墙内的用户需要什么。
比如对外这个站点提供WWW、邮件、和域名解析服务,对内满足客户通过防火墙访问INTERNET的需求,包括:浏览Web,收发邮件,使用FTP等等。这就是一个很简单的需求。制定安全规则的目标就是要最大限度的满足内部网用户的需求和最大限度的限制外部网用户对内部网的行动。一个极端安全的情况就是:内部网用户可随意访问外部网而外部网的用户不能访问内部网。
(1) 制定安全规则
明确了需求,就可以开始制定安全规则了。这里我们举例说明(如下图):
图表 1
这是一个比较典型的例子--一个对外提供Web服务并自己解析域名的网站,其他复杂的站点和服务都可照猫画虎。举这个例子的目的一是因为它比较典型,二是我认为这是一种比较灵活的设计方案,特地在这里介绍出来供大家参考和讨论。
应用Linux我们现在制定安全规则以实现:(1)隐藏所有主机,只暴露对外服务主机的对外服务端口,而且外部用户认为这些端口是Linux防火墙上的端口。(2)在内部只允许代理服务器一台主机自由对外访问,其他主机必须通过代理服务器来实现对外访问。也就是说,从外往里访问网站的Web和DNS服务的,如果满足规定的条件,Linux防火墙才能放行,走的路线是5->4->2的路线。而从内部往外的访问,只能经过代理服务器作一级代理再发出,即路线为1->3->4->5,1->3->5是走不通的。这样做的好处是:(1)外部主机只能接触到内部有限的几个端口,安全性很高。(2)内部主机对外访问又多了一道屏障代理服务器,加大了安全性。(3)不必为每台主机设置安全规则了,减轻了配置负担,也减少了出错机会。这是一个典型的例子,虽然对外服务很少,可其他的服务都可照此办理。在这个例子中我们只需要两个IP地址, 我们让DNS服务器单独使用一个IP,而其他的服务公用一个IP地址。这样我们需要在防火墙的外部网卡上设置两个地址,假如它们是202.166.66.1和202.166.66.2那么使用命令:
ifconfig 网卡名称 202.166.66.1 netmask 子网掩码
ifconfig 网卡名称:0 202.166.66.2 netmask 子网掩码
假设我们这么分配内部网地址:
防火墙 10.0.0.1
DNS服务器 10.0.0.2
代理服务器 10.0.0.3
WWW服务器 10.0.0.4
那么INTERNET地址和内部网地址的对应关系应该是:
地址、端口分配表
地址对应 |
端口号 |
协议名称 |
数据包类型 |
方向 |
202.166.66.1 <-> 10.0.0.2 |
53 |
DNS |
TCP+UDP |
进+出 |
202.166.66.2 <-> 10.0.0.4 |
80 |
HTTP |
TCP |
进 |
10.0.0.3 |
所有 |
所有 |
所有 |
出 |
现在我们可以按照上面这个表格来配置防火墙了。
(1) 配置防火墙
在配置防火墙之前,必须具备:KERNEL 2.2.X和IPCHAINS1.3.X
并且请仔细阅读 KERNEL-HOWTO、IPCHAINS-HOWTO和IP MASQUERADE MINI HOWTO,这里由于篇幅所限,就不详细描述如何安装和配置这些软件了,这些在上面所列的文档里都有详细的描述。
下面我给出防火墙的配置源程序。
首先介绍一下我编写的一个工具,是用来帮助管理员在防火墙上增加一个端口转发的链路,我把它取名叫”Enable”, 这个程序的代码如下:
#!/bin/bash
# file to enable a hole in the firewall
universe="0.0.0.0/0"
chainname=$1
internet_addr=$2
internet_port=$3
intranet_addr=$4
intranet_port=$5
protcp=$6
proudp=$7
out_interface=eth0
in_interface=eth1
echo chainname=$chainname
echo "Adding $internet_addr $internet_port <-> $intranet_addr $intranet_port .."
#adding a new chain
/sbin/ipchains -N $chainname
/sbin/ipchains -F $chainname
#adding new chain's rules
if [ $protcp = tcp ]; then
/sbin/ipchains -A $chainname -j ACCEPT -p tcp -s $universe 1024: -d $internet_addr/32 $internet_port
/sbin/ipchains -A $chainname -j ACCEPT -p tcp -s $universe 1024: -d $intranet_addr/32 $intranet_port
/sbin/ipchains -A $chainname -j ACCEPT -p tcp -s $internet_addr/32 $internet_port -d $universe 1024:
/sbin/ipchains -A $chainname -j ACCEPT -p tcp -s $intranet_addr/32 $intranet_port -d $universe 1024:
/sbin/ipchains -A forward -b -p tcp -s $universe -d $intranet_addr $intranet_port -j MASQ
/usr/sbin/ipmasqadm portfw -a -P tcp -L $internet_addr $internet_port -R $intranet_addr $intranet_port
echo TCP OK.
fi
if [ $proudp = udp ]; then
/sbin/ipchains -A $chainname -j ACCEPT -b -p udp -s $universe 1024: -d $internet_addr/32 $internet_port
/sbin/ipchains -A $chainname -j ACCEPT -b -p udp -s $universe 1024: -d $intranet_addr/32 $intranet_port
/sbin/ipchains -A forward -b -p udp -s $universe -d $intranet_addr $intranet_port -j MASQ
/usr/sbin/ipmasqadm portfw -a -P udp -L $internet_addr $internet_port -R $intranet_addr $intranet_port
echo UDP OK.
fi
#connect to input and output chains
/sbin/ipchains -A input -j $chainname
/sbin/ipchains -A output -j $chainname
这个程序的用法如下:
Enable 链名 外部主机地址 外部主机端口 对应的内部主机地址 对应的内部主机端口 tcp [udp]
下面是利用这个小工具编写的一个防火墙的配置源程序:
#!/bin/bash
#为外部网卡加上双地址
/sbin/ifconfig eth1 202.166.66.1 netmask 255.255.255.0 broadcast 202.166.66.255
/sbin/ifconfig eth1:0 202.166.66.2 netmask 255.255.255.0 broadcast 202.166.66.255
internal_interface="eth0" #内部网卡名
loopback=”lo” #Loopback名
internal_ip="10.0.0.1" #内部网卡的IP
internal_net="10.0.0.0/24" #内部网的IP范围
external_interface="eth1" #外部网卡名
external_ip="202.106.75.97" #定义拥有的Internet合法IP地址
external_net="202.106.75.0/24"
universe="0.0.0.0" #所有的IP
primarydns="202.106.75.97" #内部DNS的对内对外IP地址
portfwdns="10.101.1.225"
internet_web="202.106.75.98" #Web的对内对外IP地址
portfwweb="10.101.1.229"
dhcp_server="10.101.3.229" #内部的DHCP服务器地址
proxy="10.101.1.220" #代理服务器的地址
#------------------------------------------------------------------/sbin/ipchains -M -S 7200 600 600 # 设定MASQ Timeouts 值
echo "Loading MASQ modules.." # 调用 Masq 的附加模块
/sbin/modprobe ip_masq_cuseeme
/sbin/modprobe ip_masq_ftp
/sbin/modprobe ip_masq_irc
/sbin/modprobe ip_masq_quake
/sbin/modprobe ip_masq_vdolive
/sbin/modprobe ip_masq_raudio
#设置telnet, ftp, ftp-data 的TOS值
/sbin/ipchains -A output -p tcp -d 0.0.0.0/0 www -t 0x01 0x10
/sbin/ipchains -A output -p tcp -d 0.0.0.0/0 telnet -t 0x01 0x10
/sbin/ipchains -A output -p tcp -d 0.0.0.0/0 ftp -t 0x01 0x10
/sbin/ipchains -A output -p tcp -d 0.0.0.0/0 ftp-data -t 0x01 0x08
/sbin/ipchains -A output -p tcp -d 0.0.0.0/0 nntp -t 0x01 0x02
/sbin/ipchains -A output -p tcp -d 0.0.0.0/0 pop-3 -t 0x01 0x02
#设置所有的链路规则策略为REJECT并删除所有的旧规则
/sbin/ipchains -F
/sbin/ipchains -P input REJECT
/sbin/ipchains -P output REJECT
/sbin/ipchains -P forward REJECT
#对来自内部网卡、内部网的机器之间的数据交换一律放行。
/sbin/ipchains -A input -j ACCEPT -i $internal_interface -s $internal_net -d $internal_net
/sbin/ipchains -A output -j ACCEPT -i $internal_interface -s $internal_net -d $internal_net
/sbin/ipchains -A forward -j ACCEPT -i $internal_interface -s $internal_net -d $internal_net
# 对来自外部网卡,从自己的合法IP到其他Internet地址的数据包给与放行
/sbin/ipchains -A input -j ACCEPT -b -i $external_interface -s $external_net -d ! $internal_net
/sbin/ipchains -A output -j ACCEPT -b -i $external_interface -s $external_net -d ! $internal_net
# 防止外部主机假冒内部主机进入内部网
/sbin/ipchains -A input -j REJECT -i $external_interface -s $internal_net -d $universe/0 -l
# 允许loopback
/sbin/ipchains -A input -j ACCEPT -i $loopback -s $universe/0 -d $universe/0
#允许icmp访问
/sbin/ipchains -A input -j ACCEPT -b -p icmp -s $universe/0 -d $external_net
/sbin/ipchains -A output -j ACCEPT -b -p icmp -s $universe/0 -d $external_net
/sbin/ipchains -A forward -j MASQ -b -p icmp -s $internel_net -d $universe/0
#允许代理服务器访问任何主机的任何端口,但只准内部主机使用代理服务器
/sbin/ipchains -A input -j REJECT -p tcp -y -l -s ! $internel_net -d $proxy/32
/sbin/ipchains -A input -j ACCEPT -b -s $proxy/32 -d $universe/0
/sbin/ipchains -A output -j ACCEPT -b -s $proxy/32 -d $universe/0
/sbin/ipchains -A forward -j MASQ -b -s $proxy/32 -d $universe/0
# 允许DNS 查询和区域传输
/sbin/Enable dns $primarydns dns $portfwdns dns tcp udp
/sbin/ipchains -j ACCEPT -A input -b -p udp -s $portfwdns 53 -d $universe/0 53
/sbin/ipchains -j ACCEPT -A input -b -p tcp -s $portfwdns 1024: -d $universe/0 53
/sbin/ipchains -j ACCEPT -A output -b -p udp -s $portfwdns 53 -d $universe/0 53
/sbin/ipchains -j ACCEPT -A output -b -p tcp -s $portfwdns 1024: -d $universe/0 53
/sbin/ipchains -j MASQ -A forward -p udp -s $portfwdns 53 -d $universe/0 53
/sbin/ipchains -j MASQ -A forward -p tcp -s $portfwdns 1024: -d $universe/0 53
#Enable http
/sbin/Enable www $internet_web 80 $portfwweb 80 tcp noudp
#忽略DHCP 数据包
/sbin/ipchains -A input -j REJECT -i $internal_interface -s 0.0.0.0/0 68 -d 255.255.255.255/32 67 -p udp
/sbin/ipchains -A input -j REJECT -i $internal_interface -s $dhcp_server/32 67 -d 255.255.255.255/32 68 -p udp
#纪录所有被拒绝的包供分析
/sbin/ipchains -A input -j REJECT -l
/sbin/ipchains -A output -j REJECT -l
/sbin/ipchains -A forward -j REJECT -l
(2) 测试防火墙
完成防火墙后一定要测试一下它是否能达到设计要求,找一些工具如ISS、SATAN等等对防火墙进行测试,在正式投入使用之前排除所有问题。
(3) 远程控制
还有一个很重要的环节就是远程控制,在计算机网络如此发达的今天,不可能什么改动都要到防火墙跟前做,必须得有一个绝对安全的远程控制工具。我个人推荐使用SSH,她是一种安全、功能强大的远程控制工具。FOR UNIX的版本可免费获得,FOR WINDOWS的版本则需要付费。
结束语
近几年商业化的防火墙在数量和功能方面迅猛发展,在决定购买之前,你需要了解你需要的是什么。即使你决定购买防火墙,你仍然需要了解清楚一点关于他们是如何构筑的以及他们是如何工作的。许多站点在构筑自己的防火墙时,花费了大量的精力去评估商业化的防火墙产品。并不是说每个人都不应该购买防火墙,或者说每个人都应该自己构筑。我的观点是购买不是必须的,但比构筑稍微简单一些;她完全取决于你的情况,以及由你支配的资源。有钱花但没时间的站点经常发现购买具有吸引力,而有专长和时间但没有什么钱的站点经常发现构筑更具吸引力。
|