pf on OS X 10.7
Wednesday, 09. 14. 2011 – Category: sw
Today’s the first day that my new laptop, which runs OS X 10.7 (Lion), will sit on an untrusted network so I figured it was time to port my firewall rules across from the old one, that ran OS X 10.6 (Snow Leopard).
I cut my UNIX teeth at a cryptoanarchist shop whose culture of paranoia makes me wary of Apple’s own firewall with its emphasis on letting all the hot shinyness Just Work rather than being overly fussy about inbound connections. Furthermore, with IPv6 tunnels like aiccu, you aren’t behind the warm fuzzy comfort of NAT, you’re just there on the net with all the fun that entails. So, worth having some extra protection I reckon.
10.6 (and earlier) came with ipfw
, a packet filter that’s knocked around the BSD world for some time. It works but isn’t overly featuresome (for example, it doesn’t support NAT in-kernel, so you monkey about passing packets to an external daemon). But it was Good Enough for an end system so I supplemented the system’s “Application Firewall” with an additional ipfw
ruleset to give an approximation of safety when out and about, and way more permissive when on networks I trust.
On 10.6 I used WaterRoof to sort-of manage the ipfw
rules: in that I only really used its launchd loader and would hack on the rules by hand. In the spirit of decrufting I figured I’d sort that myself and went to remind myself how to load ipfw
rules enmasse. I noticed at the top of man page:
NAME
ipfw -- IP firewall and traffic shaper control program (DEPRECATED)
...
DESCRIPTION
Note that use of this utility is DEPRECATED. Please use pfctl(8) instead
Deprecated? Use pfctl
instead? Good news everyone – OS X 10.7 now comes with pf
, another BSD packet filter that I’ve chosen of ipfw
on BSD hosts for years off the back of its featureset (native NAT, state syncing between failover firewall pairs, traffic queing…).
Anyway, the point of this post is to point out a few things I noticed which are intriguing. Firstly, pf
is not enabled by default. Further, Apple have added some moving parts around how it is enabled. From /etc/pf.conf
:
# This file contains the main ruleset, which gets automatically loaded
# at startup. PF will not be automatically enabled, however. Instead,
# each component which utilizes PF is responsible for enabling and disabling
# PF via -E and -X as documented in pfctl(8). That will ensure that PF
# is disabled only when the last enable reference is released.
These two flags,
-E
and -X
, are absent from pf
on BSD. Here’s how they’re documented on OS X:
-E Enable the packet filter and increment the pf enable reference count.
-X token
Release the pf enable reference represented by the token passed.
This suggests that different system components might choose to enable and disable
pf
, and this is the mechanism to coordinate that. There’s a clue about which components in /etc/pf.anchors/com.apple
, which is loaded by the main /etc/pf.conf
. It defines additional rule anchors:
anchor "100.InternetSharing/*"
anchor "200.AirDrop/*"
anchor "250.ApplicationFirewall/*"
Interestingly, this host’s ApplicationFirewall has a bunch of entries in when viewed in the Preferences GUI, yet the pf
anchor of the same name is empty (and pf
was disabled when I started out):
$ sudo pfctl -a com.apple/250.ApplicationFirewall -s rules
Password:
No ALTQ support in kernel
ALTQ related functions disabled
so I’m unsure what the status of this mechanism is. I’ve not had occasion to use AirDrop or connection sharing, but would be curious to see if either use these anchors and enable
pf
temporarily.
Finally, what’s the token that’s passed to -X
? You can ask pfctl
for the current tokens:
$ sudo pfctl -s References
No ALTQ support in kernel
ALTQ related functions disabled
TOKENS:
PID Process Name TOKEN TIMESTAMP
17013 pfctl 18446743524308110600 0 days 01:05:50
I enabled
pf
with pfctl
, so that makes sense. When I did so it didn’t inform me of the token, but I suppose an enabling process would spelunk the token shortly after enabling pf
by merit of its name and PID
and pass it back when it’s finished with pf
.
Now, on with the actual job of ruleset writing and puzzling out the launchd
voodoo required to enable it at boot.
Minor whinge: Apple could do with updating /etc/protocols
:
# $FreeBSD: src/etc/protocols,v 1.14 2000/09/24 11:20:27 asmodai Exp $
Why whinge? It doesn’t know
icmp6
is a valid alias for ipv6-icmp
. Yep, minor.
4 Responses to “pf on OS X 10.7”
Recent articles
- Docker, SELinux, Consul, Registrator
(Wednesday, 04. 29. 2015 – No Comments) - ZFS performance on FreeBSD
(Tuesday, 09. 16. 2014 – No Comments) - Controlling Exim SMTP behaviour from Dovecot password data
(Wednesday, 09. 3. 2014 – No Comments) - Heartbleed OpenSSL vulnerability
(Tuesday, 04. 8. 2014 – No Comments)
Archives
- April 2015
- September 2014
- April 2014
- September 2013
- August 2013
- March 2013
- April 2012
- March 2012
- September 2011
- June 2011
- February 2011
- January 2011
- October 2010
- September 2010
- February 2010
- September 2009
- August 2009
- January 2009
- September 2008
- August 2008
- July 2008
- May 2008
- April 2008
- February 2008
- January 2008
- November 2007
- October 2007
- September 2007
- August 2007
- December 2006
- November 2006
- August 2006
- June 2006
- May 2006
- March 2006
- February 2006
- January 2006
- December 2005
- November 2005
- October 2005
October 31st, 2011 at 5:55 am
This post was a help.
I have been struggling with getting port forwarding to work under Lion (not server) for my media mac to an AVR connected by wire.
Getting the AVR to see the internet was no problem, just configuring the net interfaces (internal must be 192.168.2.0 until apple fixes that bug) and turning on InternetSharing.
But port forwarding for the AVR’s control port was not working after trying all sorts of things.
I realized that InternetSharing sets rules to PF once it starts, under the anchors that are predefined in /etc/pf.anchors/com.apple.
If you probe with pfctl after starting InternetSharing, you can see the rules and new anchors that it created.
One of the anchors was ‘natpmp’.
I used this command to set my rules and it worked!
pfctl -a com.apple/100.InternetSharing/natpmp -f 910.onkyo
(obviously rules are in 910.onkyo)
So, I did not set my own anchor (which didn’t work). It only worked when I associated my rules with that anchor.
This has to be done after InternetSharing is started, of course.
I imagine an application such as InternetSharing enables pf, loads rules, then pf only responds to rules below the anchor for the application(s) that activated it.
Ron
December 22nd, 2011 at 10:45 pm
Just wondering if you’ve made any progress on loading custom rules via 205.ApplicationFirewall ??
I’m trying to set up a rule that restricts to a specific subnet.
Something along the lines of this:
pass in inet proto tcp from $subnet to port 22
December 23rd, 2011 at 12:39 am
No, I haven’t – I’m using my own anchor and activating pfctl directly. See Ron’s comment above for an example of hooking into a pre-defined system anchor, which raises an interesting point about rule scope around these anchors.
February 10th, 2012 at 1:50 pm
Actually it’s a very strange idea to get pf from BSD instead of just do update ipfw to current BSD version (which is supports a bunch of features and, of cause, kernel NAT)