Mac OS X now has a newer PF than FreeBSD, what else is there to see?
Apple – the home of 'insanely great' and other iconic techie expressions – has enjoyed enormous success with its various iProducts in recent years as well as increasing sales of the constantly reinvented Macintosh line of personal computers.
It is also a well-established if not generally well known fact that Apple, everybody's favorite innovator, is a major consumer of open source technology and that their main pipeline to the freely licensed technology is the FreeBSD project.
Over the years there have been persistent rumors that Apple was interested in using PF as their packet filter, and some version of the code has been available to them for quite a while via FreeBSD. The last released FreeBSD as I'm writing this is 8.2, which still has PF equivalent to OpenBSD 4.1 plus selected patches (FreeBSD derivative pfSense has code roughly equivalent to OpenBSD 4.5, as will the soon-to-be-released FreeBSD 9). So it was a bit surprising to hear at BSDCan last May that the latest code drop from Apple back to the FreeBSD project contained a newer PF version than the regular stable FreeBSD had.
I'm not a regular Mac user (in fact, the last Mac I used on a daily basis was one of the first PowerPC based models), but recently Michael Dexter gave me the chance to do what I assume practically no Apple users ever do: Logging into a freshly installed Mac OS X 10.7 box via ssh.
Once in, you find that regular commands like
man pf.conf work, and
man pf.conf reveals that even if the code may be fresher than the released FreeBSD version, they still use a version with the pre-OpenBSD 4.7 syntax for NAT and redirections, and odder still, the man page has no mention of "match" rules. The lack of
match places them somewhere before OpenBSD's 4.6 version, and since we don't see any mention of
set state-defaults either, we can safely assume that the code is older than version 4.5 (which also introduced NetFlow export via the
pflow state option and the
pflow(4) pseudo-device). So whatever prompted the newer version, they were apparently not aiming for the latest and by all accounts more effcient PF code from OpenBSD.
It is possible that what Apple aimed for with their update were specific performance improvements or bugfixes that would not be in the FreeBSD version. Fortunately, Apple has published the BSD code that went into Lion, and peeking at their
pf.c (which can be found at http://opensource.apple.com/source/xnu/xnu-1699.22.73/bsd/net/pf.c, while the CVS history for the corresponding code in OpenBSD can be seen at http://www.openbsd.org/cgi-bin/cvsweb/src/sys/net/pf.c) we see that the Apple version appears to be based on revision 1.567, the revision that went into OpenBSD version 4.3, three and a half years ago.
Why they stopped there and didn't go any further is a mystery. There were several important performance improvements in the following versions, but no any major shakeups in PF configuration until version 4.7 (excepting perhaps the introduction of the "match" rules and rewritten "scrub" in 4.6), so it is a bit surprising that when Apple decided to do their own PF porting work they didn't jump further.
If Apple had taken the plunge to a modern code base such as OpenBSD 4.9 they would on the one hand have had to brace themselves as well as their users and application developers for the consequences of the syntax changes (see e.g. the tutorial slide at http://home.nuug.no/~peter/pf/ukuug2011/newsyntax.html for an overview) that would have forced people to make changes to their configurations. On the other hand, they would also have benefited from the refinement and rewriting activity (current PF developers sometimes jokingly refer to the older code as "the working prototype") that gives OpenBSD users better performance and a slightly more versatile set of configuration options.
Still at the shell command line, it is possible to take look at Apple's default PF configuration, and it becomes very clear that Apple intended that any user interaction with their machine's packet filtering would be via some sort of front end, likely one or more GUI applications. On a fresh Mac OS X Lion install, the
/etc/pf.conf file contains only these active lines:
load anchor "com.apple" from "/etc/pf.anchors/com.apple"
The rest of the file is made up of comment lines that instruct application developers to make sure they insert their own configuration parts in their own anchors and if necessary enable or disable the packet filter. In those comment lines I found what I at first thought were typos: references to the
-X options to
pfctl does not have these options, they are Apple extensions that indicate that Apple has gone to some lengths to make sure applications that interact with the packet filter configuration do not clobber each others' rules. The two options are documented as
-E Enable the packet filter and increment the pf enable reference count and
-X <token> Release the pf enable reference represented by the token passed.
Meaning, correctly used, applications that interact with your packet filter configuration will be prevented from interfering with rules they did not insert themselves.
The anchor-based configuration style and these extensions show that the PF people at Apple have very sensible ideas on how to run a system. And when you can expect that the user is protected from the finer details of packet filter configuration files by some sort of GUI front end, the end-user impact of skipping to a newer PF version and a slightly changed syntax for parts of as their base could be potentially less than in an environment like OpenBSD or FreeBSD where users are more likely to do their rule set editing by hand.
We can only guess why they only jumped as far as version 4.3 PF this time around (possibly to keep the size of the potenial diff back to FreeBSD's code manageable), but under any circumstances it is encouraging to see that there are people at Apple who take an active interest in PF development. There is perhaps good reason to hope that by their next release, Apple will have warmed to the numerous innovations and improvements to PF that have been introduced by the OpenBSD developers. It is probably not realistic to think that Apple will be in total sync with OpenBSD's code in this particular subsystem, but I for one hope that the code bases will be made to diverge less rather than more in the future.
Apple would probably help things along considerably if they started communicating directly with the OpenBSD developers who are actively involved in PF development, instead of treating the FreeBSD project as their only gateway to the open source world. We approached them. As several developers keep saying privately, Apple and other consumers of OpenBSD code such as PF and OpenSSH would do well to treat the code less like an obligation-free gift and more like a cooperative research and business effort, even if they strictly speaking are under no legal obligation to do so.
We have no problem with them using or code but we do not appreciate that they subjected it to the Apple Public Source License. They introduce some interesting ideas such as a ref count of how many times PF has been enabled or disabled but we are unable to use their implementation. Furthermore, the Apple Public Source License introduces contract law to an environment that only relied on copyright law. This is unfortunate.
Apple appears only to be interested in controlling the network access of applications, rather than building network infrastructure.
It should also come as no surprise that Apple expects users to enable and configure their firewall through graphical tools. You can enable configure the Mac OS X 10.7 firewall through
System Preferences: Security & Privacy: Firewall. You will likely need to
Click the lock to make changes. which will allow you to
Stop the firewall.
Once authenticated, you will find a limited set of
Advanced... options that will probably dissapoint any experienced PF user:
Advanced... button provides:
Allow incoming connections will give the option of
Block incoming connections
Clicking the plus symbol will simply open an open dialog box that defaults to the Applications folder, allowing one to choose an application and apply the above options.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>allowsignedenabled</key> <integer>1</integer> <key>applications</key> <array> <dict> <key>alias</key> <data> PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4K PCFET0NUWVBFIHBsaXN0IFBVQkxJQyAiLS8vQXBwbGUvL0RURCBQ TElTVCAxLjAvL0VOIiAiaHR0cDovL3d3dy5hcHBsZS5jb20vRFRE cy9Qcm9wZXJ0eUxpc3QtMS4wLmR0ZCI+CjxwbGlzdCB2ZXJzaW9u PSIxLjAiPgo8ZGF0YT4KQUFBQUFBRTZBQUlBQVFkTllXTkNiMjly QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFES2RkK0lTQ3NBQUFB QUFKTUpRV1JwZFcwdQpZWEJ3QUFBQUFBQUFBQUFBQUFBQUFBQUFB QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB QUFBQUFBQUFBQUFBCkFCR0JxTXFJM3hRQUFBQUFBQUFBQVAvLy8v OEFBQWtnQUFBQUFBQUFBQUFBQUFBQUFBQUFERUZ3Y0d4cFkyRjBh Vzl1Y3dBUUFBZ0EKQU1wMlFmZ0FBQUFSQUFnQUFNcUpRWVFBQUFB QkFBUUFBQUNUQUFJQUgwMWhZMEp2YjJzNlFYQndiR2xqWVhScGIy NXpPZ0JCWkdsMQpiUzVoY0hBQUFBNEFGQUFKQUVFQVpBQnBBSFVB YlFBdUFHRUFjQUJ3QUE4QUVBQUhBRTBBWVFCakFFSUFid0J2QUdz QUVnQVdRWEJ3CmJHbGpZWFJwYjI1ekwwRmthWFZ0TG1Gd2NBQVRB QUV2QVAvL0FBQT0KPC9kYXRhPgo8L3BsaXN0Pgo= </data> <key>bundleid</key> <string>com.adiumX.adiumX</string> <key>state</key> <integer>0</integer> </dict> ... <key>state</key> <integer>0</integer> </dict> </array> <key>exceptions</key> <array> <dict> <key>path</key> <string>/usr/libexec/configd</string> <key>state</key> <integer>3</integer> </dict> ... </array> <key>explicitauths</key> <array> <dict> <key>id</key> <string>org.python.python.app</string> </dict> </array> ... <key>firewall</key> <dict> <key>Apple Remote Desktop</key> <dict> <key>proc</key> <string>AppleVNCServer</string> <key>state</key> <integer>0</integer> </dict> </dict> ... <key>firewallunload</key> <integer>0</integer> <key>globalstate</key> <integer>1</integer> <key>loggingenabled</key> <integer>1</integer> <key>previousonstate</key> <integer>1</integer> <key>stealthenabled</key> <integer>0</integer> <key>version</key> <string>1.0a24</string> </dict> </plist>
That being the case, it is nonetheless historic that Apple has shipped more copies of PF in iOS and Mac OS X 10.7 than all of the BSD projects combined.
CFT will explore the networking capabilities of Mac OS X's PF and determine its potential as a "gateway drug" to increase BSD and PF usage among Mac OS X users.
Copyright © 2011 – 2013 Michael Dexter unless specified otherwise. Feedback and corrections welcome.