# 32.2.inetd 超级服务器

[inetd(8)](https://man.freebsd.org/cgi/man.cgi?query=inetd\&sektion=8\&format=html) 守护进程有时被称为超级服务器（Super-Server），因为它管理许多服务的连接。与启动多个应用程序不同，只需要启动 inetd 服务。当收到一个由 inetd 管理的服务的连接时，inetd 会确定该连接的目标程序，启动该程序的进程，并为其分配一个套接字。与单独以独立模式运行每个守护进程相比，使用 inetd 来处理不常用的服务可以减少系统负载。

inetd 主要用于启动其他守护进程，但也会内部处理一些简单的协议，如 chargen、auth、time、echo、discard 和 daytime。

本节介绍了配置 inetd 的基础知识。

## 32.2.1. 配置文件

inetd 的配置通过编辑 **/etc/inetd.conf** 文件完成。该配置文件中的每一行表示一个可以由 inetd 启动的应用程序。默认情况下，每一行都以注释符号（`#`）开始，这意味着 inetd 不会监听任何应用程序。要配置 inetd 监听某个应用程序的连接，只需删除该应用行开头的 `#`。

编辑完成后，通过编辑 **/etc/rc.conf** 配置 inetd 在系统启动时启动：

```sh
inetd_enable="YES"
```

要立即启动 inetd 使其开始监听已配置的服务，输入以下命令：

```sh
# service inetd start
```

待 inetd 启动，任何对 **/etc/inetd.conf** 文件的修改都需要通知 inetd：

示例 1. 重新加载 inetd 配置文件

```sh
# service inetd reload
```

通常情况下，应用程序的默认条目不需要修改，除了删除 `#`。在某些情况下，修改默认条目是适当的。

例如，以下是 [ftpd(8)](https://man.freebsd.org/cgi/man.cgi?query=ftpd\&sektion=8\&format=html) 的默认条目，使用 IPv4：

```sh
ftp     stream  tcp     nowait  root    /usr/libexec/ftpd       ftpd -l
```

条目中的七个字段如下：

```ini
服务名
套接字类型
协议
{wait|nowait}[/max-child[/max-connections-per-ip-per-minute[/max-child-per-ip]]]
用户[:组][/登录类]
服务器程序
服务器程序参数
```

其中：

**服务名**\
要启动的守护进程的服务名称。它必须与 **/etc/services** 中列出的服务相对应。此项决定了 inetd 用于监听该服务的端口。如果使用自定义服务，必须首先将其添加到 **/etc/services** 中。

**套接字类型**\
可以是 `stream`、`dgram`、`raw` 或 `seqpacket`。对于 TCP 连接使用 `stream`，对于 UDP 服务使用 `dgram`。

**协议**\
使用以下协议名称之一：

| 协议名称       | 说明                   |
| ---------- | -------------------- |
| tcp 或 tcp4 | TCP IPv4             |
| udp 或 udp4 | UDP IPv4             |
| tcp6       | TCP IPv6             |
| udp6       | UDP IPv6             |
| tcp46      | 同时支持 TCP IPv4 和 IPv6 |
| udp46      | 同时支持 UDP IPv4 和 IPv6 |

**{wait|nowait}\[/max-child\[/max-connections-per-ip-per-minute\[/max-child-per-ip]]]**\
此字段必须指定 `wait` 或 `nowait`。`max-child`、`max-connections-per-ip-per-minute` 和 `max-child-per-ip` 是可选项。

`wait|nowait` 指示服务是否能够处理自己的套接字。`dgram` 套接字类型必须使用 `wait`，而 `stream` 守护进程通常是多线程的，应该使用 `nowait`。`wait` 通常将多个套接字交给单个守护进程，而 `nowait` 为每个新套接字生成一个子守护进程。

`max-child` 设置 inetd 可以启动的子守护进程的最大数量。例如，要限制守护进程的实例数为十个，可以在 `nowait` 后面加上 `/10`。指定 `/0` 则允许无限数量的子进程。

`max-connections-per-ip-per-minute` 限制每个特定 IP 地址每分钟的连接次数。待达到限制，该 IP 地址的进一步连接将被丢弃，直到分钟结束。例如，值为 `/10` 表示每个 IP 地址每分钟最多允许十次连接尝试。`max-child-per-ip` 限制每个 IP 地址在同一时刻可以启动的子进程数。这些选项可以限制资源的过度消耗，并帮助防止拒绝服务攻击。

可以在 [fingerd(8)](https://man.freebsd.org/cgi/man.cgi?query=fingerd\&sektion=8\&format=html) 的默认设置中看到一个示例：

```sh
finger stream  tcp     nowait/3/10 nobody /usr/libexec/fingerd fingerd -k -s
```

**用户**\
守护进程将以哪个用户名运行。守护进程通常以 `root`、`daemon` 或 `nobody` 运行。

**服务器程序**\
守护进程的完整路径。如果守护进程是由 inetd 提供的内部服务，使用 `internal`。

**服务器程序参数**\
用于指定传递给守护进程的命令参数。如果守护进程是内部服务，使用 `internal`。

## 32.2.2. 命令行选项

像大多数服务器守护进程一样，inetd 有许多选项可以用来修改其行为。默认情况下，inetd 使用 `-wW -C 60` 启动。这些选项启用所有服务（包括内部服务）的 TCP 包装器，并且防止任何 IP 地址每分钟请求任何服务超过 60 次。

要更改传递给 inetd 的默认选项，可以在 **/etc/rc.conf** 中添加 `inetd_flags` 条目。如果 inetd 已经在运行，使用 `service inetd restart` 重启它。

可用的速率限制选项如下：

-c maximum\
指定每个服务的默认最大同时调用次数，默认值为无限制。可以通过在 **/etc/inetd.conf** 中使用 `max-child` 对每个服务进行覆盖。

-C rate\
指定每分钟从单个 IP 地址可以调用服务的最大次数，默认值为无限制。可以通过在 **/etc/inetd.conf** 中使用 `max-connections-per-ip-per-minute` 对每个服务进行覆盖。

-R rate\
指定每分钟服务可以被调用的最大次数，默认值为 `256`。如果设置为 `0`，则允许无限次调用。

-s maximum\
指定每个时刻单个 IP 地址可以调用服务的最大次数，默认值为无限制。可以通过在 **/etc/inetd.conf** 中使用 `max-child-per-ip` 对每个服务进行覆盖。

还有其他选项可用。有关完整的选项列表，请参见 [inetd(8)](https://man.freebsd.org/cgi/man.cgi?query=inetd\&sektion=8\&format=html)。

## 32.2.3. 安全注意事项

许多可以由 inetd 管理的守护进程在安全性上并不考虑。例如，一些守护进程（如 fingerd）可能会提供对攻击者有用的信息。只启用必要的服务，并监控系统是否有过多的连接尝试。可以使用 `max-connections-per-ip-per-minute`、`max-child` 和 `max-child-per-ip` 来限制此类攻击。

默认情况下，启用了 TCP 包装器。有关如何对各种 inetd 调用的守护进程进行 TCP 限制的更多信息，请参见 [hosts\_access(5)](https://man.freebsd.org/cgi/man.cgi?query=hosts_access\&sektion=5\&format=html)。
