Home arrow Guides arrow PF Firewall Quick Guide
PF Firewall Quick Guide PDF
Monday, 13 June 2011
   This tutorial is about PF Firewall.

To enable pf firewall add the following lines in /etc/rc.conf

Example 1. Very Simple Firewall for a desktop or laptop
Add the following lines to /etc/pf.conf :

# very simple firewall
# will allow only connections initiated from the machine
# connections initiated from outside will be blocked

block in all
pass out all keep state

In later PF incarnations previous rules are equivalent with:

block in all
pass out all

The rule "pass out all" is interpreted with keep state by default.

Example 10. Redirect HTTP Traffic With PF on a Bridge
Let's asume you have two network cards: em0 and em1 and bridge configured with both of them:


ifconfig_bridge0="addm em0 addm em1 up"
ifconfig_bridge0_alias0="inet netmask"

Create the following /etc/pf.conf file:


rdr on $int_if inet proto tcp from any to any port www -> port 8080

pass in quick on $int_if route-to lo0 inet proto tcp from any to port 8080 keep state

Set the following sysctl variable to 1:

  sysctl -w net.link.bridge.pfil_member=1

Enable PF firewall with and load rules from /etc/pf.conf file:

  pfctl -e
  pfctl -f /etc/pf.conf

Then to make PF start at boot add to /etc/rc.conf:


Kernel Config

You can load pf module at boot time from /boot/loader.conf or you can compile the kernel with PF support and also with ALTQ.
If you want to compile the kernel here is what options you might want:

kernel options for PF
device mem
device pf
device pflog
device pfsync

# altq support
options ALTQ
options ALTQ_CBQ
options ALTQ_RED
options ALTQ_RIO
options ALTQ_HFSC
options ALTQ_PRIQ

# other optimizations
options HZ=1000

Logging PF
To log PF evaluations recompile the kernel with the following options:

  device pflog

or load pflog module:

  kldload pflog

You can debug PF Firewall rules by using pflog virtual network interface.

Then we fire up pflog interface:

  ifconfig pflog0 up

To enable pflog at boot add the following line to /etc/rc.conf:


Then we can see traffic passing through firewall with tcpdump command:

  tcpdump -n -e -ttt -i pflog0

For the PF rules to be logged we will use log tag. For example we will log rules that we block using:

  block in log all                 # notice log tag.

Please note that only rules that uses log tag will be logged.

Working with Tables in PF
To create a table we add in /etc/pf.conf:

table <workstations> persist {,,}

We can also add subnets and then remove some IP's from a subnet in a table:

table <workstations> persist {, ! }

Or we can create a table from a file, where all IPs or subnets will be one for a line:

For example we will have /etc/workstations file:

And then we will create workstations table in /etc/pf.conf:

table <workstations> persist file "/etc/workstations"

To add an IP in the workstations table we either:

edit /etc/workstations file and add the IP and then reload /etc/pf.conf rules


add the IP to the table with pfctl command:

  pfctl -t workstations -T add

To show IP-s in the workstation table we use:

  pfctl -t workstations -Tshow

or (more verbose):

  pfctl -t workstations -vTshow

USEFUL! Adding a list of IP-s in a table if maximum number of connections exceed a given number of connections:

  pass in proto {tcp, udp} from any to $ext_if port ftp keep state \
    (max-src-conn 10, max-src-conn-rate 12/1 , overload <badguys> flush global)

The previous command will add in badguys table every IP that will use more than 10 simultaneous connection to $ext_if interface on port ftp or if maximum connection rate per 1 second is more than 12 connections. Then if this will happend the PF will flush the states. If we use this line with a block line for badguy table we can proactively block bruteforce attempts.

We can make the table badguys to expire after a number of seconds (for example after an hour:

  pfctl -t badguys -T expire 3600

Usefull commands and tips to debug PF rules:

pfctl -vvsr       # see PF loaded rules
pfctl -vvsn      # see PF loaded nat/redirect rules
pfctl -vvsq
       # see PF queues in realtime
pfctl -f /etc/pf.conf      # load pf.conf file

pfctl -R -f /etc/pf.conf  # load only filter rules from the rule file

pfctl -F state               # flush states
pfctl -F all                    # flush all nat, queues, rules, states etc. Note that when flushing rules, the firewall
                                     # will change to accept all in and out.

pfctl -s info        # show pf usage statistics/informations
pfctl -s all            # show all informations regarding PF

pfctl -vf /etc/pf.conf   # load pf.conf and display info verbosely
pfctl -nf /etc/pf.conf     # only test rules, do not load them

Important ! When you work with statefull firewall rules when testing rules after you've loaded new rules flush all before testing again the firewall.

To monitor PF use pftop for realtime monitor (available from ports: /usr/ports/sysutils/pftop ), use pfstat or RRDTool to draw nice graphics.


- Default pass all rule is equivalent with:  pass all flags S/SA keep state

Last Updated ( Thursday, 14 June 2012 )
< Prev   Next >

Other BSD Systems





Best BSD firewall?