Since opening a computer to network access involves many security risks, applications are designed to guard against several types of attacks. Some security features, however, may be flawed (most drastically demonstrated by the RTM Internet worm, which exploited a hole in a number of programs, including old versions of the sendmail mail daemon), or do not distinguish between secure hosts from which requests for a particular service will be accepted and insecure hosts whose requests should be rejected. We’ve already briefly discussed the finger and tftp services. Network Administrator would want to limit access to these services to “trusted hosts” only, which is impossible with the usual setup, for which inetd provides this service either to all clients or not at all.
A useful tool for managing host-specific access is tcpd, often called the daemon “wrapper.”[69] For TCP services you want to monitor or protect, it is invoked instead of the server program. tcpd checks if the remote host is allowed to use that service, and only if this succeeds will it execute the real server program. tcpd also logs the request to the syslog daemon. Note that this does not work with UDP-based services.
For example, to wrap the finger daemon, you have to change
the corresponding line in inetd.conf from this:
# unwrapped finger daemon finger stream tcp nowait bin /usr/sbin/fingerd in.fingerd
to this:
# wrap finger daemon finger stream tcp nowait root /usr/sbin/tcpd in.fingerd
Without adding any access control, this will appear to the client as the usual finger setup, except that any requests are logged to syslog’s auth facility.
Two files called /etc/hosts.allow and
/etc/hosts.deny implement access control.
They contain entries that allow and deny access to certain services and hosts.
When tcpd handles a request for a service such as
finger from a client host named
biff.foobar.com, it scans
hosts.allow and hosts.deny
(in this order) for an entry matching both the service and client host.
If a matching entry is found in hosts.allow, access
is granted and tcpd doesn’t consult the
hosts.deny file. If no match is found in the
hosts.allow file, but a match is found in
hosts.deny, the request is rejected by closing down the
connection. The request is accepted if no match is found at all.
Entries in the access files look like this:
servicelist:hostlist[:shellcmd]
servicelist is a list of service names from
/etc/services, or the keyword
ALL. To match all services except
finger and tftp, use
ALL
EXCEPT
finger, tftp.
hostlist is a list of hostnames, IP addresses,
or the keywords ALL,
LOCAL,
UNKNOWN or
PARANOID.
ALL matches any host, while
LOCAL matches hostnames that don’t
contain a dot.[70]
UNKNOWN matches any hosts whose name
or address lookup failed. PARANOID
matches any host whose hostname does not resolve back to its IP
address.[71]
A name starting with a dot matches all hosts whose domain is equal to this
name. For example, .foobar.com matches
biff.foobar.com, but not
nurks.fredsville.com. A pattern that
ends with a dot matches any host whose IP address begins with the supplied
pattern, so 172.16. matches
172.16.32.0, but not
172.15.9.1. A pattern of the form
is treated as an IP address and network mask, so we could specify
our previous example as
172.16.0.0/255.255.0.0 instead.
Lastly, any pattern beginning with a “/” character allows you to
specify a file that is presumed to contain a list of hostname or IP address
patterns, any of which are allowed to match. So a pattern that looked like
/var/access/trustedhosts would cause
the tcpd daemon to read that file, testing if any of the
lines in it matched the connecting host.n.n.n.n/m.m.m.m
To deny access to the finger and tftp
services to all but the local hosts, put the following in
/etc/hosts.deny and leave
/etc/hosts.allow empty:
in.tftpd, in.fingerd: ALL EXCEPT LOCAL, .your.domain
The optional shellcmd field may contain a shell
command to be invoked when the entry is matched. This is useful to set up
traps that may expose potential attackers. The following example creates
a log file listing the user and host connecting, and if the host is not
vlager.vbrew.com it will append the
output of a finger to that host:
in.ftpd: ALL EXCEPT LOCAL, .vbrew.com : \
echo "request from %d@%h: >> /var/log/finger.log; \
if [ %h != "vlager.vbrew.com:" ]; then \
finger -l @%h >> /var/log/finger.log \
fi
The %h and
%d arguments are expanded by
tcpd to the client hostname and service name,
respectively. Please refer to the hosts_access(5)
manual page for details.
[69] Written by Wietse Venema, wietse@wzv.win.tue.nl.
[70] Usually only local hostnames obtained from lookups in
/etc/hosts contain no dots.
[71] While its name suggests it is an extreme measure, the PARANOID keyword is
a good default, as it protects you against mailicious hosts pretending to
be someone they are not. Not all tcpd are supplied with
PARANOID compiled in; if yours is not, you need to recompile
tcpd to use it.