12.2 Controlling Access to ServersAs delivered by most vendors, Unix is a friendly and trusting operating system. By default, network services are offered to every other computer on the network. Unfortunately, this practice is not an advisable policy in today's networked world. While you may want to configure your network server to offer a wide variety of network services to computers on your organization's internal network, you probably want to restrict the services that your computer offers to the outside world. A few Unix servers have built-in facilities for limiting access based on the IP address or hostname of the computer making the service request.[6] For example, NFS allows you to specify which hosts can mount a particular filesystem, and nntp allows you to specify which hosts can read Netnews. Unfortunately, these services are in the minority: most Unix servers have no facility for controlling access on a host-by-host or network-by-network basis.
There are several techniques that you can use to control access to servers that do not provide their own systems for access control. These include:
We see TCP Wrappers, ipfw, and standalone firewalls as complementary technologies, rather than competing ones. For example, you can run TCP Wrappers on each of your computers to protect specific services, implement general-purpose rules with ipfw, and then protect your entire network with a firewall. This combination is an example of defense in depth, the philosophy of not depending on one particular technology for all of your protection. In the following sections, we will continue the discussion of using TCP Wrappers and ipfw. 12.2.1 Access Control Lists with TCP WrappersThe TCP Wrappers system is built into modern versions of the inetd program, the SSH server, and many other programs. It is included as a standalone program called tcpd on many Unix systems, including Linux, Solaris 9, BSD derivatives, and Mac OS X. If you do not have the TCP Wrappers system on your computer, fear not: you can download it from the Internet and easily install it on your computer, even if you do not have source code to your network utilities. This is one of the advantages of being a wrapper. 12.2.1.1 What TCP Wrappers doesThe 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:
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.
The actions implemented by TCP Wrappers are quite sophisticated. Specifically, options can:
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. 12.2.1.2 The TCP Wrappers configuration languageThe 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:[10]
daemon_list : client_host_list [: shell_command] in which:
For examples of using TCP Wrappers, see Section 12.5 at the end of this chapter. 12.2.1.3 Making sense of your TCP Wrappers configuration filesThe 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. 12.2.2 Using a Host-Based Packet FirewallMany Unix-based systems contain a built-in packet firewall. The firewall is controlled with rules that are loaded into the kernel at runtime. Rules can block or allow packets to flow based on packet type, host, protocol, and even packet-level flags. Using these rules, you can implement a broad variety of policies for traffic, such as:
Traditionally, Linux systems based on the 2.2 kernel have used the ipchains IP firewall, Linux systems based on the 2.4 kernel have used the netfilter IP firewall (also called iptables), and BSD-based systems (including Mac OS X) have used the ipfirewall (also called ipfw, ipf, and pf). Although these systems were developed for Linux and BSD computers serving as routers and firewalls, they can be used with great success on systems that have a single Ethernet interface. Solaris systems have used the public domain ipfilter, which must be added to the Solaris kernel by the end user, Solaris now ships with a firewall product called SunScreen.
The rules that you add to the kernel with a packet-level firewall are in addition to any access control rules that you might implement with the TCP Wrappers system (or another system). They are also in addition to any external firewall that may be protecting the network that the host is on. The kernel-level firewall can give you an additional layer of protection and is an important part of a defense-in-depth strategy. The primary disadvantage of packet-level firewalls is that they consume some CPU power; this can be a special concern on systems that are heavily loaded and in cases where the rule sets are very long—the added CPU requirements may be more than your system can handle! For most situations, however, packet-level firewalls do not place an excessive burden on the system, as they tend to be quite efficient; if your system has some CPU power to spare, you will not notice their overhead. Indeed, many people dramatically overestimate the amount of CPU power necessary for a Unix-based computer to act as a firewall. For example, FreeBSD running on an Intel-based 486 at 33 MHz can easily handle the traffic of a fully loaded T1 or DSL line. A second disadvantage of packet-level firewalls is that they can be too good: you might implement a firewall at one point, and then many months later spend hours (or days) trying to get a network service to work—a service that is specifically disallowed by the firewall. In one case, it took one of the authors of this book six months to realize that the Amanda tape backup system wouldn't work on his home computer was because the Amanda control packets were being specifically disallowed by his host-based firewall. 12.2.2.1 The ipfw host-based firewallThis section describes the ipfw host-based firewall that is part of BSD-based systems such as FreeBSD and Mac OS X. Although the commands discussed are specific to ipfw, the concepts are applicable to any host-based packet firewall system. The firewall consists of code that is linked into the BSD kernel and a series of rules that are loaded into the kernel's memory space at runtime. Each rule consists of a rule number, a filter specification, and an action. Rules are applied to all packets, whether the packets are passed from one interface to another (in the case of a Unix system that is acting as a router or gateway) or are passed from an interface to an application program (in the case of a Unix system that is acting as a network client or server).
Rules are evaluated in order until a matching rule is found, at which time the rule's action is executed. Some actions terminate the rule search for a particular packet, while other actions cause the system to look for the next matching rule. Rules are controlled using the ipfw command. Typical commands are:
There are many more commands beyond these. What's more, the syntax and subcommands of the ipfw command vary slightly from system to system. For this reason, it is vital that you consult the ipfw (or iptables or ipchains) manpage for your operating system for a complete list. Furthermore, you should always have physical access to a computer on which you are running the ipfw command and be in a position where you can reboot the computer without any hesitation. By typing the wrong command, it is very easy to leave the computer in a state such that it is unable to send or receive packets on the network. Filters for the ipfw command can be constructed using any or all of the following criteria:
Some typical actions are shown in Table 12-4.
Rules can also be assigned a probability so that they will be invoked only a certain percentage of the time. Although this is not tremendously useful for security applications, it can be useful in simulating conditions of heavy network congestion.[13]
12.2.2.2 An ipfw exampleExample 12-3 shows a typical script that starts up a simple ipfwl script that is used on a computer that has two Ethernet interfaces—one on the organization's internal network, one on the external Internet. (Despite the fact that the computer has two Ethernet interfaces, it is not configured to forward packets from one interface to another.) In this example, the internal network is the subnet 192.168.1.0/24. Note that all actual Internet addresses have been replaced with Net 10. addresses to protect the privacy of the guilty. The 300-series rules open the firewall so that any packet to or from the organization's internal network is allowed to pass freely. The 400-series rules are filters that have been added to block Internet traffic from hosts that, in the opinion of the site's operator, have shown a history of bad actions. In one case, one of the blocked sites was responsible for large amounts of unwanted email. In another case, computers at the IP address launched a series of attacks against one of the organization's nameservers in an attempt to appropriate a valuable domain name. Rather than continually reading about these attacks in the system logs, it was easier to block their packets. The 500-series rules allow a select number of protocols from anywhere else on the Internet. Note that the packets from the hosts mentioned in the 400-series rules will not be accepted because the 400-series rules execute before the 500-series rules. The remaining rules specify a variety of policies for the site in question. Of particular interest are rules 1001 and 1002, which allow remote database connections from a particular subnet but nowhere else on the Internet, and rule 2001, which blocks all incoming TCP connections that are not specifically allowed by the other rules in the firewall ruleset. The net effect of rule 2001 is that any attacker who sets up a rogue TCP/IP server will find that his service is blocked by the system's kernel. (Of course, a knowledgeable attacker who achieves superuser status can use the ipfw command to remove rule 2001; if you have a knowledgeable attacker who has achieved superuser status, you have bigger problems to worry about.) Example 12-3. A typical ipfw initialization scriptcase $1 in start) # # Allow anything from internal network. ipfw add 301 allow ip from 192.168.1.0/24 to any # # General stuff to block specific attackers out there ipfw add 460 deny ip from 10.101.236.0/24 to any ipfw add 461 deny ip from 10.192.228.15 to any ipfw add 462 deny ip from 10.211.39.250 to any ipfw add 463 deny ip from 10.20.20.1 to any ipfw add 464 deny ip from 10.60.89.18 to any # Allow SSH, SMTP, HTTP, HTTPS, and POP in from anywhere else. ipfw add 500 allow tcp from any to any 22,25,80,443,110 # Allow DNS from anywhere else. ipfw add 510 allow tcp from any to any 53 ipfw add 510 allow udp from any to any 53 # Deny syslog. ipfw add 600 deny udp from any to any 514 # Allow only X to our friends. ipfw add 700 allow tcp from 10.7.15.234/28 to any 6000-6063 ipfw add 701 allow tcp from 10.175.193.176/28 to any 6000-6063 ipfw add 702 deny tcp from any to any 6000-6063 # MySQL clients from a particular site on the network ipfw add 1001 allow tcp from 199.175.193.176/28 to any 3306 ipfw add 1002 deny tcp from any to any 3306 # LPD defenses ipfw add 1010 deny tcp from any to any 515 # SunRPC defenses ipfw add 1020 deny tcp from any to any 111 # imap only from internal network ipfw add 1030 deny tcp from any to any 143 # imaps, pops, and smtps from any network ipfw add 1100 allow tcp from any to any 465,993,995 # rtsp from any network ipfw add 1101 allow tcp from any to any 554 ipfw add 1101 allow udp from any to any 554 # Allow any outgoing packet from this host. ipfw add 2000 allow tcp from any to any out # Deny all other incoming TCP setup packets. ipfw add 2001 deny tcp from any to any setup ;; stop) ;; esac |