= Pf =

The '''Berkeley Packet Filter''' ('''pf''') is a firewall utility.

`pf(4)` is run as a service, while `pfctl(8)` is a userland interface.

<<TableOfContents>>

----



== Installation ==

All [[BSD]] distributions have `pf(8)` installed.

Note that the [[BSD/FreeBSD|FreeBSD]] implementation has diverged from the upstream project.

----



== Configuration ==

For the most basic of usecases, this is perfect.

{{{
block in all
pass out all keep state
}}}

To check the configuration of `pf(4)`, run... 

{{{
pfctl -nf /usr/local/etc/pf.conf
}}}



=== Basic Server Setup ===

A server needs to be addressable by the external network. In order to minimize repetition, macros should be used to store the TCP and UDP ports that need to be opened.

{{{
tcp_services = "{ 22 53 80 443 }"
udp_services = "{ 53 }"
icmp_types = "echoreq"

# Basic inbound TCP rule
pass in inet proto tcp $tcp_services flags S/SA keep state

# Basic inbound UDP rule
pass in inet proto udp $udp_services keep state

# Basic ICMP ping rule
pass inet proto icmp all icmp-type $icmp_types keep state

# Basic outbound connections rule
pass out proto tcp all modulate state flags S/SA
pass out proto { udp, icmp } all keep state
}}}

If you have dedicated interfaces for internal and external networks, it becomes much simpler to create rules.

{{{
ext_if="xl0"
int_if="xl1"
localnet=$int_if:network

# hardened firewall
block drop in  quick on $ext_if from $localnet to any
block drop out quick on $ext_if from any to $localnet 

# hardened ICMP rules
pass inet proto icmp from $localnet to any keep state
pass inet proto icmp from any to $ext_if keep state
}}}



=== Blocking Brute Force Attacks ===

Clients that attempt a high number of connections are often brute force attackers. `pf(4)` can easily add these addresses to a blacklisted table.

{{{
localnet = "{ 192.168.100.0/24 }"
tcp_services = "{ 22 }"
table <bruteforce> persist

block quick from <bruteforce>

pass inet proto tcp from any to $localnet port $tcp_services \
  flags S/SA keep state \
  (max-src-conn 100, max-src-conn-rate 15/5, \
  overload <bruteforce> flush global)
}}}

The `<bruteforce>` table can be cleared based on an expiry time (in seconds) using `pfctl(8)`.

{{{
pfctl -t bruteforce -T expire 86400
}}}

This can be automated with a `cron` job.

----



== See also ==

[[https://man.freebsd.org/cgi/man.cgi?pf(4)|pf(4) (FreeBSD)]]

[[https://man.freebsd.org/cgi/man.cgi?pf.conf(5)|pf.conf(5) (FreeBSD)]]

[[https://man.openbsd.org/pf|pf(4) (OpenBSD)]]

[[https://man.openbsd.org/pf.conf|pf.conf(5) (OpenBSD)]]



----
CategoryRicottone