TCP Wrappers is a freely available IP packet filtering facility written by Wieste Venema. It provides for greater and more specific control over local network services and which hosts are allowed to access them. It also makes use of the standard syslog facility to track local network use. Although it was written many years ago and has not changed much over time, TCP Wrappers remains useful because it can be configured quickly and easily, and it adds an additional layer of protection even when used in conjunction with more robust packet filters (like iptables).
How Services Use TCP Wrappers
There are two main ways TCP Wrappers can be used by a service, depending on how that service is started. Some services are controlled by the inetd program, which starts a service when a connection comes in and stops it when that connection is terminated. TCP Wrappers comes with a program called tcpd that can be inserted into the inetd configuration (in a file called /etc/inetd.conf), allowing any inetd service to be wrapped. Some versions of inetd, including xinetd and the inetds that come with newer versions of Solaris and the BSDs, have built-in support for TCP Wrappers and do not need tcpd.
One example of an inetd service is telnetd. It is started by inetd, and its startup parameters can be configured in /etc/inetd.conf.
Other services are started when the system boots and continue running indefinitely, handling their own connections. These services do not use inetd and are often called stand-alone services. They can only be wrapped if they have support for TCP Wrappers built in and are linked against the libwrap library.
The sshd service is an example of a stand-alone service. Most brands of sshd have built-in TCP Wrappers support.
Where to Get TCP Wrappers
Note: Solaris 9 and beyond, most Linux and BSD distributions, and Mac OS X have TCP Wrappers configured to run out-of-the-box, so this section can be skipped on those platforms.
The Unix Systems Support Group provides source packages for TCP Wrappers. This local distribution site is especially useful when using a private IP address on a university campus. You can also get TCP Wrappers from Wietse's FTP site. Follow the instructions in the source package to build and install TCP Wrappers.
Once installed, TCP Wrappers will do all its logging via syslog according to your /etc/syslog.conf file. The following table lists the standard locations where messages from TCP Wrappers will appear:
Operating System Path AIX /var/adm/messages *BSD /var/log/messages HP/UX /usr/spool/mqueue/syslog Irix /var/adm/SYSLOG Linux /var/log/messages Mac OS X /var/log/system.log Solaris /var/log/syslog
Wrapping Stand-alone Services
Stand-alone services with TCP Wrappers support don't need to be started any differently; they're always wrapped. Simply follow the instructions under Installing the Access Control Files to control access to these services.
A stand-alone service that does not support TCP Wrappers cannot be wrapped at all. See the documentation for the service to find out if TCP Wrappers support can be enabled at compile time.
Wrapping inetd Services
How inetd services are wrapped varies greatly depending on the version of inetd. We cover several below.
If your system does not have TCP Wrappers built in or if you are using standard inetd on most Linux distributions, your configuration will have to use the tcpd program that is part of TCP Wrappers to wrap inetd services.
In order to wrap an inetd service, you simply change its entry in /etc/inetd.conf so that tcpd is executed. For example, to wrap telnetd, change
telnet stream tcp nowait root /usr/sbin/in.telnetd in.telnetd
telnet stream tcp nowait root /usr/sbin/tcpd in.telnetd
In other words, replace the pathname of the daemon with the full path to tcpd, leaving everything else untouched.
If compiled with TCP Wrappers support (by using the --with-libwrap option to configure), xinetd will automatically apply TCP Wrappers to every service. Follow the steps under Installing the Access Control Files to configure access control.
Solaris 9 inetd and Beyond
Recent versions of Solaris have TCP Wrappers support built into inetd. To enable it, add the following line to /etc/default/inetd:
Then restart inetd using the command
pkill -HUP inetd
The BSDs (FreeBSD, OpenBSD, and NetBSD) also have an inetd with built-in TCP Wrappers support. In recent versions, support is enabled by default. It can be explicitly enabled by starting inetd with the -W and -w options:
# /usr/sbin/inetd -W -w
How these options can be added at boot time depends on the type of BSD and the version. See the system documentation for your version for details.
Creating Your Access Control Rule Set
Now that you have TCP Wrappers installed and have configured services to use it, you need to install files which determine who can and who cannot access the wrapped services. This is accomplished with two files: hosts.allow and hosts.deny, which you install in /etc/. These files contain rules that tell whether a given client (specified as a hostname or IP address) is allowed or disallowed to access a given service.
In their most basic form, the rules look like
service list : client list
where service list is a space-separated list of the services or daemons you're controlling access to, and client list is a space-separated list of the hostnames or IPs for whom you're allowing or denying access. Some examples of services are sshd, telnetd, and sendmail. Also, ALL can be used as a wildcard to represent any service or client.
Whether the client is allowed or denied depends on whether you put the rule in the hosts.allow file or the hosts.deny file. When a client tries to connect, the files are searched as follows (taken from the hosts_access(5) manual page):
- Access will be granted when a (daemon, client) pair matches an entry in the /etc/hosts.allow file.
- Otherwise, access will be denied when a (daemon, client) pair matches an entry in the hosts.deny file.
- Otherwise, access will be granted.
Here is an example of a fairly restrictive ruleset on a system that is perhaps a mail server for a small network (with the IP range 192.168.54.0 through 192.168.54.255).
popd : 192.168.54.137 imapd : 192.168.54.0/255.255.255.0 sendmail : 192.168.54.0/255.255.255.0 sshd : 192.168.54.2 172.16.234.4
ALL : ALL
The first line of hosts.allow permits access to the POP service from one IP within the subnet. (This is the one lonely user who still uses POP.) The IMAP service, however, is much more popular, so access is allowed to it from the entire subnet (note the netmask). Similarly, everyone on the subnet is allowed to connect to sendmail for outbound mail. The last line of the hosts.allow file limits access to one IP on the subnet and one external IP (perhaps the server administrator's workstation and home computer).
Anything not explicitly allowed in the hosts.allow file is denied by the catchall rule in the hosts.deny file. This default-to-deny policy is usually the most effective approach to network security.
Note that we used raw IP addresses instead of DNS hostnames. TCP Wrappers does support hostnames in rulesets; even whole domains can be specified (for example, .iupui.edu). But it's possible that an attacker could subvert your ruleset by spoofing DNS. So even though it may be a little less convenient, we opted for the more secure approach of using raw IPs.
Recommendations and Further Reading
To sum up, here are a few tips for using TCP Wrappers:
- If your system doesn't have an inetd with built-in TCP Wrappers support, give xinetd a try.
- If possible, use a default deny policy (ALL : ALL in the hosts.deny file).
- Use IP addresses instead of hostnames to thwart spoofing.
We've only touched on the many features offered by TCP Wrappers. To learn more, check out the hosts_access(5) manual page that comes with TCP Wrappers.