HxHippy

PF Firewall Configuration

Configuring the PF packet filter firewall on FreeBSD.

Last updated: 2025-01-15

Enabling PF

# /etc/rc.conf
pf_enable="YES"
pf_rules="/etc/pf.conf"
pflog_enable="YES"

# Start PF
service pf start
service pflog start

Basic Configuration

# /etc/pf.conf

# Macros
ext_if = "em0"
int_if = "em1"
tcp_services = "{ ssh, http, https }"

# Options
set skip on lo0
set block-policy drop
set loginterface $ext_if

# Normalization
scrub in all

# Default deny
block all

# Allow outbound
pass out quick on $ext_if

# Allow SSH
pass in on $ext_if proto tcp to port ssh

# Allow web services
pass in on $ext_if proto tcp to port $tcp_services

# Allow ICMP ping
pass in on $ext_if inet proto icmp icmp-type echoreq

Testing and Loading Rules

# Check syntax
pfctl -nf /etc/pf.conf

# Load rules
pfctl -f /etc/pf.conf

# Show current rules
pfctl -sr

# Show state table
pfctl -ss

# Show statistics
pfctl -si

NAT Configuration

# Enable IP forwarding
sysrc gateway_enable="YES"
sysctl net.inet.ip.forwarding=1

# /etc/pf.conf
nat on $ext_if from $int_if:network to any -> ($ext_if)

Port Forwarding

# Forward port 80 to internal server
rdr on $ext_if proto tcp from any to ($ext_if) port 80 -> 192.168.1.10 port 80

Rate Limiting

# Limit SSH connections
pass in on $ext_if proto tcp to port ssh \
    flags S/SA keep state \
    (max-src-conn 5, max-src-conn-rate 3/60, overload <bruteforce> flush global)

# Block overloaded IPs
block in quick from <bruteforce>

Tables

# Define table
table <blocklist> persist file "/etc/pf.blocklist"

# Block table entries
block in quick from <blocklist>

# Manage tables
pfctl -t blocklist -T add 1.2.3.4
pfctl -t blocklist -T delete 1.2.3.4
pfctl -t blocklist -T show

Logging

# Log blocked packets
block log all

# View logs
tcpdump -n -e -ttt -i pflog0
intermediate Networking Updated 2025-01-15
  • freebsd
  • pf
  • firewall
  • security
  • packet filter