PF cheatsheet

Please keep in mind that this post is about 4 years old.
Technology may have changed in the meantime.

Cheatsheet for the PF firewall (*BSD, macOS/iOS, Solaris, QNX/BlackBerry).

Show rules:

# pfctl -sr

The same, but more verbose:

# pfctl -vsr

Show anchors:

# pfctl -sA

Show anchors recursively:

# pfctl -vsA

Show rules recursively (including anchors):

# pfctl -a '*' -sr

Show anchors within the f2b anchor:

# pfctl -a 'f2b' -sA

Show rules for f2b/sshd anchor:

# pfctl -a 'f2b/sshd' -sr

Show rules recursively within the f2b anchor:

# pfctl -a 'f2b/*' -sr

Show tables:

# pfctl -sT

The same, but more verbose:

# pfctl -vsT

Show tables for f2b/sshd anchor:

# pfctl -a 'f2b/sshd' -sT

Recursively listing tables is not possible.

Show the contents of table <trusted>:

# pfctl -t 'trusted' -Ts

Show the contents of table <f2b-sshd> in the anchor f2b/sshd:

# pfctl -a 'f2b/sshd' -t 'f2b-sshd' -Ts

The same, but more verbose:

# pfctl -a 'f2b/sshd' -t 'f2b-sshd' -vTs

Add an IP address or IP range to table <trusted>:

# pfctl -t 'trusted' -Ta 203.0.113.12
# pfctl -t 'trusted' -Ta 203.0.113.0/24

Delete an IP address or IP range from table <trusted>:

# pfctl -t 'trusted' -Td 203.0.113.12
# pfctl -t 'trusted' -Td 203.0.113.0/24

Empty (flush) table <blocked>:

# pfctl -t 'blocked' -Tf

It may be a good idea to verify the syntax of the configuration file before restarting or reloading the firewall:

# pfctl -n -f /etc/pf.conf

Or, to review the ruleset generated from the new configuration:

# pfctl -n -f /etc/pf.conf -v

Use -vv to display rule and anchor numbers.

Logging

Logging must be enabled explicitly in pf.conf on a per-rule basis; see the PF User’s guide for more info.

Display log in real time:

# tcpdump -tttt -n -e -i pflog0

End output with ^C.

List all log entries for outbound traffic to port 80:

# tcpdump -tttt -n -e -r /var/log/pflog outbound and port 80

The same, but more verbose:

# tcpdump -v -tttt -n -e -r /var/log/pflog outbound and port 80

Get even more verbosity with -vv or -vvv.

Search the log file for a certain IP address:

# tcpdump -tttt -n -e -r /var/log/pflog host 203.0.113.12

The same, but with a compressed log file:

# bunzip2 -c /var/log/pflog.0.bz2 | tcpdump -tttt -n -e -r - host 203.0.113.12

List inbound traffic, except traffic to the Tor relay or Tor directory info:

# tcpdump -tttt -n -e -r /var/log/pflog inbound and not port 9001 and not port 9030

List blocked inbound traffic to the Tor relay:

# tcpdump -tttt -n -e -r /var/log/pflog inbound and dst port 9001 and action block

Since the output of tcpdump is plaintext, it can be further processed by tools like grep, sed, awk, etc.

Find all outgoing traffic that was not initiated by the users with UIDs 53, 123 and 256:

# tcpdump -tttt -n -e -r /var/log/pflog outbound | grep -Ev '\[uid (53|123|256)\]'

Logging of UIDs must be enabled explicitly in pf.conf, e.g.:

pass out log (user) all modulate state

More info:


Note:

When using fail2ban, the f2b anchors should NOT be specified like this in pf.conf:

anchor "f2b/*"

Instead, all anchors should be specified explicitly, otherwise recursive listing won’t work:

anchor f2b {
    anchor apache-auth
    anchor dovecot
    anchor postfix
    anchor sshd
}