Tiger's Improved Firewall (and How to Use It)

As with all the major upgrades to OS X, Apple has made much of the many enhancements and new features available in Tiger. Under the banner of improved stability and security was an upgrade to the firewall software, ipfw. More than bug fixes and polish, this update introduced a whole new firewall called ipfw2. It works just the like the old firewall, but has some new features that allow greater flexibility and more control. In this article I'll show you some of the new features and how you can use them to make managing your firewall easier.

Turning the Firewall On and Off

Against our better judgement, there are times when we just want to turn the firewall off for a moment and then turn it back on. The old firewall provided no means to do this other than to shut down the firewall and then bring it back up again. A firewall with a lot of rules did not load very quickly. With ipfw2 we can disable the firewall without shutting it down and turn it back on in an instant. First, to turn it off:

$ sudo ipfw disable firewall

All the rules are still loaded, but now all traffic is passing through on the default rule 65535 that lets everything in. If you are sharing your internet connection over another port, then this too will have stopped working as Internet Sharing adds a rule to the firewall so that it can divert traffic between your AirPort and your Ethernet port. With the firewall disabled, you will no longer be sharing your internet connection. To turn it back on:

$ sudo ipfw enable firewall

Everything is now back the way it was.

When the firewall is disabled, there is no easily visible indication. If you run sudo ipfw show it will list the all the rules despite none of them being active. To check whether the firewall is up or down you need to examine a sysctl variable to see what value it returns:

$ sysctl net.inet.ip.fw.enable
net.inet.ip.fw.enable: 0

A value of 0 indicates that the firewall is disabled, and a 1 that it's enabled.

Organizing Your Rules into Sets

When creating your own rules, you'll probably be thinking of your various rules as being members of a set ("these are the ports I must open for the services I am running" or "these are the IP addresses of the hackers that I wish to block"). To implement this with the old firewall, the best you could do was group the rules by their numbers; there was little you could do to manipulate them beyond that. ipfw2 introduces the concept of sets and allows sets of rules to be manipulated as a group. So, assuming all your services were in set 4, you could turn off access by simply issuing the command:

$ sudo ipfw set disable 4

If we look at our rules we can see that they are disabled. The -S option makes ipfw display the set numbers. By default ipfw does not display set numbers, and without -S it would not list the disabled rules at all.

$ sudo ipfw -S show
...
# DISABLED 50000 set 4 allow tcp from any to any dst-port 22 in
# DISABLED 50001 set 4 allow tcp from any to any dst-port 80 in
# DISABLED 50002 set 4 allow tcp from any to any dst-port 443 in via en1
# DISABLED 50003 set 4 allow tcp from any to any dst-port 123 in via en1
...

To turn them back on again you just need to issue the following:

$ sudo ipfw set enable 4

This means you can stop any new connections accessing your services without having to stop services or break any established connections. If you suspect that the addresses you are blocking are causing some problems, you can turn that set off for a quick test to track the problem down without having to take the whole firewall down. However there is a little bug with the enable command, nothing serious, just an inconvenience. I'll come to it later.

You can organize your rules into 32 sets for easier management. These are numbered 0 to 31 with set 31 being special. Rules in set 31 are not removed when you flush the firewall. By default, rule 65535 (the rule that is always there) is a member of set 31. With sets you can quickly change the configuration of your firewall without having to stop and start. You could select an empty set (21 for argument), disable set 21, add the new rules to the set and then enable it. This way you can bring all the new rules on line at once without having to impact the rest of the configuration. To see which sets are enabled and which are not, just issue this command: