We explained earlier that connecting your system to a network significantly increases the risk of attack. With the commonsense considerations out of the way, it's time to look more closely at basic network security. Here we discuss a simple yet effective method of reducing the risk of unwanted network access, using a tool called TCP wrappers . This mechanism "wraps" an existing service (such as the mail server), screening the network connections that are made to it and refusing connections from unauthorized sites. This is a simple way of adding access control to services that weren't originally designed for it, and is most commonly used in conjunction with the inetd or xinetd daemons.
TCP wrappers are somewhat equivalent to the security guards, or bouncers, that you might find protecting the entrance to large parties or nightclubs. When you approach a venue, you first encounter the security guard, who may ask you your name and address. The guard then consults a guest list, and if you're approved, the guard moves aside and allows you entry to the party.
When a network connection is made to a service protected by TCP wrappers , the wrapper is the first thing encountered. The wrapper checks the source of the network connection using the source hostname or address and consults a list that describes who is allowed access. If the source matches an entry on the list, the wrapper moves out of the way and allows the network connection access to the actual daemon program.
There are two ways to use TCP wrappers, depending on your Linux distribution and configuration. If you are using the inetd daemon for managing services (check to see if the file /etc/inetd.conf exists), TCP wrappers are implemented using a special daemon called tcpd. If you are using the xinetd daemon instead (check for the directory /etc/xinetd.d), xinetd is usually configured to use TCP wrappers directly. We describe each case in the following sections.
26.3.1. Using TCP Wrappers with inetd
If your system uses the inetd daemon to launch network services, it may be necessary to edit your /etc/inetd.conf file to use TCP wrappers . Let's use the finger daemon, in.fingerd, as an example. The basic idea is that instead of running the actual in.fingerd daemon, inetd launches the tcpd daemon instead. tcpd performs the TCP wrapper operation and then runs in.fingerd in its place if the connection is accepted.
Configuring TCP wrappers requires a very simple change to /etc/inetd.conf. For the finger daemon, you might have an entry in this file such as the following:
# /etc/in.fingerd finger daemon finger stream tcp nowait root /usr/sbin/in.fingerd in.fingerd
To protect the finger daemon using tcpd, simply modify the /etc/inetd.conf entry, as so:
# /etc/in.fingerd finger daemon finger stream tcp nowait root /usr/sbin/tcpd /usr/sbin/in.fingerd
Here we've caused the tcpd command to be executed instead of the actual in.fingerd command. The full pathname of the finger daemon is passed to tcpd as an argument, and tcpd uses this argument to launch the real daemon after it has confirmed that access should be allowed.
You'll need to make this change for each daemon program you wish to protect. On most Linux systems, you may find that tcpd is already configured, so these changes won't be necessary.
26.3.2. Using TCP Wrappers with xinetd
xinetd is a replacement for inetd that some distributions (such as Red Hat) are adopting. In most cases, xinetd has built-in support for TCP wrappers, so all you'll need to do is modify the TCP wrapper configuration files (/etc/hosts.allow and /etc/hosts.deny) as described in the next section. If you are installing xinetd yourself, be sure to compile support for TCP wrappers; this is described in the xinetd documentation.
26.3.3. /etc/hosts.allow and /etc/hosts.deny
TCP wrappers use two configuration files, /etc/hosts.allow and /etc/hosts.deny. These files are used to specify the access rules for each network daemon protected with TCP wrappers. The files are described in detail in the hosts_access manual page, but we cover the mechanics here because common cases are fairly simple.
When a TCP wrapper is invoked, it obtains the IP address of the connecting host and attempts to find its hostname using a reverse DNS lookup. Next, it consults the /etc/hosts.allow file to see if this host is specifically allowed access to the requested service. If a match is found, access is allowed and the actual network daemon is invoked. If no match is found in the /etc/hosts.allow file, /etc/hosts.deny is consulted to see if this host has been specifically denied access. If a match is found here, the connection is closed. If no match is found in either file, access is granted. This simple technique is powerful enough to cover most access requirements.
The syntax of hosts.allow and hosts.deny is fairly simple. Each file contains a set of rules. Each rule is generally on one line but may be split across multiple lines using a backslash at the end of the line. Each rule has the following general form:
daemon_list : client_list : shell_command
The daemon list is a comma-separated list of daemons to which the rule applies. The daemons are specified using their command basename that is, the name of the actual executable daemon program that is executed to fulfill the requested service. The client list is a comma-separated list of hostnames or IP addresses for which the rule will match. We'll demonstrate this later using an example. The shell command is optional, and specifies a command that will be executed when the rule matches. This can be used, for example, to log incoming connections.
daemon_list and client_list may contain patterns that allow you to match a number of daemons or hosts without having to explicitly name each one. In addition, you can use a number of predefined tokens to make rules simpler to read and build. The patterns are quite sophisticated, so we don't cover them in detail here; instead, we refer you to the hosts_access manual page.
Let's start with a simple hosts.deny file that looks like this:
# /etc/hosts.deny ALL: ALL
The first line is a comment. The next line is a rule that is interpreted as follows: "Deny access requests to all services from all hosts." If our /etc/hosts.allow file is empty, this rule will have the effect of denying access to everything from all hosts on the Internetincluding the local host! To get around this problem, we can make a simple change to the file:
# /etc/hosts.deny ALL: ALL EXCEPT localhost
This is nearly always a safe rule to have in place, as it's a secure default. Remember that the /etc/hosts.allow rules are consulted before /etc/hosts.deny, so by adding rules to hosts.allow we can override this default setting in hosts.deny. For example, imagine that we want to allow every host on the Internet to access the finger daemon. To do this, we add a rule to /etc/hosts.allow that looks like the following:
# /etc/hosts.allow in.fingerd: ALL
A more common use of TCP wrappers is to restrict the set of hosts that can access a service. Hosts can be specified using an IP address, hostname, or some pattern based on the address or hostname (e.g., to specify a group of hosts). For example, consider making the finger daemon available only to a small set of trusted hosts. In this case, our hosts.allow file would be modified as follows:
# /etc/hosts.allow in.fingerd: spaghetti.vpasta.com, .vpizza.com, 192.168.1.
In this example we've chosen to allow finger requests from the host named spaghetti.vpasta.com, as well as from any host in the vpizza.com domain, and from any system with an IP address beginning with the pattern 192.168.1.
The host and IP address-matching rules in hosts.allow and hosts.deny are important to understand, and the presence and location of the period characters are critical. A pattern beginning with a period is assumed to be the name of a domain to which requesting systems must belong. A pattern ending with a period is assumed to specify an IP address pattern. There are other ways of specifying groups of hosts, including NIS netgroups and explicit IP address netmasks. Full details on the configuration syntax of these patterns are available in the hosts_access manual page.