tcp wrappers are a security tool for protecting access to internet services spawned by inetd or a similar daemon. By invoking tcpd instead of the standard daemon for the service, access control can be implemented on a host-by-host and service-by-service basis. tcp wrappers can be used in conjunction with Xinetd (see the previous section for more information on Xinetd) to provide an even greater level of security.
tcp wrappers are installed by default on most modern Linux distributions. They are not configured to provide any real protection though. In the remainder of this section, we'll look at using tcp wrappers to make your system (or systems) more secure. To do this, we'll need to review how inetd works and then revise that system by introducing tcpd.
Instead of running a separate daemon for each service provided by a host, Unix and Linux run a "switchboard daemon" called inetd.3 This daemon listens to many ports, and when it receives a request on a given port, it spawns the appropriate daemon to service that request. The list of ports it listens to, and the daemons associated with that port, are given in /etc/inetd.conf and use the following syntax (both the syntax and an example are given):
# <service_name> <sock_type> <proto> <flags> <user> <server_path> <args> echo stream tcp nowait root internal
In this example, the echo service (a built-in service of the TCP and UDP protocol stacks) is defined for TCP. inetd will look up the port number for echo in the /etc/services file:
Then, whenever a TCP connection request is received on TCP port 7, inetd will hand the request to the echo server built into the TCP protocol stack. This same model is followed for every service listed in /etc/inetd.conf.
tcp wrappers are used by replacing the <server_path> portion of the /etc/inetd.conf entry with /usr/sbin/tcpd. The telnet service would be run through tcp wrappers like this:
telnet stream tcp nowait root /usr/sbin/tcpd in.telnetd
tcp wrappers will then check the IP address of the connecting client against its list of allowed and denied host rules. The allowed host rules are checked first, then the denied hosts. The checks stop at the first matching rule. If all the rules are processed without the connection being explicitly allowed or denied, the connection will be allowed.
As you can probably guess from the name, tcp wrappers are only suitable for protecting TCP-based services.4 Because UDP does not create sessions, tcp wrappers are not used to control the start up of individual daemons. If you want to control access to UDP services, you should refer to the section "iptables" for more detail on how to set up a true packet filter.
tcp wrappers at Work
To put tcp wrappers to work, we'll take a look at where we might use it, create a policy for a host, and convert /etc/inetd.conf to implement that policy with tcp wrappers.
tcp wrappers is a good solution for providing security for a group of hosts behind a more involved firewall, or for a single host that is connected to the Internet intermittently. In the latter case, some thought should be given to using packet filtering tools as well as (or instead of) tcp wrappers. If you are using tcp wrappers to protect more than one host, remember that you will have to configure and maintain it on each host.
For our example, we'll look at a single host that is already behind a firewall. It is part of the IS LAN (192.168.1.0/24) and should provide only talk and echo services to any host internally (192.168.1.0/21) through inetd. Any host on the IS LAN or on the Data Center LAN (192.168.1.1/24) should also be able to use the finger service. Connectivity and file transfer are provided via SSH and HTTP, which are not run through inetd.
We'll start with a stripped down inetd.conf , which we can then modify to use tcp wrappers. This is shown in Listing 11.
Listing 11 An inetd.conf Without tcp wrappers
# # inetd.conf -- this is a minimal inetd.conf for an IS machine. # echo stream tcp nowait root internal echo dgram udp wait root internal talk dgram udp wait nobody.tty /usr/sbin/in.talkd in.talkd ntalk dgram udp wait nobody.tty /usr/sbin/in.ntalkd in.ntalkd finger stream tcp nowait nobody /usr/sbin/in.fingerd in.fingerd
The echo servers will not need to be changed because they are internal to the protocol stack. The talk and ntalk servers cannot be protected by tcp wrappers because they are UDP services. Fortunately, these services are going to be universally provided to internal hosts, so we will rely on our firewall to keep outside connections from getting in. finger is to be limited to only those users in the 192.168.1.0/23 address range.5 This service is TCP-based, so we can use tcp wrappers to control access to it.
Our first step will be to modify inetd.conf to look like the one shown in Listing 12.
Listing 12 Using tcp wrappers in inetd.conf
# echo stream tcp nowait root internal echo dgram udp wait root internal talk dgram udp wait nobody.tty /usr/sbin/in.talkd in.talkd ntalk dgram udp wait nobody.tty /usr/sbin/in.ntalkd in.ntalkd finger stream tcp nowait nobody /usr/sbin/tcpd in.fingerd
This by itself will not control access. Our next step is to create entries in the /etc/hosts.allow and /etc/hosts.deny files to enforce the access controls we want. Our hosts.allow should look like this:
And our hosts.deny should look like this:
After these files are in place, we can restart inetd, and we'll have implemented our policy on one host. We'll still need to go to each host on the IS LAN and make the same set of changes.