|
Softpanorama
(slightly skeptical)
Open Source Software Educational Society |
May the
source be with you,
but remember the KISS principle ;-)
|
TCP Wrappers
Lecture Notes
Based on O'Reilly Practical Unix Security book
Intetd "superdaemon"
Originally, BSD Unix set a different server program running for
every network service. As the number of services grew in the mid 1980s, Unix systems
started having more and more server programs sleeping in the background, waiting
for network connections. Although the servers were sleeping, they nevertheless consumed
valuable system resources such as process table entries and swap space. Perhaps
more importantly, configuring these servers was somewhat difficult, as each server
was started up in a different way and had a different syntax for defining which
port they should bind to and which UID they should use when running.
Today's Unix systems use the Internet daemon,
inetd, to centralize the handling of lightweight
Internet services. The Internet daemon listens and accepts connections on many network
ports at the same time. When a connection is received,
inetd automatically starts up the appropriate TCP-based or UDP-based server
running under the appropriate UID. The Internet daemon also simplifies the writing
of application-specific daemons themselves, as each daemon can be written so that
it reads from the network on standard input and writes back to the network
on standard output—no special calls from the Berkeley socket library are
required.
The inetd daemon is run at boot
time as part of the startup procedure. When inetd
starts executing, it examines the contents of the /etc/inetd.conf file to
determine which network services it is supposed to manage. The program will reread
its configuration file if it is sent a HUP signal
A sample inetd.conf file
# Internet server configuration database
#
ftp stream tcp nowait root /usr/sbin/ftpd ftpd
#telnet stream tcp nowait root /usr/sbin/telnetd telnetd
#shell stream tcp nowait root /usr/sbin/rshd rshd
#login stream tcp nowait root /usr/sbin/rlogind rlogind
#exec stream tcp nowait root /usr/sbin/rexecd rexecd
#uucp stream tcp nowait uucp /usr/sbin/uucpd uucpd
#finger stream tcp nowait nobody /usr/sbin/fingerd fingerd
#tftp dgram udp wait nobody /usr/sbin/tftpd tftpd
#comsat dgram udp wait root /usr/sbin/comsat comsat
talk dgram udp wait root /usr/sbin/talkd talkd
ntalk dgram udp wait root /usr/sbin/ntalkd ntalkd
#echo stream tcp nowait root internal
#discard stream tcp nowait root internal
#chargen stream tcp nowait root internal
#daytime stream tcp nowait root internal
#time stream tcp nowait root internal
#echo dgram udp wait root internal
#discard dgram udp wait root internal
#chargen dgram udp wait root internal
#daytime dgram udp wait root internal
#time dgram udp wait root internal
Each line of the inetd.conf file contains at least six
fields, separated by spaces or tabs:
- Service name
-
Specifies the service name that appears in the /etc/services
file. inetd uses this name to determine which
port number it should listen to. If you are testing a new service or developing
your own daemon, you may wish to put that daemon on a nonstandard port. Unfortunately,
inetd requires that the service name be a symbolic
value such as smtp, rather than a numeric value such as 25.
- Socket type
-
Indicates whether the service expects to communicate via
a stream or on a datagram basis.
- Protocol type
-
Indicates whether the service expects to use TCP- or UDP-based
communications. TCP is used with stream sockets, while UDP is used with
dgram, or datagrams.
- Wait/nowait
-
If the entry is "wait," the server is expected to process
all subsequent connections received on the socket. If "nowait" is specified,
inetd will fork(
) and exec( ) a new server process for
each additional datagram or connection request received. Most UDP services are
"wait," while most TCP services are "nowait," although this is not a firm rule.
Although some manpages indicate that this field is used only with datagram sockets,
the field is actually interpreted for all services.
- User
-
Specifies the UID that the server process will be run as.
This can be root (UID 0),
daemon (UID 1), nobody
(often UID -2 or 65534), or any other user of your system. This field allows
server processes to be run with fewer permissions than
root to minimize the damage that could be done
if a security hole is discovered in a server program.
- Command name and arguments
-
The remaining arguments specify the command name to execute
and the arguments passed to the command, starting with
argv[0].
Some services, like echo,
time, and discard,
are listed as "internal." These services are so trivial that they are handled internally
by inetd rather than requiring a special program
to be run. Although these services are useful for testing, they can also be used
for denial of service attacks. You should therefore disable them.
You should routinely check the entries in the /etc/inetd.conf
file and verify that you understand why each of the services in the file is being
offered to the Internet. Sometimes, when attackers break into systems, they create
new services to make future break-ins easier. If you cannot explain why a service
is being offered at your site, you may wish to disable it until you know what purpose
it serves. In many circumstances, it is better to disable a service that you are
not sure about than it is to leave it enabled in an effort to find out who is using
it at a later point in time: if somebody is using the service, they are sure to
let you know! One easy way to list all of the services that are enabled is:
% grep -v "^#" /etc/inetd.conf
talk dgram udp wait root /usr/sbin/tcpd in.talkd
ntalk dgram udp wait root /usr/sbin/tcpd in.ntalkd
pop-3 stream tcp nowait root /usr/sbin/tcpd popper -c -C -p 2
auth stream tcp nowait nobody /usr/sbin/tcpd identd -o -E -i
Because of the importance of the /etc/inetd.conf file,
you may wish to track changes to this file using a source code control system such
as RCS or CVS. You may also wish to use a consistency-checking tool such as Tripwire
or detached PGP signatures to verify that all changes to the file are authorized
and properly recorded.
The idea of TCP Wrappers as controlling layer for Inetd
TCP Wrappers is a package developed by Wietse Venema (who also wrote the SATAN
security package) at the Eindhoven University of Technology as a countermeasure
against attacks on their university systems. TCP_wrappers is an IP packet filtering
and network access logging facility for inetd. TCP_wrappers is usually configured
to "wrap" itself around TCP-based services defined in
inetd.conf.
Tcp Wrappers is a single program called "tcpd". Unfortunately, it is distributed
under the plural name of "TCP wrappers". It is a program and 2 configuration
files. Paraphrased from the readme: With this package you can monitor and filter
incoming requests for the SYSTAT, FINGER, FTP, TELNET, RLOGIN, RSH, EXEC, TFTP,
TALK, and other network services. The package provides a tiny daemon wrapper program
that can be installed without any changes to existing software or to existing configuration
files. The wrapper reports the name of the client host and of the requested service;
the wrapper does not exchange information with the client or server applications,
and imposes no overhead on the actual conversation between the client and server
applications. Optional features are: access control to restrict what systems can
connect to what network daemons; client user name lookups with the RFC 931 etc.
protocol; additional protection against hosts that pretend to have someone elses
host name; additional protection against hosts that pretend to have someone else's
host address.
The TCP Wrappers program can log incoming connections via
syslog—whether or not the actual Internet daemon
provides logging. TCP Wrappers also allows different server executables to be invoked
for a given service depending on the source IP address of the incoming connection.
While TCP Wrappers can be run as a standalone program, today
it is most commonly used as a library (libwrap)
that is linked into the inetd program. By using
a modern inetd program, your system will automatically
honor the /etc/hosts.allow and /etc/hosts.deny files, which are described
later.
Tcp_wrappers are designed to verify a remote hostname with its IP number before
allowing a connection to be established. If a workstation's IP number and hostname
do not match when checked against the domain tables maintained by the Internet Service
Provider providing Internet connectivity for that workstation, tcp_wrappers will
close the session before the user enters a username or password. The
original tcp_wrappers work in tandem with inetd can can control all programs
launched by
inetd
like telnet and ftp using the hosts.allow
& host.deny
files. If you only want trusted networks/machine to be able to start
telnet, you just add them into
hosts.allow
and turn off everyone else with
hosts.deny.
TCP wrappers can monitor and filter
incoming requests for telnet, ftp, rlogin, rsh, finger, talk, and just about anything
else that run out of inetd.conf.
Original telnetd line in
inetd.conf.
telnet stream tcp nowait root in.telnetd in.telnetd
With TCP wrappers installed:
telnet stream tcp nowait root /usr/sbin/tcpd in.telnetd
When a remote host accesses a "wrapped" service, the connection has to first
go through the logging and access control mechanisms enforced by tcp_wrappers before
it is allowed to proceed.
There are several reasons why tcp_wrappers is an excellent security tool:
- If you must allow
network access to particular machine, you can use the improved access logging
facility provided by tcp_wrappers even for services (such as rlogin) which
traditionally do not have a good logging mechanism. These logs are extremely
useful in tracking unauthorized break-ins.
- You can have fine-grained
control over who can and cannot access Unix boxes that belong to "critical
infrastructure". Access control can be enforced differently for each wrapped
service. For example, you can limit Telnet access to a specific subnet but
allow wide open access for FTP (with improved logging).
The way to limit 'inetd' programs like telnet and ftp is with tcpwrappers using
the hosts.allow & host.deny files. If you only want trusted networks/machine to
be able to start telnet, you add them into hosts.allow and turn off everyone else
with hosts.deny. Linux Journal had a good article in a security issue a year or
so ago that I recommend. You can also limit users to ftp with the /etc/ftpusers
file. As for the shut down, I usually set up a shutdown group and set up scripts
to to call shutdown for the members.
The tcpd program can be set up to monitor incoming requests for
telnet, finger, ftp, exec, rsh,
rlogin, tftp, talk, comsat and
other services that have a one-to-one mapping onto executable files.
Operation is as follows: whenever a request for service arrives, the inetd
daemon is tricked into running the tcpd program instead of the normal server.
tcpd logs the request and does some additional checks. When all is well,
tcpd runs the appropriate server program and goes away.
Optional features include pattern-based access control, client username lookups
with the RFC 931 protocol, protection against hosts that pretend to have someone
else's host name, and protection against hosts that pretend to have someone else's
network address.
Utilities (tcpdchk and tcpdmatch) are included to aid writing of
/etc/hosts.allow and /etc/hosts.deny files. tcpdmatch
does not understand '?' syntax in /etc/inet.conf, so it
may generate spurious warnings noting that optional servers were not found.
What TCP Wrappers does
The TCP Wrappers system gives the system administrator a high
degree of control over incoming TCP connections. The system is invoked after a remote
host connects to your computer. It is invoked either through a subroutine library
that is linked into the Internet server or through a standalone program started
up through inetd. Once running, the TCP Wrappers
system performs the following steps:
-
It opens the /etc/hosts.allow file. This file contains
access control rules and actions for each protocol.
-
It scans through the file, line by line, until it finds a
rule that matches the particular protocol and source host that has connected
to the server.
-
It executes the action(s) specified in the rule. If appropriate,
control is then turned over to the network server.
-
If no matching action is found, the file /etc/hosts.deny
is opened and sequentially read line by line. If a matching line is found,
access is denied and the corresponding action performed.
-
If no match is found in either the /etc/hosts.allow
or the /etc/hosts.deny file, then the connection is allowed
by default.
If this seems overly complicated to you, you are right—it is.
The reason for having two files, /etc/hosts.allow and /etc/hosts.deny,
is to allow for backward compatibility with previous versions of TCP Wrapperss that
did not provide for different kinds of actions on each line of the file. These earlier
versions simply had a list of allowed hosts for each protocol in the file /etc/hosts.allow
and a list of hosts to deny for each protocol in the file /etc/hosts.deny.
These days, TCP Wrapperss is compiled with the -DPROCESS_OPTIONS option, which
causes the advanced rules to be properly interpreted. Unfortunately, as is often
the case, the complexity of having two incompatible modes of operation remains to
allow for backward compatibility.
|
!
|
Your /etc/hosts.deny should contain only
a single rule "ALL:ALL" to deny all access by default. Keeping all
the rules in a single file simplifies maintenance. Using /etc/hosts.allow,
which has priority over /etc/hosts.deny, ensures that if
someone else accidentally modifies the wrong file, it won't override
your rules.
|
|
The actions implemented by TCP Wrappers are quite sophisticated.
Specifically, options can:
-
Compare the incoming hostname and requested service with
an access control list to see if this host or this combination of host and service
has been explicitly denied. If either is denied, TCP Wrappers drops the connection.
-
Log the results with syslog.
-
Use the ident protocol (RFC
1413) to determine the username associated with the incoming connection. RFC
1413 superseded RFC 931, but the define in
the code has not changed.
-
Optionally send a "banner" to the connecting client. Banners
are useful for displaying legal messages or advisories.
-
Optionally run an auxiliary command. (For example, you can
have TCP Wrappers run finger to get a list
of users on a computer that is trying to contact yours.)
-
Perform a double reverse lookup of the IP address, making
sure that the DNS entries for the IP address and hostname match. If they do
not, this fact is logged. (By default, TCP Wrappers is compiled with the -DPARANOID
option, so the program will automatically drop the incoming connection if the
two do not match under the assumption that something somewhere is being hacked.)
-
Pass control of the connection to the "real" network daemon,
or pass control to some other program that can take further action.
The TCP Wrappers system allows you to make up for many deficiencies
in other network daemons. You can add logging to services that are not otherwise
logged, add sophisticated and easily changeable access control lists, and even substitute
different versions of a service daemon depending on the calling host. These are
some of the reasons that the TCP Wrappers system has become standard on both free
and commercial Unix offerings in recent years.
The TCP Wrappers configuration language
The TCP Wrappers system has a simple but powerful language and
a pair of configuration files that allow you to specify whether incoming connections
should be accepted.
If TCP Wrappers is compiled with
the -DPROCESS_OPTIONS flag, then each line of the /etc/hosts.allow and
/etc/hosts.deny files have the following format:
daemon_list : client_host_list : option [ : option ...]
Alternatively, if TCP Wrappers is compiled without the -DPROCESS_OPTIONS flag,
then each line in the /etc/hosts.allow and /etc/hosts.deny files has
the following format:
daemon_list : client_host_list [: shell_command]
in which:
- daemon_list
-
Specifies the command name (argv[0])
of a list of TCP daemons (e.g., telnetd). More
than one daemon can be specified by separating them with blanks or commas. The
reserved keyword "ALL" matches all daemons; "ALL EXCEPT" matches all daemons
except for the specific one mentioned (e.g., "ALL EXCEPT
in.ftpd").
- client_host_list
-
Specifies the hostname or IP address of the incoming connection.
More than one host can be specified by separating them with blanks or commas.
Incomplete hostnames and IP addresses can be used for wildcarding . You can
also use the format username@hostname to specify
a particular user on a remote computer, although the remote computer must correctly
implement the ident protocol. And as we noted in the discussion of
ident, the identification returned is not something
that can always be believed. The keyword ALL matches all clients; for a full
list of keywords, see the table.
- option [ : option ...]
-
Specifies one or more options that are executed for the particular
service.
- shell_command
-
Specifies a command that should be executed if the
daemon_list and client_host_list are matched. A
shell_command can be specified directly in the /etc/hosts.allow
or /etc/hosts.deny file if TCP Wrappers is compiled without the -DPROCESS_OPTIONS
flag. If TCP Wrappers is compiled with the -DPROCESS_OPTIONS flag, shell commands
must be specified with the spawn option. A
limited amount of token expansion is available within the shell command;
Syntax for the "hosts" field in the tcpwrappers
/etc/hosts.allow and /etc/hosts.deny files
|
Hostname as it appears in the /etc/hosts.allow or
/etc/hosts.deny file
|
Has the following effect
|
|
ALL
|
Matches all hosts.
|
|
KNOWN
|
Matches any IP address that has a corresponding hostname;
also matches usernames when the ident service
is available.
|
|
LOCAL
|
Matches any host that does not have a period (.) in its
name.
|
|
PARANOID
|
Matches any host for which double reverse-hostname/IP
address translation does not match.
|
|
UNKNOWN
|
Matches any IP address that does not have a corresponding
hostname; also matches usernames when the ident
service is not available.
|
|
host.domainhost.subdomain
|
Matches the specific hostname.
|
|
.subdomain.domain
|
If the hostname begins with a period (.), the hostname
will match any host whose hostname ends with the hostname (in this case,
".subdomain.domain").
|
|
111.222.333.444
|
Matches the specific IP address
111.222.333.444, for example 10.1.1.1
|
|
kkk.lll.mmm.
kkk.lll.
kkk.
|
If the hostname ends with a period (.), the hostname
is interpreted as the beginning of an IP address. The string "18." will
match any host with an IP address of 18.0.0.1 through 18.255.255.254. The
string "192.168.1." will match any host with an IP address of 192.168.1.0
through 192.168.1.255.
|
|
a pattern EXCEPT
another pattern
|
Matches any host that is matched by
a pattern except those that also match
another pattern.
|
Options available for TCP Wrappers when compiled
with -DPROCESS_OPTIONS
|
Option
|
Effect
|
|
allow
|
Allows the connection.
|
|
deny
|
Denies the connection.
|
|
Options for dealing with sub-shells
|
|
nice ±nn
|
Changes the priority of the process to ±nn.
Use numbers such as +4 or +8 to reduce the amount of CPU time allocated
to network services.
|
|
setenv name value
|
Sets the environment variable name to
value for the daemon.
|
|
spawn shell_command
|
Runs the shell_command. The streams stdin,
stdout, and stderr are connected to /dev/null to avoid conflict with
any communications with the client.
|
|
twist shell_command
|
Runs the shell_command. The streams stdin,
stdout, and stderr are connected to the remote client. This allows you to
run a server process other than the one specified in the file /etc/inetd.conf.
(Note: this will not work with most UDP services.)
|
|
umask nnn
|
Specifies the umask that should be used for
sub-shells. Specify it in octal.
|
|
user username
|
Assumes the privileges of username. (Note:
TCP Wrappers must be running as root for
this option to work.)
|
|
user username.groupname
|
Assumes the privileges of username and
sets the current group to be groupname.
|
|
Options for dealing with the
network connection
|
|
banners /some/directory/
|
Specifies a directory that contains banner files. If
a filename is found in the banner directory that has the same name as the
network server (such as telnetd), the contents
of the banner file are sent to the client before the TCP connection is turned
over to the server. This process allows you to send clients messages—for
example, informing them that unauthorized use of your computer is prohibited.
|
|
keepalive
|
Causes the Unix kernel to periodically send a message
to a client process; if the message cannot be sent, the connection is automatically
broken.
|
|
linger seconds
|
Specifies how long the Unix kernel should spend trying
to send a message to the remote client after the server closes the connection.
|
|
rfc931 [timeout in seconds]
|
Specifies that the ident
protocol should be used to attempt to determine the username of the person
running the client program on the remote computer. The timeout,
if specified, is the number of seconds that TCP Wrappers should spend waiting
for this information.
|
Token expansion available for the TCP Wrappers shell
command
|
Token
|
Mnemonic
|
Expands to
|
|
%a
|
Address
|
The IP address of the client
|
|
%A
|
Address
|
The IP address of the server (useful if the server system
has more than one network interface)
|
|
%c
|
Client info
|
username@hostname (if
username is available); otherwise, only hostname or IP address
|
|
%d
|
Daemon name
|
The name of the daemon (argv[0])
|
|
%h
|
Hostname
|
The hostname of the client (IP address if hostname is
unavailable)
|
|
%H
|
Hostname
|
The hostname of the server (IP address if hostname is
unavailable)
|
|
%p
|
Process
|
The process ID of the daemon process
|
|
%s
|
Server info
|
daemon@host
|
|
%u
|
User
|
The client username (or unknown)
|
|
%%
|
Percent
|
Expands to the "%" character
|
Theoretically the TCP Wrappers are vulnerable to IP spoofing
because it uses IP addresses for authentication. In practice, this
is not a significant concern, because TCP protocols as a rule require
bidirectional communications to do anything useful. Furthermore,
most TCP/IP implementations now use unpredictable sequence numbers,
significantly reducing the chances of a successful spoofing attack.
TCP Wrappers also provides only limited support
for UDP servers, because once the server is launched, it will continue
to accept packets over the network, even if those packets come from
"blocked" hosts, unless the UDP server is linked with the TCP Wrappers
library and has been specially written to consult the TCP Wrappers
access control lists after each new request is received.
Making sense of your TCP Wrappers configuration
files
The configuration files we have shown so far are simple; unfortunately,
sometimes things get more complicated. The TCP Wrappers system comes with a utility
called tcpdchk that can scan through your configuration
file and report on a wide variety of potential configuration errors. This is important
because the TCP Wrappers system relies on many configuration files (/etc/services,
/etc/inetd.conf, /etc/hosts.allow, and /etc/hosts.deny) and
requires that the information between these files be consistent.
Here is an example of using the tcpdchk
program; each line in this example represents a potential security problem:
% tcpdchk
warning: /etc/hosts.allow, line 24: ipop3d: no such process name in /etc/inetd.conf
warning: /etc/hosts.allow, line 39: sshd: no such process name in /etc/inetd.conf
We'll explore these "warnings" one at a time.
The first line of output refers us to line 24 of the file
/etc/hosts.allow, which is shown here:
ipop3d : ALL : ALLOW
To understand the error no such process name in /etc/inetd.conf,
we need to now refer to the file /etc/inetd.conf. This file has a line for
the ipop3d daemon, but as the warning from
tcpdchk implies, the process is not named
ipop3d—it is named popper:
# example entry for the optional pop3 server
#
------------------------------
pop3 stream tcp nowait root /usr/local/libexec/ipop3d popper
We must either change line 24 to refer to the process name
popper, or change the entry in /etc/inetd.conf
to use the name ipop3d. We'll change the file
/etc/hosts.allow and rerun the tcpdchk program.
Here is the new line 24:
popper : ALL : ALLOW
Now let's rerun the tcpdchk
program:
r2# tcpdchk
warning: /etc/hosts.allow, line 24: popper: service possibly not wrapped
warning: /etc/hosts.allow, line 39: sshd: no such process name in /etc/inetd.conf
r2#
We are now told that the service is "possibly not wrapped." This
is because tcpdchk is reading through the /etc/inetd.conf
file and looking for "tcpd," the name of the TCP Wrappers executable. Because support
for TCP Wrappers is compiled into the version of inetd
that this computer is using, tcpd is not used,
so tcpdchk reports a warning (which we ignore).
The second warning is that there is a rule in the /etc/hosts.allow
file for the sshd service, but there is no matching
daemon listed in the /etc/inetd.conf file. This is actually not an error:
the sshd service is started up directly at boot
time, not by inetd. Nevertheless, the program is
linked with the TCP Wrappers library and honors the commands in the /etc/hosts.allow
file.
The TCP Wrappers system comes with another utility program called
tcpdmatch, which allows you to simulate an incoming
connection and determine if the connection would be permitted or blocked with your
current configuration files. In the following example, we will see if the user
simsong@k1.vineyard.net is allowed to
ssh into our machine:
r2# tcpdmatch
usage: tcpdmatch [-d] [-i inet_conf] daemon[@host] [user@]host
-d: use allow/deny files in current directory
-i: location of inetd.conf file
r2# tcpdmatch sshd simsong@k1.vineyard.net
warning: sshd: no such process name in /etc/inetd.conf
client: hostname K1.VINEYARD.NET
client: address 204.17.195.90
client: username simsong
server: process sshd
matched: /etc/hosts.allow line 39
option: allow
access: granted
r2#
Ignoring the warning in the first line, we can see that permission
would be granted by line 39 of the /etc/hosts.allow file. This line reads:
sshd : ALL : allow
Programs such as tcpdchk and
tcpdmatch are excellent complements to the security
program TCP Wrappers because they help you head off security problems before they
happen. Wietse Venema should be complimented for writing and including them in his
TCP Wrappers release; other programmers should follow his example.
Before answering this question, let's first provide a little
background. TCP Wrappers has been around for many, many years. It is used to restrict
access to TCP services based on host name, IP address, network address, etc. For
more detailed on what TCP Wrappers is and how you can use it, see tcpd(1M).
TCP Wrappers was integrated into Solaris starting in Solaris 9 where both Solaris
Secure Shell and inetd-based (streams, nowait) services were wrapped. Bonus points
are awarded to anyone who knows why UDP services are not wrapped by default.
TCP Wrappers support in Secure Shell was always enabled since Secure Shell always
called the TCP Wrapper function host_access(3) to determine if a connection
attempt should proceed. If TCP Wrappers was not configured on that system, access,
by default, would be granted. Otherwise, the rules as defined in the hosts.allow
and hosts.deny files would apply. For more information on these files,
see hosts_access(4). Note that this and all of the TCP Wrappers manual
pages a stored under /usr/sfw/man in Solaris 10. To view this manual page,
you can use the following command:
$ man -M /usr/sfw/man -s 4 hosts_access
inetd-based services use TCP Wrappers in a different way. In Solaris 9, to enable
TCP Wrappers for inetd-based services, you must edit the /etc/default/inetd
file and set the ENABLE_TCPWRAPPERS parameter to YES. By default,
TCP Wrappers was not enabled for inetd.
New usage of TCP Wrappers in Solaris 10
In Solaris 10, two new services were wrapped: sendmail and rpcbind.
-
sendmail works in a way similar to Secure Shell.
It always calls the host_access function and therefore TCP Wrappers
support is always enabled. Nothing else needs to be done to enable TCP Wrappers
support for that service.
-
TCP Wrappers support for rpcbind must be enabled
manually using the new Service Management Framework ("SMF"). Similarly, inetd
was modified to use a SMF property to control whether TCP Wrappers is enabled
for inetd-based services.
To enable TCP Wrappers support for inetd-based services:
# inetadm -M tcp_wrappers=true
# svcadm refresh inetd
This will enable TCP Wrappers for inetd-based (streams, nowait) services like
telnet, rlogin, and ftp (for example):
# inetadm -l telnet | grep tcp_wrappersdefault tcp_wrappers=TRUE
You can see that this setting has taken effect for inetd by running the
following command:
# svcprop -p defaults inetd
defaults/tcp_wrappers boolean true
Note that you can also use the svccfg(1M) command to enable TCP Wrappers
for inetd-based services.
# svccfg -s inetd setprop defaults/tcp_wrappers=true
# svcadm refresh inetd
Whether you use inetadm(1M) or svccfg is really a matter of preference.
Note that you can also use inetadm or svccfg to enable TCP Wrappers
on a per-service basis. For example, let's say that we wanted to enable TCP Wrappers
for telnet but not for ftp. By default, both the global and per-service
settings for TCP Wrappers are disabled:
# inetadm -p | grep tcp_wrappers
tcp_wrappers=FALSE
# inetadm -l telnet | grep tcp_wrappers
default tcp_wrappers=FALSE
# inetadm -l ftp | grep tcp_wrappers
default tcp_wrappers=FALSE
To enable TCP Wrappers for telnet, use the following command:
# inetadm -m telnet tcp_wrappers=TRUE
Let's check out settings again:
# inetadm -p | grep tcp_wrappers
tcp_wrappers=FALSE
# inetadm -l telnet | grep tcp_wrappers
tcp_wrappers=TRUE
# inetadm -l ftp | grep tcp_wrappers
default tcp_wrappers=FALSE
As you can see, TCP Wrappers has been enabled for telnet but none of the
other inetd-based services. Pretty cool, eh?
You can enable TCP Wrappers support for rpcbind by running the following
command:
# svccfg -s rpc/bind setprop config/enable_tcpwrappers=true
# svcadm refresh rpc/bind
This change can be verified by running:
# svcprop -p config/enable_tcpwrappers rpc/bind
true
Glenn Brunette's Security Weblog
Enabling TCP Wrappers on Solaris 10
Before answering this question,
let's first provide a little background.
TCP Wrappers has
been around for many, many years. It is used to restrict access to
TCP services based on host name, IP address, network address, etc.
For more detailed on what TCP Wrappers is and how you can use it,
see tcpd(1M). TCP Wrappers was integrated into Solaris
starting in Solaris 9 where both Solaris Secure Shell and inetd-based
(streams, nowait) services were wrapped. Bonus points are awarded to
anyone who knows why UDP services are not wrapped by default.
TCP Wrappers support in Secure
Shell was always enabled since Secure Shell always called the TCP
Wrapper function host_access(3) to determine if a connection
attempt should proceed. If TCP Wrappers was not configured on that
system, access, by default, would be granted. Otherwise, the rules
as defined in the hosts.allow and hosts.deny files
would apply. For more information on these files, see
hosts_access(4). Note that this and all of the TCP Wrappers
manual pages a stored under /usr/sfw/man in Solaris 10. To
view this manual page, you can use the following command:
$ man -M /usr/sfw/man -s 4 hosts_access
inetd-based services use TCP
Wrappers in a different way. In Solaris 9, to enable TCP Wrappers
for inetd-based services, you must edit the /etc/default/inetd
file and set the ENABLE_TCPWRAPPERSparameter to YES.
By default, TCP Wrappers was not enabled for inetd.
In Solaris 10, two new services
were wrapped: sendmail and rpcbind. sendmail
works in a way similar to Secure Shell. It always calls the
host_access function and therefore TCP Wrappers support is
always enabled. Nothing else needs to be done to enable TCP Wrappers
support for that service. On the other hand, TCP Wrappers support
for rpcbind must be enabled manually using the new Service
Management Framework ("SMF"). Similarly, inetd was modified
to use a SMF property to control whether TCP Wrappers is enabled for
inetd-based services.
Let's look at how to enable TCP
Wrappers for inetd and rpcbind...
To enable TCP Wrappers support for
inetd-based services, you can simply use the following commands:
# inetadm -M tcp_wrappers=true
# svcadm refresh inetd
This will enable TCP Wrappers for
inetd-based (streams, nowait) services like telnet, rlogin,
and ftp (for example):
# inetadm -l telnet | grep tcp_wrappers
default tcp_wrappers=TRUE
You can see that this setting has
taken effect for inetd by running the following command:
# svcprop -p defaults inetd
defaults/tcp_wrappers boolean true
Note that you can also use the
svccfg(1M) command to enable TCP Wrappers for inetd-based
services.
# svccfg -s inetd setprop defaults/tcp_wrappers=true
# svcadm refresh inetd
Whether you use inetadm(1M)
or svccfg is really a matter of preference. Note that you can
also use inetadm or svccfg to enable TCP Wrappers on a
per-service basis. For example, let's say that we wanted to enable
TCP Wrappers for telnet but not for ftp. By default,
both the global and per-service settings for TCP Wrappers are
disabled:
# inetadm -p | grep tcp_wrappers
tcp_wrappers=FALSE
# inetadm -l telnet | grep tcp_wrappers
default tcp_wrappers=FALSE
# inetadm -l ftp | grep tcp_wrappers
default tcp_wrappers=FALSE
To enable TCP Wrappers for
telnet, use the following command:
# inetadm -m telnet tcp_wrappers=TRUE
Let's check out settings again:
# inetadm -p | grep tcp_wrappers
tcp_wrappers=FALSE
# inetadm -l telnet | grep tcp_wrappers
tcp_wrappers=TRUE
# inetadm -l ftp | grep tcp_wrappers
default tcp_wrappers=FALSE
As you can see, TCP Wrappers has
been enabled for telnet but none of the other inetd-based
services. Pretty cool, eh?
You can enable TCP Wrappers support
for rpcbind by running the following command:
# svccfg -s rpc/bind setprop config/enable_tcpwrappers=true
# svcadm refresh rpc/bind
This change can be verified by
running:
# svcprop -p config/enable_tcpwrappers rpc/bind
true
That is all that there is to it!
Quick, easy and painless! As always, let me know what you think!
Take care!
Technorati Tag: OpenSolaris Solaris security
Apr
06 2005, 04:30:38 PM EDT
Permalink
Trackback URL: http://blogs.sun.com/roller/trackback/gbrunett/Weblog/tcp_wrappers_on_solaris_10
- 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
- freebsd
- hpux
- 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.
... ... ...
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.
Symbolic names
%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.
... ... ...
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.
[****]
Linux
Security 101 Issue 14 By Kelley Spoon,
mars@loeffel.txdirect.net --
very good discussion of tcpd
There's a daemon that's probably been installed on your
machine that you don't know about. Or at least, you're not aware of what it
can do. It's called tcpd, and it's how we shut off access to some of
the basic services that the Bad Guys can use to get on our system.
Since tcpd can be pretty complex, I'm not going to
go into all the details and tell you how to do the fancy stuff. The goal here
is to keep the mischievous gibbons from knocking down what it took so long
for use to set up.
tcpd is called into action from another daemon,
inetd, whenever someone tries to access a service like in.telnetd,
wu.ftpd, in.fingerd, in.rshd, etc. tcpd's job is to look at two files
and determine if the person who is trying to access the service has
permission or not.
The files are /etc/hosts.allow and /etc/hosts.deny.
Here's how it all works:
- Someone tries to use a service that tcpd is
monitoring.
- tcpd wakes up, and makes a note of the attempt
to the syslog.
- tcpd then looks hosts.allow
- if it finds a match, tcpd goes back to sleep
and lets the user access the service.
- tcpd now takes a look at hosts.deny
- if it finds a match, tcpd closes the user's
connection
- If it can't find a match in either file, or if both
files are empty, tcpd shrugs, guesses it's OK to let the user on,
and goes back to sleep.
Now, there are a couple of things to note here. First, if
you haven't edited hosts.allow or hosts.deny since you
installed Linux, then tcpd assumes that you want to let everyone have
access to your machine. The second thing to note is that if tcpd finds
a match in hosts.allow, it stops looking. In other words, we can put
an entry in hosts.deny and deny access to all services from all
machines, and then list ``friendly'' machines in the hosts.allow file.
Let's take a look at the man page. You'll find the info you
need by typing man 5 hosts_access (don't forget the 5 and the
underscore).
daemon_list : client_list
daemon_list is a list of one or more daemon process names
or wildcards
client_list is a list of one or more host names, host
addresses, patterns or wildcards that will be matched
against the remote host name or address.
List elements should be separated by blanks and/or commas.
Now, if you go take a look at the man page, you'll notice
that I didn't show you everything that was in there. The reason for that is
because the extra option (the shell_command) can be used to do some neat
stuff, but *most Linux distributions have not enabled the use of this option
in their tcpd binaries*. We'll save how to do this for an article on tcpd
itself.
If you absolutely have to have this option, get the source
from
here and recompile.
Back to business. What the above section from the
hosts_access man page was trying to say is that the format of hosts.[allow|deny]
is made up of a list of services and a list of host name patterns, separated
by a ``:''
You'll find the name of the services you can use by looking
in your /etc/inetd.conf...they'll be the ones with /usr/sbin/tcpd
set as the server path.
The rules for determining host patterns are pretty simple,
too:
- if you want to match all hosts in a domain, put a ``.''
at the front.
- Ex: .bar.com will match "foo.bar.com", "sailors.bar.com",
"blue.oyster.bar.com", etc.
- if you want to match all IPs in a domain, put a "." at
the end.
- Ex: 192.168.1. will match "192.168.1.1",
"192.168.1.2", "192.168.1.3", etc.
And finally, there are some wildcards you can use:
- ALL matches everything. If in daemon_list,
matches all daemons; if in client_list, it matches all host names.
- Ex: ALL : ALL would match any machine trying
to get to any service.
- LOCAL matches host names that don't have a dot
in them.
- Ex: ALL : LOCAL would match any machine that
is inside the domain or search aliases given in your /etc/resolv.conf
- except isn't really a wildcard, but it comes in
useful. It excludes a pattern from the list.
- Ex: ALL : ALL except .leetin-haxor.org would
match all services to anyone who is not from ``*.leetin-haxor.org''
Ok. Enough technical stuff. Let's get to some examples.
Let's pretend we have a home LAN, and a computer for each
member of the family.
Our home network looks like this:
linux.home.net 192.168.1.1
dad.home.net 192.168.1.2
mom.home.net 192.168.1.3
sis.home.net 192.168.1.4
bro.home.net 192.168.1.5
Now, since no one in the family is likely to try and ``hack
root,'' we can assume they're all friendly. But....we're not so sure about
the rest of the people on the Internet. Here's how we go about setting things
up so people on home.net have full access to our machine, but no one else
does. In /etc/hosts.allow:
# /etc/hosts.allow for linux.home.net
ALL: .home.net
And in /etc/hosts.deny
# /etc/hosts.deny for linux.home.net
ALL : ALL
Since tcpd looks at hosts.allow first, we can
safely deny access to all services for everybody. If tcpd can't match
the machine sending the request to ``*.home.net'', the connection gets
refused.
Now, let's pretend that Mom has been reading up on how Unix
stuff works, and she's started doing some unfriendly stuff on our machine. In
order to deny her access to our machine, we simply change the line in
hosts.allow to:
ALL: .home.net except mom.home.net
Now, let's pretend a friend from....uh....friend.com wants
to get something off our ftp server. No problem, just edit hosts.allow
again:
# /etc/hosts.allow for linux.home.net
ALL: .home.net except mom.home.net
wu.ftpd: .friend.com
Things are looking good. The only problem is that the name
server for home.net is sometimes down, and the only way we can identify
someone as being on home.net is through their IP address. Not a problem:
# /etc/hosts.allow for linux.home.net
ALL: .home.net except mom.home.net
ALL: 192.168.1. except 192.168.1.3
ALL: .friend.com
And so on....
I have found that's it's easier to deny everybody access,
and list your friends in hosts.allow than it is to allow everybody
access, and deny only the people who you know are RBG's. If you are running a
private machine, this won't really be a problem, and you can rest easy.
However, if you're trying to run a public service (like an
ftp archive of Tetris games for different OS's) and you can't afford to be
this paranoid, then you need shouldn't put anything in hosts.allow,
and just put all of the people you don't want touching your machine in
hosts.deny
In case of broken links
please try to use Google search. If you find the page please notify
us about new location
Tip of the Month: Enabling TCP Wrappers in Solaris 10
Before answering this question, let's first provide a little background.
TCP Wrappers has been around for many, many years. It is used to restrict
access to TCP services based on host name, IP address, network address, etc.
For more detailed on what TCP Wrappers is and how you can use it, see tcpd(1M).
TCP Wrappers was integrated into Solaris starting in Solaris 9 where both Solaris
Secure Shell and inetd-based (streams, nowait) services were wrapped. Bonus
points are awarded to anyone who knows why UDP services are not wrapped by default.
TCP Wrappers support in Secure Shell was always enabled since Secure Shell
always called the TCP Wrapper function host_access(3) to determine if
a connection attempt should proceed. If TCP Wrappers was not configured on that
system, access, by default, would be granted. Otherwise, the rules as defined
in the hosts.allow and hosts.deny files would apply. For more
information on these files, see hosts_access(4). Note that this and all
of the TCP Wrappers manual pages a stored under /usr/sfw/man in Solaris
10. To view this manual page, you can use the following command:
$ man -M /usr/sfw/man -s 4 hosts_access
inetd-based services use TCP Wrappers in a different way. In Solaris 9, to
enable TCP Wrappers for inetd-based services, you must edit the /etc/default/inetd
file and set the ENABLE_TCPWRAPPERSparameter to YES. By default,
TCP Wrappers was not enabled for inetd.
In Solaris 10, two new services were wrapped: sendmail and rpcbind.
sendmail works in a way similar to Secure Shell. It always calls the
host_access function and therefore TCP Wrappers support is always enabled.
Nothing else needs to be done to enable TCP Wrappers support for that service.
On the other hand, TCP Wrappers support for rpcbind must be enabled manually
using the new Service Management Framework ("SMF"). Similarly, inetd
was modified to use a SMF property to control whether TCP Wrappers is enabled
for inetd-based services.
Let's look at how to enable TCP Wrappers for inetd and rpcbind...
To enable TCP Wrappers support for inetd-based services, you can simply use
the following commands:
# inetadm -M tcp_wrappers=true
# svcadm refresh inetd
This will enable TCP Wrappers for inetd-based (streams, nowait) services
like telnet, rlogin, and ftp (for example):
# inetadm -l telnet | grep tcp_wrappers
default tcp_wrappers=TRUE
You can see that this setting has taken effect for inetd by running
Note that you can also use the svccfg(1M) command to enable TCP Wrappers
for inetd-based services.
# svccfg -s inetd setprop defaults/tcp_wrappers=true
# svcadm refresh inetd
Whether you use inetadm(1M) or svccfg is really a matter of
preference. Note that you can also use inetadm or svccfg to enable
TCP Wrappers on a per-service basis. For example, let's say that we wanted to
enable TCP Wrappers for telnet but not for ftp. By default, both
the global and per-service settings for TCP Wrappers are disabled:
# inetadm -p | grep tcp_wrappers
tcp_wrappers=FALSE
# inetadm -l telnet | grep tcp_wrappers
default tcp_wrappers=FALSE
# inetadm -l ftp | grep tcp_wrappers
default tcp_wrappers=FALSE
To enable TCP Wrappers for telnet, use the following command:
# inetadm -m telnet tcp_wrappers=TRUE
Let's check out settings again:
# inetadm -p | grep tcp_wrappers
tcp_wrappers=FALSE
# inetadm -l telnet | grep tcp_wrappers
tcp_wrappers=TRUE
# inetadm -l ftp | grep tcp_wrappers
default tcp_wrappers=FALSE
As you can see, TCP Wrappers has been enabled for telnet but none
of the other inetd-based services. Pretty cool, eh?
You can enable TCP Wrappers support for rpcbind by running the following
command:
# svccfg -s rpc/bind setprop config/enable_tcpwrappers=true
# svcadm refresh rpc/bind
This change can be verified by running:
# svcprop -p config/enable_tcpwrappers rpc/bind
true
That is all that there is to it! Quick, easy and painless! As always, let
me know what you think!
Take care!
Controlling access to network services can be a challenge. Firewalls
are useful for controlling access in and out of a particular network, but
they can be difficult to configure. TCP wrappers and
xinetd control access to services by hostname and IP addresses. In
addition, these tools also include logging and utilization management capabilities
that are easy to configure.
Purpose of TCP Wrappers
Many modern network services, such as SSH, Telnet, and FTP, make use
of TCP wrappers, a program that is designed
to stand between an incoming request and the requested service. TCP
wrappers is installed by default with a server-class installation of
Red Hat Linux, providing many advantages over running a variety of different
services, each with their own access control methods.
The idea behind TCP wrappers is that, rather than allowing an incoming
client connection to communicate directly with a network service daemon
running as a separate process on a server system, the target of the
request is "wrapped" by another program, allowing a greater degree of
access control and logging of who is attempting to use the service.
The functionality behind TCP wrappers is provided by
libwrap.a, a library that network services,
such as xinetd, sshd,
and portmap, are compiled against. Additional
network services, even networking programs you may write, can be compiled
again libwrap.a to provide this functionality.
Red Hat Linux bundles the necessary TCP wrapper programs and library
in the tcp_wrappers-<version>
RPM file.
TCP Wrapper Advantages
When someone attempts to access a network service using TCP wrappers,
a small wrapper program reports the name of the service requested
and the client's host information. The wrapper program does not
directly send any information back to the client, and after the
access control directives are satisfied, the wrapper gets out of
the way, not placing any additional overhead on the communication
between the client and server.
TCP wrappers provide two basic advantages over other network
service control techniques:
- The connecting client is unaware that
TCP wrappers are in use. Legitimate users will not notice
anything different, and attackers never receive any additional
information about why their attempted connections failed.
- TCP wrappers operate in a manner that
is separate from the applications the wrapper program protects.
This allows many applications to share a common set of configuration
files for simpler management.
By Trevor Warren <trevor@freeos.com>
This tool has been successfully used for shielding off systems and for detection
of cracker activity. It has no impact on legal computer users, and does not
require any change to existing systems software or configuration files. The
tool has been installed world-wide on numerous UNIX systems without any source
code change. Such is the beauty of TCP Wrappers.
Almost every application of the TCP/IP protocols is based on a client-server
model. For example, when someone uses the telnet command to connect to a host,
a telnet server process is started on the target host. The server process connects
the user to a login process. A few examples are shown in table 1.
client server application
________________________________
telnet telnetd remote login
ftp ftpd file transfer
finger fingerd show users
systat systatd show users
Table 1. Examples of TCP/IP client-server pairs and
their applications.
The usual approach is to run one daemon process that waits for all kinds
of incoming network connections. Whenever a connection is established this daemon
(usually called inetd on our Linux boxes) runs the appropriate server program
and goes back to sleep, waiting for other connections. See the example as illustrated
below.
client server application
________________________________
telnet telnetd remote login
(foo1.bar) (foo2.bar)
We are on a client Linux box called foo1.bar and want to connect to a remote
Linux box called foo2.bar which resides on a remote network. We then use the
telnet client application from my box i.e foo1.bar to connect to the remote
telnet server box foo2.bar. Have a look at the graphical illustrations as given
below.
------------------- ----------------- -----------
foo1.bar---| client(ftp,telnet..) |---------| INETD server |--------| login |
-------------------- ----------------- -----------
Figure 1. The inetd daemon process listens on the ftp,
telnet etc. network ports and waits for incoming con-
nections. The figure shows that a user has connected to
the ftp/telnet port.
----------------- ----------------- ---------
user---| telnet client |--------| telnet server |--------| login |
----------------- ----------------- ---------
(foo1.bar) (foo2.bar)
Figure 2. The inetd process has started a telnet
server process that connects the user to a login pro-
cess. Meanwhile, inetd waits for other incoming con-
nections. This illustrates an unprotected machine.
Fortunately, the author of TCP wrapper came up with a simple solution that
did not require any change to existing software, and that turned out to work
on all UNIX systems that were ever tried it on. The trick was to make a swap.
Move the vendor-provided network server programs to another place, and install
a trivial program in the original place of the network server programs. Whenever
a connection was made, the trivial program would just record the name of the
remote host, and then run the original network server program.
----------------- -----------------
user---| telnet client |---------| tcp wrapper |----> logfile
----------------- -----------------
(foo1.bar) (foo2.bar)
Figure 3. The original telnet server program has been
moved to some other place, and the tcp wrapper has tak-
en its place. The wrapper logs the name of the remote
host to a file. This illustrates a protected machine.
----------------- ----------------- ---------
user---| telnet client |---------| telnet server |-------| login |
----------------- ----------------- ---------
(foo1.bar) (foo2.bar)
Figure 4. The tcp wrapper program has started the real
telnet server and no longer participates. The user can-
not notice any difference.
Lets look at the logs capable of being generated by our TCP wrapper application.
May 22 14:43:29 tuegate: systatd: connect from monk.rutgers.edu
May 22 15:08:30 tuegate: systatd: connect from monk.rutgers.edu
May 22 15:09:19 tuewse: fingerd: connect from monk.rutgers.edu
May 22 15:14:27 tuegate: telnetd: connect from cumbic.bmb.columbia.edu
May 22 15:23:06 tuegate: systatd: connect from cumbic.bmb.columbia.edu
May 22 15:23:56 tuewse: fingerd: connect from cumbic.bmb.columbia.edu
Some of the first cracker connections observed with the tcp wrapper program
by the author. Each connection is recorded with: time stamp, the name of the
local host, the name of the requested service (actually, the network server
process name), and the name of the remote host.
Automatic reverse fingers had proven useful in the authors fight against
the cracker, so he decided to integrate the "ad hoc" reverse finger tool with
TCP Wrappers. To this end, the access control language was extended so that
arbitrary shell commands could be specified.
/etc/hosts.allow:
in.tftpd: LOCAL, .foo.bar
/etc/hosts.deny:
in.tftpd: ALL: /usr/ucb/finger -l @%h 2>&1 | /usr/ucb/mail wswietse
This is an example of a booby trap on the tftp service. The entry in the
first access control file says that tftp connections from hosts within its own
domain are allowed. The entry in the second file causes the TCP Wrapper to perform
a reverse finger in all other cases. The "%h" sequence is replaced by the actual
remote host name. The result is sent to the administrator by email.
Our discussion till now gives only a limited illustration of the use of booby
traps. Booby traps can be much more useful when installed on firewall systems,
whose primary purpose is to separate an organizational network from the rest
of the world. A typical firewall system provides only a limited collection of
network services to the outer world. For example, telnet and smtp. By placing
booby traps on the remaining network ports one can implement an effective early-warning
system.
April, 2005 (BigAdmin)
First let's first provide a little background.
TCP Wrappers has been around for many, many years (see
Wietse Venema's FTP archive).
It is used to restrict access to TCP services based on host name, IP address,
network address, and so on. For more details on what TCP Wrappers is and how
you can use it, see tcpd(1M).
TCP Wrappers was integrated into the Solaris Operating System starting in the
Solaris 9 release, where both Solaris Secure Shell and
inetd-based
(streams, nowait) services were wrapped. Bonus points are awarded to anyone
who knows why UDP services are not wrapped by default.
TCP Wrappers support in Secure Shell was
always enabled since Secure Shell always called the TCP Wrapper function
host_access(3)
to determine if a connection attempt should proceed. If TCP Wrappers was not
configured on that system, access, by default, would be granted. Otherwise,
the rules as defined in the hosts.allow
and hosts.deny
files would apply. For more information on these files, see
hosts_access(4).
Note that this and all of the TCP Wrappers manual pages are stored under
/usr/sfw/man
in the Solaris 10 OS. To view this manual page, you can use the following command:
$ man -M /usr/sfw/man -s 4 hosts_access
inetd-based
services use TCP Wrappers in a different way. In the Solaris 9 OS, to enable
TCP Wrappers for inetd-based
services, you must edit the /etc/default/inetd
file and set the ENABLE_TCPWRAPPERS
parameter to YES.
By default, TCP Wrappers was not enabled for
inetd.
In the Solaris 10 OS, two new services
were wrapped: sendmail
and rpcbind.
sendmail
works in a way similar to Secure Shell. It always calls the
host_access
function and therefore TCP Wrappers support is always enabled. Nothing else
needs to be done to enable TCP Wrappers support for that service. On the other
hand, TCP Wrappers support for
rpcbind must be enabled
manually using the new Service Management Facility (SMF). Similarly,
inetd
was modified to use a SMF property to control whether TCP Wrappers is enabled
for inetd-based
services.
Solaris 9 SSH already has libwrap support compiled on. In S10 and later rpcbind
is linked with libwrap so TCP Wrapper style controls are available for all RPC-based
protocols (NIS, NFS etc)
Commentor:
Casper Dik
Added: September 7, 2004
Comment:
It is rather pointless to install TCP wrappers for Solaris 9 and later as the
version included in the OS is exactly the same as the one available on porcupine.
That version has also been reved twice because of bugs we ran into. Solaris
9 SSH already has libwrap support compiled on. In
S10 and later we also provide rpcbind linked with libwrap.
Copyright © 1996-2008 by Dr. Nikolai Bezroukov.
www.softpanorama.org was
created as a service to the UN Sustainable Development Networking Programme (SDNP)
in the author free time.
Submit
comments This document is an industrial compilation designed and created
exclusively for educational use and is placed under the copyright of the
Open Content License(OPL).
Original materials copyright belong to respective owners. Quotes are made
for educational purposes only in compliance with the fair use doctrine.
Standard disclaimer: The statements, views and opinions presented on
this web page are those of the author and are not endorsed by, nor do they necessarily
reflect, the opinions of the author present and former employers, SDNP or any other
organization the author may be associated with. We do not warrant the correctness
of the information provided or its fitness for any purpose.
Last modified:
June 02, 2008