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.”[1]
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.[2]
UNKNOWN matches any hosts whose name
or address lookup failed. PARANOID
matches any host whose hostname does not resolve back to its IP
address.[3]
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
n.n.n.n/m.m.m.m 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.
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.