Running Linux, 5th Edition - Matthias Kalle Dalheimer [463]
/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 Internet—including 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,