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