Quick and dirty fix for 10.2

October 2nd, 2002: 10.2 changes a few things. I don't have time to update the web page, but David Mackler provided me with a new set of rules that include modification to get the IP correctly, use the new state-aware firewall, allow rendezvous to work properly and a new StartupItem. Read the present web page, but use this file instead of the one provided below.

Setting up firewall rules on Mac OS X 10.1

Preamble

This page describes how I set up firewall rules on my Mac OS X 10.1 home computer using the built-in firewall (ipfw). You need to use a terminal. If you want something simpler, go get the excellent Brick House or Firewalk which both have simple options and a nice interface. However, if you have a dynamic IP, you can't use them (at least the last time I checked): the IP address changes and you need to change the rules to reflect that. Moreover, I have a tiny private network to share files with an iBook which means I actually have two IP addresses: the outside IP (on interface pppoe0, dynamic IP) and an internal IP (inside interface en0, fixed IP 192.168.0.1). This configuration allows me to plug in an iBook at anytime at the back of my G4 and log in to kill jobs if I ever lose the console (not that I ever did, but it's nice to have it there).

With a dynamic IP, you must make sure that the firewall is always synchronized with your IP. For instance, if you disconnect, then reconnect, your IP might have changed, but your firewall rules have not. You must then change the firewall rules to reflect the change of your IP. A script is available at the bottom of this page to do just that.

It might come to your attention at that point that your DNS Agent seems to timeout pretty often, especially when you set up the rules. I don't know why that is.

The layout for the code (black outline, dark background) is identical to the one used on the very useful Stepwise. I thought it looked good.

ipfw firewall rules for Mac OS X 10.1

I deserve no credit whatsoever since Peter Brezny at BSDToday has published an article on that. The original of this file can be found at http://www.bsdtoday.com/2000/December/Features359.html. The only thing I did is to make slight modifications:

Modify the file to suit your needs: outside interface (pppoe? ppp?) and inside interface (necessary?) as well as mail, ns1, ns2 and ntp. I left all of the original comments in and commented out the lines I modified. I found a few interesting tutorials on Firewalls at OnLamp.com if you want more info. Hopefully, my modifications are correct. Feel free to email me for corrections.

Download

You can get all the necessary files in the tar file MacOS_X_Firewall.tar. The tar file contains:

The firewall rules

The rules are described below. To execute it, do sh rc.firewall.current as root, or sudo sh rc.firewall.current. Once you know it works, you can set up the computer to start the firewall automatically. The log is found at /var/log/system.log. If you make a mistake and it locks up, wait or type ipfw flush, look at the system.log and start over. You can look up every denied connection by typing grep "Deny" /var/log/system.log. I highlited my changes in blue.

You need to modify the document in order to provide some information about your configuration, right after the line that says: # Define your variables.

rc.firewall.current:


#!/bin/sh

# Originally found at http://www.bsdtoday.com/2000/December/Features359.html
# By Peter Brezny
# Modifications done to support dynamic IP and default OS X configuration
# Available at: http://www.novajo.ca/firewall.html
#
# Simple stateful network firewall rules for IPFW with NAT v. 1.01
# See bottom of file for instructions and description of rules
# Created 20001206206 by Peter Brezny, pbrezny@purplecat.net (with a great
# deal of help from freebsd-security@freebsd.org).  Specific questions
# about the use of ipfw should be directed to freebsd-ipfw@freebsd.org or
# more general security questions to freebsd-security@freebsd.org.
# Use this script at your own risk.
#
# if you don't know the a.b.c.0/xx notation for ip networks the ipsubnet
# calculator can help you. /usr/ports/net/ipsc-0.4.2
#
###########################
# Note: This does not apply to Mac OS X
#
# Brief Installation instructions
#
#	Name this script /etc/rc.firewall.current
#	Edit /etc/rc.conf to include
#		gateway_enable="YES"
#		firewall_enable="YES"
#		firewall_script="/etc/rc.firewall.current"
#		natd_enable="YES"
#		natd_interface="***"  #replace with your external ifX
#		natd_flags="-dynamic"
#	Make sure your kernel is configured to handle ipfw and natd
#	See the FreeBSD handbook on how to do this.
#
############################
# Make sure logging is enabled (disabled by default)
if [ `/usr/sbin/sysctl -n net.inet.ip.fw.verbose` == 0 ] ; then
        /usr/sbin/sysctl -w net.inet.ip.fw.verbose=1
fi

#
# Define your variables
#
fwcmd="/sbin/ipfw"	#leave as is if using ipfw
oif="ppp0"		#set to outside interface name: for DSL ppp0 in 10.1.x, pppoe0 in 10.0.x
			#set to outside ip address
oip=`/sbin/ifconfig $oif| grep inet | awk '{ print $2 }'`;
onwr="$oip/8"		#set to outside network range
iif="en0"		#set to internal interface name
inwr="192.168.0.0/16"	#set to internal network range
iip="192.168.0.1"	#set to internal ip address
mail="your.mail.server" # mail server sometimes requires 113

ns1="your.name.server"	#set to primary name server best if = oif
ns2="your.name.server"	#set to secondary name server best if = oif
ntp="your.time.server"	#set to ip of NTP server or leave as is

#
# End of required user input if you only intend to allow ssh connections to
# this box from the outside. If other services are required, edit line 96
# as necessary.
#
###
# Rules with descriptions
#
#       Basic rules: there is no need to modify anything in this first section.
#       This is the bare minimum to block simple spoofing.
###
#
#	Force a flush of the current firewall rules before we reload
	$fwcmd -f flush

#	Allow your loop back to work
	$fwcmd add allow all from any to any via lo0

#	Prevent spoofing of your loopback
	$fwcmd add deny log all from any to 127.0.0.0/8


#	Allow DNS traffic from internet to query your DNS (for reverse
#	lookups etc).
#	(Seems to be necessary to put it here to make sure lookups are allowed ASAP)
#	$fwcmd add allow udp from any 53 to $ns1 53 via $oif (Good with dynamic rules)
#	$fwcmd add allow udp from any 53 to $ns2 53 via $oif (Good with dynamic rules)
	$fwcmd add allow udp from any 53 to $oip via $oif
	$fwcmd add allow udp from $oip to any 53 via $oif

#
#	Stop spoofing of your internal network range
	$fwcmd add deny log ip from $inwr to any in via $oif
#
#	Stop spoofing from inside your private ip range
	$fwcmd add deny log ip from not $inwr to any in via $iif
#
#	Stop private networks (RFC1918) from entering the outside interface.
	$fwcmd add deny log ip from 192.168.0.0/16 to any in via $oif
	$fwcmd add deny log ip from 172.16.0.0/12 to any in via $oif
	$fwcmd add deny log ip from 10.0.0.0/8 to any in via $oif
	$fwcmd add deny log ip from any to 192.168.0.0/16 in via $oif
	$fwcmd add deny log ip from any to 172.16.0.0/12 in via $oif
	$fwcmd add deny log ip from any to 10.0.0.0/8 in via $oif
#
# 	Stop draft-manning-dsua-01.txt nets on the outside interface
	$fwcmd add deny log all from 0.0.0.0/8 to any in via $oif
	$fwcmd add deny log all from 169.254.0.0/16 to any in via $oif
	$fwcmd add deny log all from 192.0.2.0/24 to any in via $oif
	$fwcmd add deny log all from 224.0.0.0/4 to any in via $oif
	$fwcmd add deny log all from 240.0.0.0/4 to any in via $oif
	$fwcmd add deny log all from any to 0.0.0.0/8 in via $oif
	$fwcmd add deny log all from any to 169.254.0.0/16 in via $oif
	$fwcmd add deny log all from any to 192.0.2.0/24 in via $oif
	$fwcmd add deny log all from any to 224.0.0.0/4 in via $oif
	$fwcmd add deny log all from any to 240.0.0.0/4 in via $oif
#
###
#       User rules: Some of the rules below are dependent on your configuration.
#       They might require some adjustments. They are emphasized with the
#       word "ADJUST".
###
# 	ADJUST: If you use NATD (for your 192.168.0.1 interface for instance)
# 	you must uncomment the following:
#	Divert all packets through natd
#	$fwcmd add divert natd all from any to any via $oif

#
#	Allow all established connections to persist (setup required
#	for new connections).
	$fwcmd add allow tcp from any to any established

#
#	ADJUST: Allow incoming requests to reach the various services.
#	To allow multiple services you may list them separated
#	by a coma, for example ...to $oip 22,25,110,80 setup
#	If you have an internal interface (e.g. if you do not run NATd) 
#	uncomment the second line to enable AppleTalk on it.
#	$fwcmd add allow tcp from any to $oip 22 setup
	$fwcmd add allow tcp from any to $oip 21,22,80,548 setup
#	$fwcmd add allow tcp from any to $iip 548 setup via $oif
	
#
#	NOTE: you may have to change your client to passive or active mode
#	to get ftp to work once enabled, only ssh, ftp and appletalk enabled by default.
#	21:ftp            enabled by default
#	22:ssh            enabled by default
#	23:telnet
#	25:smtp
#	110:pop
#	143:imap
#	80:http
#	443:ssl
#	548:appleshare    enabled by default

#
#	Allow icmp packets for diagnostic purposes (ping traceroute)
#	you may wish to leave commented out.
	$fwcmd add allow icmp from any to any
#
#	Allow required ICMP
	$fwcmd add allow icmp from any to any icmptypes 3,4,11,12
#
#	Allow time update traffic
	$fwcmd add allow udp from $ntp 123 to $oip 123

#	Politely and quickly rejects AUTH requests (e.g. email and ftp)
	$fwcmd add reset tcp from $mail to $oip 113
#
#	Checks packets against dynamic rule set below.
#	$fwcmd add check-state (Does not work in OS X)
#
#	Allow any traffic from firewall ip to any going out the
#	external interface
#	$fwcmd add allow ip from $oip to any keep-state out via $oif (Does not work in OS X)
	$fwcmd add allow ip from $oip to any out via $oif
#
#	Allow any traffic from local network to any passing through the
#	internal interface
#	$fwcmd add allow ip from $inwr to any keep-state via $iif (Does not work in OS X)
	$fwcmd add allow ip from $inwr to any via $iif

#
#	Deny everything else
	$fwcmd add 65435 deny log ip from any to any
#
#####################################################
#
# End firewall script.


Installing and starting the firewall

You need either option 1) or option 2), not both.

1) Dynamic IP address with ppp connection (most modems)

There used to be a shell script that would monitor the IP address and adjust the firewall accordingly when required. This broke with 10.1.x. However, I found out in the mean time that there is a much simpler way of doing that. With a ppp connection (i.e. modem), two scripts are automatically called when the connection is up and when the connection is taken down. They are /etc/ppp/ip-up and /etc/ppp/ip-down (see man pppd for more info in the terminal). Hence, one simply has to start the firewall in /etc/ppp/ip-up and flush the firewall in /etc/ppp/ip-down. I have provided two very simple ip-up and ip-down scripts. It assumes you will keep rc.firewall.current in /usr/local/sbin/. The script ip-up also works around a small bug in natd for 10.1 where it does not reset itself after a change of IP address (look at ip-up for more info, but it is pretty trivial).

Dynamic IP: start firewall when connection is up

cd /wherever/you/downloaded/MacOS_X_Firewall

sudo install -o root -g admin -m 0700 rc.firewall.current /usr/local/sbin/
sudo install -o root -g admin -m 0770 ip-up ip-down /etc/ppp/

You do not need anything in the /Library/StartupItems/ directory and if you do have a /Library/StartupItems/Firewall directory, you should delete it. You are done.

2) Static IP address without ppp

The best thing to do with a static IP address is to set up the firewall at boot time by adding an item in /Library/StartupItems/Firewall/. In the archive provided above, you will find Firewall and StartupParameters.plist which you will copy into /Library/StartupItems/. It assumes you will keep rc.firewall.current in /usr/local/sbin/.

Static IP: start firewall on startup

cd /wherever/you/downloaded/MacOS_X_Firewall

sudo install -o root -g admin -m 0700 rc.firewall.current /usr/local/sbin/
sudo install -o root -g admin -m 0770 Firewall StartupParameters.plist /Library/StartupItems/Firewall/

Next time you reboot, the firewall will be up. For now, you should simply do: sudo /Library/StartupItems/Firewall/Firewall. No need to reboot, you are done.

Troubleshooting

There are a few problems when you have a firewall:

Contact information

You can email me at dccote@novajo.ca for corrections, comments or questions.