Enhancing Network Security with tcp_wrapper
Christopher Bush
More than just the Internet concerns the security-minded systems administrator. The same technology that made the Internet what it is - TCP/IP - has now been widely deployed on private LANs, as more companies have realized the benefits of open systems solutions, and software giants have embraced those solutions and technologies in their product offerings. Now, the same vulnerabilities exist on private internal networks, even if they aren't connected to the Internet. It is widely recognized that most computer security breaches result from attacks within an organization. Even if you are connected to the Internet, and protected by a seemingly impenetrable firewall, you still must protect yourself from attack over the network.
So what does a savvy systems administrator do? You can cross your fingers and hope. You can rely on your network administrator to provide strong network security. Both are bad ideas. You should have an overall enterprise security architecture, which consists of many pieces. Developing an overall security strategy is far beyond the scope of this article. I have, however, provided a list of resources that you may wish to consult as you develop a strategy (see sidebar "UNIX Network Security Resources"). In this article, I will present a detailed description of one of the tactical tools that should be included in any plan to provide solid network security on your UNIX systems. That tool is Wietse Venema's tcp_wrapper (sometimes called log_tcp or tcpd). This article covers the basics of installing and using the software, and more information is contained in an accompanying article on the Sys Admin Web site at: www.samag.com.
What Is tcp_wrapper? The tcp_wrapper software provides an extra level of security for network services such as telnet, ftp, tftp, rlogin, and more. Essentially, it is a small daemon program that acts as a "security blanket" for server daemons that provide these network services. The tcp_wrapper daemon, tcpd, does not actually interact directly with either the client or the server for the protected applications. One of the fundamental requirements for using the tcp_wrapper is that your system uses the network service "super daemon", inetd, to start server daemons like telnetd, etc. The tcpd daemon forms an additional layer, or wrapper, between inetd and the application server daemon. See Figure 1.
Under normal, unsecure conditions, inetd listens on several ports for incoming connection requests, and spawns the appropriate application server daemons as necessary. If inetd gets a connection request on TCP port 23, the standard telnet port, it will spawn the telnet daemon (telnetd or in.telnetd), and the connection request will be handed off to that process. The client then communicates directly with that server daemon, freeing inetd to continue listening for other requests. With the tcp_wrapper software installed and configured, inetd will spawn tcpd, which will perform some logging functions through the syslogd(8) daemon, and optionally, will do some access control checking. If access to the requested service is granted, tcpd spawns the "real" network service daemon, and tcpd goes away. The client then communicates directly with the application server daemon. As you can see, once a connection has been established between the client and the protected server daemon, tcpd imposes no additional overhead on that client-server interaction. It does not filter the data exchanged between client and server, or perform any additional checks for that connection.
The security provided by tcpd is two-fold. First, it logs all connection attempts to protected services using the syslog facility. This points out another major requirement of using the tcp_wrapper tool. You need to be running the syslogd(8) daemon, either on the same host or through a centralized loghost server. I consider logging a security feature because without it, you have no record of connection requests in your logs. The basic setup of inetd and the application servers do not provide this logging. A solid audit trail should be an integral part of building and running secure systems. The second security feature of tcp_wrapper is the ability for the tcpd daemon to perform access control. This allows you to selectively accept or reject connection requests before they ever reach the protected service's daemon. That is why it is called a wrapper. It forms a protective layer between the client and server.
In the following sections, I'll discuss how to install and configure the tcp_wrapper software to achieve the logging and access control needed to administer secure network services on your systems.
Downloading and Installing I downloaded the most recent version, tcp_wrapper 7.6, from CERT's web site. CERT (Computer Emergency Response Team) was established by DARPA and based at Carnegie Mellon University in 1988, primarily in response to the now infamous Morris worm. The URL for the tcp_wrapper package is:
http://www.cert.org/ftp/tools/tcp_wrappers/tcp_wrappers_7.6.tar.gz
Once you have downloaded the package, unzip it and extract the tar archive in your source tree. For example, I'll assume you have downloaded the file above to your /usr/local/src directory:
% cd /usr/local/src
% gunzip tcp_wrappers_7.6.tar.gz
% tar -xvf tcp_wrappers_7.6.tar
% cd tcp_wrappers_7.6
You are now ready to compile the source and install it on your system. A Makefile for compilation of the source is included. However, unlike much of the freely available software for UNIX, there is no Configure (or configure) script. If there are any concerns you need to take into account to build the tcp_wrapper package on your version of UNIX, you should edit the Makefile yourself, and judiciously comment or uncomment various lines. The good news is that seemingly every variety of UNIX is supported, and the Makefile is generously commented, making it relatively simple to get going.
To see instructions for the minimal changes you must make, type the command:
% make what
You will see a brief message indicating that you must edit the Makefile and set the REAL_DAEMON_DIR macro to get started. The value you assign to REAL_DAEMON_DIR depends entirely upon how you will install the tcp_wrapper daemon, tcpd. You have two choices for your installation, referred to in the README file accompanying the software as the "easy" and "advanced" installations, respectively. In the easy install, you will move protected server daemons into a separate directory, and replace them in their original location with copies of tcpd, renamed to the same file name as the original daemon. For example, you might move all of the server daemons you will be protecting to usr/sbin/real_daemons.
% mkdir /usr/sbin/real_daemons
% mv /usr/sbin/in.telnetd /usr/sbin/real_daemons
% cp /usr/local/tcp_wrappers_7.6/tcpd /usr/sbin/in.telnetd
You would repeat the last two commands for each daemon you will be protecting. If this is how you intend to use tcp_wrapper, then before building the software, you must edit the Makefile and set REAL_DAEMON_DIR to the location to which you moved the actual server daemons, in this case /usr/sbin/real_daemons. Installing tcp_wrapper this way requires no modification to the configuration file for inetd, /etc/inetd.conf. With this setup, when inetd gets a connection request, it thinks it is still spawning the real server daemon. In reality, you have "faked it" into starting tcpd, which will then start the real server daemon based on the value of REAL_DAEMON_DIR that was compiled in.
I've never been comfortable with this method of installing the tcp_wrapper software. With no changes to /etc/inetd.conf and no daemon named tcpd lying around in /usr/sbin or wherever, it isn't as obvious from an initial system survey that tcpd is in use. This can be troublesome to new systems administrators who are unfamiliar with the systems for which they are responsible. It also can be troublesome for forgetful administrators like me. With this type of installation, if you install a vendor patch that installs a new version of one of the network service daemons, it will replace the fake one (the copy of tcpd) that you have in place. Now, instead of spawning tcpd for this service, inetd will spawn the real server daemon, and any access control and logging you thought you were doing for that service with tcpd will be gone. This is definitely not a good thing.
The second, or "advanced" technique for installing the tcp_wrapper software involves setting REAL_DAEMON_DIR in the Makefile to the same directory as your vendor-supplied network server daemons. In most cases, this is either /usr/sbin, /usr/etc, or perhaps /usr/libexec for BSD systems. In the advanced installation, you leave these network server daemons where they are, install tcpd somewhere (most likely in this same directory), and modify /etc/inetd.conf, so that inetd will spawn tcpd for protected services. I'll cover the modifications to inetd.conf in detail later.
If you are eager to get started, you can make the tcp_wrapper software without ever editing the Makefile. You will be accepting the default settings for all optionally configurable macros, and setting the REAL_DAEMON_DIR macro on the command line. Simply scan the Makefile for the appropriate build target for your UNIX type. Let's say you're building on Linux (congratulations!); you can get going quickly by typing:
% make REAL_DAEMON_DIR=/usr/sbin linux
The software should build easily, leaving the executable files right there in the source directory. I'll assume you are performing the advanced installation and will be editing /etc/inetd.conf, which will be discussed in the next section. For now, you'll want to copy the executables and man pages to the appropriate locations on your system. Copy the tcpd executable to the same directory as your other network daemons - the directory you assigned as a value to REAL_DAEMON_DIR. Copy the man pages (tcpd.8, tcpdmatch.8, tcpdchk.8, hosts_access.5, hosts_options.5) to the appropriate directory. This is usually /usr/local/man. A few very useful utility programs will get built as well. These are tcpdmatch, tcpdchk, try_from, and safe_finger. I copied these to /usr/local/etc. You should put them wherever you like to keep non-vendor administrator utilities. These utilities are discussed in the accompanying Web article mentioned earlier.
You now have a tcp_wrapper installation ready for configuration that is using all of the default options. This should be sufficient for most installations, and I recommend using this build, with the "advanced" installation method, until you are comfortable with configuring and using the software. If at a later time, you wish to explore some of the optional macros in the Makefile, feel free. These macros are also discussed briefly in the accompanying Web article.
Configuring and Using tcp_wrapper Now that tcp_wrapper has been compiled and installed, it's time to get everything else set up and "wrap up" your network services. I will assume you've installed tcpd using the advanced method, so I'll discuss the necessary modifications to /etc/inetd.conf. I'll also assume you are familiar with inetd and the format of the inetd.conf file and limit the discussion to those modifications necessary to use tcp_wrapper.
A typical service in inetd.conf has a line like this for starting the telnet server:
telnet stream tcp nowait root /usr/sbin/in.telnetd in.telnetd
The sixth field is the most important piece for configuring tcp_wrapper. This field is where the path to the server daemon is specified and is where you will make your modification and tell inetd to run tcpd instead. The line above becomes:
telnet stream tcp nowait root /usr/sbin/tcpd in.telnetd
This assumes you have installed tcpd in /usr/sbin. The tcpd daemon will get the real daemon name (in.telnetd in the example above) from the argument field in inetd.conf (the last field), and will spawn that daemon after performing its logging and access control checks. Thus, setting REAL_DAEMON_DIR properly at compile time is very important. tcpd needs to know where to find the real server daemon. Don't worry, though, if you have server daemons in inetd.conf that don't live in this default directory. This may be the case for third party application daemons, license server daemons, or other open source software you may have built. You can specify the full path to the real server daemon right there in inetd.conf. For example:
ftp stream tcp nowait root /usr/sbin/tcpd \ /usr/local/sbin/wu.ftpd -l -i -a
Note that in the above example, there are other command-line arguments related to the start of the real server daemon. They will be passed right along when tcpd starts this daemon.
That's about it for configuring inetd.conf. Make similar changes for each server you wish to protect, and don't forget to send a HUP signal to inetd when you're done.
Once you have tcpd wrapped around your network services, you will start seeing messages being logged through syslog for connection requests. Since we haven't configured any access control rules yet, these should be messages indicating that a connection has been accepted. An example of a typical syslog message from tcpd, telnetd in this case, looks like this:
Jan 17 21:12:03 rocinante in.telnetd[367]: connect from lerxst.bushnet.net
The next step is to configure some access control rules, so you can let the good guys in and keep the bad guys out. There are two files that contain access control rules: /etc/hosts.allow and /etc/hosts.deny. They each contain rules of the following form:
daemon_list : client_list [: shell command]
A complete reference to the access control rule language can be found in the hosts_access(5) man page included with the distribution.
The daemon_list is the list of server daemons to which this rule applies. The client_list is a list of client host names or IP addresses, optionally with user names, to which the rule applies. The optional shell command can be any UNIX command or script to be executed in a spawned shell whenever the rule matches against a particular connection request. Both the daemon_list and client_list can contain multiple items, separated by either whitespace or a comma.
When tcpd receives a connection request, it attempts to find a matching rule by examining these files in a specific order. First, /etc/hosts.allow is searched, sequentially. If a match is found, the connection is allowed, and is handed off to the real server daemon. If no match is found in hosts.allow, tcpd searches for a matching rule in /etc/hosts.deny. If a match is found there, the connection is refused. If no match is found in either file, the connection is implicitly accepted. If either file is missing, or contains no rules, that step in the process is simply ignored. A hosts.deny file with no rules would result in all connections being accepted, regardless of the contents of /etc/hosts.allow.
What tcp_wrapper Can't Do As discussed previously, the tcpd daemon goes away after a connection is established between a client and server. For this reason, it can do nothing to protect daemons that service more than one client at a time, other than to provide access control and logging of the first request. The NFS mount daemon, mountd(8), is a good example of this. The Web server daemon, httpd, is also a poor candidate for protection with tcpd for similar reasons. There may also be server daemons, typically UDP-based ones, that remain running for a time after the client disconnects, either waiting for another message from the same client, or to service another client. Many UDP or RPC/UDP daemons behave this way. One example of such a service is the talk service, in.talkd(8). Typically, services that use the wait flag in the inetd.conf file are like this. Again, you may only realize the benefits of tcp_wrapper with these services on the initial client request that resulted in the server daemon being spawned. With these restrictions in mind, feel free to use tcpd for whatever other services spawned normally by inetd that you feel necessary.
Security Architecture The tcp_wrapper software should be just one tool you use in implementing an overall security strategy. That strategy should also include a firewall if you are connected to the Internet, physical security for your people and systems, host and filesystem security, password control and administration, and perhaps even encryption. These should be backed by a concisely documented and enforceable security policy that all employees or members of your organization have read, understood, and agreed to. Detailing such a strategy and accompanying policy is far beyond the scope of this article. The sidebar contains a brief list of resources that should prove invaluable to you as you seek the tools and information you need to create and implement an enterprise-wide security architecture.
Instead, I have shown you the ins and outs of a particular tool that, while just one small piece of the puzzle, is an important piece. The tcp_wrapper package can be configured a number of different ways, making it adaptable to just about any network security policy.
Depending on your organization and the services you provide on your systems, you may find yourself implementing one of two diametrically opposed security policies. The first says, "That which is not explicitly allowed is denied." This is either an extremely paranoid approach (not necessarily a bad thing), or one for specialized systems where you know exactly who needs access to your system(s), and from where they will be connecting. Many Internet Web hosting service companies will do this with telnet and ftp services on their publicly accessible Web servers. They need to provide telnet and ftp access to the customer's Webmaster, so she can manage the content on the site. But only that person should ever have need for those services. On the other hand, the world at large should have http/https access (if it's a public Web site). It simply isn't possible to just put the Web server behind a firewall or filtering router and deny all incoming TCP connections. It wouldn't make for a very successful Web site. By using tcp_wrapper on the Web server, the hosting company can provide a reasonably secure way for the customer's Webmaster to manage the site, while allowing the general public to browse the site's content. See the accompanying Web article for more information on Web server usage.
Conclusion The tcp_wrapper software is clearly a powerful tool that should be part of any security implementation. You cannot afford to rely solely on one or two utilities cobbled together on a few key systems, though. Security requires a rigorous, disciplined approach that is clearly documented, and proactively managed. Don't just implement tcp_wrapper on a couple of your systems. And, don't ignore the access control capabilities just because you're behind a firewall and think all the people in your organization are trustworthy. That guard at the farm gate will do you no good if the fox has been hired to work at the hen house.
Consider also how tcp_wrapper will complement, or interact with, other security tools you use. Also consider ways in which you can make tcp_wrapper easier to administer. Heavily used systems will result in copious amounts of logging to your syslog daemon. If you have a lot of systems, you may want to centralize syslog activity onto one single host, the loghost. If so, that may mean only one or two primary log files to scan, but they will also be much larger. A useful utility that I think complements tcp_wrapper nicely is called swatch, available from:
ftp://ftp.stanford.edu/general/security-tools/swatch
The swatch utility, written in Perl, is a handy tool for scanning system logs for desired patterns. Results of scans can be emailed, or a shell script can be triggered, enabling you to send pages or whatever other kind of alerting you may be able to script. There is a multitude of other freely available security tools you'll want to have a look at also. Visit:
http://www.stanford.edu/group/itss-ccs/ \ security/Bestuse/software.html
for a good list.
COPS is another utility that complements tcp_wrapper. COPS will report on the internal integrity of your system, including alerting you to files that have changed since a baseline checkpoint. If your system has been compromised through some other means, and your /etc/hosts.allow or /etc/hosts.deny files have been modified, you'll want to know about it as soon as possible. COPS is one way to do that.
Security is a big part of systems administration. Depending upon the number of systems you are responsible for, it can also be a big problem. Take advantage of tools like tcp_wrapper, and implement them wisely and uniformly, and in conjunction with an overall strategy that includes other tools. You'll sleep better at night, as will your users, knowing that everything is safe and sound.
About the Author
Chris Bush is a Programmer Analyst for a major mid-west bank in Cleveland, Ohio. He does Web site management, Web development, Internet/Intranet architecture, UNIX systems administration, and dabbles with Linux at home in his spare time. He can be reached at chris.bush@stratos.net.
|