where to put pfctl rules to make them persistent

ok i found out how to use pfctl on OS X Mavericks/Server 3


i have some set of rules and they work if i type two commands:


pfctl -e # to enable packet filter

pfctl -f myrules


but where should i put all this to be persistent (across reboots and OS upgrades)

What i a recommended place?

OS X Mountain Lion (10.8.5)

Posted on Oct 28, 2013 3:09 AM

Reply
12 replies

Oct 28, 2013 3:51 PM in response to Akorzh

Lingon is a GUI that allows access to the launchd data; there's an older free version of the app around, and there's a version of Lingon in the App Store. There are launchd examples around the 'net, as well.


For finding your way 'round the Unix layers of the file system and related, see the File System Programming Guide (PDF) (HTML); that has an intro to the Mac app directories, to sandboxing on OS X, and to the Unix directories.

Oct 30, 2013 2:18 AM in response to Leland Wallace

yeah thanks i also guessed to add -e string myself.

but the rules do not load at boot:


what i have is right permissions/owner:


bash-3.2# ls -l com.apple.pf*

-rw-r--r-- 1 root wheel 647 29 окт 13:23 com.apple.pfctl.plist

-rw-r--r-- 1 root wheel 138 24 окт 19:11 com.apple.pfd.plist


and following contents:


bash-3.2# cat com.apple.pfctl.plist

<?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>Disabled</key>

<false/>

<key>Label</key>

<string>com.apple.pfctl</string>

<key>WorkingDirectory</key>

<string>/var/run</string>

<key>UserName</key>

<string>root</string>

<key>GroupName</key>

<string>wheel</string>

<key>Program</key>

<string>/sbin/pfctl</string>

<key>ProgramArguments</key>

<array>

<string>pfctl</string>

<string>-e</string>

<string>-f</string>

<string>/etc/pf.conf</string>

</array>

<key>RunAtLoad</key>

<true/>

</dict>

</plist>


but rules are not loaded at boot so i have to run sudo pfctl -e -f /etc/pf.conf


so anyone can suggest what is wrong in my setup?

Oct 30, 2013 7:07 AM in response to Leland Wallace

I had the same problem.


It turned out that the ProgramArguments are not correct in the original plist file.

Changing

<string>pfctl</string>

into

<string>/sbin/pfctl</string>

and adding

<string>-e</string>

solved my issue.


My complete plist file is:

<?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>Disabled</key>

<false/>

<key>GroupName</key>

<string>wheel</string>

<key>Label</key>

<string>com.apple.pfctl</string>

<key>Program</key>

<string>/sbin/pfctl</string>

<key>ProgramArguments</key>

<array>

<string>/sbin/pfctl</string>

<string>-e</string>

<string>-f</string>

<string>/etc/pf.conf</string>

</array>

<key>RunAtLoad</key>

<true/>

<key>UserName</key>

<string>root</string>

<key>WorkingDirectory</key>

<string>/var/run</string>

</dict>

</plist>

Oct 28, 2013 2:51 PM in response to Akorzh

To minimise the disruption to the system (there are several services that muck with pf)

add your rules in an anchor file (in a file under /usr/local) and add the anchor to the

system anchors file in:

/etc/pf.anchors/com.apple


pf can be set to start at boot via launchd

sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.pfctl.plist


launchd is the Mac OS X "replacement" for init & init scripts.


HTH

- Leland

Oct 29, 2013 1:40 PM in response to Akorzh

no that will just make sure the rules are loaded correctly.


you can edit the plist file to add a -e to the pfctl command though.


<key>ProgramArguments</key>

<array>

<string>pfctl</string>

<string>-e</string> <<<<< add this line

<string>-f</string>

<string>/etc/pf.conf</string>

</array>


And it will start pf at boot, though not as early in the boot process as one would hope.


HTH

- Leland

Oct 31, 2013 3:27 AM in response to Akorzh

so it looks weird: just after boot:

We see that initially pfctl is not loaded, but the lauchctl has it already loaded.

after unload and load it works...

So any ideas?


bash-3.2# pfctl -sr

No ALTQ support in kernel

ALTQ related functions disabled

bash-3.2# launchctl load -w /System/Library/LaunchDaemons/com.apple.pfctl.plist

com.apple.pfctl: Already loaded

bash-3.2# launchctl unload /System/Library/LaunchDaemons/com.apple.pfctl.plist

bash-3.2# launchctl load -w /System/Library/LaunchDaemons/com.apple.pfctl.plist

bash-3.2# pfctl -sr

No ALTQ support in kernel

ALTQ related functions disabled

scrub-anchor "com.apple/*" all fragment reassemble

anchor "com.apple/*" all

Dec 18, 2013 2:43 AM in response to Akorzh

Credit where it's due: Keith Stattenfeld confirmed my hunch independently, and Scott Lowe actually had the problem solved, though I didn't realize it until later.


When you use

pfctl
with the
-f
flag, you get an output message warning that using
-f
with a filename other than
/etc/pf.conf
can result in rules and anchors and such getting overwritten (because you're starting it with a file other than the default file). This isn't a problem when using
-f /etc/pf.conf
, but
pfctl
doesn't know that, so it tries to print this "helpful" message before exiting normally with status 0.


This all works fine when you're doing it from the command line. But when you ask

launchd
to do it for you, there is no output set up for
stdout
or
stderr
, and this causes
pfctl
to exit abnormally with status 1, not starting the packet filter.
launchd
unhelpfully reports only that it exited with status 1 and didn't start, and you're left to puzzle out why.


You could probably add a "quiet" flag to

pfctl
to suppress this, but having less information is what got us into this mess in the first place. As noted at the top, Scott Lowe figured this out for Mountain Lion and it still works. The link goes to a launchd item you can add to do the trick. Notice how it sets up standard out and standard error with log files, so when there are errors, they actually get written somewhere you can read! His login item does not set the working directory to
/var/run
, but you can add that.


You can just drop this in a new

launchd
plist, and leave the system one as it is. The system one exits because it can't write the message it wants to write, and then your new launchd item will try again and get it right. Alternatively, if Apple fixes the
pfctl
item for
launchd
, it will start correctly and then yours will exit (with proper logging!) because the packet filter is already running. Either way, the answer is "
pfctl
wants to write text, so set up standard output and error channels so it can write text."

Dec 18, 2013 8:19 AM in response to Akorzh

The way we are handling pftcl is a bit of cheat, i.e. the best way 🙂


We have used IceFloor to edit the rules. See http://www.hanynet.com/icefloor/


IceFloor installs its own launchdaemon and a shell script and creates its own pf config files. (So that it does not get upset with any Apple changes to the standard pf files.)


Rather than installing IceFloor on every Mac we have copied the launchdaemon, shellscript and config files to every client Mac and when they are rebooted the launchdaemon runs the shell script which starts pf with the config files we built with IceFloor. I have even written an installer package using Apple's PackageMaker to copy all the files in to the right places which gets installed by DeployStudio during imaging.

This thread has been closed by the system or the community team. You may vote for any posts you find helpful, or search the Community for additional answers.

where to put pfctl rules to make them persistent

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple Account.