为您的计算机披上安全毯
随着互联网的飞速发展,计算机系统的安全性已成为大型企业、小型企业和个人关注的焦点。几乎每周都会发现某些网络中的安全漏洞。许多公司通过在其内部网络和互联网之间安装防火墙来降低威胁,但对于在家中或办公室运行 Linux 的单个用户来说,这种选择通常过于昂贵且繁琐。TCP_wrappers 由荷兰埃因霍温理工大学的 Wietse Venema 编写。它提供了一种简单、优雅且有效的方法来保护您的网络服务免受入侵者的访问和可能的滥用。
在本文中,我们将讨论 TCP_wrappers 是什么以及它们如何工作,以及如何配置 TCP_wrappers 以保护您的机器免受未经授权的访问。我们还将讨论 TCP_wrappers 的一些更高级的功能,这些功能提供详细的日志记录,甚至可以帮助跟踪试图闯入您机器的尝试。
首先,我们需要了解传输控制协议 (TCP) 连接(例如 telnet)是如何完成的。TCP 网络连接基于“客户端/服务器”模型。telnet 程序是一个客户端,它与服务器程序或守护程序通信,该守护程序称为 telnetd 或 in.telnetd,具体取决于您的机器设置方式。由于大多数 Linux 发行版在 /usr/sbin 目录中使用名称 in.serviced 来表示网络守护程序,因此在本文的剩余部分中,我将使用该命名约定。
所有网络服务请求首先都通过“互联网守护程序”inetd。(与生活中的所有事物一样,此规则也有例外,请参阅下面的“TCP_wrappers 不能做什么”。)此守护程序使用两个配置文件来确定如何响应网络连接请求。文件 /etc/services 列出了特定服务的名称以及这些服务的端口号。文件 /etc/inetd.conf 列出了服务的名称以及提供服务的程序或守护程序的名称。列表 1 和 列表 2 包含来自 /etc/services 和 /etc/inetd.conf 文件的一些示例行。
如果我坐在 my.linux-box.com 并键入命令
telnet your.machine.com
我的 telnet 客户端发送一个信息包,其中包含(除其他内容外)源地址 my.linux-box.com、目标地址 your.machine.com 和连接的端口号。telnet 的端口号是 23。inetd 在 /etc/services 中查找端口 23,找到服务名称 telnet。然后它在 /etc/inetd.conf 中查找 telnet,发现它需要运行名为 in.telnetd 的守护程序,该守护程序在列表 2 的最右列中列出。inetd 运行 in.telnetd,将其连接到端口 23,然后继续监听更多连接。in.telnetd 响应我的客户端,要求提供用户名和密码,并启动 telnet 会话。
如果您不希望其他人 telnet 进入您的计算机怎么办?您可以修改 in.telnetd 的代码,以查看连接请求的源地址,并拒绝来自本地机器或域外部的任何地址。如果 telnet 是唯一的网络服务,这将很容易,但是有数十种网络服务,并且修改每个守护程序以限制对您机器的访问将是一场噩梦。
此时,TCP_wrappers 可以提供帮助。wrapper 程序是一个微小的守护程序,它位于 inetd 和网络守护程序(例如 in.telnetd 和 in.ftpd)之间。由于所有 TCP 连接都以基本相同的方式启动,因此可以使用单个 wrapper 程序来控制对几乎所有 TCP 网络服务的访问。
当安装 wrapper 时,互联网守护程序将被重新配置为运行 wrapper 而不是普通网络守护程序。wrapper 检查连接的源地址和它希望连接的服务,并决定是否允许连接。如果 your.machine.com 拒绝了我对 telnet 会话的请求,我只会看到连接被断开。如果请求被允许,则一切正常进行,并且 wrapper 永远不会实际与我的 telnet 客户端交互。在这两种情况下,wrapper 都会在系统日志中写入一条注释,让您知道我是否成功连接到您的机器。
每个主要的 Linux 发行版都预装了 TCP_wrappers,作为网络包的一部分。要查看您的机器上是否安装了 TCP_wrappers,请在 /etc 目录中查找两个名为 hosts.allow 和 hosts.deny 的文件。这些是 TCP_wrapper 守护程序 tcpd 使用的配置文件。您还可以查看您的 /etc/inetd.conf 文件中是否有如下行
telnet stream tcp nowait root /usr/sbin/tcpd \ in.telnetd
telnet 选项 /usr/sbin/tcpd 表示,每当有人尝试 telnet 连接到您的机器时,他将首先连接到 TCP wrapper。
TCP_wrappers 很可能在您的 Linux 系统上,因此在本文中我将不介绍从头开始编译它们的过程。有关如何下载和安装 TCP_wrappers 的更多信息,请参阅侧边栏“在哪里获取 TCP_wrappers”。
正如我上面提到的,TCP_wrappers 守护程序 tcpd 从两个文件 /etc/hosts.allow 和 /etc/hosts.deny 获取有关是否允许或拒绝访问的指令。tcpd 首先扫描 /etc/hosts.allow 以查找与特定服务和计算机主机名匹配的“规则”,然后搜索 /etc/hosts.deny。如果未找到匹配项,则允许访问。默认情况下,大多数发行版都以“完全开放”的方式发布 TCP_wrappers,即文件 /etc/hosts.allow 和 /etc/hosts.deny 为空,允许所有人访问您机器上的所有互联网服务。
在配置 TCP_wrappers 之前,您必须决定您希望您的机器是“主要开放”还是“主要关闭”。“主要开放”意味着大多数服务对互联网上的大多数其他计算机可用;这对于阻止访问少数几个有问题的站点或关闭一两个服务很有用。“主要关闭”意味着大多数服务对大多数其他计算机关闭。对于正常家庭使用的个人计算机来说,“主要关闭”可能是更好的选择,而且它肯定是更安全的选择。
让我们先看一下“主要开放”配置。由于我们允许大多数连接,因此 /etc/hosts.allow 文件保持为空。在 /etc/hosts.deny 文件中,让我们放入一个规则,拒绝来自机器 nasty.badguy.net 和域 cracker.org 中任何人的 telnet 和 rlogin 访问。/etc/hosts.deny 中的必要行将是
in.telnetd in.rlogind : nasty.badguy.net \ .cracker.org
注意 cracker.org 前面的前导“.”。它向 tcpd 发出信号,拒绝访问该互联网域中的任何机器。由于这些站点上的黑客可能知道如何利用 telnet 和 rlogin 以外的网络服务,因此您可以使用通配符 ALL 拒绝访问所有服务
ALL : nasty.bad-guy.com .cracker.org可以替换特定主机名的其他通配符包括 LOCAL、UNKNOWN、KNOWN 和 PARANOID。LOCAL 匹配任何名称中没有“.”的名称,即您本地域中的主机名。KNOWN 和 UNKNOWN 分别指在域名服务中找到或未找到的主机。PARANOID 匹配任何名称与其互联网地址不匹配的主机。此选项不常用,因为 wrapper 被编译为在检查 hosts.allow 和 hosts.deny 文件之前拒绝访问任何符合此条件的主机。为了允许我们本地域中的机器访问所有网络服务,我们可以将以下行放入 /etc/hosts.allow 中
ALL : LOCAL现在让我们看一下“主要关闭”配置。请记住,首先检查 hosts.allow,然后检查 hosts.deny,最后,只有在 hosts.deny 中未找到匹配项时才允许访问。为了关闭所有外部机器的所有服务,我们在 hosts.deny 文件中使用以下规则
ALL : ALL在 hosts.allow 中,我们仅列出我们希望其他人使用的特定服务。当然,我们仍然希望访问我们自己机器上的所有服务。假设我们还希望从我们的互联网服务提供商在 my.isp.net 处提供的 shell 帐户 telnet 进入我们的机器,并且我们希望允许任何人 finger 我们的帐户。放入 /etc/hosts.allow 文件中的规则是
ALL : localhost in.telnetd : my.isp.net in.fingerd : ALL现在,如果我们也想阻止来自 cracker.org 的黑客使用 finger 获取有关我们的信息,我们可以修改此项
ALL : localhost in.telnetd : my.isp.net in.fingerd : ALL EXCEPT .cracker.org如您所见,存在相当大的灵活性——但这种灵活性也带来了混淆的可能性,甚至更糟糕的是,错误。如果 TCP_wrappers 的配置文件不正确,您可能 认为 您是安全的,但实际上您并非如此。为了检查您的配置并测试其保护,Wietse Venema 提供了两个额外的程序:tcpdchk 和 tcpdmatch。
tcpdchk 检查配置文件中是否存在任何问题。它可以判断您是否错误地使用了 ALL 或 LOCAL 等通配符,访问规则中是否存在不存在的主机名,/etc/inetd.conf 文件中是否存在由 tcpd 控制的服务的规则等等。例如,我的机器上上述“主要关闭”配置的 tcpdchk 输出产生以下信息
# tcpdchk -v Using network configuration file: /etc/inetd.conf >>> Rule /etc/hosts.allow line 6: daemons: ALL clients: localhost access: granted >>> Rule /etc/hosts.allow line 7: daemons: in.telnetd clients: my.isp.net warning: /etc/hosts.allow, line 7: my.isp.net: \ host not found access: granted >>> Rule /etc/hosts.allow line 8: daemons: in.fingerd clients: ALL EXCEPT .cracker.org access: granted >>> Rule /etc/hosts.deny line 10: daemons: ALL clients: ALL access: denied
我使用了 -v 开关来使 tcpdchk 生成更详细的输出。请注意,该程序说找不到 my.isp.net,这完全正确,因为它是一个为本示例虚构的主机名。另请注意,我没有收到同样虚构的 .cracker.org 的类似消息。那是因为它针对整个域,而 tcpdchk 不检查域是否已注册,而是检查特定主机名是否在 DNS 中。
tcpdmatch 针对互联网连接的 虚拟 请求测试您的配置。您提供守护程序的名称和主机名,它会告诉您是否允许或拒绝该连接。例如,如果我想知道 www.linuxjournal.com 的网站管理员是否可以 finger 我的系统上的用户,我将输入以下内容
# tcpdmatch in.fingerd webmaster@www.linuxjournal.com client: hostname www.ssc.com client: address 199.184.169.67 client: username webmaster server: process in.fingerd matched: /etc/hosts.allow line 8 access: granted
请注意,tcpdmatch 找到了 www.linuxjournal.com 的真实主机名为 www.ssc.com,并报告了其互联网地址。最后一行告诉我,确实允许从此主机进行 finger。
在 S. Garfinkel 和 G. Spafford 于 1996 年撰写的 实用 UNIX 和互联网安全,第二版(O'Reilly & Associates 出版)中,作者指出
像 tcpdchk 和 tcpdmatch 这样的程序是对安全程序 tcpwrapper 的极佳补充,因为它们可以帮助您在安全问题发生之前就将其消除。Wietse Venema 值得称赞,因为他想到编写并将它们包含在他的 tcpwrapper 版本中;其他程序员应该效仿他的榜样。
我完全同意。
TCP_wrappers 每次请求连接时都会在您的系统日志中写入一条消息,无论是否授予访问权限。日志中的这些条目本身就足以在您的系统上安装 TCP_wrappers。消息通过标准 syslog 工具写入,默认情况下与邮件事务转到同一位置。在我的 Linux 发行版 Caldera Network Desktop(基于 Red Hat Linux)中,默认设置已更改,以便将消息写入与其他守护程序相同的日志文件(LOG_DAEMON 工具)。
无论如何,当有人通过 telnet 访问我的机器时,类似这样的消息会放入 /var/log/messages 中
Apr 9 17:24:58 ads in.telnetd[15339]: connect from somewhere.else.com
如果连接被拒绝,则消息将显示
Apr 9 17:25:15 ads in.telnetd[15604]: refused connect from someother.place.com如果我想查看我的日志中所有 telnet 尝试,我可以简单地键入命令
grep telnetd /var/log/messagesTCP_wrappers 可以通过使用“陷阱”为我提供更多信息。可以将 TCP_wrappers 配置为在请求某些服务时 运行 shell 命令。假设我有理由怀疑 nasty.badguy.com 的某人试图使用简单文件传输程序 (TFTP) 窃取我的密码文件。在我的 /etc/hosts.deny 文件中,我可以放入以下行(此示例直接来自 TCP_wrappers 附带的 hosts_access(5) 手册页)
in.tftpd : nasty.bad-guy.com : ( /usr/sbin/safe_finger -l @%h |\ /bin/mail -s %d->%h root) &拒绝来自 nasty.badguy.com 的所有用户访问 TFTP。此外,命令
safe_finger @nasty.badguy.com被运行,结果通过管道传输到发送给 root 用户的邮件消息中,主题行为
in.tftpd->nasty.bad-guy.comsafe_finger 是与 TCP_wrappers 一起提供的命令,它剥离任何“坏”字符,如控制序列和数据溢出。运行 safe_finger @hostname 会生成当前登录到该系统的所有人的列表。字符串 %h 和 %d 称为扩展,tcpd 会将它们替换为相应的主机名和守护程序进程的文本。其他扩展包括客户端互联网地址 %a 和客户端用户名 %u。
现在,这不是一个完美的解决方案,因为我们的黑客朋友可能禁用了他的 finger 服务或更改了它以提供虚假信息;但是,此示例确实向我们展示了 TCP_wrappers 程序的强大功能。
/etc/hosts.allow 和 /etc/hosts.deny 文件中的访问控制语言非常简单但功能强大,但可以编译 TCP_wrappers 以包含对正常访问控制的更强大的扩展。您可以不使用行
service : host
在配置文件中,您可以使用行
service : host : option : option ...其中 option 可以是 allow、deny 或许多其他高级选项。
要启用高级选项,请使用 -DPROCESS_OPTIONS 编译 wrapper 程序。我的 Caldera/Red Hat 发行版以这种方式编译 wrapper。要检查您的发行版是否具有高级选项,请运行 tcpdchk<\!s>-a。在我的系统上,我看到以下输出
warning: /etc/hosts.allow, line 6: implicit "allow" at end of rule warning: /etc/hosts.allow, line 7: my.isp.net: host not found warning: /etc/hosts.allow, line 7: implicit "allow" at end of rule warning: /etc/hosts.allow, line 8: implicit "allow" at end of rule
消息 implicit<\!s>"allow" 表明我的 wrapper 版本正在 /etc/hosts.allow 文件中查找其他选项。如果您的发行版未编译 PROCESS_OPTIONS,您将看不到此消息。
使用高级选项,我们可以完全取消 /etc/hosts.deny 文件,因为可以将 "allow" 和 "deny" 的选项添加到任何规则。我们可以更改日志记录级别、控制网络服务的优先级(“nice 值”)、使用 RFC 931 “ident”协议查找用户名以及为每个服务显示自定义“横幅”。
有关这些高级功能的更多信息,请参阅 TCP_wrappers 附带的 hosts_options(5) 手册页,或上面引用的 Garfinkel & Spafford 书籍(对于任何关心网络安全的人来说,都是必读之物)。现在,让我们转换我们的 /etc/hosts.allow 和 /etc/hosts.deny 文件以使用高级选项。不再需要 etc/hosts.deny 文件。在 /etc/hosts.allow 中,我们将规则重写如下
ALL : localhost : allow in.telnetd : my.isp.net : allow in.fingerd : ALL EXCEPT .cracker.org : allow in.tftpd : nasty.bad-guy.com : spawn \ (/usr/sbin/safe_finger -l @%h |\ /bin/mail -s %d-%h root) & : deny ALL : ALL : deny
用英语来说,这意味着以下内容
允许来自我们自己机器的所有服务。
允许来自 my.isp.net 的 telnet。
允许来自除 cracker.org 域中的主机之外的所有地方的 finger。
不允许来自 nasty.badguy.com 的 tftp,如果他们尝试,我们将设置“陷阱”以找出罪魁祸首。
拒绝来自其他任何地方的所有其他服务。
正如我们所见,TCP_wrappers 提供了一种简单有效的方法来控制对我们机器的访问。但是,我们仍然必须记住“计算机安全中没有绝对的安全,只有更安全或更不安全。” 与所有安全措施一样,TCP_wrappers 也有其局限性。
首先也是最重要的是,wrapper 无法控制在启动时启动并运行到系统关闭的服务的访问。像 sendmail 和 httpd(万维网服务器)这样的服务属于这一类。这些服务始终在监听自己的端口,并且需要自己的访问控制。关于 sendmail 和万维网的安全性的讨论内容可以填满整卷书籍,而且肯定超出了本文的范围。
TCP_wrappers 也可能容易受到“主机名欺骗”的影响。像 rsh 和 rlogin 这样的服务依赖于主机名的正确性。如果您使用的 DNS 服务器无法在其中查找主机名,则攻击者有可能通过将其计算机的名称隐藏在您的机器“信任”的名称后面来“欺骗”名称查找。您可以通过在本地 /etc/hosts 文件中为互联网地址和主机名添加条目来阻止这些攻击,这样您就不依赖于外部 DNS 查找(额外的好处是主机名查找速度更快)。请注意,您现在负责保持 /etc/hosts 文件是最新的。如果 /etc/hosts 文件中的计算机更改了其互联网地址,则访问将被拒绝,直到您更改其条目为止。幸运的是,这种情况很少发生,我经常在我的 /etc/hosts 文件中为我经常联系的计算机以及每个允许访问我的机器的主机添加条目。
TCP_wrappers 还做了一些额外的工作来避免名称欺骗攻击。当使用默认选项 PARANOID 编译时(请参阅上面关于通配符的讨论),wrapper 不仅通过查找其名称来检查互联网地址,还通过查找其地址来检查。如果两者不匹配,则会自动拒绝访问。
另一个漏洞可能来自“源路由”,即来自某些“外部”地址的计算机声称是“内部”的可信计算机。可以使用 KILL_IP_OPTIONS 编译 TCP_wrappers 以禁用源路由。幸运的是,我们 Linux 用户通常不必担心这种攻击,因为 IP 源路由在内核本身中默认情况下是关闭的。
最后,即使您可以使用 wrapper 来控制对某些服务的访问,避免利用服务的最佳方法是从一开始就完全关闭它。如果您不需要使用 rsh 或 rlogin,请编辑您的 /etc/inetd.conf 文件,并在 shell 和 login 服务的行前面加上井号 #。此建议适用于您不使用的任何其他服务。永远不会启动的服务上的安全漏洞无法被利用。“如有疑问,请注释掉”是我的座右铭。
TCP_wrappers 是用于控制对您的 Linux 计算机的访问的廉价且有效的工具。即使不使用 wrapper 的访问控制功能,通过系统日志跟踪到您机器的每个连接的能力也可能非常宝贵。TCP_wrappers 可以使用广泛的范围或简单的笔触来控制访问。无论哪种方式,我都希望本文提高了您对可以轻松控制机器“网络面貌”的认识。
Lee Brotzman 是 Advanced Data Solutions 的副总裁,该公司是宾夕法尼亚州州立大学的一家咨询公司。他目前担任互联网安全讲师,并在许多美国政府机构开设了 Unix 系统安全课程。他还担任网络信息系统和电子出版的设计和开发顾问。他与他的妻子/商业伙伴(十五年)以及他们的三个孩子、一条狗、两只猫和一条靠狗饼干为生的金鱼(这让猫非常紧张)居住在州立大学。可以通过电子邮件 leb@vicon.net 与他联系。