使用 xinetd

作者:Jose Nazario

作为 inetd 的替代品,xinetd 提供了访问控制、改进的日志记录和资源管理。它已成为 Red Hat 7 和 Mandrake 7.2 的标准 Internet 超级守护进程。本文旨在帮助您开始使用它的一些功能——希望能涵盖一些更有趣的功能——并且基于 xinetd 2.1.8.8pre3 中可用的功能。

序言

xinetd 的原始作者 Panagoitis Tsirigotis (panos@cs.colorado.edu) 似乎已经放弃了这个项目。Rob Braun (bbraun@synack.net) 接手了这个项目,现在负责维护该软件包。我在当前状态的软件包中注意到的一个问题是,我必须添加几个头文件才能使 select( ) 在我的旧 libc5 系统上工作。如果您需要它们,它们如下所示:

xinetd/internals.c.orig
Fri Jun 16 19:00:15 2000
+++ xinetd/internals.c
Fri Jun 16 19:00:53 2000
@@ -12,6 +12,8 @@
 #include <time.h>
 #include <fcntl.h>
 #include <syslog.h>
 #include <unistd.h>
 #include <sys/time.h>
 #include "sio.h"
关于 xinetd

xinetd 用带括号的扩展语法替换了常见的 inetd 行。此外,还为日志记录和访问控制提供了新的可能性。虽然 inetd 允许使用 Venema 的 tcp_wrappers 软件 (tcpd) 控制 TCP 连接,但您无法控制 UDP 连接。此外,它在处理 RPC (端口映射器) 类型服务方面表现不佳。另外,虽然您可以使用 inetd 控制连接速率(例如,通过在 wait 或 no wait 参数后附加一个数字,例如,nowait.1 表示每秒一个实例),但您无法控制实例的最大数量。这可能会导致进程表攻击,例如,有效的拒绝服务。通过使用 xinetd,我们可以阻止这种情况。

我通常使用以下命令启动 xinetd,将其放置在启动 Internet 服务的启动脚本中:

/usr/sbin/xinetd -filelog /var/adm/xinetd.log -f /etc/xinetd.conf

这告诉 xinetd 将所有内容记录到文件 /var/adm/xinetd.log,并使用配置文件 /etc/xinetd.conf。本文的大部分内容将讨论此配置文件。

编译时选项

您应该注意的提供额外访问控制的三个编译时选项是 libwrap、loadavg(负载平均阈值监视器)和 IPv6 支持。与大多数支持 libwrap 的守护进程(如 portmappersendmail)一样,configure 脚本中的 “with-libwrap” 选项告诉 xinetd 构建时链接对 tcp_wrappers 文件 /etc/hosts.allow 和 /etc/hosts.deny 的支持。这些 xinetd 的选项与它们对 inetd 的作用完全相同,并支持所有 xinetd 控制的守护进程。请注意,如果您从头开始使用 xinetd,则不再需要使用 tcpd,因为访问控制在 xinetd 内部完成。但是,如果您从 inetd/tcpd 迁移并且不想更改您的访问文件,则对 libwrap 的支持非常有用。

第二个有趣的配置选项是支持负载平均监视,这是通过 ./configure 脚本中的 with-loadavg 选项完成的。sendmail 支持在高负载时断开连接,假设它已经失控并正在拖垮机器。可以使用此配置选项启用 max_load 选项,以根据机器的负载平均值限制对任何或所有服务的连接。

最后,添加 IPv6 支持的配置选项是通过在 ./configure 中使用 with-inet6 功能来完成的。这为 xinetd 添加了对 IPv6 地址和连接的支持。请注意,您的内核(和网络)必须支持 IPv6 才能使其生效。当然,IPv4 支持仍然保留。

配置文件

xinetd 配置文件,通常是 /etc/xinetd.conf,可以手动构建,也可以从 inetd.conf 文件自动构建。前者更耗时且容易出错;后者可以使用 itox 实用程序或 xconv.pl 脚本轻松完成。虽然 itox 实用程序正被放弃而倾向于 xconv.pl 脚本,但它仍然有用。但是,请注意,重复运行它将覆盖现有文件。itox 和 xconv 的工作方式相同,但我们将展示 itox 的用法:

$ itox < /etc/inetd.conf > xinetd.conf

较新的实用程序 xconv 比 itox 更了解注释和 tcpd 的使用。对于 itox,您必须指定守护进程所在的目录,例如 /usr/sbin。您可能要包含的第一个部分是 defaults 部分。顾名思义,这给出了 xinetd 服务的默认值:

defaults
{
   instances       = 25
   log_type        = FILE /var/adm/servicelog
   log_on_success  = PID HOST EXIT
   flags           = NORETRY
   log_on_failure  = HOST RECORD ATTEMPT
   only_from       = 129.22.0.0
   no_access       = 129.22.210.61
   disabled        = nntp uucp tftp bootps who
                     shell login exec
   disabled       += finger
}
立即,我们可以看到 xinetd 配置参数的语法:<指令> <运算符> <值>。表 1 列出了 xinetd 理解的指令。我们将在此处忽略的指令包括 flags、type、env 和 passenv。我们将在下面详细讨论 only_from 和 no_access,以及日志记录选项。

表 1. xinetd 的指令

运算符非常简单,可以是 = 或 +=。使用 = 时,右侧的值被赋予左侧的指令。+= 也非常直观,用于将值附加到已定义的指令。如果没有它,较早的指令将被覆盖。这也可以用于分散访问列表,或者,例如,分散在多行上。

服务描述由以下格式给出:

servicename
{
        directive = value
        directive += value
}

Servicename 必须在 /etc/services 中列出,才能在正确的套接字上并使用正确的协议发生。

关于访问控制的说明

实际上,关于 xinetd 如何进行访问控制的几句话。首先,xinetd 控制连接,而不是数据包。它是一个用户空间守护进程,就像 inetd 一样。因此,虽然它会阻止来自被禁止连接到服务的主机的 SYN 或 connect() 尝试,但它不会阻止“隐身”扫描,例如 FIN 扫描 [一种利用设置了 FIN 标志的 TCP 数据包的端口扫描,通常使用诸如 NMAP 之类的工具执行]。不要依赖 xinetd 作为防火墙来阻止端口扫描。一个足智多谋的入侵者将能够使用此信息来收集您的各种服务的访问控制列表。幸运的是,这可以被 xinetd 记录下来,当您查看日志时,您的偏执传感器应该会响起。

其次,截至 2.1.8.8pre3,当系统尝试连接时,xinetd 会执行名称查找。以前,它过去在启动时进行查找,但现在已经更改。

使用访问控制实际上非常简单。第一个指令是 only_from,它列出了我们将接受连接的网络或主机。此指令设置了可以被 no_access 覆盖的规则。您可以使用网络号,例如 10.0.0.0 或 10,或网络名称,包括 *.my.com 或 .my.com 与此指令一起使用。主机名和主机的 IP 地址也可以在此处使用。使用指令 0.0.0.0 匹配所有主机并监听所有地址。一旦满足条件,就使用 no_access 指令解析拒绝。同样,可以指定网络或主机。

服务配置

让我们看看此信息的一些基本应用。我们要看的第一个服务是 echo 服务,它是 inetd 和 xinetd 内部的服务。

service echo
{
        socket_type     = stream
        protocol        = tcp
        wait            = no
        user            = root
        type            = INTERNAL
        id              = echo-stream
}

Echo 以 root 身份运行,是一个 tcp 流,并在内部处理。echo-stream 的 id 指令将显示在日志中。在没有 only_from 或 no_access 指令的情况下,对配置的此服务的访问是无限的。

现在,让我们看一下常规服务,在本例中是 daytime 服务:

service daytime
{
        socket_type     = stream
        protocol        = tcp
        wait            = no
        user            = nobody
        server          = /usr/sbin/in.date
        instances       = 1
        nice            = 10
        only_from       = 0.0.0.0
}

同样,任何人都可以连接到它,但我们指定一个要运行的可执行文件(以 nobody 身份)来返回信息。这个例子并没有比之前的例子扩展太多。现在我们来看另一个用于安全 shell 版本 1 的服务。这样做是为了防止 sshd 的资源耗尽。

service ssh1
{
        socket_type     = stream
        protocol        = tcp
        instances       = 10
        nice            = 10
        wait            = no
        user            = root
        server          = /usr/local/sbin/sshd1
        server_args     = -i
        log_on_failure  += USERID
        only_from       = 192.168.0.0
        no_access       = 192.168.54.0
        no_access       += 192.168.33.0
}
在这里,我们在之前的工作基础上构建。回想一下,当 sshd 从像 inetd 或 xinetd 这样的超级服务器启动时,需要使用 -i 标志启动它,因此我们将它放在 server_args 指令中。注意:将标志添加到 server 指令将导致它失败。一次最多只能有十个人使用此服务,这在本文示例所用的服务器上不是问题。除了默认信息外,如果连接方无法连接,我们还会记录 RFC 1413 中描述的连接方的用户 ID。最后,我们列出了两个无法访问此服务的网络。
日志记录和 xinetd

logging 指令理解几个可用于获取有关您的服务器的信息的值(参见表 2)。

表 2. 各种日志记录指令值

因此,添加有关日志记录的详细信息的典型行可能看起来像下面列出的那些。对于成功连接的服务,我们通常希望记录生成的服务的进程 ID、连接的主机以及它退出的时间:

log_on_success  = PID HOST EXIT

这将为我们提供有用的信息,用于调试和管理正常的服务器操作。对于失败,我们记录我们期望的内容:

log_on_failure  = HOST RECORD ATTEMPT
在这里,我们记录连接的主机、连接被拒绝的原因以及有关连接主机的其他信息(有时是尝试连接的用户 ID)。这些是推荐的基线,可让您很好地了解您的服务器。

回想一下,在上面的 defaults 部分中,我们正在记录到 /var/adm/servicelog。我们已指示 xinetd 记录所有信息,包括失败和成功。我们的大部分信息将如下所示:

00/9/13@16:05:07: START: pop3 pid=25679 from=192.168.152.133
00/9/13@16:05:09: EXIT: pop3 status=0 pid=25679
00/10/3@19:28:18: USERID: telnet OTHER :www

使用此信息,可以轻松调试 xinetd 和正常操作。也很容易发现安全问题,例如您想要尝试阻止的连接尝试。只需在日志中 grep “FAIL”,这些条目就会立即突出显示。

00/10/4@17:04:58: FAIL: telnet address from=216.237.57.154
00/10/8@22:25:09: FAIL: pop2 address from=202.112.14.184
处理安全问题需要另一篇文章,但可以肯定地说,不要将报告的地址视为可靠信息,因为它可能是伪造的。

相比之下,xinetd.log 文件包含来自 xinetd 的信息。这对于调试给出错误的连接很有用。

00/10/25@21:10:48 xinetd[50]: ERROR: service echo-stream,
accept:
Connection reset by peer
重新配置 xinetd

您可以在 xinetd 运行时编辑 xinetd.conf 文件。要使其重新配置,请向 xinetd 进程发送信号 SIGUSR1:

# ps -ax | grep xinetd
   50  ?  S    5:47 /usr/sbin/xinetd -filelog /var/adm/xinetd.log -f /etc/xinetd.conf
# kill -SIGUSR1 50

Tail 您正在使用的 -filelog,以确保它已重新启动并调整了您所做的更改。如果您是远程连接,请务必在注销之前执行此操作,并确保您可以重新登录。

请注意,使用 -HUP(就像对 inetd 进行重新配置一样)实际上会导致 xinetd 停止运行。这是按设计进行的,目的是阻止那些重新配置您的 xinetd 并尝试在不理解文档的情况下重新加载它的黑客。

何时使用 xinetd

就我个人而言,我几乎将 xinetd 用于我的所有服务;唯一看到性能显着下降的服务是我的 Web 守护进程 Apache。对于它来说,太多的进程必须太快启动才能实现时间效率。DNS 服务也应加载到 xinetd 中;性能损失太大了。

但是,我确实在 xinetd 之外运行 sendmail,从而可以精细地控制谁可以连接。我的 sendmail 配置如下所示:

service smtp
{
        socket_type   = stream
        protocol      = tcp
        wait          = no
        user          = root
        server        = /usr/sbin/sendmail
        server_args   = -bs
        instances     = 20
        nice          = 10
        only_from     += 0.0.0.0
        no_access     += 129.22.122.84 204.0.224.254
}

即使在高流量邮件服务器上,性能损失也可以忽略不计。我还将 sshd 加载到 xinetd 中,以防止对其进行进程表攻击。

结论

我希望本文对您配置和调整 xinetd 以满足您的需求有所帮助。如您所见,即使在安装了 tcp_wrappers 的情况下,它提供的功能也比 inetd 多得多。Solar Designer (http://www.openwall.com/) 提供了一个针对稍旧版本的 xinetd,版本 2.2.1 的补丁,该补丁允许基于每个 IP 进行实例控制,这有助于阻止简单的进程表攻击。但是请注意,简单的伪造可以绕过这一点。我不知道此补丁是否已应用于更高版本的 xinetd,或者是否可以应用。

Using xinetd
José Nazario 是一名生物化学研究生,即将完成他的博士学位。副项目包括 Linux 和其他 UNIX 变体、软件和安全相关事项,以及办公室外的爱好,如飞蝇钓和摄影。
加载 Disqus 评论