Freorit

Open Source & Security Practitioner
Firewall Security OpenBSD Stateful Filtering Monitoring ca. 18 min read Intermediate Updated: 2025

OpenBSD PF Firewall: Stateful Security Without Complexity

OpenBSD PF (Packet Filter) is a modern firewall for admins who want to understand what their system does. This guide explains stateful filtering, threat detection, and centralized observability—without unnecessary complexity.

Why OpenBSD?

If you're a Linux admin, you know iptables, firewalld, nftables. They work, but OpenBSD PF (Packet Filter) takes a different approach:

For Whom?

You want a firewall that's simple to understand, requires minimal maintenance, and where security isn't optional. Not: "Let me stack iptables rules to the sky."

PF Firewall Basics

What is PF?

PF is a kernel-based firewall system. Unlike Linux iptables, which run through netfilter, PF is implemented directly in the OpenBSD kernel and optimized for it.

Core features:

PF vs. Linux iptables/nftables

Aspect PF (OpenBSD) Linux iptables
Location in stack Kernel-integrated Kernel subsystem (netfilter)
Syntax Declarative, top-to-bottom Imperative, rule-by-rule
Default policy Explicit deny Depends on config
State table Central, auto-optimized Via conntrack module
Reload Atomic (rules + state table) Sometimes needs flush/reload

Architecture: Stateful Filtering

How stateful filtering works

Unlike stateless firewalls that inspect each packet individually, a stateful firewall remembers context:

Stateful Filtering: Connection Flow Client Outbound request PF State Table Entry created Status: established Server Inbound response State lookup Return traffic Automatically allowed (no explicit rule needed) Simplified ruleset Allow outbound & PF handles return traffic Scalable, maintainable, fewer mistakes

Practical benefit: You only write "allow internal hosts to reach the outside"—return traffic is automatically clear.

Example ruleset (conceptual)


# Default: Block everything
set block-policy drop

# Define internal interface
int_if = "re0"
ext_if = "pppoe0"

# Allow: loopback, internal traffic
pass on lo0
pass on $int_if proto tcp from any to any port 22

# Allow: Outbound, return automatically
pass out on $ext_if proto tcp from any to any

# Rate limiting: Too many connections from one source
pass in on $ext_if proto tcp to any port 22 \
(max-src-conn 10, max-src-conn-rate 5/60)

# Source tracking: Block IPs doing port scans
pass in on $ext_if proto tcp flags SYN/SYN,ACK
table <bruteforce> persist
block in quick from <bruteforce>
    

Note: Real production rules are longer and more granular.

Threat Detection & Monitoring

OpenBSD firewall alone isn't enough

PF filters layers 3/4 (IP/TCP/UDP). But:

Solution: Add threat detection (IDS) + centralized logging.

The three layers

Layer Tool Detects
3/4 (IP/TCP) OpenBSD PF Port scans, SYN floods, rate anomalies
7 (Application) IDS (Suricata/Snort) HTTP payloads, SQL injection, exploits
Everywhere Centralized logging (Syslog) Correlation, time series, anomalies

Monitoring setup (simplified)

OpenBSD Router PF Logs Firewall events SNMP metrics State table, traffic IDS alerts Threat detection Central observability stack Syslog receiver Logs → Loki Prometheus Metrics storage Alert manager IDS + PF alerts Grafana dashboards Visualization & real-time alerts Daily operations | Anomaly detection | Incident response

What to monitor:

Verification: Logs arrive centrally, no manual SSH to router needed. Everything is queryable.

Practical Overview

Hardware

Compact hardware (e.g., mini-PCs, old workstations) work perfectly. You don't need an enterprise appliance.

Routing and filtering flow

Simplified:

Internet | v WAN interface (em0) | v OpenBSD kernel: PF firewall ├─ State inspection ├─ NAT translation └─ Rate limiting / blocking | v LAN interface (re0) | v Internal network

Typical problems

Best Practices

1. Least privilege

2. Monitoring in the design

3. Testing before deployment

4. Documentation

5. Incremental complexity

Not everything at once. Each phase should run stably before the next begins.

Summary