Friday, June 16, 2006

Firewall Configuration

OS X uses the "ipfirewall" packet filtering system inherited from BSD. At boot time, the firewall is configured based on information stored in the Property List file "/Library/Preferences/com.apple.sharing.firewall.plist". This file lists TCP and UDP ports on which incoming traffic should be accepted, and also defines menu items for use by OS X's graphical firewall configuration tool. By default. the plist file starts like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "
;http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>allports</key>
<array>
<string>3283</string>
<string>22</string>
<string>5900</string>
</array>
<key>alludpports</key>
<array>
<string>3283</string>
<string>123</string>
<string>5900</string>
</array>
....

The allports entry seems to specify which TCP ports are acceptable, and the alludpports entry seems to specify UDP ports. I say "seems" since I haven't been able to find any documentation that explicitly says this.

Note that the plist file only gives you access to a very limited subset of the ipfirewall capabilities. In particular, you can only specify ports (not hosts) and you can only set limits on incoming traffic (not outgoing). For complete access to the abilities of ipfirewall, you can use the command-line "ipfw" tool.

For example, if we wanted to accept traffic destined for port 22, we could type:

ipfw add allow tcp from any to any dst-port 22 in

Type "ipfw list" to see the current list of firewall rules. The port 22 entry under allports in the plist file generates exactly the rule shown in the example above. With ipfw we can go further, though. For example, we might want to only allow hosts on the local network (say, 192.178.1.0) to connect to the ssh port. For information about using ipfw, see the ipfw man page.

The second part of the plist file is a key called "firewall" that defines services that will be displayed in the OS X graphical firewall configuration tool. Here's an excerpt from that part of the file:

....
<key>Remote Login - SSH</key>
<dict>
<key>editable</key>
<integer>0</integer>
<key>enable</key>
<integer>1</integer>
<key>port</key>
<array>
<string>22</string>
</array>
<key>row</key>
<integer>3</integer>
</dict>
....

Each entry contains the name of a service (e.g., "Remote Login - SSH"), an "editable" key, which determines whether users are allowed to enable/disable the service's firewall entries through the graphical interface; an "enable" key, which determines whether the service is on or off by currently; an array of port numbers which must be open in order for this service to work properly; and a key called "row" which determines the order in which the services will be displayed to the user.

In my previous post, I arranged to have the zebedee service start automatically at boot time. Zebedee listens on port 11965, so in order to use it, I needed to open this port in the firewall. I did this by:
  1. copying /Library/Preferences/com.apple.sharing.firewall.plist into a temporary file elsewhere, called junk.plist
  2. running "plutil -convert xml1 junk.plist", since the original file was a binary plist
  3. editing junk.plist with a text editor (emacs, in this case), adding port 11965 to the allports section and adding a "Zebedee" section to the "firewall" key, so this service's ports could be enabled/disabled from the graphical interface.
  4. running "plutil -convert binary1 junk.plist" and then copying the file back to its original location as com.apple.sharing.firewall.plist

After this, I rebooted and checked with "ipfw list" to make sure port 11965 was allowed. (It was.)

At the bottom of the plist file there are a few other flags used by the firewall system. In particular, there's a "loggingenabled" key. If set to 1, firewall information will be logged to the file /var/log/ipfw.log. If you're having trouble connecting to a computer and you suspect it may be a firewall problem, this is the first place to look.

No comments: