端口敲门

作者:Martin Krzywinski

防火墙管理员在设计全面的规则集时,面临着平衡灵活性和安全性的挑战。防火墙应提供针对恶意用户的保护,同时允许受信任的用户连接。不幸的是,根据 IP 地址和端口进行过滤并不能区分连接用户,因此始终无法过滤掉坏人。坏人可能并且确实来自受信任的 IP 地址。开放端口仍然是必要的漏洞:它们允许连接到应用程序,但也可能变成攻击的门户。本文介绍了一种新的安全系统,称为 端口敲门,其中受信任的用户通过跨闭合端口传输信息来操纵防火墙规则。

简而言之,用户尝试连接到一系列闭合端口。服务器端数据包过滤防火墙记录失败的连接,并由监控防火墙日志文件的守护进程检测到。当收到格式正确的敲门序列(充当身份验证中使用的密钥的角色)时,将根据序列的信息内容来操纵防火墙规则。这种基于用户的身份验证系统既强大(由内核防火墙介导),又隐蔽——无法检测到联网机器是否正在监听端口敲门。端口敲门不需要任何开放端口,并且可以扩展为传输编码在端口序列中的任何类型的信息。

在常用的防火墙中,过滤是通过连接主机的 IP 地址或该主机连接的端口来完成的。防火墙在任何用户身份验证发生之前检查数据包并与之交互;因此,它们不会区分进行连接的用户。预计一旦防火墙批准数据包并允许其进入网络,下游应用程序将处理用户身份验证。通常,这在保护和灵活性之间提供了足够的平衡。某些 IP 范围(例如,对黑客友好的网吧)可能会完全阻止传入流量,而其他 IP 范围中的主机可能被允许连接到通常对公众不可用的端口(专有/敏感应用程序)。不幸的是,这种基于 IP 的过滤有可能将受信任的用户锁定在您的系统之外。灵活性受到限制,因为来自被阻止的 IP 范围的任何人都无法连接,无论其信任状态如何。同时,保护被削弱,因为来自被阻止的 IP 范围的任何人实际上都可以旅行并从未经过滤的主机连接。

最终,只要端口保持开放,网络应用程序就容易受到攻击。使用入侵检测系统并保持应用程序更新可以在很大程度上提供保护,但它们仅针对已知的、衍生的或预期的攻击提供保护。

为了消除与公共开放端口相关的风险,端口敲门提供了一种跨闭合端口工作的身份验证系统。然而,必须颠覆对这些端口的使用,因为所有数据包都被拒绝。幸运的是,在大多数执行即使是最基本日志记录的防火墙中,信息已经以日志文件中指示连接尝试的条目的形式跨闭合端口流动。

考虑以下示例。少量端口(100-109)配置为拒绝所有流量——不向连接客户端发回 ICMP 错误数据包——并且记录所有尝试的连接。在本示例中,防火墙 IP 为 IPF,连接客户端 IP 为 IPC。关闭端口并记录连接的相应 ipchains 命令是

ipchains -A input -p tcp -s 0/0 -d IPF/32 100:109 -j DENY -l

用户尝试从 IPC 按顺序连接到以下防火墙端口:102、100、100、103。从用户的角度来看,连接静默失败。但是,在防火墙上,已记录了 102、100、100、103 数字序列。

Feb 12 00:13:26 ... input DENY eth1 PROTO=6 IPC:64137 IPF:102 ...
Feb 12 00:13:27 ... input DENY eth1 PROTO=6 IPC:64138 IPF:100 ...
Feb 12 00:13:27 ... input DENY eth1 PROTO=6 IPC:64139 IPF:100 ...
Feb 12 00:13:28 ... input DENY eth1 PROTO=6 IPC:64140 IPF:103 ...

敲门序列出现在防火墙日志中,用户已跨闭合端口传输数据。

端口敲门系统的任何实现都需要提供一些基本功能。首先,需要设计某种方法来监视防火墙日志文件。文章稍后更全面地讨论了列表 2 中提供的一个简单的 Perl 应用程序,该应用程序跟踪文件。其次,需要一种方法从日志文件中提取端口序列,并将它们的有效负载转换为可用的信息。在此步骤中,重要的是能够 (a) 检测端口序列何时开始和结束,(b) 在存在不属于序列的虚假连接尝试的情况下正确检测端口序列,以及 (c) 跟踪同时从不同远程 IP 到达的多个端口序列。可以设计用于生成端口序列的编码,以最大限度地减少序列的长度。例如,序列 100、102 可以对应于一个或一系列预定义的操作(例如,为特定 IP 打开端口 ssh/22 15 分钟,然后关闭端口)。最后,一旦从序列中派生出信息,实现必须提供某种方法来操纵防火墙规则。

端口敲门的优势

端口敲门的关键功能之一是它为没有开放端口的联网机器提供了一种隐蔽的身份验证和信息传输方法。不可能通过使用端口探测成功确定机器是否正在监听敲门序列。因此,尽管可以发起暴力攻击来尝试猜测端口和序列的形式,但可以轻松检测到此类违规尝试。

其次,由于信息以连接尝试的形式流动,而不是以典型的数据包数据有效负载的形式流动,因此在不知道此系统到位的情况下,通过监视流量不太可能检测到此身份验证方法的使用。为了最大限度地降低拦截方构建功能序列的风险,可以加密包含序列远程 IP 的信息内容。

第三,由于身份验证内置于端口敲门序列中,因此无需更改现有应用程序。通过调整解释特定序列的方式,可以轻松实现一次性密码。序列可能对应于打开端口特定时间长度的请求,然后在一段时间后关闭端口,并且永远不再向同一 IP 打开端口。此外,可以使用一次性密钥来加密序列,使其对于没有密钥的人来说是无法破译的。

端口敲门的缺点

要使用端口敲门,需要一个执行敲门的客户端脚本。客户端和任何关联的数据都应视为机密,并保存在可移动介质上,例如 USB 密钥。客户端的使用对每个连接都施加了开销。某些位置(例如图书馆或网吧)可能不允许执行任意程序。

为了使用端口敲门,需要分配多个端口供此系统专用。随着此类端口数量的增加,对于给定数量的信息有效负载,敲门序列变得更短,因为编码符号的数量增加了。实际上,通常可以分配 256 个空闲特权端口(在 1-1024 范围内,不一定是连续的)并将其用于监听端口敲门。

最后,任何以自动化方式操纵防火墙规则的系统都需要仔细的实现。对于最初没有端口打开的场景,如果监听守护进程失败或无法正确解释敲门,则无法远程连接到主机。

应用

在本节中,概述了三个示例,说明了如何使用端口敲门系统。

1. 单端口,固定映射

只需要连接到一个端口 (ssh/22)。ssh 守护进程正在运行;所有特权端口都已关闭,包括 ssh/22;并且正在记录寻址到端口 30、31、32 的数据包。以下端口序列被识别

31,32,30        open ssh/22 to connecting IP
32,30,31        close ssh/22 to connecting IP
31,30,32        close ssh/22 to connecting IP and disregard further knocks from this IP

有充分理由保持偏执的管理员可以通过启动到端口 31、32、30 的 TCP 连接来打开其系统上的 ssh/22 端口。在 ssh 会话结束时,将使用上面显示的第二个序列关闭端口。如果管理员连接的主机不受信任(例如,击键可能被窃听),则使用第三个序列将拒绝来自该 IP 的所有进一步流量,从而防止任何人复制会话。这假设端口序列和系统登录凭据没有被第三方捕获并在合法会话结束之前使用。

在此示例中,系统仅理解三个序列,因为需求仅要求少量明确定义的防火墙操作。选择序列不是单调递增的 (30、31、32),因此它们不会被远程端口扫描触发。如果要通过此系统保护多个端口,则需要在端口序列和灵活的防火墙规则之间派生映射。这将在下一个示例中介绍。

2. 多端口,动态映射

在此示例中,网络可能正在运行任意数量的应用程序。端口 100-109 用于监听敲门。端口序列预计采用以下形式

102,100,110  10a,10b,10c,10d  10(a+b+c+d mod 10)        110,100,102
header          payload             checksum                 footer

前三个和最后三个端口让端口敲门守护进程知道序列正在开始和结束。接下来的四个端口编码要打开的端口 (abcd)。例如,如果需要连接到端口 143,则序列将为 100、101、104、103。序列中的最后一个元素是校验和,用于验证序列有效负载。在本示例中,校验和为 8 (1+4+3 mod 10)。因此,序列元素为 108,完整序列将为

102,100,103  100,101,104,103 108 103,100,102

当检测到此序列时,端口 143 将对传入的 IP 地址可用。如果端口已打开,则敲门会使其关闭。敲门可以扩展为包含其他信息,例如预期的会话长度,该信息可用于在设定的时间后关闭端口。

3. 使用加密的映射

可以加密敲门序列中包含的信息,以提供额外的安全措施。在此示例中,分配并记录了 256 个端口。形式的敲门映射

remote IP  port   time   checksum

使用,其中远程 IP、端口、时间和校验和(其他字段的总和 mod 255)被加密。可以使用 Perl 的 pack("C*",STRING) 命令将加密的字符串映射到八个无符号字符,请参阅列表 1。

列表 1. 映射加密的字符串

实现

提出了端口敲门的最小原型 Perl 实现。该实现由 knockclient(负责发起敲门序列)和 knockdæmon(负责监视防火墙日志和操纵规则)组成。

Knockclient

完整的客户端如列表 1 所示。Lincoln Stein 的 Crypt::CBC 模块用作 Crypt::Blowfish 的代理来执行加密。未加密的敲门序列由七个值组成:四个 IP 字节、一个端口(在此实现中限制为 0-255 范围)、一个时间标志和一个校验和 (mod 255)。在防火墙 (IP=IPF) 上敲门以打开 IP=IPC 上的端口 ssh/22,然后在 15 分钟后关闭端口,将通过如下调用客户端来执行

knockclient -i IPC -r IPF -p 22 -t 15

客户端打包七个整数的列表,执行加密,并将字符串解包为无符号字符 (0-255)。然后将这些值映射到 745-1000 范围内的端口序列。

Knockdæmon

knockdæmon 如列表 2 所示。此应用程序使用 File::Tail 在防火墙日志文件中查找新行。解析与端口 745-1000 的连接尝试对应的行,以获取远程 IP 和端口号。为每个传入的 IP 维护一个存储端口的 8 元素队列。当队列大小达到 8 时,将解密其内容。如果解密成功且校验和正确,则采取适当的操作并清除队列。如果解密失败,则删除最旧的队列端口元素,并且守护进程继续监视。

列表 2. knockdæmon

防火墙规则由对 ipchains 二进制文件的系统调用来操纵,尽管也可以使用 Jonathan Schatz 的 IPChains Perl 模块。如果要关闭端口(如时间标志所示),则使用 Jose Rodrigues 的 Schedule::At 模块来计划使用 at 队列系统删除规则。

结论

端口敲门是一种隐蔽的身份验证系统,它使用闭合端口来执行受信任用户的身份识别。这种新颖的方法提供了建立与完全隔离的系统上运行的应用程序的连接的方法,该系统最初没有任何端口是开放的。

电子邮件:martink@bcgsc.ca

加载 Disqus 评论