November 12, 2010

Weekend Project: Replace Inetd with Xinetd for Better Network Administration

 

Xinetd is an alternative to the traditional super-server Internet daemon, inetd, the process that starts and stops all non-persistent network servers. Xinetd acts as a drop-in replacement for inetd, but it can do more than just start and stop services on your Linux machine in response to incoming TCP or UDP connections. The real advantage of Xinetd is that it allows more fine-grained control, including access control lists (ACLs), rate-limiting, time-based access, and stream redirection.

Xinetd is packaged by all major Linux distributions, so you can install it through the package management system. Barring that, you can download the latest release from xinetd.org and compile it with the usual ./configure; make; sudo make install process. There are no unusual dependencies to speak of. The only particular risk you undertake installing it if your distribution marks it as conflicting with the inetd package so that you cannot have both installed at the same time. Back up your /etc/inetd.conf file before you proceed.

 

Configuration Basics

Inetd's configuration file consists of a single line for each service, listing the service's name (as it is listed in the /etc/services file), the socket type (generally stream for TCP and dgram for UDP), the protocol, a "wait" or "nowait" directive that tells inetd whether or not to wait for the server to return before processing further connections, the user as whom the server should run, and the pathname of the server to launch, followed by any arguments. For instance,

imap stream tcp nowait root /usr/sbin/tcpd imapd
sane-port stream tcp nowait saned:saned /usr/sbin/saned saned

The first line launches an IMAP daemon whenever a request comes in on TCP port 220; the second is for network-sharing a SANE scanner, which uses the non-IETF-assigned TCP port 6566, and runs as the saned user.

Xinetd's configuration file /etc/xinetd.conf uses a different syntax, with braces-delimited stanzas holding the options for each service. Every entry begins with service servicename, followed on subsequent lines by individual attributes and their assigned values. For example,

service imap
{
  socket_type    = stream
  protocol       = tcp
  wait           = no
  user           = root
  only_from      = 192.168.2.102 localhost
  banner_fail    = /usr/local/etc/your_failure_banner
  server         = /usr/sbin/imapd
  log_on_failure += USERID
}

The first few lines specify the same settings as shown in the inetd example: TCP, stream, no waiting, run-as-root. The final few, however, indicate some of xinetd's additional options. The only_from attribute allows you to specify a space-separated list of allowable hosts and IP addresses. The banner_fail attribute allows you to specify a text file displayed to the remote host when a connection is denied (such as originating the connection from a disallowed IP address). You can also give a banner_success attribute to be displayed when a connection is established, and a banner attribute that is always displayed, regardless of success or failure.

The log_on_failure attribute lists what information is written to the log whenever a connection is disallowed. Note that the operator used is "+=" instead of "=" -- this has the effect of adding the userid of the connection to the information that is logged by default. As you might guess, log_on_success is also available, and there are several data values that Xinetd can log, including the remote host and total traffic count.

You can set up your entire Xinetd configuration entirely within /etc/xinetd.conf, or you separate out different services into their own configuration files. To do this, you end /etc/xinetd.conf with an includedir directive, giving as its argument a directory in which Xinetd should look for additional configuration files. Some distributions do this by default, usually with /etc/xinetd.d/ as the configuration directory. Every file in the specified directory will be parsed, unless its filename either begins with a dot (.) or ends with a tilde (~).

In this case, you should probably have a "defaults" stanza in your /etc/xinetd.conf file. This is a special stanza that assigns base attributes for every connection. Some attributes that apply to individual services (such as socket_type and server) do not apply in defaults; but you can save space by placing commonly-used attributes here rather than repeating them for each service. For example,

defaults
{
  log_type       = FILE /var/log/services.log
  log_on_success = PID
  log_on_failure = PID HOST
  instances      = 20
  banner_success = /usr/local/welcome_message
}

Access Control Measures

Beyond extra conveniences like banners and logging options are Xinetd's administrative functions, with which you can set and enforce network policy and respond to certain kinds of attacks.

The only_from attribute in the above example is the most basic form of access control; unlike using /etc/hosts_allow, however, you can configure only_from values for every service individually, or set a site-wide policy in your defaults stanza, and adjust it for specific services by using the += and -= operators in individual entries. The mirror image of only_from is no_access, which can disable access to a service based on IP or hostname. Both attributes can also accept an IP address range using ip/netmask formatting.

The access_times directive allows you to enable or disable connections based on the system time. You specify the time intervals when the service will accept connections, in hour:minute ranges. For example, access_times 05:00-11:30 13:00-16:30 keeps the service available from 5 AM to 11:30 AM, then closes it for a leisurely lunch break, and reopens it from 1:30 PM to 4:30PM. As the example shows, you can chain together multiple time intervals in one line. Conversely, you can use deny_time to dictate times when the service will be made unavailable to incoming connections.

These fixed-policy measures can be combined with adaptive settings that allow you to trigger service shutdown based on the machine's state or network traffic. The per_source attribute, for example, takes an integer as its argument, and limits the number of simultaneous connections that a single host may make using the service. This could be used to limit the number of SMTP connections made, which could be effective in catching machines infected with spam-bot viruses.

The cps attribute allows you to set a connection frequency threshold (in connections per second), above which the server will be shut down for a configurable amount of time. This allows you to prevent denial-of-service attacks based on flooding the service. Placing a setting of cps = 80 60 in a particular service's stanza says that Xinetd will respond to 80 connections per second, but if the rate of connections hits 81, it will stop the service, wait 60 seconds, then start processing new connections again.

You can also configure shutdown-threshold values for system load (using the max_load attribute), as well as address space (using rlimit_as), CPU-seconds (with rlimit_cpu), or even stack size (rlimit_stack).

Fun with Hosts and Interfaces

The redirect attribute allows you to forward a TCP (but not a UDP) connection to a different host entirely. The syntax is simple, redirect = ip-address port-number. When a connection on the matching service comes in, Xinetd starts a TCP connection to the listed IP address and port, and forwards all of the traffic to it.

This gives you a simple and effective way to redirect particular services (perhaps to machines not accessible to the outside network) without touching the firewall rules. That might be a useful feature for temporarily redirecting a service, or when combined with other access control measures, to redirect services based on their source and time of day.

Xinetd also has the ability to bind a particular service to a particular network adapter. This can be helpful when one service generates a large volume of traffic, or if you want to make a service available only over a wired connection (eth0) and not wireless (wlan0). You can use either the interface or bind attributes in the service's stanza, followed by the IP address of the interface.

Most of Xinetd's configuration tricks can be accomplished with a combination of other programs -- inetd, TCP Wrapper, hosts_allow and hosts_deny, iptables, etc. But what that smorgasbord of utilities does not do is provide a single, unified interface through which you can simply and easily compose your network service policy.

Click Here!