内容:
响应攻击
ipdrop
ipdrop:说明
tcplimit
host-tcplimit
user-outblock
参考资料
关于作者
灵活(有趣)的网络安全性
Daniel Robbins (
[email protected])
总裁兼 CEO,Gentoo Technologies, Inc.
2001 年 4 月
防火墙非常有趣,但在需要对防火墙规则进行快速且复杂的更改时,您会做些什么?很简单。请使用本文中演示的 Daniel Robbins 的动态防火墙脚本。可以使用这些脚本来增加网络安全性和响应性,并激发您自己的创造性设计。
了解动态防火墙脚本好处的最佳方法是在运行时查看它们。要这样做,让我们假设我是一家 ISP 的系统管理员,最近我建立了基于 Linux 的防火墙,用于保护我的客户和内部系统免遭因特网上恶意用户的攻击。为了实现这个目的,我的防火墙使用新的 Linux 2.4 iptables 有状态功能,以允许我的客户和服务器建立新的外出连接,当然还允许新的进入连接,但仅限于“公共”服务,如 web、ftp、ssh 和 SMTP。由于我使用了缺省拒绝设计,因此会自动拒绝任何从因特网到非公共服务(如 squid 代理缓存或 Samba 服务器)的连接。现在,我有一个非常不错的防火墙,它为我公司的所有客户提供了非常好的保护。
在第一个星期左右,防火墙的工作非常出色,但在这之后却发生了件讨厌的事:我最大的对手 Bob(他为另一家 ISP 工作,是我们的竞争对手)决定用大量信息包攻击我的网络,试图阻止我向客户提供服务。糟糕的是,Bob 已经仔细研究了我的防火墙,他知道我在保护内部服务时,端口 25 和 80 必定是可以公开访问的,这样我才可以接收邮件和响应 HTTP 请求。Bob 决定利用这一点,他想用吸干带宽的方法来攻击我的 Web 和邮件服务器。
大约在 Bob 实施攻击一分钟之后,我注意到信息包逐渐占满了上行链路。在查看了 tcpdump 的情况之后,我确定这还是 Bob 实施的另一次攻击,我推算出他用于发起攻击的 IP 地址。现在我已经有了这个信息,我需要做的就是阻止这些 IP 地址,我想这大概能解决问题 -- 很简单的解决方案。
响应攻击
我迅速使用 vi 打开防火墙设置脚本,并开始改动 iptables 规则、修改防火墙,这样它就可以阻止那些 Bob 发出的恶意进入信息包。大约一分钟左右,我找到了添加合适 DROP 规则的确切位置,并添加了这些规则。然后,我启动防火墙,但又马上停止了它……哎,我在添加规则时犯了一个小错。我再次装入防火墙脚本,改正问题,30 秒之后,将已将防火墙调整成阻止这个月内 Bob 发起的所有攻击。起先,它似乎成功地挫败了攻击……直到问讯台的电话铃声响起。显然,Bob 已经中断我的网络大约 10 分钟,现在我的客户打电话来询问究竟发生了什么情况。更遭的是,几分钟后,我发现上行链路又被占满了。看来 Bob 这次使用了一组全新的 IP 地址来实施攻击。我也做出响应,立即开始修改防火墙脚本,只不过这次我有一点惊慌 -- 也许我的解决方案还不那么完美。
以下就是上述情况中出错的原因。虽然我有一个不错的防火墙,还迅速标识了网络问题的原因,但我无法修改防火墙的行为以使它能够及时应付威胁。当然,当网络受到攻击时,您希望能够立即响应,在紧急状态下被迫修改主防火墙设置脚本不仅在时间上很紧迫,而且效率非常低。
ipdrop
如果有一个特别设计的特殊 "ipdrop" 脚本,它可以插入阻止我指定的 IP 地址所需的规则,那么情况会好多了。有了这样的脚本,阻止防火墙就不再是两分钟的折磨;它只需 5 秒钟。由于这个脚本可以让我不必手工编辑防火墙规则,这就消除了出错的主要根源。我所要做的只是确定要阻止的 IP 地址,然后输入:
# ipdrop 129.24.8.1 on
IP 129.24.8.1 drop on.
ipdrop 脚本会立即阻止 129.24.8.1,这是本周 Bob 的当前恶意 IP 地址。这个脚本明显提高了您的防御能力,因为现在阻止 IP 并不是件费神的事。现在,让我们看一下 ipdrop 脚本的实现:
ipdrop bash 脚本
#!/bin/bash
source /usr/local/share/dynfw.sh
args 2 $# "${0} IPADDR {on/off}" "Drops packets to/from IPADDR. Good for obnoxious
networks/hosts/DoS"
if [ "$2" == "on" ]
then
#rules will be appended or inserted as normal
APPEND="-A"
INSERT="-I"
rec_check ipdrop $1 "$1 already blocked" on
record ipdrop $1
elif [ "$2" == "off" ]
then
#rules will be deleted instead
APPEND="-D"
INSERT="-D"
rec_check ipdrop $1 "$1 not currently blocked" off
unrecord ipdrop $1
else
echo "Error: "off" or "on" expected as second argument"
exit 1
fi
#block outside IP address thats causing problems
#attackers incoming TCP connections will take a minute or so to time out,
#reducing DoS effectiveness.
iptables $INSERT INPUT -s $1 -j DROP
iptables $INSERT OUTPUT -d $1 -j DROP
iptables $INSERT FORWARD -d $1 -j DROP
iptables $INSERT FORWARD -s $1 -j DROP
echo "IP ${1} drop ${2}."
ipdrop:说明
如果留意最后突出显示的四行,您会看到将适当规则插入防火墙表的真正命令。可以看到,$INSERT 环境变量的定义随着运行方式是 "on" 还是 "off" 而变化。iptables 行执行时,会适当插入或删除特定规则。
现在,让我们看一下规则本身的功能,规则应该与任何类型的现有防火墙或甚至在没有防火墙的系统上正常工作;您所需要的只是 2.4 内核中的内置 iptables 支持。我们阻止来自恶意 IP(第一个以 iptables 开头的行)的进入信息包,阻止标题为恶意 IP(下一个以 iptables 开头的行)的外出信息包,然后关闭涉及这个特殊 IP(最后两个以 iptables 开头的行)的转发。一旦这些规则就位,系统就只废弃任何属于其中一个类别的信息包。
另一个简短注释:您还会注意到对 "rec_check"、"unrecord"、"record" 和 "args" 的调用。这些是在 "dynfw.sh" 中定义的 helper bash 函数。"record" 函数将被阻止的 IP 记录到 /root/.dynfw-ipdrop 文件中,而 "unrecord" 从 /root/.dynfw-ipdrop 中除去记录项。如果要重新阻止一个已被阻止的 IP,或者取消阻止当前未阻止的 IP,可以使用 "rec_check" 函数来放弃带错误消息的脚本。"args" 函数负责确保我们接收到正确数量的命令行自变量,它还负责打印有帮助的用法信息。我已经创建了包含所有这些工具的 dynfw-1.0.tar.gz;有关详细信息,请参阅本文结尾的参考资料部分。
tcplimit
如果需要限制使用某个特定基于 TCP 的网络服务,可能是某些会在终端上产生大量 CPU 负载的服务,那么下一个动态防火墙脚本会非常有用。这个脚本称作 "tcplimit",它使用一个 TCP 端口、一个速率、一个比例和 "on" 或 "off" 作为自变量:
# tcplimit 873 5 minute on
Port 873 new connection limit (5/minute, burst=5) on.
tcplimit 使用新的 iptables "state" 模块(确保已经在内核中启用了这个模块或已经装入了这个模块),以在某个特定时间周期内只允许一定数量的新进入连接。在本示例中,防火墙只允许每分钟有 5 个新连接到 rsync 服务器(端口 873) -- 如有必要,可以指定您希望每秒/分钟/小时或每天有多少连接。
tcplimit 为限制非基本服务提供了一个好方法 -- 因此对非基本服务的大量通信量不会中断网络或服务器。在我遇到的情况中,我使用 tcplimit 来设置使用 rsync 的最大上限,以防止太多 rsync 连接占据我的 DSL 线路。限制了连接的服务都记录在 /root/.dynfw-tcplimit 中,如果我要关闭新连接限制,只要输入:
# tcplimit 873 5 minute off
Port 873 new connection limit off.
tcplimit 运行时会在 "filter" 表中创建一个全新的链。这个新的链将拒绝所有超出指定限度的信息包。然后,一个规则将插入 INPUT 链,该 INPUT 链将要发送到目标端口(本例中是 873)的所有进入 NEW 连接信息包重定向到这个特定链,这样便有效地限制了新的进入连接,但又不会影响所建立连接中的信息包。
关闭 tcplimit 时,INPUT 规则和该特定链将被删除。这是件奇妙的事,它真正体现了让经过精心测试的、可靠的脚本来为您管理防火墙规则的重要性。由于使用了 ipblock,tcplimit 脚本将与任何类型的防火墙,甚至没有防火墙的系统兼容,只要您在内核中启用了正确的 iptables 功能。
host-tcplimit
host-tcplimit 非常类似于 tcplimit,但它限制某些新的 TCP 连接,这些连接来自某个特定 IP 地址并且指向您的服务器上某个特定 TCP 端口。host-tcplimit 特别适用于防止某个人滥用您的网络资源。例如,假设您在运行 CVS 服务器,而您发现某个新的开发人员似乎建立了一个脚本来每隔 10 分钟就用资源库更新它的源码,这样每天就消耗了大量的多余网络资源。然而,当您给他发送电子邮件以指出他的错误行为时,却会收到一条进入消息,全文如下:
嗨,伙计!
我很荣幸能参与您的开发项目。我刚创建了一个脚本,
用来每隔 10 分钟更新一次代码的本地副本。我将出去
旅游两个星期,但等到回来之后,我将会得到最新的源
代码,那时我就可以交差了!现在我要出门了……两周
后再见!
谨启,
Newbie(新手)
对于这种情况,一个简单的 host-tcplimit 命令就可以解决问题:
# host-tcplimit 1.1.1.1 2401 1 day on
现在,限定了 Newbie 先生(IP 地址 1.1.1.1)每天只能有一个 CVS 连接(端口 2401),这样就节省了许多网络带宽。
user-outblock
最后一个,也可能是所有动态防火墙脚本中最有趣的一个就是 user-outblock。这个脚本提供了一种理想的方式,它允许特定用户 telnet 或 ssh 到您的系统中,但不允许这个用户从命令行建立任何新的外出连接。以下的示例适合于使用 user-outblock。假设有一个特殊家庭在我的 ISP 拥有帐户。父母使用图形电子邮件客户机来阅读他们的邮件,偶尔也会在网上冲浪,但他们的儿子恰巧是位狂热的黑客,他经常使用 shell 访问来对他人的计算机搞一些恶作剧。
一天,您发现他与一些系统建立了 ssh 连接,而那些系统似乎属于巴基斯坦武装力量 -- 啊,天哪!您想要引导这个年轻人参加更有益的活动,所以应执行以下操作:
首先,应检查系统,确保已除去了所有网络二进制程序(如 ssh)中的 suid 位:
# chmod u-s /usr/bin/ssh
现在,他试图用来与网络交互的任何进程都属于他自己的用户标识。现在您可以使用 user-outblock 阻止这个用户标识(恰巧是 2049)启动的所有外出 TCP 连接:
# user-outblock 2049 on
UID 2049 block on.
现在,他可以登录和阅读邮件,但不能使用您的服务器来建立 ssh 连接以及类似连接。现在,他可以在自己家的个人计算机上安装 ssh 客户机。然而,如果要限制他家的个人电脑到 Web、邮件和外出 ssh 连接(仅限于到您的服务器),建立这样的动态防火墙脚本也不太难。
参考资料
由于我发现这些动态防火墙脚本如此实用,我已经创建了一个小巧的 tarball (dynfw-1.0.tar.gz) 文件,您可以将它下载并安装到您的机器上。
如果要安装,解开 tarball,运行其中的 install.sh 脚本。此脚本将一个共享的 bash 脚本安装到 /usr/local/share/dynfw.sh 中,并将动态防火墙脚本安装到 /usr/local/sbin。如果希望将它们安装到 /usr/share 和 /usr/sbin 中,在运行 install.sh 之前只要输入以下命令:
# export PREFIX=/usr
我还将动态防火墙脚本代码部分添加到 Gentoo Linux 网站上,您可以访问这个网站以获取最新版本的 tar 文件。我还要继续改进,并添加到这个集合中,以使全世界的系统管理员可以使用真正实用的资源。在我们的内核中已经有了 iptables,应该开始利用它!
tcpdump 是研究低级信息包交换和验证防火墙是否正常工作的必备工具。如果您还没有,想方法弄到它。如果已经有了,则应该使用它。如果已经使用它了……干得好!:)
netfilter 小组的主页上有许多优秀的资源,包括 iptables 源码,有 Rusty 的优秀作品 "unreliable guides"。这些作品包括基本网络概念 HOWTO、netfilter (iptables) HOWTO、NAT HOWTO 和适合于开发人员的 netfilter 修改 HOWTO。该网站上还有 netfilter 常见问题解答以及其它内容。
网上还有许多好的 netfilter 资源;但是,不要忘了基础知识。iptables man 页面非常详细,并且它是 man 页面的范例。
现在可以使用高级 Linux 路由和流量控制 HOWTO。它很好地显示了如何使用 iptables 来标记信息包,然后根据这些标记来使用 Linux 路由功能发送信息包。
可以使用 netfilter (iptables) 邮件列表,而且有一个适用于 netfilter 开发人员。使用这些 URL 还可以访问邮件列表档案。
关于作者
Daniel Robbins 居住在新墨西哥州的 Albuquerque。他是 Gentoo Technologies, Inc. 的总裁兼 CEO,Gentoo Linux(用于 PC 的高级 Linux)和 Portage 系统(Linux 的下一代移植系统)的创始人。他还是 Macmillan 书籍 Caldera OpenLinux Unleashed、SuSE Linux Unleashed 和 Samba Unleashed 的合作者。Daniel 自二年级起就与计算机结下不解之缘,那时他首先接触的是 Logo 程序语言,并沉溺于 Pac-Man 游戏中。这也许就是他至今仍担任 SONY Electronic Publishing/Psygnosis 的首席图形设计师的原因所在。Daniel 喜欢与妻子 Mary 和新出生的女儿 Hadassah 一起共度时光。可通过
[email protected] 与 Daniel 联系。