pfctl - howto add an anchor and make it active / load it
Solution 1:
In my understanding of pf your major anchor is missing. You may either use Apple's anchor(s) or a user defined anchor.
A user defined anchor is preferred:
-
Modify /private/etc/pf.conf:
Add two lines to pf.conf like this:
... load anchor "com.apple" from "/etc/pf.anchors/com.apple" # # usr.home anchor point # anchor "usr.home/*" load anchor "usr.home" from "/etc/pf.anchors/usr.home"
-
Create a file usr.home. In the example below I create an anchor SSH blocking SSH access from a local network to some IPs of the host:
sudo nano /etc/pf.anchors/usr.home
and add
# # usr.home ruleset, referred to by the modified /etc/pf.conf file. # See notes in that file regarding the anchor point in the main ruleset. # # # SSH anchor point. # anchor "SSH" load anchor "SSH" from "/etc/pf.rules/pfssh.rule"
-
Now create a new directory
sudo mkdir /etc/pf.rules
and the referenced file with:
sudo nano /etc/pf.rules/pfssh.rule
and the following content:
block in quick inet proto { tcp, udp } from 10.0.0.0/8 to { 10.128.8.145, 10.129.8.145 } port 22
-
Parse and test your pf.conf and your anchor file to make sure that they are error-free:
sudo pfctl -vnf /etc/pf.conf sudo pfctl -vnf /etc/pf.anchors/usr.home
-
Reload pf:
sudo pfctl -d sudo pfctl -e -f /etc/pf.conf
You can add additional anchors to your major usr.home anchor as demontrated in the major com.apple anchor.
You can also add additional dynamic sub-anchors with the following command (here I add a temporary block HTTP rule similar to the SSH rule - check the creation of a transitory sub-anchor: usr.home/HTTP here!):
echo "block drop in quick proto tcp from 10.0.0.0/8 to any port 80" | sudo pfctl -a usr.home/HTTP -f -
The temporary anchor doesn't survive a reboot!
One possible command to remove the temporary rule immediately is:
echo "" | sudo pfctl -a usr.home/HTTP -f -
A handy script to check all loaded anchors and rules is pfdump:
pfdump.sh:
#!/bin/bash
function pfprint() {
if [ -n "$1" ];then
sudo pfctl -a "$2" -s"$1" 2>/dev/null
else
sudo pfctl -s"$1" 2>/dev/null
fi
}
function print_all() {
local p=$(printf "%-40s" $1)
(
pfprint r "$1" | sed "s,^,r ,"
pfprint n "$1" | sed "s,^,n ,"
pfprint A "$1" | sed "s,^,A ,"
) | sed "s,^,$p,"
for a in `pfprint A "$1"`; do
print_all "$a"
done
}
print_all
All files mentioned require an empty new line at the end!