Wrap a Security Blanket Around Your Computer

TCP_wrappers provide a simple, elegant and effective means to safeguard your network services.
Installing TCP_wrappers

Every major Linux distribution comes with TCP_wrappers installed as part of the networking package. To see if you have TCP_wrappers installed on your machine, look in the /etc directory for two files called hosts.allow and hosts.deny. These are the configuration files used by the TCP_wrapper daemon, tcpd. You can also look at your /etc/inetd.conf file for lines like this:

telnet stream tcp nowait root /usr/sbin/tcpd \

The telnet option /usr/sbin/tcpd indicates that whenever someone tries to telnet to your machine, he will first connect to the TCP wrapper.

TCP_wrappers is probably on your Linux system, so I won't go into the process of compiling them from scratch in this article. See the sidebar “Where to Get TCP_wrappers” for more information on how to download and install TCP_wrappers.

Configuring TCP_wrappers

As I mentioned above, the TCP_wrappers daemon tcpd gets its instructions on whether to allow or deny access from the two files /etc/hosts.allow and /etc/hosts.deny. tcpd first scans /etc/hosts.allow for “rules” that match the particular service and computer host name, then searches /etc/hosts.deny. If no match is found, access is allowed. By default, most distributions ship TCP_wrappers “Completely Open”, i.e., the files /etc/hosts.allow and /etc/hosts.deny are empty, allowing access to all Internet services on your machine to everyone.

Before you configure TCP_wrappers, you must decide whether you want your machine to be “Mostly Open” or “Mostly Closed”. Mostly Open means that most services are available to most other computers on the Internet; this is useful for blocking access to just a few troublesome sites or to close off one or two services. Mostly Closed means that most services are closed off to most other computers. For personal computers with normal at-home usage, Mostly Closed is probably the way to go, and it is certainly the more secure option.

Let's look at a “Mostly Open” configuration first. Since we are allowing most connections, the /etc/hosts.allow file is left empty. In the /etc/hosts.deny file, let's put in a rule to deny access to telnet and rlogin to anyone coming from the machine nasty.badguy.net and anyone in the domain cracker.org. The requisite line in /etc/hosts.deny would be:

in.telnetd in.rlogind : nasty.badguy.net \

Note the leading “.” in front of cracker.org. It signals tcpd to deny access to any machine in that Internet domain. Since the crackers at these sites probably know how to exploit network services other than telnet and rlogin, you can deny access to all services using the wild card ALL:

ALL : nasty.bad-guy.com .cracker.org
Other wild cards that can replace specific host names include LOCAL, UNKNOWN, KNOWN and PARANOID. LOCAL matches any name without a “.” in it, i.e., host names in your local domain. KNOWN and UNKNOWN refer to hosts either found or not found in the Domain Name Service, respectively. PARANOID matches any host whose name does not match its Internet address. This option is not often used, since the wrappers are compiled to reject access to any host that matches this condition before checking the hosts.allow and hosts.deny files. To allow access to all network services to machines in our local domain, we can put the following line in /etc/hosts.allow:
Now let's look at a “Mostly Closed” configuration. Remember that hosts.allow is checked first, then hosts.deny and, finally, access is allowed only if no match is found in hosts.deny. To close all services to all outside machines, we use the following rule in our hosts.deny file:
In hosts.allow we list only those specific services we want others to use. Of course, we still want to access all of our own services on our own machine. Suppose that we also want to telnet into our machine from a shell account provided by our Internet Service Provider at my.isp.net, and we want to allow anyone to finger our accounts. The rules to put in the /etc/hosts.allow file are:
ALL        : localhost
in.telnetd : my.isp.net
in.fingerd : ALL
Now, if we would also like to keep the crackers from cracker.org from using finger to get information about us, we can modify this:
ALL        : localhost
in.telnetd : my.isp.net
in.fingerd : ALL EXCEPT .cracker.org
As you can see, there is quite a bit of flexibility—but with this flexibility comes the possibility of confusion and, even worse, error. If the configuration files for TCP_wrappers are wrong, you may think you are secure, when in fact you are not. To check your configuration and test its protection, Wietse Venema provided two additional programs: tcpdchk and tcpdmatch.

tcpdchk checks the configuration files for any problems. It can tell if you have used wild cards like ALL or LOCAL incorrectly, if there are nonexistent host names in the access rules, if there are rules for services controlled by tcpd in the /etc/inetd.conf file and much more. For example, the output from tcpdchk for the above Mostly Closed configuration on my machine yielded the following information:

# tcpdchk -v
Using network configuration file: /etc/inetd.conf
>>> Rule /etc/hosts.allow line 6:
daemons:  ALL
clients:  localhost
access:   granted
>>> Rule /etc/hosts.allow line 7:
daemons:  in.telnetd
clients:  my.isp.net
warning: /etc/hosts.allow, line 7: my.isp.net: \
        host not found
access:   granted
>>> Rule /etc/hosts.allow line 8:
daemons:  in.fingerd
clients:  ALL EXCEPT .cracker.org
access:   granted
>>> Rule /etc/hosts.deny line 10:
daemons:  ALL
clients:  ALL
access:   denied

I used the -v switch for tcpdchk to generate more verbose output. Note that the program says my.isp.net was not found, which is perfectly true, since it is a host name made up for this example. Also, note that I did not get a similar message for the equally fictitious .cracker.org. That is because it is for an entire domain, and tcpdchk doesn't check if a domain is registered, but rather if a particular host name is in the DNS.

tcpdmatch tests your configuration against a virtual request for an Internet connection. You provide the name of the daemon and a host name, and it tells you whether that connection would be allowed or denied. For example, if I would like to know if the webmaster at www.linuxjournal.com can finger users on my system, I would enter the following:

# tcpdmatch in.fingerd webmaster@www.linuxjournal.com
client:   hostname www.ssc.com
client:   address
client:   username webmaster
server:   process  in.fingerd
matched:  /etc/hosts.allow line 8
access:   granted

Note that tcpdmatch found the real host name of www.linuxjournal.com to be www.ssc.com and reports its Internet address. The last line tells me that finger is indeed allowed from this host.

In Practical UNIX and Internet Security, Second Edition by S. Garfinkel & G. Spafford, O'Reilly & Associates, 1996, the authors state:

Programs like tcpdchk and tcpdmatch are excellent complements to the security program tcpwrapper, because they help you head off security problems before they happen. Wietse Venema is to be complimented for thinking to write and include them in his tcpwrapper release; other programmers should follow his example.

I wholeheartedly agree.