TCP wrappers are intended to provide wrapper daemons that can be installed without any changes to existing software. Most TCP/IP applications depend on the client/server model -- i.e., when a client requests a connection, a server process is started on the host. TCP wrappers work by interposing an additional layer, or wrapper, between client and server.
In the basic service, the wrapper simply logs the name of the client host and requested service, then hands this information over to the real daemon; it neither exchanges information with the client or server nor imposes overhead on the actual conversation between the two. Optional features may be enabled, including access control, client-user name lookups, and additional protection against hostname spoofing.
(The current version of the software, 7.6, can be obtained via FTP. See the Resources section below for the URL.)
Compilation
Many Unix flavors are supported by TCP wrappers, so you shouldn't have any trouble building from source. There are, however, a few decisions to make at compile time. Features, for example, can be turned on or off through definitions. Here is a list, with default values shown where appropriate:
STYLE = -DPROCESS_OPTIONS : |
Enable language extensions. This is disabled by default. |
FACILITY = LOG_MAIL : |
Where do log records go? I prefer to set this to LOG_DAEMON so that everything goes to /var/log/daemon . |
SEVERITY = LOG_INFO : |
Indicates what level to give to the log message. The default, LOG_INFO , is fine. |
HOSTS_ACCESS : |
When compiled with this option, wrapper programs support a simple form of access control. Because this is the raison d'être of the suite, it's defined by default. |
PARANOID : |
When compiled with -DPARANOID , wrappers will always try to look up and double-check the client hostname, and will always refuse service in the case of a discrepancy between hostname and IP address. This is a reasonable policy for most systems. When compiled without -DPARANOID , wrappers still perform hostname lookup; however, where such lookups give conflicting results for hostname and IP address, hosts are not automatically rejected. They can be matched with the PARANOID wildcard in the access files, and a decision is made on whether or not to grant access. |
DOT = -DAPPEND_DOT : |
This appends a dot to every domain name -- transforming example.com into example.com. for instance. This is done because on many Unix systems the resolver will append substrings of the local domain and try to look up those hostnames before trying to resolve the name it has actually been given. Use of the APPEND_DOT feature stops this waste of time and resources. It is off by default. |
AUTH = -DALWAYS_RFC931 : |
Will cause the system to always try to look up the remote username. For this to be of any use, the remote host must run a daemon that supports the finger protocol. Such lookups aren't possible for UDP-based connections. By default, this is turned off and the wrappers look up the remote username only when the access control rules specify such behavior. |
RFC931_TIMEOUT = 10 : |
Sets the username lookup timeout. |
-DDAEMON_UMASK = 022 : |
This is the default file permissions mask for processes run under the control of the wrappers. |
ACCESS = -DHOSTS_ACCESS : |
Sets host access control. This feature can also be turned off at runtime by providing no, or empty, access control tables. Enabled by default. |
TABLES = -DHOSTS_DENY=\"/etc/hosts.deny\" --DHOSTS_ALLOW=\"/etc/hosts.allow\" : |
Sets the pathnames for the access control tables. |
HOSTNAME = -DALWAYS_HOSTNAME : |
Sets the system to always attempt to look up the client hostname. If this is disabled, the client hostname lookup is postponed until the name is required by an access control rule or by a %letter expansion. If this is what you want, note that PARANOID mode must be disabled as well. This is on by default. |
-DKILL_IP_OPTIONS : |
This is for protection against hosts that pretend they have someone else's host address --i.e., host address spoofing. This option isn't needed on modern Unix systems that can stop source-routed traffic in the kernel -- e.g., Linux, Solaris 2.x, 4.4 BSD and derivatives. |
-DNETGROUP : |
Determines whether or not your system has NIS support. This is used only in conjunction with host access control, so if you're not using that, don't bother about this in any case. Off by default. |
Some definitions are given that work around system bugs (just the basics here; see makefile
for details). The standard define is BUGS = -DGETPEERNAME_BUG -DBROKEN_FGETS - DLIBC_CALLS_STRTOK
.
Having set the options to your requirements, type make sys-type
, with sys-type
being one of the following:
generic
(includes most bsd-ish systems that have sys5 compatibility)
386bsd
aix
alpha
apollo
bsdos
convex-ultranet
dell-gcc
dgux
dgux543
dynix
epix
esix
freebsd
hpux
irix4
irix5
irix6
isc
iunix
linux
machten
mips<(untested)
ncrsvr4
netbsd
next
osf
power_unix_211
ptx-2.x
ptx-generic
pyramid
sco
sco-nis
sco-od2
sco-os5
sinix
sunos4
sunos40
sunos5
sysv4
tandem
ultrix
unicos7
unicos8
unixware1
unixware2
uts215
uxp
In the unlikely event that none of these match your system, you'll have to edit the system dependencies sections in the makefile and do a make other
.
There are two ways to install the software -- the easy way and the advanced way.
Easy installation
The easy recipe requires no changes to existing software or configuration files. Basically, you move the daemons you want to protect to the directory specified in REAL_DAEMON_DIR
in the makefile, replacing them with copies of the tcpd
program. For example, for Telnet:
$ mkdir REAL_DAEMON_DIR $ mv /sbin/in.telnetd REAL_DAEMON_DIR $ cp tcpd /sbin/in.telnetd
That's all there is to it. Note that the wrapper, all files used by the wrapper, and all directories in the path leading to those files should all have read-only, or read-and-execute only, access. They must not be writable, so use modes 755 or 555. There is no need for the wrapper to be set-uid
.
Advanced installation
The advanced installation method leaves your existing daemons alone, but involves simple modifications to the inetd
configuration file, /etc/inetd.conf
. This is the model I prefer because changes to it are straightforward. For each service to be protected by wrappers, tcpd
should be executed in place of the original daemon, passing the original daemon pathname as an argument to tcpd
. An example will make this more clear.
Here is a standard inetd.conf
record for Telnet service:
telnet stream tcp nowait root /sbin/in.telnetd /sbin/in.telnetd
And here is the same record after modification to support TCP wrappers:
telnet stream tcp nowait root /sbin/tcpd /sbin/in.telnetd
After editing this file, remember to tell inetd
to reread it with kill -1
.
Access control
The core idea behind TCP wrappers is that of an access control policy. The policy rules are held in two files: /etc/hosts.allow
and etc/hosts.deny
. These are the default pathnames, which can be changed in the makefile.
Access can be controlled per host, per service, or in combinations thereof. Access control can also be used to connect clients to particular services, depending on the requested service, the origin of the request, and the host address to which the client connects. For example, a www
daemon might be set to serve documents in French when contacted from within the France, but otherwise respond in English.
The format of these files is described in detail by hosts_access(5)
. Basically, each file consists of a set of rules, which are searched for first in hosts.allow
and then hosts.deny
. The search stops at the first match, so if a host is granted access in host.allow
it doesn't matter if it's then blocked in hosts.deny
. Remember, the first rule matched determines what action the system will take.
There are two basic keywords, allow
and deny
. Both are used in conjunction with either specific hostnames or a wildcard from the list below.
A string beginning with .
matches all hostnames that conclude with that string. For example, .example.com
would match dunne.example.com
. A string ending with .
matches all hosts whose IP addresses begin with that sequence. For example, 192.168.
would match all addresses in the range 192.168.xxx.xxx
. A string beginning with @
is treated as an NIS netgroup name. A string of the form n.n.n.n/m.m.m.m
is treated as a network/mask pair.
There are also some special shorthand names:
ALL
: Always matches
LOCAL
: Matches any host whose name doesn't contain a dot character
UNKNOWN
: Matches a user whose name is unknown, and matches any host whose name or address is unknown
KNOWN
: Matches a user whose name is known, and matches any host whose name and address is known
PARANOID
: Matches any host whose name doesn't match its address
There is also a set of symbolic names that expand to various information about the client and server. The full list of such expansions is shown in the table below.
%a |
The client IP address |
%c |
Client information: user@host, user@IP, etc |
%d |
argv[0] from the daemon process |
%h |
Client host name or IP address |
%n |
Client host name |
%p |
Process id of the daemon |
%s |
Server information |
%u |
Client username |
%% |
Literal % |
Examples
There are several typical forms of access control that provide examples of using the access control files. Explicitly authorized hosts are listed in hosts.allow
, while most other rules are put in hosts.deny
.
To deny all access, leave hosts.allow
blank and put this in hosts.deny
.
/etc/hosts.deny: ALL: ALL
To allow all access, simply leave both files blank. To allow controlled access, add rules to hosts.allow
and hosts.deny
as appropriate. The simplest way to do this is to list banned sites in hosts.deny
.
/etc/hosts.deny: evilcrackers.com: ALL
On the other hand, you can also deny access to all save selected sites:
/etc/hosts.allow: example.com: ALL /etc/hosts.deny: ALL:ALL
Remember, the first match is the important one -- the ALL
in hosts.deny
won't block example.com
.
Booby traps
A useful feature is the ability to trigger actions on the host which are based on attempted connections. For example, should you detect a remote site attempting to use your TFTP server, the following rule in /etc/hosts.deny
not only rejects the attempt, but notifies the system administrator:
in.tftpd: ALL: finger -l @%h 2>&1 | mail -s 'remote tftp attempt' sysadm
Note that use of this feature relies on the PROCESS_OPTIONS
option. This option also provides some other useful features:
spawn <shell_command>
-- Run the specified shell command as a child process.
twist <shell_command>
-- Replace the current process by the specified shell command.
banners <pathname>
-- Copy the contents of the file in<pathname>
to the client. This is useful for sites that are required to display a site policy banner to all users.
See the host_options(5)
man page for full details of these and other options.
Logging
Log records are written to the syslog daemon, syslogd
, with facility and level as specified in the makefile at compile time. What happens to the logs there is determined by the syslogd
config file, /etc/syslog.conf
. If PROCESS_OPTIONS
has been defined, the facility and level can be changed at runtime, using the keyword severity
. For example severity mail.info
specifies logging with facility mail
at level info
. An undotted argument is understood as a level.
Conclusion
In this article, I've shown you how to install and configure TCP wrappers in order to protect against common attempts to compromise a Unix box connected to the Internet. There are several advantages to using this software:
- There is no need to modify existing daemons
- Only simple (and optional) changes to one existing configuration file are necessary
- There is no impact on genuine users
- It provides protection against a variety of cracking techniques
- It provides the ability to install trip wires that notify of an attempted break-in
A good account of the thinking that led to the creation of the TCP wrappers is the paper "TCP Wrapper: Network Monitoring, Access Control, and Booby Traps," which is available from the same FTP site as the TCP wrappers software. Look for tcp_wrapper.<format>.Z
.
- Version 7.6 of the TCP wrappers software:
ftp://ftp.porcupine.org/pub/security/
This story, "Securing your network: An introduction to TCP wrappers" was originally published by ITworld.