内核角落 - iptables 的隐藏宝藏
Linux 的 iptables 允许以远低于许多商业产品的成本实现强大的防火墙。基本的 iptables 防火墙是数据包过滤器,这意味着它们一次检查通过它们的网络通信一个数据包,并决定如何处理这些数据包。简单的配置可以用于丢弃某些数据包并接受其他数据包。通常根据数据包发送到的 IP 地址和端口号以及其传播方向来决定对特定数据包应用哪种策略。iptables 还可以使用状态信息,根据数据包相关的连接状态做出更明智的选择。这被称为连接跟踪。
一个简单且高效的防火墙配置阻止从公共互联网发起的入站 TCP/IP 连接数据包和 UDP 交换,同时允许通过转换地址出站。这使用户可以自由访问外部世界,同时保护他们免受不必要的入侵。这种配置有点过于简单,可能需要额外的过滤器才能真正有用,但基本概念很简单。
除了这些简单的数据包过滤标准之外,iptables 还有更多功能。其中一些附加功能相当为人所知,甚至可能进入一些现成的 Linux 发行版,但一些不太为人所知的功能值得研究。这些是我打算在本文中向您指出的隐藏宝藏。要描述所有可能的功能和与其相关的选项需要一本书,因此我在这里所做的只是标记它们的存在,并将您放在探索的道路上。
Netfilter 有两组组件,内核和用户模式部分。用户模式组包括 iptables 和相关的实用程序、库、手册页和脚本。内核组件是对现有内核源代码的补丁和一些额外的模块。
对于新手来说,将补丁应用于像 Linux 内核这样庞大而复杂的系统可能是一项艰巨的任务,而且这条道路上布满了陷阱和潜在的盲点。一个糟糕或不兼容的补丁很容易产生无法编译的内核,或者更糟的是,无法启动的内核。Netfilter 团队试图通过为我们提供机器人指南 POM 或 Patch-o-matic 来解决这些难题。POM 是补丁集合和一个用于将它们应用于内核的脚本,即使对于相对新手来说,使用起来也是一种乐趣。
POM 包含的内核补丁根据其历史和质量分为多个组。其中一些是每个 iptables/Netfilter 安装中所需的基础补丁。其他的是可选或实验性的附加功能,提供有趣的功能,我将在本文中描述其中一些功能。这些是承诺的隐藏宝藏,POM 文档将其描述为“可能已损坏,可能很酷的扩展”。
运行 POM 很简单;从 ftp.netfilter.org 上的目录 /pub/patch-o-matic 下载最新的 Patch-o-matic tarball,将其还原到您的系统上,并在以 root 身份登录时运行以下命令。确保给出正确的内核源代码目录名称作为 KERNEL_DIR 参数的值
KERNEL_DIR=/usr/src/linux-2.4 ./runme extra
字符串模块可能是 POM 宝藏中最广泛使用的额外功能。它允许将数据包与出现在其数据有效负载中任何位置的字符串进行匹配。该模块有各种用途,但需要仔细应用,以免过于狂热。一种可能的用途是阻止从 Web 下载 ELF 可执行文件。我们可以设置一个过滤器,通过查找来自面向互联网的接口且源端口为 80 的 TCP/IP 数据包来识别 Web 返回流量。如果我们知道 ELF 文件以十六进制字符 7f 开头,后跟字母 ELF(确实如此),我们可以使用字符串匹配来搜索此序列。非 ASCII 字符可以通过使用管道符号将它们括起来嵌入到字符串中,因此我们使用|7F|ELF。假设面向互联网的网络接口是 eth0,命令是
iptables -A FORWARD -i eth0 -p tcp --sport 80 \ -m string --string '|7F|ELF' -j DROP
将十六进制字符嵌入到字符串中的语法是在 iptables 1.2.8 中引入的。如果您使用的是早期版本,则需要求助于技巧。例如
--string "`dd if=/bin/ls bs=4 count=1 2>/dev/null`"
获取 /bin/ls 的前四个字符,这是一个包含我们想要的字符串的 ELF 文件。
我们可以通过声明我们信任来自 192.168.0.5 的内容来扩展此示例,因此,不想将过滤器应用于该服务器。这可以通过在 IP 地址上添加反向匹配来轻松完成,如下所示
iptables -A FORWARD -i eth0 -p tcp ! \ -s 192.168.0.5 --sport 80 -m string \ --string '|7F|ELF' -j DROP
此示例有两个问题突出了字符串匹配模块的问题。首先,该规则匹配任何数据包,只要该数据包在数据中的任何位置包含此序列,而不仅仅是在文件开头。这意味着该规则可能会匹配误报并阻止我们不希望阻止的数据包。其次,如果我们正在查找的字符串实际上被分成两个相邻的数据包,则不会匹配。该模块需要整个字符串出现在单个数据包中。
因此,字符串模块很有用,但很基础。它不允许不区分大小写的匹配,也不允许指定字符串的位置,也不允许在数据流中跨多个数据包拆分时找到字符串。编写此模块的扩展版本有很大的空间。
mport 扩展允许单个规则使用扩展语法指定多个端口号和范围。在没有 mport 的情况下,iptables 命令可以在单个命令中指定单个端口或相邻端口范围。有了 mport,语法允许更复杂的结构。例如,我们可以使用单个命令允许 X 终端、Web 和邮件,如下所示
iptables -A INPUT -p tcp -m mport \ --dports 80,110,21,6000:6003 -j ACCEPT
如果不使用 mport,则必须使用四个单独的命令来指定
iptables -A INPUT -p tcp --dports 80 -j ACCEPT iptables -A INPUT -p tcp --dports 110 -j ACCEPT iptables -A INPUT -p tcp --dports 21 -j ACCEPT iptables -A INPUT -p tcp --dports 6000:6003 \ -j ACCEPT
使用单个规则代替四个规则提供潜在的性能优势,因为通过系统的数据包需要更少的处理。它还使规则文件的维护更容易,因为需要相同处理的服务可以轻松地组合在一起。正如您可能猜到的那样,mport 是 multiple ports(多端口)的缩写。
time 模块允许规则将一天中的时间和一周中的某天引入到匹配逻辑中。示例用途是在午餐时间才允许访问个人网站,或者在例行维护期间将 Web 流量转移到辅助服务器。以下示例使 Web 服务在周五凌晨 4 点到 6:30 之间不可访问,大概是为了系统维护
iptables -A INPUT -p tcp -d 80 -m time \ --timestart 04:00 --timestop 06:30 --days Fri \ --syn -j REJECT
如果您珍视自己的生命或欣赏风景的变化,您真的不想徘徊到焦油坑中。它们是自然界中粘蝇纸的等价物;靠得太近,您就不会匆忙离开。iptables 的 TARPIT 组件是网络的等价物:如果您不明智地与作为焦油坑的端口建立 TCP/IP 连接,您会发现很难关闭连接并释放已使用的系统资源以供将来使用。
为了实现这种焦油坑状态,iptables 接受传入的 TCP/IP 连接,然后切换到零字节窗口。这迫使攻击者的系统停止发送数据,很像在终端上按 Ctrl-S 的效果。攻击者关闭连接的任何尝试都会被忽略,因此连接保持活动状态,并且通常在 12-24 分钟后超时。这消耗攻击者系统上的资源,而不是运行焦油坑的 Linux 服务器或防火墙。您可以使用以下 iptables 命令将数据包传递到坑中
iptables -A INPUT -p tcp -m tcp -dport 80 -j TARPIT
您可能不想在同一系统上使用 conntrack 和 TARPIT,特别是如果您预计会用这种特殊品牌的粘蝇纸捕获大量苍蝇。每个卡住的连接都会消耗 conntrack 资源。
迷惑潜在攻击者的一种方法是使您的 Linux 系统看起来像一台 Microsoft Windows 机器,方法是使 netbios 端口响应端口扫描。然后将任何连接请求传递到焦油坑。这具有浪费攻击者时间的效果,因为他们感觉到可能的开口并试图获得访问权限。他们会因长时间超时和明显的错误目标而感到沮丧。以下规则之类的规则会产生此结果
iptables -A INPUT -p tcp -m tcp -m mport \ --dports 135,139,1025 -j TARPIT
另一种可能性是 TARPIT 除您真正想要使用的端口之外的所有端口。这再次导致外部人员将每个端口都视为打开状态,并浪费时间尝试获得访问权限。此外,这样的配置阻止 tcpdump 正确确定服务器上运行的操作系统。在此示例中,我们允许 Web 和电子邮件流量,并使其他所有内容陷入困境
iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT iptables -A INPUT -p tcp -m tcp --dport 25 -j ACCEPT iptables -A INPUT -p tcp -m tcp -j TARPIT
您可以在 www.spinics.net/lists/netfilter/msg17583.html 上找到一个有趣的真实故事,讲述 TARPIT 和字符串如何帮助一位特定的系统管理员(不是我)。
随机匹配模块仅基于随机选择来匹配数据包。您可以通过设置数据包匹配的概率来调整逻辑,范围在 0% 到 100% 之间。示例应用包括模拟有故障的连接或服务器,或跨多个镜像 Web 服务器分配负载。以下示例在三台服务器之间分配 Web 流量。第一个规则将 33% 的连接发送到 192.168.0.100 的服务器。接下来的 33% 发送到 192.168.0.101,最后三分之一捕获剩余部分并将它们传递到 192.168.0.102
iptables -t nat -A PREROUTING -i eth0 -p tcp \ --dport 80 --syn -m random --average 33 \ -j DNAT --to-destination 192.168.0.100:80 iptables -t nat -A PREROUTING -i eth0 -p tcp \ --dport 80 --syn -m random --average 50 \ -j DNAT --to-destination 192.168.0.101:80 iptables -t nat -A PREROUTING -i eth0 -p tcp \ --dport 80 --syn -j DNAT \ --to-destination 192.168.0.102:80
可以挖掘和享受数十个宝藏。我在这里描述了少量,但还有很多。只需运行runme脚本并在显示时阅读补丁描述是了解可用内容的一种方法。以下是您可以找到的更多示例
RSH、MMS(媒体流)、PPTP、Quake、RPC 和 Talk 的连接跟踪。
通过 /proc 文件系统扩展对配置和状态信息访问的支持。
扩展对 IPv6 功能的支持。
在 IP 数据包中操作选项、TTL 等。
对 NAT 连接进行更精细的控制。
控制配额和带宽使用限制。
反操作系统指纹识别逻辑和端口扫描检测。
连接标记(和标记测试)。
使用 POM 添加的补丁不会将其描述添加到 iptables 手册页中,因此我们需要转向其他地方寻求文档。用于调用这些扩展的基本语法可以使用 iptables 内置帮助工具显示。例如,iptables -m random -help给出通常的帮助消息,但在末尾显示随机模块的参数。相同的技术可以应用于其他模块。
您还可以参考 Patch-o-matic 目录结构中保存的模块帮助文件。随机模块的文件是 base/random.patch.help。可以为其他补丁找到类似的文件。
最后,利用 Netfilter 网站 www.netfilter.org/patch-o-matic,其中包含每个 POM 补丁的描述。
大多数 iptables 扩展都有两个部分,Linux 内核的补丁和供 iptables 用户空间程序使用的配置助手库。在 www.lowth.com/howto/add-iptables-modules.php 上概述了将 POM 模块添加到内核和 iptables 工具的详细过程。总之,我们需要采取的步骤是更新您的系统;下载最新的 Patch-o-matic 源代码;使用 runme 脚本修补内核;重新编译并安装修补后的内核;以及重新编译并安装 iptables 软件。
我们已经看到 Linux 的 Netfilter 为构建有效的防火墙提供了一套出色的功能,但并非所有这些功能都在许多 Linux 发行版上默认安装。Patch-o-matic 软件允许管理员通过自动化的 Linux 内核修补方法来扩展其防火墙的基本功能。
最后,请记住这个想法:我们已经看到 iptables/Netfilter 有许多令人兴奋的可能性隐藏在初始检查之外。其他软件包很可能也是如此。这是开源软件乐趣的一部分;没有什么真正隐藏的。存在的一切都在那里等待着熟练的寻求者去发现。
Chris Lowth 在 Intercai Mondiale (www.intercai.co.uk) 担任顾问,这是一家位于英国的电信、IT 和商业咨询公司。他设计安全软件和网络管理 (OSS) 解决方案,并尝试弹吉他。可以通过 chris@lowth.com 联系 Chris。