Pf

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

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


Installation

All BSD distributions have pf(8) installed.

Note that the 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

pf(4) (FreeBSD)

pf.conf(5) (FreeBSD)

pf(4) (OpenBSD)

pf.conf(5) (OpenBSD)


CategoryRicottone

Pf (last edited 2023-04-08 17:07:13 by DominicRicottone)