Access control is a technique for limiting access. Routers and hosts that use access control check the address of a host requesting a service against an access control list. If the list says that the remote host is permitted to use the requested service, the access is granted. If the list says that the remote host is not permitted to access the service, the access is denied. Access control does not bypass any normal security checks. It adds a check to validate the source of a service request, and retains all of the normal checks to validate the user.
Access control systems are common in terminal servers and routers. For example, Cisco routers have an access control facility. Access control software is also available for UNIX hosts. Two such packages are xinetd and the TCP wrappers program. Clearly, there are a variety of ways to implement access controls. In this section we use TCP wrappers ("wrapper").
The wrapper package performs two basic functions: it logs requests for Internet services, and provides an access control mechanism for UNIX systems. Logging requests for specific network services is a useful monitoring function, especially if you are looking for possible intruders. If this were all it did, wrapper would be a useful package. But the real power of wrapper is its ability to control access to network services.
The wrapper software is available through the http://csrc.nist.gov/tools/tools.htm Web page. The wrapper tar file contains the C source code and Makefile necessary to build the wrapper daemon tcpd.
Make tcpd and then install it in the same directory as the other network daemons. Edit /etc/inetd.conf and replace the path to each network service daemon that you wish to place under access control with the path to tcpd. The only field in the /etc/inetd.conf entry affected by tcpd is the sixth field, which contains the path to the network daemon.
For example, assume that the entry for the finger daemon in /etc/inetd.conf on our Solaris system is:
finger stream tcp nowait nobody /usr/etc/in.fingerd in.fingerd
finger stream tcp nowait nobody /usr/etc/tcpd in.fingerd
Now when inetd receives a request for fingerd, it starts tcpd instead. tcpd then logs the fingerd request, checks the access control information, and, if permitted, starts the real finger daemon to handle the request.
Make a similar change for every service you want to place under access control. Good candidates for access control are ftpd, tftpd, telnetd, rshd, rlogind, rexecd, and fingerd. Obviously, tcpd cannot control access for daemons that are not started by inetd, such as sendmail and NFS.
Using the wrapper on our Slackware 96 Linux system is even easier. There is no need to download and install the tcpd software. It comes as an integral part of the Linux release. You don't even have to edit the /etc/inetd.conf file because the sixth field of the entries in that file already point to the tcpd program, as shown below:
finger stream tcp nowait nobody /usr/sbin/tcpd in.fingerd -w
The information tcpd uses to control access is in two files, /etc/hosts.allow and /etc/hosts.deny. Each file's function is obvious from its name. hosts.allow contains the list of hosts that are allowed to access the network's services, and hosts.deny contains the list of hosts that are denied access. If the files are not found, tcpd permits every host to have access and simply logs the access request. Therefore, if you only want to monitor access, don't create these two files.
If the files are found, tcpd checks the hosts.allow file first, followed by the hosts.deny file. It stops as soon as it finds a match for the host and the service in question. Therefore, access granted by hosts.allow cannot be overridden by hosts.deny.
The format of entries in both files is the same:
service-list : host-list [: shell-command]
The service-list is a list of network services, separated by commas. These are the services to which access is being granted (hosts.allow) or denied (hosts.deny). Each service is identified by the process name used in the seventh field of the /etc/inetd.conf entry. This is simply the name that immediately follows the path to tcpd in inetd.conf. (See Chapter 5, Basic Configuration , for a description of the arguments field in the /etc/inetd.conf entry.)
Again, let's use finger as an example. We changed its inetd.conf entry to read:
finger stream tcp nowait nobody /usr/etc/tcpd in.fingerd
Therefore, we would use in.fingerd as the service name in a hosts.allow or hosts.deny file.
The host-list is a comma-separated list of hostnames, domain
names, Internet addresses, or network numbers.
The systems listed in the host-list are granted access
(hosts.allow) or denied access (hosts.deny) to the services
specified in the service-list. A hostname or an Internet
address matches an individual host. For example, peanut is a
hostname and 172.16.12.2 is an Internet address. Both match a
particular host. A domain name matches every host within that domain;
e.g., .nuts.com matches almond.nuts.com,
peanut.nuts.com, pecan.nuts.com, and any other hosts in the
domain. When specified in a
tcpd access control list, domain names always start with a dot
.). A network number matches every IP address within that network's
address space. For example, 172.16. matches 172.16.12.1, 172.16.12.2,
172.16.5.1, and any other address that begins with 172.16. Network
addresses in a tcpd access control list always end with a dot
A completed hosts.allow entry that grants FTP and telnet access to all hosts in the nuts.com domain is shown below:
ftpd,telnetd : .nuts.com
Two special keywords can be used in hosts.allow and
hosts.deny entries. The keyword
ALL can be used in the
service-list to match all network services, and in the
host-list to match all hostnames and addresses. The second
LOCAL, can be used only in the host-list. It matches
all local hostnames. tcpd considers a hostname "local" if it
contains no embedded dots. Therefore, the hostname
peanut would match on
LOCAL, but the hostname
peanut.nuts.com would not match. The following
entry affects all services and all local hosts:
ALL : LOCAL
The final field that can be used in these entries is the optional shell-command field. The shell command specified in this field will execute whenever a match occurs. The command is executed in addition to the normal functions of the access list match. In other words, if a match occurs for an entry that has an optional shell command, tcpd logs the access, grants or denies access to the service, and then passes the shell command to the shell for execution.
A more complete example of how tcpd is used will help you understand these entries. First, assume that you wish to allow every host in your local domain (nuts.com) to have access to all services on your system, but you want to deny access to every service to all other hosts. Make an entry in /etc/hosts.allow to permit access to everything by everyone in the local domain:
ALL : LOCAL, .nuts.com
ALL in the services-list indicates that this rule applies
to all network services. The colon (:) separates the services-list
from the host-list. The keyword
LOCAL indicates that all local
hostnames without a domain extension are acceptable, and that the
.nuts.com string indicates that all hostnames that have the
nuts.com domain name extensions are also acceptable. To prevent
access from everyone else, make an entry in the /etc/hosts.deny
ALL : ALL
Every system that does not match the entry in /etc/hosts.allow is
passed on to /etc/hosts.deny. Here the entry denies access to
everyone, regardless of what service they are asking for. Remember,
ALL in the services-list field, only services started by
inetd, and only those services whose entries in inetd.conf
have been edited to invoke tcpd, are affected. This does not
provide security for any other service.