当前位置:Linux教程 - Linux - 使用Linux创建网桥式防火墙

使用Linux创建网桥式防火墙

作者:Henry Stilmack
原文出处:http://www2.linuxjournal.com/articles/misc/0041.html
翻译:ideal
 

联合天文学中心在夏威夷岛的Manua Kea的14,000英尺高的山顶上拥有两个天文望远镜,还在Hilo市有自己的办公室及其他设施,该组织是是通过夏威夷大学连接到Internet上的,夏威夷大学在自己的B类IP地址范围内给天文中心分配了三个子网。以前天文中心的网络安全性是由出口路由器的ACL(访问控制列表)连同Soloris或Linux系统的主机访问控制(tcpwrappers)来实现的。最近天文中心的一个主要英国资助基金会在一次审核后强烈推荐安装防火墙来增强网络的安全性。在对几种商业和免费的防火墙产品进行调研以后,发现它们都需要对内部网络的三个不同子网地址都重新进行分配,分配为192.168的内部地址。内部网络的在三个子网上共有超过200个节点,某些嵌入式微处理器系统甚至需要重新烧制EEPROM以实现IP变换,这是一个非常麻烦和庞杂的任务。因此就开始寻找透明防火墙解决方案,实现即能保持原有的地址分配,又能实现对内部网络的防护。

Linux 2.2以上版本都支持以太网桥接方式。一个网桥的一个接口接收到数据报以后,通过检查目的MAC地址以后被转发到另外一个接口上,而不去检查源或目的IP地址。一个名为AC2I的法国公司发布了一个内核补丁实现在网桥化的接口上使用ipchains进行数据报过滤。这种解决方案能实现透明的防火墙,同时保证对内部网络提供上层的保护和访问控制。下面我们就讨论如何架设一个网桥式防火墙。

硬件配置

为了实现高效的防火墙和网络检测,系统CPU必须足够的强大和快速。该系统架设在一台拥有256M内存和500MHz的赛扬CPU系统之上。测试显示桥能满足一个10M以太网的速度要求,而不会出现丢包现象。系统需要三块网卡,其中两块网卡支持网桥的实现,另外一块用来实现对防火墙的管理。

磁盘容量并不是很重要,但是所有的log信息应该被保存下来。若希望维护某些本地logging(用于某些配置和检测工具),则需要确保拥有足够的免费空间-防火墙和入侵检测记录往往非常庞大。

安装Linux

下面的讨论都基于Linux2.2.16(redhat7.0)版本内核,若使用2.4内核,iptables将会替代ipchains实现内核防火墙。

首先进行标准的Linux安装,但是基本上不要选择任何应用软件包,甚至包括xinet/inetd,因为在该系统上不需要运行任何服务。不要安装编译/开发工具,因为若系统被攻破则入侵者就不那么容易编译任何程序。但是需要安装Perl(某些报告工具是需要的)和OpenSSH(用于远程管理)。确保安装ipchains软件包-这对于就防火墙设置是必须的。一个web浏览器也许会很有用处。若你仅仅接收来自内部网络的时间更新那么安装NTP则不会有多大坏处。你可以选择安装某些X11应用,tcpwrapper及某些网络监控包(whois,finger,tcpdump,traceroute,nc等等)。创建一个非root账号,使用该账号登录系统。

安装时,仅仅配置一个主以太接口-该接口将是被保护网络的一个节点-为其配置一个固定的网络地址,此时应该将其连接到一个空的HUB上,在进行安全设置以后再将其连接到网络中。当系统安装完毕并重新启动时,在lilo引导系统时键入linux single以单用户模式引导进入系统,编辑/etc/hosts.allow来只允许管理机通过SSH来连接进入系统,然后重新启动按照正常模式引导进入系统。然后再将主以太接口连接到内部网络中。

创建支持网桥方式的内核

按照基本的内核编译步骤进行,只不过需要关闭大多数的选项开关,而仅仅打开一些必须的内核编译开关。

进入到/usr/src目录下,拷贝内核源代码到一个新创建的linux-fw目录下:

# cd /usr/src;mkdir linux-fw;cp -r linux-2.2.16 ./linux-fw
# rm linux;ln -s ./linux-fw linux

对linux源代码打linux_brfw2补丁,该补丁为ipchains添加了一个名为bridgein的缺省规则链。该链将被用来存放网桥式防火墙规则,但是该规则链中的规则只能使用ACCEPT或DENY目标,使用REJECT及MASQ是没有意义的。可以从http://ac2i.tzo.com/bridge_filter/处得到该补丁。

# patch -p0
进入/usr/src/linux目录,配置内核(这里假设你已经有编译内核的经验),和网桥式防火墙相关的配置选项开关为:

CONFIG_MODVERSIONS=N
CONFIG_FIREWALL=Y
CONFIG_FILTER=Y
CONFIG_IP_FIREWALL=Y
CONFIG_IP_FIREWALL_NETLINK=Y
CONFIG_IP_ROUTE_FWMARK=Y
CONFIG_BRIDGE=Y

然后编译内核:

# make dep;make clean;make bzImage;make install

使用新生成的内核启动系统。

设置网桥

登录进入防火墙系统,假设是使用eth0作为管理接口,ifconfig -a将显示系统接口情况:

brg0 Link encap:Ethernet HWaddr FE:FD:04:E0:13:B5
BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0

eth0 Link encap:Ethernet HWaddr 00:90:27:B3:17:5C
inet addr:NNN.NNN.NNN.253 Bcast:NNN.NNN.NNN.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:2242346 errors:0 dropped:0 overruns:0 frame:0
TX packets:3616430 errors:0 dropped:0 overruns:0 carrier:0
collisions:589902 txqueuelen:100
Interrupt:9 Base address:0xde80

eth1 Link encap:Ethernet HWaddr 00:01:02:CD:55:38
BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:65714 errors:0 dropped:0 overruns:0 frame:0
TX packets:1832954 errors:0 dropped:0 overruns:0 carrier:1
collisions:500 txqueuelen:100
Interrupt:10 Base address:0xdc00

eth2 Link encap:Ethernet HWaddr 00:01:02:C1:14:F1
BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:2011596 errors:0 dropped:0 overruns:0 frame:0
TX packets:238126 errors:0 dropped:0 overruns:0 carrier:2
collisions:666 txqueuelen:100
Interrupt:11 Base address:0xd880

lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:3924 Metric:1
RX packets:1676447 errors:0 dropped:0 overruns:0 frame:0
TX packets:1676447 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0

为了使网桥工作,需要安装brcfg应用。可以从Matthew Grant的linux路由器项目地址http://lrp.plain.co.nz/tarballs/bridgex_0.30.tar.gz得到源代码。编译生成二进制可执行程序,并将其拷贝到/usr/sbin/brcfg下,然后执行下面的命令来使网桥启动运行:

# ifconfig eth1 promisc up
# ifconfig eth2 promisc up
# brcfg start
# brcfg device eth1 enable
# brcfg device eth2 enable

几分钟以后,当网桥学习得到了两端网端的mac地址范围以后,将能实现在两块网卡之间透明地转发数据报。

防火墙配置

防火墙本身是由ipchains软件包来实现的,上面的内核补丁添加了一个新的缺省规则链-bridgein,该链的规则作用于通过充当网桥的接口的数据报。由于该链属于输入链,每个规则必须指定接口,也就是数据报是从哪个接口进入系统的。每条链的缺省规则都被设置为ACCEPT,多条规则被加进bridgein链来实现访问策略,最后一条规则应该是DENY来限制没有明确指定允许的数据报。


防火墙的访问策略被设计为适用在如下的网络拓朴中:



该设计的突出特色是:

* 所有的公共服务器(HTTPD, FTP, SMTP, SSH)位于防火墙之外;
* 所有从Internet到内部网络的数据流均经过防火墙;
* 从受保护的内部网到公共服务器的数据流不做限制;
* 内部受保护的网络到Internet的数据流都被允许;
* 从公共服务器到受保护的内部网络的数据流进行了一定的限制,只有那些实际需要的服务数据流才允许通过(输出到内部网络的NFS、从公共邮件服务器到内部网络的SMTP数据、SSH);
* 从Internet发起到内部网络的数据连接被禁止。

下面就是一个按照上面的原则生成ipchians规则的脚本:
Listing 2. Annotated Script for Bridging Firewall Setup

#!/bin/sh
#####################################################################
# firewall.sh - set up ipchains rules for a bridging firewall
#
# Copyright (c) 2000 UK/Canada/Netherlands Joint Astronomy Centre
#
# Permission to use, copy, modify, distribute,
# and sell this software and its documentation
# for any purpose is hereby granted without fee,
# provided that the above copyright notice appear
# in all copies and that both that copyright notice
# and this permission notice appear in
# supporting documentation, and that the name
# Joint Astronomy Centre not
# be used in advertising or publicity pertaining
# to distribution of this
# software without specific, written prior
# permission.
#
# THIS SOFTWARE IS PROVIDED ``AS-IS. THE JOINT
# ASTRONOMY CENTRE DISCLAIMS
# ALL WARRANTIES WITH REGARD TO THIS
# SOFTWARE, INCLUDING WITHOUT
# LIMITATION ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE, OR NONINFRINGEMENT.
# IN NO EVENT SHALL THE JOINT
# ASTRONOMY CENTRE BE LIABLE FOR ANY DAMAGES
# WHATSOEVER, INCLUDING SPECIAL,
# INCIDENTAL OR CONSEQUENTIAL DAMAGES,
# INCLUDING LOSS OF USE, DATA, OR
# PROFITS, EVEN IF ADVISED OF THE
# POSSIBILITY THEREOF, AND REGARDLESS OF
# WHETHER IN AN ACTION IN CONTRACT,
# TORT OR NEGLIGENCE, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
#
# (There. That should satisfy the lawyers.
# In Plain English, heres the
# software. Do whatever you want with it.
# If anything breaks, its your
# fault and your problem. Don come
# crying to us. We e not paying
# anyone for anything.)
#######################################################################
IPCHAINS=/sbin/ipchains

#############################
# Definitions
#############################
firewallhost=N.N.N.N/32 # EDIT - your firewall
# address here
mynet="""" # EDIT - your network/mask
# here
Any=""0.0.0.0/0""
localhost=""127.0.0.1/32""
EXT_IF=eth2 # EDIT - This is the
# interface which will
# connect to the Internet
INT_IF=eth1 # EDIT - This is the
# interface which will
# connect to your
# protected network
##########################################
# Public (outside the firewall) servers
##########################################
WWW_SERVER= # EDIT - address of your
# public WWW server
FTP_SERVER= # EDIT - address of your
# public FTP server
SMTP_SERVER= # EDIT - address of your
# public mail server
INTERNAL_SMTP= # EDIT - address of your
# internal mail hub
SSH_SERVER= # EDIT - address of your
# public login (SSH) server
NNTP_SERVER= # EDIT - address of your
# upstream News server
INTERNAL_NTP= # EDIT - address of your
# internal NTP server
#############################
# Set default policies
#############################
$IPCHAINS -P input ACCEPT
$IPCHAINS -P forward ACCEPT
$IPCHAINS -P output ACCEPT
#############################
# Flush any old rules
#############################
$IPCHAINS -F
#############################
# Create 2 new chains
#############################
$IPCHAINS -N public
$IPCHAINS -N private

# Since this is a bridge, not a router,
# you really don need any of these
# input rules

# forward rules

# output rules

#############################
# Bridge chain - pass packets to appropriate
# chain based on their input
# interface
#############################
# bridgein rules
$IPCHAINS -A bridgein -s $mynet -d $Any -i $INT_IF -j private
$IPCHAINS -A bridgein -s $Any -d $mynet -i $EXT_IF -j public
# Deny anything not explicitly matched in one of the other chains
$IPCHAINS -A bridgein -p tcp -s $Any -d $Any -j DENY -l
$IPCHAINS -A bridgein -s $Any -d $Any -j DENY -l

#############################
# ""Public"" rules - these control who/what gets to
# talk through the
# firewall from the Internet
# to your protected network
#
# These are examples - modify to suit your own
# security needs
#############################
# public rules
# ICMP - allow echo-request from the ""public""
# servers back in to the
# internal net. Do we need this? In any case,
# block all echo-request
# packets from anyone else. Don bother to
# log ping attempts.
# Allow some of the other useful ICMP messages
$IPCHAINS -A public -p icmp -s $mynet 8 -d $mynet -i $EXT_IF -j ACCEPT
$IPCHAINS -A public -p icmp -s $Any 8 -d $mynet -i $EXT_IF -j DENY
# ICMP - allow echo-reply from anyone, so we can ping out.
$IPCHAINS -A public -p icmp -s $mynet 0 -d $mynet -i $EXT_IF -j ACCEPT
# ICMP - allow destination-unreachable
$IPCHAINS -A public -p icmp -s $Any 3 -d $mynet -i $EXT_IF -j ACCEPT
# ICMP - allow source-quench
$IPCHAINS -A public -p icmp -s $Any 4 -d $mynet -i $EXT_IF -j ACCEPT
# ICMP - allow time-exceeded
$IPCHAINS -A public -p icmp -s $Any 11 -d $mynet -i $EXT_IF -j ACCEPT
# ICMP - allow parameter-problem
$IPCHAINS -A public -p icmp -s $Any 12 -d $mynet -i $EXT_IF -j ACCEPT
#######################################
# Services
#######################################
# SSH - Assumes you have a machine on the outside
# of the firewall to which
# users can login via SSH, then, once
# authenticated, connect to
# any of the protected hosts
$IPCHAINS -A public -p tcp -s $SSH_SERVER -d $mynet ssh -i $EXT_IF -j ACCEPT
# Allow replies from any SSH server anywhere
# back in - only if SYN not set
$IPCHAINS -A public -p tcp -s $Any ssh -d $mynet -i $EXT_IF -j ACCEPT ! -y
#######################################
# Telnet - allow replies from telnet servers
# back in - only if SYN not set
$IPCHAINS -A public -p tcp -s $Any telnet -d $mynet -i $EXT_IF -j ACCEPT ! -y
#######################################
# WWW - allow replies from standard HTTP/HTTPS
# servers - only if SYN not set
$IPCHAINS -A public -p tcp -s $Any www -d $mynet -i $EXT_IF -j ACCEPT ! -y
$IPCHAINS -A public -p tcp -s $Any https -d $mynet -i $EXT_IF -j ACCEPT ! -y
#######################################
# FTP - Allow replies from external FTP servers
# - only if SYN not set
$IPCHAINS -A public -p tcp -s $Any ftp -d $mynet -i $EXT_IF -j ACCEPT ! -y
$IPCHAINS -A public -p tcp -s $Any ftp-data -d $mynet -i $EXT_IF -j ACCEPT ! -y
#######################################
# SMTP - only allow incoming Email from the
# ""public"" server to the internal hub
$IPCHAINS -A public -p tcp -s $SMTP_SERVER -d $INTERNAL_SMTP smtp -i $EXT_IF -j ACCEPT
$IPCHAINS -A public -p tcp -s $SMTP_SERVER smtp -d $INTERNAL_SMTP -i $EXT_IF -j ACCEPT ! -y
#######################################
# WHOIS - allow replies from any WHOIS server
$IPCHAINS -A public -p tcp -s $Any whois -d $mynet 1024:65535 -i $EXT_IF -j ACCEPT ! -y
#######################################
# Finger - allow replies from any finger server
$IPCHAINS -A public -p tcp -s $Any finger -d $mynet 1024:65535 -i $EXT_IF -j ACCEPT ! -y
#######################################
# Auth - allow IDENT replies
$IPCHAINS -A public -p tcp -s $Any auth -d $mynet 1024:65535 -i $EXT_IF -j ACCEPT ! -y
#######################################
# News - allow replies from the NNTP server
$IPCHAINS -A public -p tcp -s $NNTP_SERVER nntp -d $mynet 1024:65535 -i $EXT_IF -j ACCEPT ! -y
#######################################
# NTP - let your internal NTP server synchronize
# with a clock somewhere.
# For better security, specify the external
# NTP servers.
$IPCHAINS -A public -p udp -s $Any ntp -d $INTERNAL_NTP ntp -i $EXT_IF -j ACCEPT
#######################################
# DNS - allow DNS replies back in
$IPCHAINS -A public -p udp -s $Any domain -d $mynet 1024:65535 -i $EXT_IF -j ACCEPT
$IPCHAINS -A public -p tcp -s $Any domain -d $mynet 1024:65535 -i $EXT_IF -j ACCEPT ! -y
#######################################
# NFS - let internal hosts mount disks from
# the ""public"" servers.
# Do we need this?
$IPCHAINS -A public -p tcp -s $mynet 2049 -d $mynet -i $EXT_IF -j ACCEPT
$IPCHAINS -A public -p tcp -s $mynet -d $mynet 2049 -i $EXT_IF -j ACCEPT
#######################################
# RPC - let the ""public"" servers contact the
# portmapper on internal hosts.
# Do we need this?
$IPCHAINS -A public -p udp -s $mynet 0:1023 -d $mynet sunrpc -i $EXT_IF -j ACCEPT
#######################################
# UDP - Allow general UDP traffic between
# ""public"" and ""protected"" hosts.
# Do we need this?
$IPCHAINS -A public -p udp -s $mynet 0:1023 -d $mynet -i $EXT_IF -j ACCEPT
$IPCHAINS -A public -p udp -s $mynet 1024:65535 -d $mynet -i $EXT_IF -j ACCEPT
#######################################
# Established connections from unprivileged ports
$IPCHAINS -A public -p tcp -s $Any 1024:65535 -d $mynet -i $EXT_IF -j ACCEPT ! -y
# Deny (and log!) everything not explicitly allowed
$IPCHAINS -A public -s $Any -d $Any -i $EXT_IF -j DENY -l

######################################
# ""Private"" rules - these control which internal
# hosts can talk through the
# firewall, and to whom
#
# In most cases, these should be fairly liberal.
######################################
# private rules
######################################
# ICMP - Allow echo replies back out to the
# ""public"" servers, as well as
# allowing some of the more useful
# messages back out to anyone.
$IPCHAINS -A private -p icmp -s $mynet 0 -d $mynet -i $INT_IF -j ACCEPT
# ICMP - Allow echo-request
$IPCHAINS -A private -p icmp -s $mynet 8 -d $Any -i $INT_IF -j ACCEPT
# ICMP - Allow destination-unreachable
$IPCHAINS -A private -p icmp -s $mynet 3 -d $Any -i $INT_IF -j ACCEPT
# ICMP - allow source-quench
$IPCHAINS -A private -p icmp -s $mynet 4 -d $Any -i $INT_IF -j ACCEPT
# ICMP - allow time-exceeded
$IPCHAINS -A private -p icmp -s $mynet 11 -d $Any -i $INT_IF -j ACCEPT
# ICMP - Allow parameter-problem
$IPCHAINS -A private -p icmp -s $mynet 12 -d $Any -i $INT_IF -j ACCEPT
######################################
# Services
######################################
# SMTP - restrict SMTP to only between
# the ""public"" server and the internal
# mailhub. Log any unauthorized attempts
$IPCHAINS -A private -p tcp -s $INTERNAL_SMTP -d $SMTP_SERVER smtp -i $INT_IF -j ACCEPT
$IPCHAINS -A private -p tcp -s $mynet -d $Any smtp -i $INT_IF -j DENY -l
#####################################
# Pretty much allow anything else.
$IPCHAINS -A private -p tcp -s $mynet 0:1023 -d $Any -i $INT_IF -j ACCEPT
$IPCHAINS -A private -p tcp -s $mynet 1024:65535 -d $Any -i $INT_IF -j ACCEPT
$IPCHAINS -A private -p udp -s $mynet 0:1023 -d $Any -i $INT_IF -j ACCEPT
$IPCHAINS -A private -p udp -s $mynet 1024:65535 -d $Any -i $INT_IF -j ACCEPT

若希望更多的了解如何定义ipchains规则,请参考IPCHAINS HOWTO:

http://www.redhat.com/mirrors/LDP/HOWTO/IPCHAINS-HOWTO.html.

其他工具

防火墙系统的一个有用的工具就是snort的入侵检测系统(IDS),snort是通过定义一个数据报过滤规则集来检测常见的网络入侵行为。随着新的入侵手段的出现,snort的规则库也在不断更新,Snort可以被配置为发送告警到Log文件,或通过就email等方式通知管理员。它甚至可以配置为发现入侵行为时自动添加阻塞规则来防止入侵进一步进行,虽然该特性还不够完善。Snort及一些相关的脚本可以在 http://www.snort.org/得到.

Gfcc是一个非常不错的图形方式察看及修改防火墙规则的工具。可在icarus.autostock.co.kr下载该工具。

启动配置

桥和防火墙应该在系统的网络部分启动以后马上启动,下面的脚本将用来启动防火墙,设置和启动桥,最后再启动Snort。这里假设上面的防火墙脚本定义在/etc/firewall。本脚本应该被安装在/etc/rc.d/init.d/bridge。安装该脚本以后,运行chkconfig bridge on来安装适当的运行级别链接。

Listing 3. Script for Starting the Firewall
#!/bin/bash
#
# bridge This shell script takes care of installing bridging for dsl
#
# description: Uses brcfg to start bridging and ifconfigs eths
# processname: bridge
# config:

# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

# See how we were called.
case ""$1"" in
start)
echo -n ""Configuring firewall rules:""
/etc/firewall
echo
echo -n ""Configuring bridge: ""
ifconfig eth1 promisc up
ifconfig eth2 promisc up
brcfg start
brcfg device eth1 enable
brcfg device eth2 enable
echo
echo ""Starting Snort: ""
/usr/local/bin/snort -c /usr/local/etc/snort/snort-lib -s -i eth2 -D
echo
;;
stop)
# Stop daemons.
brcfg stop
ifconfig eth1 -promisc down
ifconfig eth2 -promisc down
;;
restart)
$0 stop
$0 start
;;
status)
brcfg
;;
*)
echo ""Usage: bridge {start|stop|restart|status}""
exit 1
esac

exit 0
Uses

应用

一个包过滤桥在很多情况下都非常有用。它是一个实现在一个现有网络中添加防火墙的快速且易于实现的方法,而无需修改网络地址分配或者使用NAT。它同样可以用于在局域网上创建受保护或受限制的子网。而且由于桥接口对外没有IP地址,并且不运行任何IP协议栈,因此很多常见的入侵攻击及DOS攻击都对它不会产生威胁。