设置服务
首先,想象一下您拥有的 TCP/IP 连接(从以太网连接到来自您友好的邻里网络提供商的 SLIP/PPP 连接的任何连接),实际上是 65,536 条线路(每条线路都可以同时处理许多不同的 会话)进入您的机器。其中一些线路专用于服务于单一目的,但大多数线路是开放供使用的。
这些进入您机器的独立线路中的每一条都称为端口,并且每台通过 TCP/IP 连接到另一台机器的 Linux 机器,都有 65,536 个可用端口。这些端口中的每一个都允许两台机器之间建立连接,前提是在一端有一个程序正在监听该端口,而在另一端有一个程序试图连接到它。如果请求与远程端的连接,并且远程端上的一个程序正在监听该端口,则建立连接。这可以是几乎任何类型的连接,因为 telnet、FTP、HTTP(万维网)和 SMTP(邮件)都使用套接字来获取和接收数据。套接字是本地机器、本地端口、远程机器和远程端口的整个组合,它定义了可用的通信通道之一。这些通道的数量实际上仅受可用内存的限制。
现在,有两种方法可以确保远程端能够接收连接。第一种方法是启动一个程序,使其始终在后台运行,等待连接。这可能是最简单的方法,但需要一些编程技能,并要求程序始终在内存中。如果您选择将程序作为守护程序运行,并且不经常使用它,它最终只会浪费内存并被交换到磁盘。
第二种选择是让一个程序监听所有端口,然后,如果请求连接,则启动关联的程序。这很好,因为程序仅在需要时才运行,但对于启动时需要加载大量文件或可能被非常频繁调用的程序来说,它可能太慢并且也会浪费 CPU 功率。
在 Linux 中,与大多数版本的 Unix 一样,这两种选择都存在。一些程序(如 http 守护程序或 sendmail/smail 或 NFS 守护程序)在后台运行,并在内存中根据需要创建和删除自身的副本。这些程序通常可能具有需要长达 30 秒才能加载的大型数据文件。通过一次加载程序,然后在需要时派生自身,这些程序可以将启动时间缩短到仅几秒钟。其他程序,如 in.telnetd,它处理传入的登录连接,不需要那么多时间加载到内存中,并且可以保持在内存之外直到需要时。
对于 in.telnetd 和其他小型程序,inetd(Internet 守护程序;也称为“超级服务器”)服务就派上用场了。inetd 监视它可以监视的所有端口,如果它看到连接请求,它会检查其列表,看看是否有东西想要监视该端口。如果其列表中有条目,它会启动该程序,输入和输出都通过套接字定向。否则,它会拒绝连接,您会在终端上看到熟悉的“连接被拒绝”。
设置 inetd 程序的方法是编辑一个名为 /etc/inetd.conf 的文件。在此文件中,您可能会找到一些看起来像 图 1 的行。
现在让我们解密一下。任何以 # 开头的行都被 inetd 视为注释。任何其他行都被分解为 6 个部分
1) 服务 - 这定义了 inetd 正在监视的端口。此名称位于 /etc/services 文件中。如果您在那里查看,您会看到如下行
ftp 21/tcp telnet 23/tcp smtp 25/tcp mail
这里定义了我们最喜欢的三种服务。ftp、telnet 和 smtp。ftp 使用端口 21,telnet 使用端口 23,smtp 使用端口 25。这些连接在 /etc/services 中,这样您就不必记住 ftp 是端口 21。您只需告诉 inetd ftp,它就会计算出其余部分。
2) 套接字类型 - 这可以是 stream 或 dgram(用于数据报)。流通常用于长时间打开的连接,并且(对于您可能看到的每种情况)使用 tcp 协议。Telnet 或 FTP 是很好的例子。数据报是一个小的数据包,其中没有真正的连接,并且(同样,对于您可能看到的每种情况)将使用 udp 协议。也可使用 raw、rdm 和 seqpacket。
3) 协议 - tcp 用于流,udp 用于数据报套接字类型。这些类型在 /etc/protocols 中定义。
4) 标志 - Wait 和 Nowait。这仅适用于数据报套接字类型。任何其他类型都应定义为 nowait。如果数据报套接字连接到另一个套接字并释放套接字以供 inetd 打开另一个端口,则将其定义为 nowait。否则,inetd 应等待连接关闭。
5) 用户[.组] - 这定义了运行以下程序的用户(和可选的组)。它通常是 root,但某些程序您可能希望对其进行安全保护并以较低的用户身份运行。
6) 命令行 - 当 inetd 在该端口上找到活动时要运行的命令(包括任何命令行参数)。几乎所有旨在从 inetd 运行的程序都以“in”开头命名,以使其显而易见。
您可能会注意到,在程序前面看到了 /usr/bin/tcpd。tcpd 程序执行一些 inetd 没有的功能。例如,tcpd 可以通过 syslog(3) 工具记录连接(有关 syslog 的讨论,请参见 Linux Journal 第 11 期),验证主机名,查找正在连接的远程用户的名称,并拒绝或允许访问您可以指定的主机的一些服务。其中一些选项需要重新编译 tcpd 程序,但可以大大提高系统的安全性。您可以做的一件事,无需重新编译,是限制向已知会给您带来麻烦的站点提供的服务。要拒绝站点对 telnet(和其他)的访问,请创建一个名为 /etc/hosts.deny 的文件。在其中,您可以首先列出您要拒绝的访问,一个冒号,然后是拒绝访问的主机。
首先,列出您要拒绝的程序名称。这可以是 in.fingerd、in.telnetd、in.ftpd 等。您也可以使用关键字 ALL 来表示所有服务。
接下来,通过以下方法列出您要拒绝访问的主机
1) 以“.”开头的网络名称将拒绝所有以其作为最后一个网络名称的主机访问。.clarkson.edu 将拒绝来自 Clarkson 的任何主机的访问,例如 craft.camp.clarkson.edu。.edu 将拒绝 .edu 域中的任何人。
2) 以“.”结尾的网络名称将拒绝所有以匹配字符串作为网络名称前缀的主机访问。例如,128.153. 将拒绝整个 Clarkson 域,而 128.153.16. 将拒绝 Clarkson 域的一部分。
3) ALL 拒绝所有人访问,LOCAL 匹配其解析名称不包含句点 (.) 的主机。许多域名服务器会将本地子网上的名称解析为仅主机名,而不是 host.subnet.net。例如,craft.capm.clarkson.edu 对于同一子网上的另一台主机可能只显示为 craft。host_access (5) 的手册页将解释更多通配符。
4) 关键字 EXCEPT 将豁免根据其他规则将被拒绝的特定主机。
因此,一个 /etc/hosts.deny 示例可能如下所示
ALL: .clarkson.edu EXCEPT: craft.camp.clarkson.edu
这将拒绝 Clarkson 域中任何人的所有访问,除了机器 craft.camp.clarkson.edu 上的用户。
您还可以设置一个 /etc/hosts.allow,遵循与 /etc/hosts.deny 相同的方法,不同之处在于 hosts.allow 指定了要明确允许谁访问。如果主机被拒绝和允许之间存在冲突,则 /etc/hosts.allow 中的条目优先,并且允许访问。为了使站点更安全,您可以在 /etc/hosts.deny 中放置 ALL: ALL(以拒绝所有人访问),然后在 /etc/hosts.allow 中列出您要允许的所有主机。这样,只有您指定的主机才能访问 tcpd 运行的服务。此外,如果您只有一个 hosts.allow 文件,而没有 hosts.deny 文件,则只有 hosts.allow 中列出的主机才被允许任何访问。
有关如何在您的站点使用 tcpd 的更多信息,请参阅 tcpd(8) 和 hosts_allow(5) 的手册页。
现在,这一切是如何工作的?让我们在 /etc/inetd.conf 中添加一些内容。一些简单易用的东西,比如“fortune”端口。许多 Linux 安装都包含 /usr/games/fortune 命令,并且端口 17 上存在 qotd(每日名言)端口。因此,我们将设置 inetd,以便如果您 telnet 到端口 17,您将获得 fortune 命令的输出。因此,以 root 身份登录到您的机器,并确保 inetd 正在运行。如果它没有运行,您将需要为您的机器设置 TCP/IP。即使您没有连接到任何东西,您仍然可以设置环回设备并连接到自己。
首先,确保 qotd 在您的 /etc/services 中定义
qotd 17/tcp
接下来,我们将在 /etc/inetd.conf 中添加行,以使 inetd 启动 fortune。这可以添加到 /etc/inetd.conf 中的任何位置
qotd stream tcp nowait root /usr/sbin/tcpd \ /usr/games/fortune
您必须重启 inetd 才能使其重新读取 inetd.conf 文件。一种仅在 Linux 下有效但应始终在 Linux 下轻松工作的方法是
linux:/# killall -HUP inetd
在某些系统上,inetd 进程的 PID 可能保存在文件中,例如 /var/run/inetd.pid,而在没有 inetd.pid 文件的非 Linux 系统上,您将必须使用 ps 命令来查找 inetd 进程的 PID。
现在,如果您 telnet 到 localhost 端口 17,您会发现如下内容
linux:/# telnet localhost 17 Trying 127.0.0.1 Connected to localhost Escape character is '^]'. Money is the root of all wealth Connection closed by foreign host. linux:/#
您只能对它使用几个程序。像 joe 这样使用 curses 的东西,或者任何使用 SVGAlib 的东西都无法工作,因为它无法打开您的 tty(记住:对于 Linux 来说,您是从其他地方 telnet 连接进来的)。
您放入 inetd.conf 文件中的任何程序都应具有良好的安全性。这意味着
1) 验证(并在必要时修改)进程运行的用户。许多需要 root 权限,但有些不需要。
2) 验证连接到 TCP/IP 套接字的程序的安全性。像 /usr/games/fortune 这样的程序不是交互式的,但像旧的 sendmail 这样的程序让互联网蠕虫几年前得以在机器中传播。(请注意,sendmail 漏洞已修复。)
3) 通过添加像 tcpd 这样的东西来为 inetd 增加额外的安全性,这将允许您拒绝或允许各种主机连接到您的机器。查看 tcpd 手册页以获取有关 tcpd 的更多信息。
现在您已经设置了服务,您可以挂钩自己的服务并将它们用于任何您想要的目的。如果您对此文章有疑问或意见,或者有您希望在未来Linux Journal中看到的某个主题,请发送电子邮件至 komarimf@craft.camp.clarkson.edu。
Mark Komarinski (komarimf@craft.camp.clarkson.edu) 毕业于克拉克森大学(位于非常寒冷的纽约州波茨坦),获得计算机科学和技术传播学位。他现在住在纽约州特洛伊,并在退伍军人事务部担任程序员,在那里度过大部分空闲时间。