Fun with OS X and the Firewall

Tuesday, April 04, 2006, at 08:46AM

By Eric Richardson

As I mentioned that I would a few days ago, I moved our office network from a little Netgear DSL router to letting the Xserve do NAT and firewall.

That went ok, but I was really frustrated by the process of using Apple's firewall configuration through the Server Admin. Fundamentally my issue was that Apple's utility wants to deal in rules defined by IP spaces, and that's just not proper. When dealing with a router type host, it seems clear to me that you need to define your rules based on interfaces. While it's possible to do this in the Advanced settings, that's not at all easy to figure out (in fact I think it would be easier for anyone using that to simply write their own rules).

When I first tried to set up the firewall using the address classes I locked down most everything on the "any" network side (hoping to only allow established traffic back in), and allowed everything on the "10." network. Theoretically that should mean that internal traffic can get out (and back), but external traffic is stymied.

I applied these rules and got nowhere.

First Custom Try

I googled, and found some really basic ipfw rules for doing state and NAT. I eventually ended up with:

#!/bin/sh
IPFW='/sbin/ipfw'
$IPFW -f -q flush
$IPFW add 4 allow ip from any to any 547 via en0

# do NAT
$IPFW add 5 divert natd ip from any to any via en1

# allow all loopback traffic
$IPFW add 25 allow ip from any to any via lo0

$IPFW add 26 allow ip from 255.255.255.255 to any via en0
$IPFW add 30 allow ip from 10.0.0.1 to any via en0 

# deny peopple trying to spoof as local on the external interface
$IPFW add 100 deny ip from 10.0.0.0/8 to any in via en1

# run our state check
$IPFW add 200 check-state

# allow internal traffic and add state
$IPFW add 310 allow ip from 10.0.0.0/8 to any keep-state

# allow local traffic and add state
$IPFW add 400 allow ip from 69.236.151.154 to any keep-state

# allow external access to ssh
$IPFW add 500 allow ip from any to any ssh in via en1

# deny what we haven't approved
$IPFW add 65000 deny ip from any to any

That did NAT just fine, but I didn't find out until Monday morning that it wasn't allowing DHCP connections.

Back to the Admin Tool

Faced with the need for the network to work before more people got in to the office I went back to the admin tool and tried going back to the rules I didn't quite like. Still no luck.

No internal machines could connect to the DHCP server and get an IP address. After a while of blindly clicking things I finally allowed DHCP's port on the any side. Then it dawned on me -- a machine requesting an address via DHCP doesn't have an IP address, and therefore won't match the 10. rules I was pretending applied to all internal hosts.

That had actually been my problem in the custom ruleset as well -- I was filtering off 10.0.0.0/8 instead of just any and the interface.

Fixing the Custom Ruleset

To fix the custom ruleset should just be a matter of adding one rule:

$IPFW add 31 allow ip from any to any 67 in via en0

I haven't had a chance to test that yet, though, so YMMV.

Next up is adding traffic shaping rules.