Although it might seem like there is nothing you can do to protect your machine, there are certain measures you can take to limit network risks. We will look at limiting per-service access with TCP Wrappers and using the built-in firewall, ipfw.
A common way to restrict access to some TCP services is to use the TCP Wrappers program. TCP Wrappers is a package that monitors and filters requests for TCP (Transmission Control Protocol) services. We don't look at the protocol in any detail here—that's a book subject in itself. Suffice it to say that the protocol has enough control information in it that we can use a package like TCP Wrappers to filter some of that traffic. TCP Wrappers can be used to restrict certain network services to individual computers or networks.
To make use of this program on some flavors of Unix, TCP Wrappers must be installed by the system administrator. This isn't a necessary step in Mac OS X because the TCP Wrappers program comes preinstalled on the system. You can use TCP Wrappers for services that you have running out of inetd or xinetd. The /etc/inetd.conf file in Mac OS X already assumes that you use TCP Wrappers, as evidenced by a line such as the following:
#ftp stream tcp nowait root /usr/libexec/tcpd ftpd -l
The /usr/libexec/tcpd portion of the previous line indicates that TCP Wrappers is used to call ftpd.
Although using TCP Wrappers with inetd is the default in Mac OS X, it isn't the default for using xinetd. That's because of the controls already available in xinetd. Recall that xinetd has the only_from and no_access directives, which can help you to restrict access to services. If you decide that you want to use TCP Wrappers for host access restrictions on a service controlled by xinetd, you need to add a flag, NAMEINARGS, to the service and further expand the server_args line to include the full path to the service. Replace the original path to the server with the path to tcpd. Here's an example for using TCP Wrappers for restricting access to the FTP service in xinetd:
service ftp { disable = no socket_type = stream wait = no user = root server = /usr/libexec/tcpd server_args = /usr/libexec/ftpd -l groups = yes flags = REUSE NAMEINARGS }
NOTE
To make use of TCP Wrappers with xinetd, libwrap support has to be compiled in. The xinetd that comes with Mac OS X has libwrap support. If you are using xinetd, check your logs and you will see a line indicating this:
Dec 5 13:42:08 localhost xinetd[370]: xinetd Version 2.3.11 started with libwrap options compiled in.
If you decide to update your xinetd, and you're using TCP Wrappers or think that you might want to use it, be sure to compile in the libwrap option.
The particularly difficult part about using TCP Wrappers is configuring it. In this section, we look at two ways you can configure TCP Wrappers in Mac OS X: the traditional method of using two control files and a newer method that uses only one control file.
Traditionally, TCP Wrappers has two control files: /etc/hosts.allow and /etc/hosts.deny. We look at the traditional method in more detail because it's the default setup for a machine when extended processing options aren't enabled. An understanding of the traditional method should carry over to the new method. Be sure to read the hosts_access and hosts_options man pages for detailed information.
Here's the format of the access control files:
daemon_list : client_list : option : option ...
Through /etc/hosts.allow, you can allow specific services for specific hosts.
Through /etc/hosts.deny, you can deny services to hosts and provide global exceptions.
The easiest way to think of and use these configuration files is to think of TCP Wrappers as putting up a big fence around all the services on your machine.
The specifications in /etc/hosts.deny tell the fence what services are on the outside of the fence and, therefore, aren't denied. The fence can appear to be around different sets of services for different clients. For example, an /etc/hosts.deny file might look like this:
ALL EXCEPT ftpd : 192.168.1. : banners /usr/libexec/banners ALL : 140.254.12.100 140.254.12.135 : banners /usr/libexec/banners ALL EXCEPT ftpd sshd : ALL : banners /usr/libexec/banners
This file says
For the subdomain 192.168.1., deny all connections except connections to the FTP daemon, ftpd.
For the specific machines 140.254.12.100 and 140.254.12.135 (maybe they're troublemakers), deny absolutely all connections.
For all other IP addresses, deny everything except connections to ftpd and to the secure-shell daemon sshd.
The banners /usr/libexec/banners entry is an option that tells tcpd that if it denies a connection to a service based on this entry, try to find an explanation file in this location. Use this option if you need to provide an explanation as to why the service isn't available.
The specifications in /etc/hosts.allow make little gates through the fences erected by /etc/hosts.deny for specific host and service combinations. For example, an /etc/hosts.allow file might look like this:
ALL: 140.254.12.137 192.168.2. 192.168.3. popd: 140.254.12.124 140.254.12.151 192.168.1.36
This file says
Allow connections to any TCP service from the host 140.254.12.137 and all hosts in the 192.168.2. and 192.168.3. subdomains. (Perhaps the 192.168.2. and 192.168.3. subdomains are known highly secure networks, and we really trust 140.254.12.137 because it's so well run.)
Allow connections to the popd service for three specific machines: 140.254.12.124, 140.254.12.151, and 192.168.1.36.
If used in combination with the previous /etc/hosts.deny file, these allowances still stand. They override the denials in /etc/hosts.deny; even though the 192.168.1. subdomain is denied all access except to ftpd by /etc/hosts.deny, the specific machine 192.168.1.36 has its own private gate that allows it access to the popd service as well.
NOTE
Services with a smile or without? There can be a bit of confusion as to the name of the service to put in an /etc/hosts.allow or /etc/hosts.deny file. If it's a service out of inetd.conf, the name to use generally is the service name from the leftmost column of the inetd.conf file, or of the /etc/services file (or corresponding NetInfo directory). If this doesn't work, try adding a d to the end of the service name (ftp → ftpd).
Other services use names that don't seem to be recorded officially anywhere. Other services that you encounter and decide to wrap with TCP Wrappers might require a bit of experimenting on your part. So far, my experience has been that their names are relatively easy to guess.
Now that you've seen how the traditional method of controlling TCP Wrappers works, let's take a brief look at a newer method that uses only the /etc/hosts.allow file. The newer method can be used on systems where extended option processing has been enabled. This is indeed the case with Mac OS X. Nevertheless, both methods work in Mac OS X.
In the single file, /etc/hosts.allow, you specify allow and deny rules all in the same file. With the /etc/hosts.allow only method, tcpd reads the file on a first-match-wins basis. Consequently, it's important that your allow rules appear before your deny rules.
For example, to restrict access to ftpd only to our host, 140.254.12.124, we would use these rules:
ftpd: 140.254.12.124 127.0.0.1 localhost: ALLOW ftpd: ALL: DENY
In the first line, we allow our host, 140.254.12.124, access to ftpd using various addresses that it knows for itself. On the second line, we deny access to all other hosts. If we reversed these lines, even the host that we want to allow ftpd access to would be denied access.
After you've sufficiently tested that you have properly set up your allow and deny rules, there's nothing else you need to do to keep TCP Wrappers running. As you're testing your rules, check your logs carefully to see where, if at all, the behaviors are logged. You'll rarely see entries for tcpd itself in your logs, but you might see additional logging for a wrapped service under that service.
As you saw earlier in the book, it's possible to tunnel connections over SSH. If you do decide to run the FTP service on your machine, you might be interested in restricting access to the service so that anyone who uses the service has to tunnel it through SSH. You saw in detail how to configure a Mac client running traditional Mac OS to do this, and you saw how to set up a tunnel in the command line in Mac OS X. We've not yet officially seen how to configure the Mac OS X machine to permit this.
The key to setting this up is restricting access to the desired service to your host by its IP address and as localhost addresses. Sometimes it can be helpful to include your machine by its name, too, but we haven't encountered this problem on a Mac OS X machine.
To restrict access to ftpd so that a user would have to tunnel her FTP connection, you could have an /etc/hosts.deny file like this:
ALL EXCEPT sshd: ALL
In this example, all services are denied except sshd.
In the /etc/hosts.allow file, add a line for your host that includes your host's IP address, 127.0.0.1 and localhost.
ftpd: 140.254.12.124 127.0.0.1 localhost
In this example, our host, 140.254.12.124, is the only host allowed access to ftpd.
In the /etc/hosts.allow only method
sshd: ALL: ALLOW ftpd: 140.254.12.124 127.0.0.1 localhost: ALLOW ftpd: ALL: DENY
As you've already seen, Mac OS X has basic tools available to help you secure your machine. In addition to the basic tools, Mac OS X comes with a firewall package called ipfw.
There are a few graphical packages available for configuring and using ipfw, the built-in firewall. There is a commercial package called Firewall Builder, which is available for a variety of platforms and supports a variety of firewalls, including ipfw, and looks like it should be a powerful product. Firewall Builder is available at http://www.fwbuilder.org/.
A freely available package, sunShield, should install itself as a System Preferences pane, and looks like it should be an intuitive package to use. Unfortunately, it does not install under Tiger as of this writing. You might check on it from time to time at http://www.sunProtectingFactory.com/sunShield/shield_news.html.
A fairly intuitive package is a shareware product called BrickHouse. The latest version is currently available at http://brianhill.dyndns.org/BetaStuff/ . The developer's page is http://personalpages.tds.net/~brian_hill/.
There are also full-featured firewalls available, such as Intego NetBarrier, Norton Symantec Personal Firewall, and Firewalk X, but we are limiting our discussion to BrickHouse, which can be used to help configure the built-in firewall.
Even if you are just using an application such as BrickHouse, which configures ipfw for you, you cannot use the Firewall section of the Sharing preferences pane at the same time.
Because you'll probably want to see some of the before-and-after effects of BrickHouse, we suggest that you take a quick look at a couple commands before you get started with the application.
Run this command:
brezup:root root # ipfw show
65535 49873 13969242 allow ip from any to any
What you just did was ask ipfw to show you the current firewall settings. As you probably guessed, ipfw on Mac OS X ships in an open state.
To correctly configure a firewall, you need to know the network interfaces being used on your system, especially if you are also hoping to use BrickHouse to help you set up your Mac OS X machine as a gateway for your home network. This process requires you to correctly identify the interface of your internal (private) network and main Internet connection. As we saw earlier, you can get this information from ifconfig -a or the Info section of Network Utility.
Because the firewall package can be tricky to work with, what you try to do in BrickHouse might make your machine completely unusable. This is no fault of BrickHouse, but you should be prepared to remove components that you might have BrickHouse install. Depending on your situation, this might be possible only in single-user mode. If you haven't yet put your machine in single-user mode, we suggest that you do so before you do anything in BrickHouse. If you tried single-user mode a while ago but have forgotten what you did, take this moment to try again. Press Command-S while rebooting to get into single-user mode. The last few lines that appear are as follows (the actual prompt might vary):
Singleuser boot - fsck not done Root device is mounted read-only If you want to make modifications to files, run '/sbin/fsck -y' first and then '/sbin/mount -uw /' localhost#
After you have downloaded and installed BrickHouse, you're ready to start using it.
1. | The Setup Assistant appears. Please note that you can also use the Setup Assistant at any time later by clicking on the Assistant button in the main BrickHouse window. The first part of the Setup Assistant is the External Network sheet, shown in Figure 28.18. Select your connection type and IP address assignment method (dynamic or static). Connection-type choices vary with what is available on your machine. Figure 28.18. The BrickHouse Setup Assistant begins with your External Network settings. |
2. | The Public Services sheet, shown in Figure 28.19, is next. Check the boxes by the services that you want your machine to run. If you're not sure what a service is, select it, and a description appears at the bottom of the window. If you typically share your machine over an AppleTalk network, don't forget to check the appropriate AppleTalk services. Figure 28.19. In the Public Services sheet, select the services you want your machine to run. |
3. | The next sheet to appear is the Firewall Setup Complete sheet, shown in Figure 28.20. To enable the configuration, click Apply Configuration. To install a startup script, click Install Startup Script. If you're interested in using your Mac OS X machine as a gateway for an internal network, click the Setup IP Sharing button. If you decide that you want to make changes to your configuration, you can make changes in the main window and apply a new configuration. Additionally, you can install or remove a startup script under the application's Options menu. Figure 28.20. In the Firewall Setup Complete sheet, you can preliminarily finalize your setup or you can continue your setup by clicking on the Setup IP Sharing button to configure your machine to serve as a gateway for an internal network. |
4. | If you plan to set up your Mac OS X machine as a gateway for your internal network, the next sheet that appears is the IP Sharing sheet, shown in Figure 28.21. Here you select how your machine connects to the internal network and what internal IP address should be used for the machine. Connection choices vary with the machine. Figure 28.21. Make specifications about your local network in the IP Sharing sheet.When you've completed this sheet, BrickHouse displays another sheet giving you instructions on starting IP sharing in BrickHouse. At this time, BrickHouse doesn't configure IP sharing to start at boot time. |
You've just completed the initial BrickHouse setup. Now let's take the time to examine the rest of the BrickHouse interface. The default interface is the Quick Configuration, shown in Figure 28.22. The filters you selected during the setup process are shown under the tab for your interface.
The Advanced button opens a sheet, shown in Figure 28.23, that enables you to edit some additional settings involving rules for some select protocols, DHCP, and your domain name service. The bottom-right buttons enable you to add, edit, and delete filters. When you add a filter, you can choose among the same options you saw in the Setup Assistant, as well as Custom Service, which enables you to specify a port or port range. The interface for adding a filter is shown in Figure 28.24. You can rearrange the order of filter rules by dragging them around in the main window.
From the toolbar, you can access the Setup Assistant at any time by clicking the Assistant button. The Setup Assistant always starts from scratch. The IP Sharing button opens a sheet that enables you to further configure IP sharing. You can add, edit or delete a gateway, as well as add, edit or delete redirected services. The IP Sharing sheet is shown in Figure 28.25.
The Monitor button enables you to monitor the firewall. The Settings button enables you to manipulate settings files. You can duplicate, rename, delete, import, and export. By clicking the Log button, you can access the Daily Firewall Log window, from which you can enable logging. If you want logging to be enabled at startup, be sure to reinstall the startup script, which you can do by either clicking the Install button or under the Options menu. Even if you don't think you want to have logging all the time, you might find that having logging on at this stage helps you troubleshoot problems with the firewall configuration.
In addition to the default Quick Configuration mode is the Expert Configuration mode, accessible by clicking the Expert button. The Expert Configuration window, shown in Figure 28.26, is a split window that displays the rules that are being passed to ipfw as well as a configuration file for natd, which redirects packets to another machine if you configured your machine as a gateway. Not only can you edit in this window, but you can also check your syntax.
It's worthwhile to experiment with some filters that you might be most concerned about while you're still in the BrickHouse interface. With each set you want to try, just click the Activate button to apply those settings. The Quick Configuration mode is useful for adding basic filters, whereas the Expert Configuration mode enables you to tweak the configuration. When you have a set that you are happy with, don't forget to save the settings. If you're working in the Expert Configuration mode, you might also want to save the settings in a text file in a Terminal window just to be sure that you can easily find the file without the graphical interface. When you're relatively satisfied with the results, install the startup script if you want the firewall to start at startup.
If your Mac OS X machine is an NFS client, don't test to see whether the mounts still work in the graphical interface. If your mounts aren't working properly, you might hang your console when you check. If you check in the Terminal, you can continue testing until you're finally satisfied. For a Mac OS X machine that's an NFS client, you might ultimately find it necessary to add a line in the Expert mode that allows all traffic from your NFS server.
Finally, you should be aware of the options available under the Options menu: Allow Changes, Quick Configuration, Expert Configuration, Apply Settings, Install Startup Script, Clear All Rules, and Remove Startup Script. Only some of those options are available in the toolbar.
When you're satisfied with your firewall configuration, reboot your machine—especially if you had BrickHouse install a startup script for you. This tells you exactly what behavior to expect from the firewall starting from scratch. If something undesirable occurs, the potential cause for the behavior is fresh in your mind and more easily fixed.
The easiest way to examine ipfw is to see how BrickHouse has manipulated it for you.
Run the first command that you ran before you started:
brezup:root root # ipfw show
01000 1598 388140 allow ip from any to any via lo*
01003 0 0 check-state
01004 414 45788 allow tcp from any to any established
01005 0 0 allow ip from any to any frag
01006 0 0 allow icmp from any to any icmptypes 0,3,4,11,12,13,14
02000 26 8124 allow udp from any 67-68 to any dst-port 67-68 via en0
02001 0 0 allow udp from any to 255.255.255.255 dst-port 67-68 via en0
65535 30394 5645940 allow ip from any to any
You should now have more output than you did previously. The open rule, which was the only rule before you started, is now the last rule. The Firewall Monitor in BrickHouse is a graphical view of ipfw show.
Next run ifconfig -a. If you configured your machine to be a gateway, you should now see information about your machine's interface to the internal and external networks. If you didn't configure your machine to be a gateway, you shouldn't see any changes.
If you had BrickHouse install a startup script, you now have a /Library/StartupItems/Firewall directory:
brezup:sage sage $ ls -l /Library/StartupItems/Firewall/
total 2352
-rwxr-xr-x 1 root admin 496 Dec 6 15:33 Firewall
-rw-r--r-- 1 root admin 598 Dec 6 15:33 StartupParameters.plist
-rwxr-xr-x 1 root admin 1195908 Dec 6 15:33 fwutil
Here's a sample startup script installed by BrickHouse to start the firewall and its logging facilities:
brezup:sage sage $ more /Library/StartupItems/Firewall/Firewall
#!/bin/sh
# Firewall Boot Script
# Generated by BrickHouse
#===========================================================
# Activate Firewall Filters
#===========================================================
/sbin/ipfw -q /etc/firewall.conf
#===========================================================
# Enable IP Firewall Logging
#===========================================================
/usr/sbin/sysctl -w net.inet.ip.fw.verbose=1
/usr/sbin/sysctl -w net.inet.ip.fw.verbose_limit=65535
As you can see from the startup script, BrickHouse installed a configuration file that it called firewall.conf in /etc. Look at the configuration file, especially if you didn't switch to the Expert Configuration mode in BrickHouse. The file is nicely commented. If you need to make additional changes to the ruleset, you can do so either in the BrickHouse interface or you can directly edit the /etc/firewall.conf file. Be sure to check the ifpw man page for specific details. The ipfw program reads the configuration file on a first-match-wins basis.
The general format of the lines BrickHouse created in the /etc/firewall.conf file is
add <rule_number> <action> <protocol> from <source> to <destination> [<options>] [via <interface>]
If you selected AppleShare as one of your services, you have entries that look approximately like this:
################################################# ## AppleShare IP ################################################# add 2010 allow tcp from any to 140.254.104.243 548 setup keep-state in via en0
The first line is a rule that enables incoming TCP packets from any host to the host machine on port 548 via the interface en0. The setup rule option matches TCP packets with SYN bits, but no ACK bits. The keep-state rule option keeps the connection alive, even during idle sessions.
As mentioned in the previous section, if your Mac OS X machine is an NFS client, you might have to allow all incoming packets to the NFS server. You could do that with a rule like this:
ipfw add <rule_number> allow ip from <NFS_Server-IP> to <host_IP> via en0
The ip packet description means all packets. You can also use all. Select command documentation for ipfw is included in Table 28.2.
BrickHouse might also have installed a configuration file, /etc/natd.conf, for natd, which is used for IP Sharing. Here's a sample /etc/natd.conf created by BrickHouse:
interface en0 use_sockets yes same_ports yes
This configuration file specifies the interface to be used. In addition, the use_sockets option is included as well as the same_ports option. The use_sockets option allocates a socket for the connection, and is useful for guaranteeing connections when ports conflict. The same_ports option specifies that natd should try to keep the same port number when altering outgoing packets. This also aids in guaranteeing the success of the connection.
18.117.184.189