inetd是监视一些网络请求的守护进程,其根据网络请求来调用相应的服务进程来处理连接请求。它可以为多种服务管理连接,当 inetd 接到连接时,它能够确定连接所需的程序,启动相应的进程,并把 socket 交给它 (服务 socket 会作为程序的标准输入、 输出和错误输出描述符)。 使用 inetd 来运行那些负载不重的服务有助于降低系统负载,因为它不需要为每个服务都启动独立的服务程序。
inetd是通过rc系统启动的。inetd_enable选项默认设为NO,但可以在安装系统时,由用户根据需要sysinstall通过来打开。
inetd.conf则是inetd的配置文件。inetd.conf文件告诉inetd监听哪些网络端口,为每个端口启动哪个服务。在任何的网络环境中使用Linux系统,第一件要做的事就是了解一下服务器到底要提供哪些服务。不需要的那些服务应该被禁止掉,最好卸载掉,这样黑客就少了一些攻击系统的机会。查看“/etc/inetd.conf”文件,了解一下inetd提供哪些服务。用加上注释的方法(在一行的开头加上#号),禁止任何不需要的服务,再给inetd进程发一个SIGHUP信号。
从理论上说,UNIX® 是内核,或者说低层软件,它控制对文件系统、内存和处理器等计算机资源的访问。但是,用更通俗的话来说,UNIX 是指在操作系统上运行的一整套软件。实际上,通常说的 “它是一台 UNIX 机器” 是指系统的基础功能:UNIX 机器通常提供 shell 界面、并行访问、强大的安全性和各种连网的服务。
实际上,UNIX(内核等)被选用的原因通常是它的连网应用。FTP、POP、SMTP 和 HTTP 最初都是在 UNIX 上实现的,而且一直在 UNIX 上使用。UNIX 系统还通过运行服务(常常称为守护进程 )实现各种功能,包括与中心时钟执行同步(网络时间协议)、交换新闻(网络新闻传输协议)、把主机名解析为 IP 地址(DNS)等。在大多数 UNIX 机器上的 /etc/services 中可以找到常用的一部分服务。这个文件与 清单 1 相似。
清单 1. /etc/services(UNIX 网络服务目录)中常见的条目
ftp 21/tcp
fsp 21/udp fspd
ssh 22/tcp
ssh 22/udp
telnet 23/tcp
smtp 25/tcp mail
/etc/services 中的每个条目列出服务的名称;服务使用的端口号和协议(TCP 或 UDP);服务的别名(可能没有,也可能有多个别名)。每个系统守护进程都通过检查 /etc/services 寻找它提供服务时要使用的端口和协议。
例如,处理入站电子邮件的守护进程会寻找 “smtp”(服务名称)或 “mail”(别名之一),在端口 25 上监听到达的 TCP 连接。类似地,远程登录守护进程在文件中搜索 “ssh”,在端口 22 上监听到达的 TCP 连接。
小公司的服务器可能运行多个服务,分别负责与世界时钟同步、提供 Web 页面、传输电子邮件、支持远程 shell 访问、打印页面、传输文件、连接数据库、监视系统的稳定性、提供域名以及通过 NFS 共享文件。这种配置并不少见,这主要是因为守护进程的开销不大。守护进程通常设计为在空闲时休眠,等待请求。当服务请求出现时,守护进程醒来,响应并处理请求,然后继续休眠。
尽管如此,大量休眠的进程仍然会影响系统性能。因此,如果预期会经常请求某一服务,比如有稳定的 Web 访问请求,那么有必要具有一个长期运行的守护进程。否则,最好把守护进程重新配置为根据需要执行。
但是,系统如何提供随时可用的服务并在需要的时候启动?解决方案是使用代理服务,它预测到达的各种请求,根据后续处理的需要启动适当的服务。在 UNIX 和 Linux® 系统上,这个代理称为 inetd。
给定一个服务列表,inetd 会监视对这些服务的端口和协议的请求。当发生活动时,inetd 把入站请求映射到标准输入 (stdin)、标准输出 (stdout) 和标准错误 (stderr),并启动适当的守护进程。服务处理数据并终止。inetd 把资源消耗保持在最低水平,并且让守护进程更容易编写。
inetd 监听许多端口并在接收到请求时启动服务。服务处理请求并退出。有一些服务例外。例如,传输电子邮件的 SMTP 服务器通常独立地运行。
根据它的作用,inetd 常常被称为 “超级服务员”。在近几年,inetd 已经被它的变体 xinetd 替代了。这两个软件的用途是相同的,但是后者更安全并提供许多特性,可以在系统负载过重时限制访问。inetd 和 xinetd 的配置相似,但是不完全相同。系统可以运行 inetd 或 xinetd,但是不能同时运行两者。因为后者更安全,它是首选的,所以本文后面一直使用它。
xinetd 是开放源码的,很容易构建在 UNIX 以及 OpenBSD 和 Linux 等变体上。到 2009 年 10 月底,xinetd 的最新版本是 2.3.14,可以从 xinetd 主页获取它(参见 参考资料)。下载 xinetd 的源代码之后,解压压缩文件,运行配置脚本)并构建软件。在安装 xinetd 之前,一定要备份 inetd 配置(如果有的话),然后禁用和/或删除 inetd。禁用 inetd 的步骤取决于使用的 UNIX 变体;参见系统的 inetd 手册页。执行这个修改很可能需要超级用户访问权。
无论如何安装和启用 xinetd,如果以前运行过 inetd,就必须把 inetd 配置文件 inetd.conf 转换为与 xinetd 兼容的文件。可以手工地执行转换,也可以使用 xinetd 提供的转换脚本替您修改文件:
1
2
$ xconv.pl < /etc/inetd.conf > /etc/xinetd.conf
$ mv /etc/inetd.conf /etc/inetd.conf.sav
Xconv.pl 是 xinetd 提供的 Perl 脚本。后一个步骤(把 inetd 配置文件转移到标准位置之外)只是一项预防措施。
可以完全在 /etc/xinetd.conf 中配置 xinetd。但是,按照惯例,通常在这个文件中提供默认设置,并在特殊目录 /etc/xinetd.d 中包含多个配置文件 — 每个服务一个文件。例如,下面是 Ubuntu 上安装的 xinetd 配置文件:
1
2
3
4
5
6
defaults
{
log_type = SYSLOG daemon info
}
includedir /etc/xinetd.d
defaults 提供 xinetd 控制的所有 服务的值。服务可以覆盖这些全局默认值。在这里,log_type 的默认值指定每个守护进程应该把日志条目发送到哪里(如果启用日志的话)。SYSLOG 选项把输出发送到 syslog(中心系统日志)。info 要求只记录信息性消息。其他值包括 emerg、alert、crit、err、warning、notice 和 debug。第一个值 emerg 从 xinetd 生成最少的输出;最后一个值 debug 提供最详细的输出。如果在从 xinetd 启动某个服务时遇到了问题,可以启用更详细的日志选项以帮助判断问题的原因。
/etc/xinetd.d 中的文件采用与 xinetd.conf 相同的格式。其中有一个操作,包含零个、一个或更多操作数,还有一组放在大括号 ({}) 中的变量和值。例如,清单 3 是 /etc/xinetd.d/imap,这是用于 IMAP 服务的条目。(IMAP 是用于读取和管理电子邮件的邮箱协议。它与 POP 相比有一个重要的优点:IMAP 邮箱可以跨任意数量的系统保持同步。)
虽然有一些小差异,但是这个片段看起来应该很熟悉。这个脚本作为用户 martin 运行,因为它不需要特殊的特权。一般来说,应该提供尽可能少的特权 — 不仅是在这里,在授予对任何系统资源的访问权时都应该这样。对于 TCP 协议服务,必须设置 wait=no。server 指向要运行的脚本或可执行程序,log_type 指定更高的日志记录级别,这有助于解决服务中的任何问题。
重新启动 xinetd,或者向它的进程发送一个重新设置信号。要想重新启动 xinetd,应该在 /etc/init.d 或系统保存启动脚本的地方寻找控制脚本。运行下面这样的命令:
$ sudo /etc/init.d/xinetd restart
另一种方法是向 xinetd 守护进程发送重新设置信号。信号 SIGHUP 让 xinetd 重新读取它的配置,并且根据新的参数,可能会关闭连接。使用的命令是:
$ sudo pkill -SIGHUP xinetd
如果系统没有 pkill(它根据进程名寻找进程 ID),那么使用 ps aux | grep xinetd 寻找进程号,然后使用 sudo kill -SIGHUP pid,其中的 pid 是进程 ID。
为了测试这个新服务,创建一个名为 /tmp/xinetd 的目录,创建 Ruby 脚本并把它保存在 /tmp/xinetd/find.rb 中。用 chmod +x /tmp/xinetd/find.rb 把这个文件设置为可执行的。接下来,创建一些目录和文本文件:
$ mkdir a b c
$ touch a/d.txt b/e.txt
现在可以测试新服务。当端口 11000 上出现入站连接时,xinetd 启动 Ruby 脚本。发送到标准输出的任何脚本输出会被发送到发出请求的机器上的标准输出。这个脚本不需要输入,但是如果需要,发出请求的机器上的标准输入会被传递给脚本。Telnet 提供一种连接任何服务的简便方法:
$ telnet localhost 11000
Trying 127.0.0.1…
Connected to localhost.
Escape character is ‘^]’.
/tmp/xinetd/b/e.txt
/tmp/xinetd/a/d.txt
Connection closed by foreign host.
成功了!端口打开了,控制被传递给脚本,脚本生成了预期的输出。
运行 xinetd 的更多原因
xinetd 有许多优点。它只在需要时运行守护进程,这可以节省资源。它提供一个额外的安全层,可以通过 “修改根目录” 把服务隔离在一个目录中。最重要的是,它实际上可以把任何脚本或程序转换为服务。但是要注意一点:如果您的服务非常受欢迎,应该考虑用 C 等高效的语言重写它。处理请求越快,性能就越好。
inetd 是一个守护程序,通过一个集中的配置文件(inetd.conf)来管理大多数入网连接。xinetd 守护程序是 inetd 的替代,它提供许多改进的或新的特性,以及更容易的配置。Ted 解释了 inetd 背后的概念,并且给出了在您自己的站点上设置 xinetd 的示例。
经典的 inetd 守护程序已经存在很久了。有几种替换 inetd 的功能的方法,但是最灵活、最简便的方法似乎是 xinetd。inetd 能做的,xinetd 也能做,并且 xinetd 还能做更多的事情。譬如,TCP 封装、模块化配置、连接重定向和入站连接的负载限制,而这些只是使得 xinetd 成为系统管理员良好选择的部分特性。
本文是为从初学者到中级系统管理员这样的读者而准备的,并且文中的说明和示例并不尝试假设您已经熟悉 inetd。在本文中,我们将研究 xinetd 的一些简单用法,从安装到安全性策略的实现。
开始之前
为实现本文的目的,您的系统最好安装了最近的主流(2000 或更新)UNIX(Linux、Solaris、BSD)。这些示例在 Perl 和 UNIX(以及其它操作系统)的早期版本上也可以运行,但是它们功能方面的障碍应该由读者作为练习来解决。给定的特定示例是用于 Red Hat Linux 的,但是它们在其它系统上应该也可以运行(除 chkconfig 以外)。
inetd 到底是什么
对于 UNIX 系统管理员,inetd 和 cp/rm/mv 命令一样基本。它总是存在,并准备着处理入站连接。但它到底是什么?它用来做什么?
首先从 TCP/IP (它也包括 UDP,但我们目前还不考虑)开始回答。当您建立与一台主机的连接时,实际上是创建了一个 TCP/IP 连接(通常是一个套接字) — 这好象是在您和主机之间打了一个电话。TCP/IP 连接由起始主机和接收主机唯一地定义,但还有其它标识。如果我们都连接到一台服务器,它如何区分 webserver、telnet、SSH、FTP 和其它连接呢?套接字也通过建立连接所使用的端口来定义。例如,端口 21 是入站 FTP、端口 22 是 SSH、端口 23 是 TELNET(有关其它大多数端口,可以查看 UNIX 系统上的 /etc/services)。
一旦建立了连接,某人就在另一端拿起了电话。这可以是接线员或直线。直线表示您直接连接到了服务器,而接线员是涉及 inetd 的方法。接线员实际上处理一组入站直线(主机上的端口),并亲自将它们交给负责的程序(服务器)。
UDP 是另一种连接方法。象 TCP 一样,UDP 基本上是和某人的对话,但是不保证它是可靠的。UDP(继续使用电话的比喻)就象将消息扔到传送带上,让接收者站到另一端。您可以从传送带得到许多消息,但是如果消息太多(网络流量高)或者读取消息费时太久(服务器忙),则接收者可能会丢失一些消息。
如果使用 inetd,在执行一些检查后,您被重定向到特定服务器。只有一个配置文件 — inetd.conf,管理所有入站连接。因而在系统上添加、删除、更改或复查服务变得更为简单。例如,在 Solaris 系统上使用 TCP 封装器将 ftp 定义如下:
清单 1,FTP 服务的 inetd.conf 定义 ftp stream tcp nowait root /usr/sbin/tcpd in.ftpd
这些是创建一个 FTP 连接所需的全部参数。简单地说,我们以面向流(stream)的方式使用 TCP/IP(tcp)时,同时允许多个 FTP 连接(nowait)、作为 root 运行以及调用 FTP(接下来,TCP 封装器将调用 FTP 守护程序)。
用一上午的时间解析很困难吗?绝对困难。有必要这么复杂吗?不。xinetd 继承了 inetd 的设计并将它模块化,这意味着每个服务都可以存在于它自己的配置文件中。xinetd 还添加了一些象 TCP 封装器之类的功能部件,使得配置更加简单。
xinetd 保持了中央配置(接线员)方法,将所有配置文件存储到单一位置,通常是 /etc/xinetd.conf 和 /etc/xinetd.d/*,使系统管理员可以更容易地获得。模块化配置意味着,您可以通过将服务复制到 xinetd.d 目录来向多台机器上分发该服务,也可以用同类的手段除去它。甚至可以指定额外的包含目录。
最后,xinetd FAQ(请参阅本文后面的参考资料)声明了 RPC 程序在 xinetd 下运行得不太好。不过没问题,对 RPC 使用 inetd,并对其它所有服务使用 xinetd。这就象雇了两个接线员,一个说西班牙语,另一个说所有其它语言。
xinetd 简介
那么 xinetd 是什么?一句话,它就是个程序。处理入站网络连接没什么神奇。可以使用 Perl、Python 或 Java 来处理。Xinetd 是用 C 编写的,而且它和它的前辈 inetd 一样快,如果不是更快的话(例如,TCP 封装器不必为每个入站连接而执行;它们在启动时装入内存)。
xinetd 正在开发中。(您的版本可能过时了,所以请务必到主页上查找最新的版本;请参阅参考资料。)因为它正在开发中,所以 xinetd 的安全漏洞得以迅速弥补,而不象 inetd 那样薄弱,通常要很长时间才能弥补。当然,xinetd 是随源代码一起交付的,所以您可以复查源代码并自己找到可能存在弱点的地方。
如何使用 xinetd 定义服务呢?编写一个服务文件,它除了指定 /etc/xinetd.conf 中所指定的一般参数之外,还指定特定配置。所以,如果 /etc/xinetd.conf 是这样的:
清单 2,样本 xinetd.conf(标准的 Red Hat 7.1) defaults
{
instances = 60
log_type = SYSLOG authpriv
log_on_success = HOST PID
log_on_failure = HOST
cps = 25 30
}
service telnet
{
flags = REUSE
socket_type = stream
wait = no
user = root
server = /usr/sbin/in.telnetd
log_on_failure += USERID
disable = yes
}
includedir /etc/xinetd.d
您放到 /etc/xinetd.d 中的每个服务文件都会继承这些缺省值,并指定它自己的参数。这里,telnet 服务在顶级定义,而不是在子目录中定义。这太棒了,这种模块性允许复杂的配置。
要使 xinetd 重新读取配置文件,不必重新启动它。只要向它发送 USR2 信号即可。
那些参数表示什么意思?让我们通读整个清单。您也可以在命令行下使用 man xinetd.conf 来查看列表(如果那个帮助页面正确安装的话),但这个概述试图用更简单的术语来解释参数,并不假定您已经知道关于套接字和服务的所有信息。一些参数(rpc_version、rpc_number)被跳过。
常规参数
id
该服务的唯一名称。服务名称在花括号之前指定,但是 ID 使逻辑上相同的服务可能拥有多个协议。这是对于临时用户的受限使用。例如,NFS 服务可以在 UDP 或 TCP 传输协议上运行。在 Red Hat Linux 7.1 上,TCP 版本(在 /etc/xinetd.d/time 中)和 UDP 版本(在 /etc/xinetd.d/time-udp中)中提供了对于 xinetd 来说内部的时间服务。
type
这实际上应该称为“特殊类型”,因为它只适用于特殊服务。它可以是以下几种类型的组合:“RPC”,用于 RPC 服务(由 SUN 引入的远程过程调用,导致了很多安全性问题,最好避免使用);“INTERNAL”,用于构建到 xinetd 内部的服务,譬如时间服务;“UNLISTED”,用于在系统列表(/etc/services 或用于 RPC 服务的 /etc/rpc)中找不到的非标准服务。
flags
这里放置着所有额外标志。列表很长并且技术性很强;我们感兴趣的标志包括 REUSE(用于套接字重用,譬如 telnet)、NAMEINARGS/NOLIBWRAP(如果您希望手工调用 TCP 封装器或者完全地避免使用封装器)、NODELAY/KEEPALIVE(用于调整 TCP 套接字)、DISABLE(覆盖顶级“disable”参数)以及 SENSOR(用于检测和防止某些类型的“拒绝服务(denial-of-service)”网络攻击)。
disable
除非您希望禁用某项服务,否则总是把它设成“no”。Red Hat Linux 的 chkconfig 程序将为您打开或关闭“disable”参数;在 Red Hat 上,用 chkconfig 启用和禁用特定服务可能比手工方式简单些。请注意,chkconfig 预期在 /etc/xinetd.d/SERVICE 中找到服务文件。所以对于上面清单 2 中的示例,chkconfig 将不会在请求时打开或关闭 telnet。可以将它认为是一个错误或特性,取决于您的观点。
socket_type
通常您希望这个参数设置成“stream”,除非使用 UDP 服务,此时设置成“dgram”。该参数也可以设置成“raw”和“seqpacket”,但极少见。
protocol
这是连接所用的协议,通常是“tcp”或“udp”,但是在理论上您可以使用来自 /etc/protocols 的任何值。
wait
如果设置成“no”,xinetd 将为每个连接上的服务启动一个新的处理程序。如果是“yes”,xinetd 预期该处理程序处理所有后续连接直到它死亡。在大多数情况下,这个参数是“no”。
server, server_args
处理程序的程序名,以及它应当获得的参数。处理程序名不应该象在 inetd 环境下那样,出现在参数中。
port
服务的端口。通常不需要,因为端口通过 /etc/services 文件来映射到服务。
redirect
允许 xinetd 将所有服务的流量发送给另一台主机。因此,受防火墙保护的主机可以通过中央 xinetd 转发器接受安全流量,而不必建立与外部网络的连接。在某些工作中,可以采用这个特征来在两台主机间执行故障转移服务。
banner, banner_success, banner_fail
一个将要在“任意/一个成功/一个不成功”连接上打印的来自文件的定制文本块。
enabled
在全局级别上补充“disabled”参数和 DISABLE 标志。
include, includedir
告诉 xinetd 要包含文件或目录。
环境参数
user, group, umask, groups
当启动服务处理程序时,xinetd 应该扮演的 UNIX 属性。这主要用于非安全服务。
nice
确定该服务对于系统有多重要的 UNIX 优先级级别。可以针对您的系统调整它,请查看“nice”的 man 页面。
env
用于服务处理程序的环境变量。
passenv
应该向下传递到服务处理程序的 xinetd 中的环境变量。
资源管理参数
instances
可以同时启动的处理程序数。可以调整这个参数以防止拒绝服务攻击。如果您希望缺省(无限制)行为,将它设置成“UNLIMITED”。
max_load
I: ) 如果系统过载,停止接受连接。负载数取决于系统,仅当您确实知道自己在做什么时才能调整它。
rlimit_as, rlmist_cpu, rlimit_data, rlimit_rss, rlimit_stack
rlimit 参数指定用于服务处理程序的资源限制(内存、CPU 以及特定内存区域)。
特定于安全性的参数
only_from, no_access
对 TCP 封装器的补充,这是阻挡主机建立与我们的连接的方法之一。请注意,缺省值是允许对任何人的访问,除非 TCP 封装器(其规则通常在 /etc/hosts.allow 中)另有规定。
access_times
一天中服务可用的时间。例如,“6:00-23:00”意味着服务从上午 6 点到晚上 11:01 可用。
log_type, log_on_success, log_on_failure
各种日志记录选项。USERID 标志可能特别麻烦,因为它向连接的主机询问关于与我们连接的用户,这使得处理变慢。尽可能避免使用 USERID。
bind
允许服务特定于接口,通常是出于安全性考虑。例如,在网络内部的 FTP 服务只是 FTP,而外部 FTP 连接将生成入侵者警报。“id”参数在这里很有用。
per_source
指定来自源 IP 的服务的最大实例数。对于处理“单源拒绝服务(single-source denial-of-service)”攻击或出错程序建立的过多连接非常有用。
cps
每秒允许的最大连接数,以及服务再度启用之前的秒数。“30 45”表示“每秒 30 个入站连接,如果超过限制,则等待 45 秒”。主要用于对付拒绝服务攻击。
deny_time
对引发 SENSOR 标志的人拒绝服务的时间。
替换 TCP 封装器
经典的 TCP 封装器软件包是个非常有用的工具。通过一个集中式的文件(通常是 /etc/hosts.allow 和 /etc/hosts.deny),针对每个服务,根据需要来允许或拒绝对任何主机的访问。不幸的是,TCP 封装器库不太了解系统负载、资源限制、多重攻击之类的情况。xinetd 合并了 TCP 封装器功能性(通过 libwrap 库),所以您可以顺利地迁移到 xinted,并继续使用和以前相同的配置文件。
这差不多就是迁移所要做的全部工作了。保持旧的 hosts.deny 和 hosts.allow 文件,xinetd 将乐意遵循它们。但是,请牢记,xinetd 有许多在 TCP 封装器基础上改进的连接控制选项。例如,限制每秒连接数或过载时的连接数,可以成为对服务器管理极有价值的帮助。
确保您是使用 libwrap 选项编译 xinetd 的,否则,它将不知道 TCP 封装器。如果 xinetd 来自于 Red Hat Linux 上的 RPM,确保您在开放机器“之前”,测试 TCP 封装器文件是否正常运行。
高级用途:故障转移
尽管可以有多种方法使用 xinetd,redirect 参数为我们提供了最有趣的使用方法。众所周知,故障转移很难实现,并且硬件故障转移很昂贵。这里所描述的方法(通过简单的软件)既便宜又有效。它具有单故障点 — 重定向点,所以您应该考虑该方式是否可接受。如果不能接受,那么,硬件故障转移就贵得有道理了。
首先,确定一种方法从两台或者更多的机器中选出一台“活动的”机器。假设您通过一个脚本 set_active.pl 来完成(我们将为 telnet 服务完成该步,但是它对任何其他服务也有效,只要能保持服务切换到其他服务器而不带来不良影响)。脚本将采用我们用来设置新故障转移的机器名,以及给我们适当的用于编辑的 /etc/xinetd.d/SERVICE 文件的服务名。请随意定制脚本以编辑不同文件,或使用不同参数。可以用一行“perl -p -i -e”脚本执行这个作业,但您可以在将来对这种方法作许多扩展,并可以对参数执行错误检查。
这太简单了。现在只要决定调用这个脚本的过程即可 — 可以是手工、通过一个 cron 作业、或者由另一个程序触发。此时,它成为体系结构决策。别忘了在这时向 xinetd 发送 USR2 信号,如果愿意,也可以重新启动它。在 Red Hat Linux 上可以用“pkill -USR2 xinetd”完成信号的自动化,而重新启动 xinetd 只要使用“/etc/rc.d/init.d/xinetd restart”(在 Linux 上)或者其它类似命令(在大多数 UNIX 系统上)。
这种故障转移将“不会”对数据库连通性生效,除非在数据库端做许多额外工作。建议您最好将它用于诸如 rsync、ssh、ftp 和 telnet 之类的协议,其中,故障转移机器彼此没有相互依赖性。
Linux inetd 有多个服务
1, 开启方式 命令行输入 inetd。
2, 开启服务选择 /etc/inetd.conf ftp telnet etc.
开启服务对应程序建立软连接 指向 busybox 对应程序 busybox cp .
开启对应端口 /etc/server