Brett Leeser
2002 年 10 月 简介 很久以来,在 PC 上运行的 Linux 一直被公认为家庭网络的既便宜又安全的防火墙解决方案。既然 Linux 可以在 iSeries 服务器上运行,那么 iSeries 客户就有很大的机会将 Linux 防火墙用于他们的企业网络。但是,当为您的业务而考虑在 iSeries 服务器上添加 Linux 防火墙时,有两个非常重要的考虑事项:可靠性和成本。本方案将演示如何在 iSeries 服务器上设置一个既便宜(因为所有软件都是完全免费的)又可靠(由于有几秒钟内的自动故障转移功能)的 Linux 防火墙。下图显示了该方案的设置。
Heartbeat 简介 对于企业,网络故障会严重影响公司形象并影响雇员生产力。例如,客户在尝试访问一个网站时会受到挫败,可能会转向竞争者,或者雇员会收不到重要的电子邮件。高可用性是企业必需的东西。 Linux 本来就在内核中提供防火墙功能。但 Linux 内核没有为防火墙提供高可用性功能。这就是开放源码社区要进行援救的地方。在因特网上快速搜索有关 Linux 的高可用性功能时您会找到高可用性 Linux 项目(High-Availability Linux Project)。高可用性 Linux 项目已开发了 heartbeat 应用程序。该应用程序的源码是开放的,可免费使用。Heartbeat 提供了具有主/备份模型的高可用性,并处理下列功能:启动和停止必需的服务、监控群集中的节点和 IP 地址接管。Heartbeat 处理所有 Linux 服务,从而使防火墙变成高度可用,您只需要编写 Linux 防火墙的服务脚本即可。我们将在“创建防火墙服务”一节中讨论该步骤。 Heartbeat 安装与设置 第一步是在 iSeries 服务器上安装和配置两个 Linux 分区。如果还未在 iSeries 服务器上安装和配置两个 Linux 分区,请参考 IBM(R) 红皮书“Linux on the IBM iSeries Server: An Implementation Guide”(SG24-6232),以获取详细的指示信息。可以在 IBM Redbooks(TM) 网站上在线查看该红皮书。 接着,需要在每个 Linux 分区上编译和安装 heartbeat 应用程序。倘若您拥有编译源代码所必需的编译器,则 Heartbeat 应该可以在任何 Linux 分发版上编译和安装。本方案使用了 SuSE Linux Enterprise Server(SLES) 7 for iSeries 服务器分发版。首先,从高可用性 Linux 项目网站下载 heartbeat 源代码。为本方案下载的版本名称为 heartbeat.4.9.1-tar.gz。tar 和 gz 扩展名表示:包是用 Linux tar 实用程序产生的,并用 gzip 实用程序进行了压缩。要对该包中的文件进行解压缩,发出命令 tar -zxvf heartbeat.4.9.1.tar.gz。这将创建名为 heartbeat.4.9.1 的目录。 通过使用命令 cd heartbeat.4.9.1,将当前目录更改为新的 heartbeat 文件夹。然后,用一个简单的命令 make install 编译并安装 heartbeat。现在,在 /etc/init.d 目录中,将有一个名为 heartbeat 的脚本。该脚本应该用于启动、停止、重新启动或检查 heartbeat 的状态。该脚本的语法如下: heartbeat {start|stop|status|restart}
但是,在可以启动 heartbeat 之前,必须创建三个配置文件并将它们放在 /etc/ha.d 目录中。这三个配置文件是 ha.cf、haresources 和 authkeys。下面我们将更详细地讨论这三个配置文件。 首先,在解包 heartbeat 源文件的 doc 目录中有每个配置文件的样本。可以用下列三个命令,将这三个文件分别复制到 /etc/ha.d 目录: cp /path-to-heartbeat.4.9.1-folder/doc/ha.cf /etc/ha.d/
cp /path-to-heartbeat.4.9.1-folder/doc/haresources /etc/ha.d/
cp /path-to-heartbeat.4.9.1-folder/doc/authkeys /etc/ha.d/
一旦复制了这些配置文件,就编辑每个文件中的配置,以应用于设置。请确保配置文件对于两个 Linux 分区都是相同的。我们将在以下几节中讨论本方案中使用的配置。 ha.cf 第一个配置文件是 ha.cf,它包括 heartbeat 应用程序的一般配置信息。下面是本方案所使用的 ha.cf 中的配置行: keepalive 1 => 该参数指定两次 heartbeat 之间的秒数。在本方案中,每秒一次 heartbeat。 deadtime 10 => 该参数指定等待声明主机死机的时间。指定 10 表示 heartbeat 将在节点停止响应 10 秒之后启动故障转移。 initdead 60 => 该参数指定 heartbeat 首次启动时死机时间应该为多久。如果 heartbeat 在引导时启动,这对于给网络启动留出时间很重要。初始死机时间应该至少是死机时间参数的两倍。 udpport 694 => 该参数指定当发送 UDP heartbeat 包时要使用的端口。 udp eth2, eth3 => 该参数指定在哪个(哪些)接口上发送 heartbeat。在本方案中,两个 iSeries 服务器虚拟以太网 LAN 都完全专用于 heartbeat。如果节点之间存在速度极高的通信并且网络的可靠性极高,那么这有助于减轻实际网络的负载。 node linux1 node linux2 => 节点参数告诉 heartbeat 哪些系统与群集有关。节点名的正确性是非常重要的。要确保节点名正确,在 Linux 分区上使用命令 uname -n,并使用与 uname 中显示的完全相同的名称。 haresources 第二个配置文件是 haresources。该文件指定哪些资源是群集的一部分,哪个节点是主要的。本方案的 haresources 文件仅包含一行: linux1 10.0.0.1 192.168.105.11 HA_firewall
haresources 文件中该行的语法是 node-name resource1 resource2...resourceN。在本方案中,节点名是 linux1,这指定 linux1 节点是主节点。只要 linux1 是活动的,它就将控制在该配置文件中指定的任一资源。参数 10.0.0.1、192.168.105.11 和 HA_firewall 表示 IP 地址 10.0.0.1 和 192.168.105.11 以及脚本 HA_firewall 是群集的资源。 当 IP 地址被指定为群集资源时,heartbeat 提供节点之间的 IP 地址接管。不应该把在 haresources 中指定的任何 IP 地址配置为任一节点上任何适配器的 IP 地址。当启动 heartbeat 应用程序时,它将故障转移 IP 地址分配给适当的节点。本方案使用两个故障转移 IP 地址,这样在 iSeries 服务器和不可信的网络看来,不管哪个节点处于资源控制之中,防火墙始终有相同的 IP 地址。 authkeys 最后一个 heartbeat 配置文件是 authkeys。该配置文件用于确定将在节点之间使用什么类型的认证以及对认证使用什么密钥。根据高可用性 Linux 项目网站,可以使用三种认证算法,它们是 crc、md5 和 sha1。您所使用的认证算法取决于您所期望的安全性结果和可用的处理能力结果。要获得最低的安全性和处理能力,可使用 crc。要获得稍多一点的处理能力和安全性,可使用 md5。最后,要获得最高的处理能力和安全性,可使用 sha1。authkeys 文件的格式是: auth <number>
<number> <authentication method> [<authkey>]
在本方案中,heartbeat 在一个 iSeries 服务器虚拟以太网 LAN 上进行广播。iSeries 服务器虚拟以太网 LAN 专用于两个 Linux 分区,由于这个原因,所以使用 crc 进行认证就足够安全了。但是,在本方案中,出于安全可靠方面考虑,使用 md5: auth 1
1 md5 THIS_IS_MY_MD5_KEY
显然,出于安全性方面的原因,您应该为密钥指定不同的东西。要使用不同算法,只需指定 sha1 而不是 md5。对于 crc 算法,不需要任何密钥,所以只需指定 crc 而不是 md5,并除去密钥部分。 有关这个配置文件的最后一条重要注意事项是:heartbeat 要求 authkeys 文件具有严格的权限,因为它对于安全性很重要。为了确保 authkeys 有正确的权限,以 root 用户身份,发出命令 chmod 600 authkeys。这设置 authkeys 的权限,使它只对 root 用户可读。 创建防火墙服务 haresources 配置文件将名为 HA_firewall 的 Linux 服务指定为群集资源,所以现在必须在两个 Linux 分区上创建该服务。大多数 Linux 分发版都将 Linux 服务脚本放在 /etc/init.d 目录中。然而,heartbeat 应用程序不会访问 /etc/init.d 目录中的服务,所以要确保 heartbeat 可以找到 HA_firewall 脚本,必须将它放在 /etc/ha.d/resource.d 目录中。对于本方案,HA_firewall 服务脚本被保存在 /etc/init.d 目录中,以与所有 Linux 服务一致。然后,将 HA_firewall 脚本的符号链接放在 /etc/ha.d/resource.d 目录中。一旦创建了 HA_firewall 脚本,就用命令 ln -s /etc/init.d/HA_firewall /etc/ha.d/resource.d/HA_firewall 创建该服务的符号链接。现在,在 heartbeat 可以找到 HA_firewall 脚本的目录中有一个至该脚本的符号链接。符号链接的确只是至实际脚本文件的指针。 如果是第一次编写 Linux 服务脚本,请查看 /etc/init.d 目录中的其它脚本,以获得有关如何做的示例。在两个 Linux 分区上用于本方案的防火墙服务脚本如下: 代码免责声明信息 本文档包含编程示例。 IBM 授予您非独家版权许可证来使用所有编程代码示例,您可以根据这些示例生成适合您自己特定需要的相似功能。 IBM 提供的所有样本代码只是为了说明而已。这些示例并没有在所有条件下完全测试过。因此,IBM 无法保证或暗示这些程序的可靠性、可服务性或功能。 这里包含的所有程序都是“按现状”提供的,没有任何形式的保证。特此声明免除有关非侵害性、适销性和适用于某特定用途的隐式保证。
1 # script to start the HA firewall
2 #
3
4 # include the /etc/rc.config file
5 . /etc/rc.config
6
7 #
8 # The echo return value for success (defined in /etc/rc.config).
9 #
10 return=$rc_done
11
12 case "$1" in
13 start)
14 /root/start_firewall
15 rc_status -v
16 ;;
17 stop)
18 rc_status -v
19 /root/end_firewall
20 ;;
21 restart|reload)
22 $0 stop ${2+"$2"} && $0 start ${2+"$2"}
23 rc_status
24 ;;
25 status)
26 iptables -n -L | grep 'Chain INPUT' > /tmp/output
27 read OUTPUT < /tmp/output
28 rm -f /tmp/output
29 case "$OUTPUT" in
30 "Chain INPUT (policy DROP)")
31 echo "Firewall running."
32 rc_status -v
33 ;;
34 *)
35 echo "Firewall not running."
36 exit 0
37 esac
38 ;;
39 *)
40 echo "Usage: $0 {start|stop|status)}"
41 exit 1
42 esac
| 本脚本的目的是为 heartbeat 提供启动、停止、重新启动和检查防火墙状态的方法。前 10 行是 Linux 服务的注释和常规设置。第 12 行是 case 语句,该语句检查脚本的第一个参数(名为 $1)是 start、stop、restart 或 reload、status 还是其它任何东西。如果参数不是所期望的参数,则 case 语句将打印出脚本的用法。如果脚本参数启动,则 HA_firewall 脚本通过调用 start_firewall 脚本启动防火墙。要结束防火墙,它调用 end_firewall 脚本。HA_firewall 脚本通过列出所有防火墙规则并检查输入链上的 DROP 策略来检查防火墙状态。如果缺省策略是 DROP,则脚本假设防火墙正在运行。其原因是 end_firewall 脚本(我们将在下一节中讨论)清除所有防火墙规则并且将输入链的缺省策略设置为 ACCEPT。将输入策略更改为 ACCEPT 是必需的,这样,一旦清除所有防火墙规则,就不会丢弃所有信息包。 创建防火墙启动和停止脚本 HA_firewall 脚本调用 /root/start_firewall 和 /root/end_firewall 这两个脚本来启动和停止防火墙。创建这些脚本并不困难,但确实需要一些 iptables 知识。Linux 使用命令 iptables 来配置 Linux 防火墙。要获取有关 iptables 的更多信息,请参阅 iptables 网站或者在 Linux 中使用命令 man iptables。 start_firewall 脚本通过将必需的模块装入内核、启用 IP 转发并将所有防火墙规则装入内核来启动防火墙。end_firewall 脚本通过除去所有防火墙规则(除了内核中的规则外)来结束防火墙。剩余的一个规则将丢弃所有与不可信接口的往来流量。必须将所有流量丢弃至不可信接口,以确保当防火墙没有运行时,Linux 分区无权访问不可信网络。该步骤确保热备份无权访问不可信网络,直到它接管主节点为止。引导时,主节点和备份节点都存在这一相同的安全性漏洞。由于这个原因,end_firewall 脚本应该在引导时自动运行。请参考特定 Linux 分发版文档,以获取配置 end_firewall 脚本以在引导时运行的信息。 在每个 Linux 分区上都应该存在 start_firewall 和 end_firewall 脚本,而且 start_firewall 脚本应该在两个 Linux 分区上包含完全相同的防火墙规则。为了帮助确保确实是这样,只要在一个 Linux 分区上创建 start_firewall 脚本,将它复制到另一个 Linux 分区上,然后仅编辑第二个系统上不相同的变量(如 IP 地址)。 下面几节包括了本方案中使用的启动和结束脚本,仅供参考。这个经验报告未提供有关网络安全性或防火墙配置的全面信息,且不推荐将一种安全性设计备用方案替代另一种方案。下面几个脚本的唯一目的是显示使用 iptables 的示例防火墙规则,并且仅仅作为入门示例。 代码免责声明信息 本文档包含编程示例。 IBM 授予您非独家版权许可证来使用所有编程代码示例,您可以根据这些示例生成适合您自己特定需要的相似功能。 IBM 提供的所有样本代码只是为了说明而已。这些示例并没有在所有条件下完全测试过。因此,IBM 无法保证或暗示这些程序的可靠性、可服务性或功能。 这里包含的所有程序都是“按现状”提供的,没有任何形式的保证。特此声明免除有关非侵害性、适销性和适用于某特定用途的隐式保证。 end_firewall
#!/bin/sh
UNSECURE_IFC="eth0"
echo "Ending the firewall..."
#******************************************************
# This script will clear out iptables and disable all
# traffic on the unsecure interface but still allow
# traffic on the secure interface for remote configuration
# when no firewall is running.
#******************************************************
#******************************************************
# Reset the default policies on the INPUT, FORWARD, and
# OUTPUT chains
#******************************************************
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
#******************************************************
# Flush all the rules in the filter and nat tables
#******************************************************
iptables -F
iptables -t nat -F
#******************************************************
# Erase all chains that are not the default chains
# (INPUT, OUTPUT, and FORWARD)
#******************************************************
iptables -X
iptables -t nat -X
#******************************************************
# Drop all traffic coming in or going out the
# unsecure interface
#******************************************************
iptables -A INPUT -i $UNSECURE_IFC -j DROP
iptables -A OUTPUT -o $UNSECURE_IFC -j DROP
echo "Done."
| 代码免责声明信息 本文档包含编程示例。 IBM 授予您非独家版权许可证来使用所有编程代码示例,您可以根据这些示例生成适合您自己特定需要的相似功能。 IBM 提供的所有样本代码只是为了说明而已。这些示例并没有在所有条件下完全测试过。因此,IBM 无法保证或暗示这些程序的可靠性、可服务性或功能。 这里包含的所有程序都是“按现状”提供的,没有任何形式的保证。特此声明免除有关非侵害性、适销性和适用于某特定用途的隐式保证。 start_firewall
#!/bin/sh
echo "Starting firewall..."
#******************************************************
# Define variables, including the secure interface (inside interface)
# and the unsecure interface (outside interface).
#******************************************************
INSIDE="eth1"
OUTSIDE="eth0"
HEARTBEAT_IFC1="eth2"
HEARTBEAT_IFC2="eth3"
LOOPBACK="lo"
#An IP address that will be seen by clients
# on the untrusted network and can be used to
# access to the iSeries server.
PUBLIC_IP="192.168.105.11"
#The iSeries server private IP address
PRIVATE_IP="10.0.0.11"
#******************************************************
# Remove the ipchains module (if it is in the kernel) since it causes
# problems with the iptables module.
#******************************************************
rmmod ipchains
#******************************************************
# Insert needed modules for iptables and connection-tracking
# Note: This is not needed if if the modules are built into
# the kernel.
# Note: The modules are located in
# /lib/modules/2.4.1/kernel/net/ipv4/netfilter
# replace the '2.4.1' with whatever kernel version you have
#******************************************************
echo "Loading the needed modules..."
# for general iptables
insmod ip_tables
# for general iptables rules
insmod iptable_filter
# for connection tracking
insmod ip_conntrack
# for connection tracking of FTP
insmod ip_conntrack_ftp
# for doing SNAT and DNAT
insmod iptable_nat
# for logging
insmod ipt_LOG
#******************************************************
# Enable IP forwarding
#******************************************************
echo "Enabling IP forwarding..."
echo "1" > /proc/sys/net/ipv4/ip_forward
#******************************************************
# Flush all rules from the kernel in case there are
# firewall rules already loaded.
#******************************************************
iptables -F
iptables -t nat -F
#******************************************************
# Set default policies for the INPUT, FORWARD, and OUTPUT chains
#******************************************************
echo "Loading all the rules..."
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT DROP
#******************************************************
# Allow all traffic to and from loopback device
#******************************************************
iptables -A INPUT -i $LOOPBACK -j ACCEPT
iptables -A OUTPUT -o $LOOPBACK -j ACCEPT
#******************************************************
# Allow all UDP traffic on the two VLANs
# because that is what the hearbeat packets use for
# the heartbeat.
#******************************************************
iptables -A INPUT -i $HEARTBEAT_IFC1 -p UDP -j ACCEPT
iptables -A OUTPUT -o $HEARTBEAT_IFC1 -p UDP -j ACCEPT
iptables -A INPUT -i $HEARTBEAT_IFC2 -p UDP -j ACCEPT
iptables -A OUTPUT -o $HEARTBEAT_IFC2 -p UPD -j ACCEPT
#******************************************************
# Perform NAT on all packets going to and from the iSeries
# server. These two rules will change the source
# address(SNAT) on all traffic coming from the iSeries
# server and will change the destination address(DNAT)
# on all traffic going to the iSeries server.
#******************************************************
iptables -t nat -A POSTROUTING -o $OUTSIDE -s $PRIVATE_IP -j SNAT
--to-source $PUBLIC_IP
iptables -t nat -A PREROUTING -i $OUTSIDE -d $PUBLIC_IP -j DNAT
--to-destination $PRIVATE_IP
#******************************************************
# Allow ports 80 and 443, for HTTP traffic, going to
# the private IP address of the iSeries server. We
# specify the private IP address because the packet
# going to the public IP address will have been NAT'd
# to the private IP address.
#******************************************************
iptables -A FORWARD -d $PRIVATE_IP -p tcp --dport 80 --sport 1024:65535 -j
ACCEPT
iptables -A FORWARD -d $PRIVATE_IP -p tcp --dport 443 --sport 1024:65535 -j
ACCEPT
#******************************************************
# Everything that hasn't matched any rules above will
# be logged here. The log prefix is optional and allows
# for an "eye catcher" when viewing the logs. Iptables
# logs to the file /var/log/messages.
#
# After logging, the packets will get dropped
# because we set the default policy to DROP above.
#******************************************************
iptables -A INPUT -j LOG --log-prefix ' ## DROPPED (INPUT) ## '
iptables -A FORWARD -j LOG --log-prefix ' ## DROPPED (FORWARD) ## '
iptables -A OUTPUT -j LOG --log-prefix ' ## DROPPED (OUTPUT) ## '
echo "Done."
|
|