Sunday, December 17, 2006

Using GUI Tools

Many Linux distributions provide GUI interfaces that permit configuration of basic networking features, common servers, and often other aspects of system operation. These tools vary substantially from one distribution to another, although they do share certain commonalities. They can usually be launched from a menu option in the distribution's default K Desktop Environment (KDE) or GNU Network Object Model Environment (GNOME) desktops, or they can be launched by typing their names in xterms. (You may need to be root to launch these tools, particularly in the latter way.) These tools include Linuxconf (used by Red Hat and many of its derivatives, including Mandrake), YaST and YaST2 (used by SuSE), and ksysv (a GUI variant on ntsysv, discussed earlier).

Friday, December 15, 2006

Using Local Startup Scripts

Most Linux distributions start the majority of their standard servers through either SysV startup scripts or a super server. One notable exception to this rule is the X server, which is often started through a line near the end of /etc/inittab, which launches the X server only in a particular runlevel. Slackware also does things a bit differently, using /etc/rc.d/rc.inet2 to start most of its servers. Most distributions provide a "local" startup script, which is intended to be modified by the system administrator to handle starting unusual system-specific servers, running initialization utilities, and so on. Table 4.1 lists the local startup scripts for several common Linux distributions.

The usual reason to use a local startup script is that you're adding a server that you don't want to run via a super server and that doesn't come with an appropriate SysV startup script. Because SysV startup scripts are closely tied to specific distributions, you might not have an appropriate SysV startup script if you obtained a server from a source other than your own distribution. For instance, if you're running Mandrake but install a server intended for SuSE, the SuSE SysV startup script may not work on your Mandrake system. You may also run into this problem if you obtain the server in source code form from the server's author; an original source such as this is unlikely to include customizations for specific Linux distributions. The code may compile and run just fine, but you'll need to start the server yourself.

Of course, it's possible to write your own SysV startup scripts for such servers. You can do this by modifying a working SysV startup script. You might try modifying the startup script for an equivalent tool (such as an earlier version of the server you're installing, if you've resorted to a third-party source because your distribution's official tool is out of date), or some randomly selected startup script. This process can be tricky, though, particularly if you're not familiar with your distribution's startup script format or with shell scripting in general. (SysV startup scripts are written in the bash shell scripting language.) If you run into problems, or if you're in a hurry and don't want to put forth the effort to create or modify a SysV startup script, you can start it in the local startup script.

You can modify the local startup script using your favorite text editor. To start a server, simply include lines in the file that are the same as the commands you'd type at a command prompt to launch the program. For instance, the following line starts a Telnet server:

/usr/sbin/in.telnetd

If the server doesn't start up in daemon mode by default (that is, if it doesn't run in the background, relinquishing control of your shell if you launch it directly), you should use an ampersand (&) at the end of the command line to tell the server to run in the background. Failure to do this will cause the execution of the startup script to halt at the call to the server. This may be acceptable if it's the last line in the script, but if you want to start additional servers, the subsequent servers won't start if you omit the ampersand.

You may, of course, do something more complex than launching a server using a single line. You could use the bash shell's conditional expressions to test that the server file exists, or launch it only under certain circumstances. These are the sorts of tasks that are usually performed in SysV startup scripts, though, so if you want to go to that sort of effort, you might prefer writing your own SysV startup script.

One important point to keep in mind is that different distributions' local startup scripts aren't exactly equivalent to one another. For instance, SuSE runs its boot.local script earlier in the boot process than Red Hat runs its rc.local. Therefore, SuSE's local startup script is more appropriate for bringing up interfaces or doing other early startup tasks, whereas Red Hat's script is better for launching servers that rely on an already-up network connection. If the tasks you want to perform in the startup script are very dependent upon the presence or absence of other servers, you may be forced to create a SysV startup script with a sequence number that's appropriate for the tasks you want to perform.

The usual reason for using a local startup script is to create a quick-and-dirty method of launching a server or running some other program. Once launched, the local startup script provides no easy way to shut down the server (as does the stop parameter to most SysV startup scripts); you'll have to use kill, killall, or a similar tool to stop the server, if you need to do so.

Thursday, December 14, 2006

Setting Access Control Features

Part of the appeal of xinetd is that it combines access control features that closely resemble those of TCP Wrappers in the super server itself. This can simplify configuration. The TCP Wrappers and xinetd access control features aren't exactly identical, though, so there are situations in which one tool or the other is superior. Like other xinetd configuration options, you can set access control features either globally or for specific servers. Major access control options include the following:
  • Host-based restrictions— The only_from and no_access options are conceptually very similar to the contents of the /etc/hosts.allow and /etc/hosts.deny files for TCP Wrappers, but xinetd sets these features in its main configuration file or server-specific configuration file. Specifically, only_from sets a list of computers that are explicitly allowed access (with all others denied access), whereas no_access specifies computers that are to be blacklisted. If both are set for an address, the one with a more specific rule takes precedence. For both options, addresses may be specified by IP address (for instance, 172.23.45.67), by network address using a trailing .0 (for instance, 172.23.0.0 for 172.23.0.0/16) or with an explicit netmask (as in 127.23.0.0/16), a network name listed in /etc/networks, or a hostname (such as badguy.threeroomco.com). If a hostname is used, xinetd does a single lookup on that hostname at the time the server starts, so if the hostname-to-IP address mapping changes, a hostname may not be very effective.
  • Temporal restrictions— You can specify a range of times during which the server is available by using the access_times option. This option requires an access time specified as hour:minute-hour:minute, such as 08:00-18:00, which restricts access to the server to the hours of 8:00 AM to 6:00 PM. Times are specified in a 24-hour format. Note that this restricts only the initial access to the server. For instance, if the Telnet server is restricted to 8:00 AM to 6:00 PM, somebody could log in at 5:58 PM and stay on indefinitely.
  • Interface restrictions— You can bind a server to just one network interface using the bind or interface options (they're synonyms), which take the IP address associated with an interface. For instance, if eth1 is linked to 172.19.28.37, bind = 172.19.28.37 links a server only to eth1. Any attempt to access the server from eth0 is met with silence, as if the server weren't running at all. This feature is most useful on routers and other computers linked to more than one network, but it's also of interest to those with small internal networks and dial-up links. For instance, you can bind servers like Telnet or FTP to your local Ethernet interface, and they won't be available to the Internet at large via your PPP connection.
Although this and the preceding section outline the most useful xinetd options, there are some less often used options that aren't described here. You should consult the xinetd man page for further information on additional options

Wednesday, December 13, 2006

The /etc/xinetd.conf File Format

As a new super server with expanded capabilities, xinetd requires a new file format. The /etc/xinetd.conf file controls xinetd, but both Red Hat and Mandrake provide only a minimal xinetd.conf file. This file includes default settings for all servers and a line that causes xinetd to read all the files in /etc/xinetd.d and treat them as supplementary configuration files. Thus, xinetd configuration is something like SysV configuration, in that each server has its own control file named after the server, such as /etc/xinetd.d/telnet to control the Telnet server. You can configure xinetd using just its main xinetd.conf file if you prefer, but server packages for Red Hat and Mandrake often drop their startup files in /etc/xinetd.d.

Whether it's located in /etc/xinetd.conf or a file in /etc/xinetd.d, a xinetd server definition spans several lines; however, a basic definition includes the same information as an inetd.conf entry. For instance, the following xinetd definition is mostly equivalent to the inetd.conf entry presented earlier for a Telnet server:

service telnet
{
socket_type = stream
protocol = tcp
wait = no
user = root
server = /usr/sbin/in.telnetd
}

This entry provides the same information as an inetd.conf entry. The xinetd configuration file format, however, explicitly labels each entry and splits them across multiple lines. Although this example presents data in the same order as does the inetd configuration, this order isn't required. Also, the xinetd definition doesn't call TCP Wrappers, although it could (you'd list /usr/sbin/tcpd on the server line, then add a server_args line that would list /usr/sbin/in.telnetd to pass the name of the Telnet server to TCP Wrappers).

In addition to the standard inetd features, xinetd provides many configuration options to expand its capabilities. Most of these are items that appear on their own lines between the curly braces in the service definition. The most important of these options include the following:
  • Security features— As noted earlier, xinetd provides numerous security options, many of which are roughly equivalent to those provided by TCP Wrappers. These are discussed in greater depth in the upcoming section "Setting Access Control Features."
  • Disabling a server— You can disable an inetd server by commenting out its configuration line. You can accomplish the same goal by adding the disable = yes line to a xinetd server definition. The same effect can be achieved in the main /etc/xinetd.conf file by using the disabled = server_list option in the defaults section, where server_list is a space-delimited list of server names. Various configuration tools use one of these methods to disable servers, and in fact a disable = no line may be present for servers that are active.
  • Redirection— If you want to pass a request to another computer, you can use the redirect = target option, where target is the hostname or IP address of the computer that should receive the request. For instance, if you include the redirect = 192.168.3.78 line in the /etc/xinetd.d/telnet file of dummy.threeroomco.com, attempts to access the Telnet server on dummy.threeroomco.com will be redirected to the internal computer on 192.168.3.78. You might want to use this feature on a NAT router to allow an internal computer to function as a server for the outside world. The iptables utility can accomplish the same goal at a somewhat lower level, but doing it in xinetd allows you to apply xinetd's access control features.
  • Logging— You can fine-tune xinetd's logging of access attempts using the log_on_success and log_on_failure options, which determine what information xinetd logs on successful and unsuccessful attempts to access a server. These options take values such as PID (the server's process ID, or PID), HOST (the client's address), USERID (the user ID on the client system associated with the access attempt), EXIT (the time and exit status of the access termination), and DURATION (how long the session lasted). When setting these values, you can use a += or -= symbol, rather than =, to add or subtract the features you want to log from the default.
  • Connection load limits— You can limit the number of connections that xinetd will handle in several ways. One is the per_source option, which specifies how many connections xinetd will accept from any given source at any one time. (UNLIMITED sets xinetd to accept an unlimited number of connections.) The instances option specifies the maximum number of processes xinetd will spawn (this value may be larger than the per_source value). The cps option takes two space- separated values: the number of connections xinetd accepts per second and the number of seconds to pause after this limit is reached before enabling access again. You can adjust the scheduling priority of the servers that xinetd runs using the nice option, which sets a value in much the same way as the nice program. Finally, max_load takes a floating-point value that represents the system load average above which xinetd refuses further connections. Taken together, these options can reduce the chance that your system will experience difficulties because of certain types of denial of service (DoS) attacks or because of a spike in the popularity of your servers.
You can use most of these options directly in the server definition or in the defaults section in the main /etc/xinetd.conf file. If placed in the latter location, the feature applies to all servers handled through xinetd, unless overridden by a competing option in the server definition area.

If you make changes to the /etc/xinetd.conf file or its included files in /etc/xinetd.d, you must restart the xinetd server program. Because xinetd itself is usually started through a SysV startup script, you can do this by typing a command such as /etc/rc.d/init.d/xinetd restart, although the startup script may be located somewhere else on some distributions. Alter natively, you can pass xinetd the SIGUSR1 or SIGUSR2 signals via kill. The former tells xinetd to reload its configuration file and begin responding as indicated in the new file. The latter does the same, but also terminates any servers that have been inactivated by changes to the configuration file.

Tuesday, December 12, 2006

Using xinetd

Traditionally, inetd has been the super server used on Linux systems. Since 2000, however, a shift has begun toward the use of an alternative, xinetd (pronounced "zi-net-dee"). As a first approximation, you can think of xinetd as being a combination of inetd and TCP Wrappers. This is only a rough analogy, though; there are things that xinetd can do that inetd with TCP Wrappers can't do, and things that inetd with TCP Wrappers can do that xinetd alone can't do. In the end, though, xinetd is more flexible because it can be combined with TCP Wrappers, if required, to extend its flexibility. In early 2002, Red Hat and Mandrake are the two major distributions that use xinetd by default, but you can add xinetd to other distributions if you like.

Monday, December 11, 2006

Using TCP Wrappers

As mentioned earlier, TCP Wrappers functions as an intermediary between inetd and the ultimate target server. The reason for doing this is security: TCP Wrappers can apply rules to determine whether or not a given connection should be allowed, thus protecting the server from unwanted accesses. For instance, suppose you want to allow only people on your own local network to access your computer's Telnet server. If you were running the Telnet server directly, it would have to be programmed to reject unwanted accesses, but not all servers include such code. Placing the responsibility for limiting access in TCP Wrappers extends the flexibility of the system without requiring extensive rewriting of all your server programs.

TCP Wrappers is controlled through two files: /etc/hosts.allow and /etc/hosts.deny. These files have identical formats, but they have opposite actions—hosts.allow specifies computers that are to be allowed access to the computer, with all others denied access; hosts.deny specifies computers that are to be denied access, with all others allowed access. When a server is listed in both files, hosts.allow takes precedence. This allows you to set a restrictive policy in hosts.deny but override it to grant access to specific computers. For instance, you could disallow access to all computers in hosts.deny, then loosen that restriction in hosts.allow. If a server isn't specified in either file (either explicitly or through a wildcard, as discussed shortly), TCP Wrappers grants access to that server to all systems.

As with many other configuration files, a pound sign (#) at the start of a line indicates a comment. Other lines take the following form:

daemon-list : client-list

The daemon-list is a list of one or more servers to which the rule applies. If the list contains more than one server, commas or spaces may separate the server names. The names are those listed in /etc/services. The ALL wildcard is also accepted; if the daemon-list is ALL, then the rule applies to all servers controlled by TCP Wrappers.

The client-list is a list of computers that are to be allowed or denied. As with the daemon-list, the client-list can consist of just one entry or a list separated by commas or spaces. You can specify computers in any of several ways:
  • IP addresses— You can list complete IP addresses, such as 10.102.201.23. Such an entry will match that IP address and that IP address only.
  • IP address range— There are several ways to specify ranges of IP addresses. The simplest is to provide fewer than four complete bytes followed by a period. For instance, 10.102.201. matches the 10.102.201.0/24 network. You can also use an IP address/netmask pair, such as 10.102.201.0/24. IPv6 addresses are also supported, by a specification of the form [n:n:n:n:n:n:n:n]/len, where the n values are the IPv6 address and len is the length in bits of the range to be matched.
  • Hostname— You can provide a complete hostname for the computer, such as badcracker.threeroomco.com. This will match that computer only. Because this method relies upon a hostname lookup, though, it's subject to problems if your DNS servers go down or if the person who controls the domain modifies its entries.
  • Domain— You can match an entire domain or subdomain much as you can match a single hostname. The difference is that you must precede the domain name with a period, as in .threeroomco.com—this example matches all the computers in the threeroomco.com domain.
  • NIS netgroup name— If a string is preceded by an at symbol (@), the string is treated as a Network Information Services (NIS) netgroup name. This method relies upon your network having a functioning NIS configuration.

In addition, the client-list specification supports more wildcards than does the daemon-list specification. Specific wildcards you may use include the following:

  • ALL— This wildcard matches all computers.
  • LOCAL— This wildcard is intended to match all local computers, based on hostname. If the computer's hostname lacks a period, it's considered local.
  • UNKNOWN— This wildcard matches computers whose hostnames aren't known by your name resolution system.
  • KNOWN— This wildcard matches computers whose hostname and IP addresses are both known to the system.
  • PARANOID— This wildcard matches computers whose names and IP addresses don't match.

These last three options should be used with care, since they usually depend upon proper functioning of DNS, and DNS can be unreliable because of transient network problems. For instance, if a client's own DNS system is down or inaccessible, you might be unable to verify its hostname. As an example of a short but complete /etc/hosts.allow file, consider the following:

telnet,ftp : 192.168.34. dino.pangaea.edu

ssh : LOCAL .pangaea.edu

The first line specifies identical restrictions for the Telnet and FTP servers, allowing access only to the 192.168.34.0/24 network and the host called dino.pangaea.edu. The second line applies to SSH and restricts access to local computers and all those in the pangaea.edu domain. Because no other servers are listed in the daemon-list fields, TCP Wrappers doesn't block access to any other server. For instance, if you were to run Apache through inetd and TCP Wrappers, everybody would be granted access to Apache with this configuration.

In addition to matching entire computers, you can use the user@computer form to match individual users of the remote system. This form, however, requires that the client computer run an ident (aka auth) server, which returns the name of the user who is using a given network port. Your own server can query the client's ident server about the connection attempt, thus getting the username associated with that attempt. This may cause additional delays, however, and the information often isn't particularly trustworthy, especially from random hosts on the Internet. (You're more likely to want to use this feature to control access from specific users of systems that you control.)

The EXCEPT operator is another special keyword; it specifies exceptions to the rules just laid out. For instance, consider the following /etc/hosts.deny entry:

www : badcracker.org EXCEPT goodguy@exception.badcracker.org

This example denies access to the Web server to all the computers in the badcracker.org domain, unless the connection is coming from goodguy@exception.badcracker.org. (Because /etc/hosts.allow takes precedence over /etc/hosts.deny, entries in the former can also override those in the latter.)

If your goal is to run a very secure system, you may want to begin with the following /etc/hosts.deny file:

ALL : ALL

This blocks access to all computers for all servers handled by TCP Wrappers. You must then explicitly open access to other servers in /etc/hosts.allow. You should open access as little as possible. For instance, you might only give access to computers in a specific network block or domain for sensitive servers like Telnet. (Telnet passes all data in an unencrypted form, so it's a poor choice for logins over the Internet as a whole. See Chapter 13, Maintaining Remote Login Servers, for a discussion of this issue.)

Sunday, December 10, 2006

The /etc/inetd.conf File Format

You can configure inetd through the /etc/inetd.conf file. Aside from comments (lines that begin with a pound sign, #, that inetd ignores), inetd.conf consists of a series of lines, each of which defines a single server. A sample line resembles the following:

telnet stream tcp nowait root /usr/sbin/tcpd in.telnetd

Each line consists of a series of fields, which are separated by spaces or tabs. The meaning of each field is as follows:
  • Server name— The first field is the name of the server protocol, as recorded in /etc/services. In the case of the preceding example, the server protocol name is telnet, and if you check /etc/services, you'll see that this name is associated with 23/tcp—in other words, TCP port 23. There must be an entry in /etc/services in order for inetd to handle a server. For this reason, you may need to edit /etc/services if you want inetd to handle some unusual server. In most cases, though, /etc/services has the appropriate entries already.
  • Socket type— The second field relates the network socket type used by the protocol. Possible values are stream, dgram, raw, rdm, and seqpacket.
  • Protocol type— The third field is the name of the protocol type, which in this context means a low-level network stack protocol such as TCP or UDP. Possible protocol values appear in /etc/protocols, but the most common values are tcp and udp.
  • Wait/Nowait— The fourth field takes just one of two values, wait or nowait, and is meaningful only for datagram (dgram) socket types (other socket types conventionally use a nowait value). Most datagram servers connect to a socket and free up inetd to handle subsequent connection attempts. These servers are called multi-threaded, and they require a nowait entry. Servers that connect to a socket, process all input, and then time out are said to be single-threaded, and they require wait entries. You may optionally add a number to these values, separated by a period, as in wait.60. This specifies the maximum number of servers of the given type that inetd may launch in one minute. The default value is 40.
  • Username— You can tell inetd to launch a server with a specific user's privileges. This can be an important security feature, because restricting privileges for servers that don't require extensive access to the system can prevent a bug from causing a security breach. For instance, the Apache Web server usually doesn't need unusual privileges, so you could launch it as nobody or as some special account intended only for Apache. The preceding example shows the username as root because root privileges are needed to launch the login processes required by a Telnet server. If you add a period and a group name, the specified group name is used for the server's group privileges. For instance, nobody.nogroup launches a server with the username nobody and the group nogroup.
  • Server program— The sixth field specifies the name of the server program that inetd launches when it detects an incoming connection. The preceding example gives /usr/sbin/tcpd as this program name. In reality, tcpd is not a server; it's the program file for the TCP Wrappers program, which is described shortly. Most Linux distributions that use inetd also use TCP Wrappers, and so launch most inetd-mediated servers through tcpd. You can bypass TCP Wrappers for any server you like, although it's generally best to use TCP Wrappers for reasons that are described shortly.
  • Server program arguments— The final field is optional. When present, it contains any arguments that are to be passed to the server program. These arguments might modify the server's behavior, tell it where its configuration files are, and so on. In the case of servers launched through TCP Wrappers, the argument is the name of the ultimate target server, such as in.telnetd in the preceding example. (You may add the ultimate server's arguments to this list, if it needs any.)

You can edit /etc/inetd.conf using any text editor you like. Be sure that any new entries you create, or existing ones you modify, span a single line. (Long filenames, server arguments, and the like sometimes produce lines long enough that some editors will try to wrap the line onto two lines, which will cause problems.) If you need to add an entry for a server you've installed, consult the server's documentation to learn what its inetd.conf entry should look like. In some cases, you can model an entry after an existing one, but without knowing what values to enter for the server name, socket type, and so on, such an entry might not work.

Most distributions that use inetd ship with an /etc/inetd.conf file that contains entries for many different servers. Many of these entries are commented out, so they're inactive. You can activate a server by uncommenting such a line, if the matching server is installed. Some inetd.conf files include multiple entries for any given service; for instance, a file might have two or three different entries for different FTP servers. If yours is like this, be sure you uncomment only the line corresponding to the specific server you've installed, such as ProFTPd or WU-FTPD.