LUNAROPS · OPERATIONAL UPLINK 100% UPTIME 1,247d POSTS 893 JEFF.MOON@LUNAROPS.DEV UTC --:--:--

pfSense and OPNsense: The Complete Home Lab Firewall Guide

pfsenseopnsensefirewallnetworkinghomelabroutersecuritywireguardopenvpnvlansdhcpdnsnatsuricatapfblockernghaproxycarphigh-availability
Contents

Your ISP-supplied router is a security liability masquerading as a convenience. It runs firmware that gets updated once every few years (if ever), exposes a web interface that’s been the subject of countless CVEs, and gives you essentially no visibility into what’s actually happening on your network. The moment you start running servers, VMs, or anything beyond casual browsing, you need a real firewall.

pfSense and OPNsense are BSD-based open-source firewall distributions that turn commodity x86 hardware into enterprise-grade network appliances. They support everything from basic NAT to multi-WAN failover, IDS/IPS, VPN concentrators, VLAN trunking, traffic shaping, and high availability clustering — all from a polished web GUI backed by battle-tested FreeBSD networking code.

This guide takes you from zero to a hardened, production-quality firewall deployment. It covers both platforms in depth so you can make an informed choice.


Part 1: pfSense vs OPNsense — Choosing Your Platform

History and the Fork

pfSense was created in 2004 by Chris Buechler and Scott Ullrich as a fork of m0n0wall, itself a pioneering embedded firewall project. For a decade it was the open-source firewall. In 2015, Netgate acquired majority control of the project, and the relationship between Netgate and the community soured over licensing decisions and concerns about the project’s open-source future.

In January 2015, the same month Netgate’s acquisition was announced, a group of pfSense contributors — led by Ad Schellevis and Jos Schellevis — forked pfSense and created OPNsense. The name is a play on “open” and “sense,” emphasizing the commitment to open-source principles.

The tension came to a head in 2021 when Netgate re-licensed pfSense CE under the Apache 2.0 license and made statements that were widely interpreted as hostile to community forks. OPNsense explicitly uses a 2-clause BSD license throughout.

Philosophy and Governance

pfSense is controlled by Netgate, a commercial entity. The community edition (CE) is free, but Netgate’s business model centers on pfSense Plus (formerly pfSense+ and TAC subscriptions) for enterprise customers and their hardware appliances. Development priority leans toward features that benefit enterprise customers and Netgate’s hardware product line.

OPNsense is governed by Deciso B.V., a Dutch company, but with a much stronger emphasis on community participation. Their business model focuses on their own hardware (Deciso DEC series appliances), Business Edition subscriptions, and OPNcentral for multi-instance management. The project maintains a public roadmap and accepts community contributions more readily.

Licensing

pfSense CE OPNsense
License Apache 2.0 BSD 2-Clause
Source availability Yes Yes
Commercial version pfSense Plus (subscription) Business Edition
Fork-friendly Debated Yes

Update Cadence

OPNsense releases major versions every six months (January and July) with weekly minor releases in between. The rolling release model means you can stay current without waiting for a major version bump. OPNsense on 2026-03-25 is at version 25.1.x.

pfSense CE releases are less predictable and have historically lagged behind. pfSense Plus (the subscription tier) gets updates faster. pfSense CE is currently at 2.7.x.

Winner for update cadence: OPNsense, by a wide margin.

UI and User Experience

Both use a web-based GUI, but the design philosophy differs significantly.

pfSense UI:

  • Older, more utilitarian design
  • Very familiar to longtime network admins
  • Navigation: top menu bar with dropdowns
  • Configuration is often directly on the relevant page
  • Some pages haven’t changed in a decade (which is either comforting or alarming, depending on your perspective)

OPNsense UI:

  • Modern, responsive design (based on Bootstrap)
  • Sidebar navigation with collapsible sections
  • Dashboard is highly customizable with widgets
  • Better mobile/tablet experience
  • Consistent UX patterns across all plugins
  • More discoverable for new users

Both UIs expose the same fundamental concepts, but OPNsense’s is easier to navigate without prior experience.

Community and Documentation

pfSense has a larger existing knowledge base (it’s been around longer) but the community has splintered. The Netgate forums are the official channel; Reddit’s r/PFSENSE is active.

OPNsense has a growing, highly engaged community. The OPNsense forums, r/OPNsenseFirewall subreddit, and official documentation (docs.opnsense.org) are all active and well-maintained.

Our recommendation: For new deployments, OPNsense is the better choice. The faster update cycle, cleaner UI, stronger open-source commitment, and active community make it the more future-proof option. pfSense remains a solid choice if you’re migrating an existing deployment or if your team has deep pfSense expertise. This guide covers both in parallel.


Part 2: Hardware Requirements and Recommendations

Both pfSense and OPNsense run on FreeBSD (pfSense on FreeBSD 14, OPNsense on HardenedBSD — a security-focused FreeBSD fork). Hardware requirements are modest.

Minimum Specifications

Component Minimum Recommended Heavy Use (IDS/IPS, multiple VPNs)
CPU 64-bit, 1 GHz 4+ core, 2+ GHz 8+ core with AES-NI
RAM 1 GB 4 GB 8–16 GB
Storage 8 GB SSD 32 GB SSD 64+ GB SSD
NICs 2 ports (WAN+LAN) 4+ ports 4–8 ports with Intel chipset

AES-NI is important if you plan to run VPNs or encrypted DNS. Both pfSense 2.5+ and OPNsense require AES-NI — nearly all x86_64 hardware from 2012 onwards supports it, but verify before buying old hardware.

NIC Chipsets

The NIC chipset matters enormously. BSD has mature, performant drivers for:

  • Intel i210/i211/i350/i82574L (em/igb driver) — Gold standard. Found on Intel server NICs, Protectli appliances, and many mini PCs. Reliable, performant, excellent driver support.
  • Intel X550/X710 (ixl driver) — For 10GbE deployments. Excellent.
  • Realtek RTL8111/8125 (re driver) — Common in cheap hardware. Works but can be flaky at high throughput. Avoid for WAN-facing interfaces if possible.

Avoid Broadcom NICs in BSD-based firewalls — driver support is poor compared to Linux.

Hardware Options

Protectli makes x86 firewall appliances specifically designed for pfSense/OPNsense. No-name-brand clones exist but Protectli’s build quality and driver compatibility are excellent.

Model CPU RAM Ports Price (approx)
VP2420 Intel Celeron J6412 4–16 GB 4x 2.5GbE ~$300–$400
VP4650 Intel Core i5-1235U 8–32 GB 6x 2.5GbE ~$500–$700
VP6650 Intel Core i7-1165G7 8–64 GB 6x 2.5GbE ~$700–$900

All Protectli models use Intel NICs. They ship without RAM/storage so you size them for your needs.

Netgate Appliances

Netgate sells appliances preloaded with pfSense Plus (subscription required):

  • Netgate 1100 — Entry-level, ARM-based, 3 ports, ~$200. Good for homes.
  • Netgate 4100 — Intel Atom, 6 ports, ~$600. SMB sweet spot.
  • Netgate 6100 — Intel Atom C3558R, 10 ports, ~$900. Multi-WAN/HA setups.

Note: Netgate appliances come with pfSense Plus, not CE. The CE license can be installed but is not officially supported on Netgate hardware.

Mini PCs (DIY)

Cost-effective options that work well:

Minisforum, Beelink, CWWK make mini PCs with multiple NICs:

  • CWWK N100 4-port (4x i226 2.5GbE) — ~$200. Excellent value, Intel i226 NICs.
  • Minisforum MS-01 — i9 CPU, 2x 10GbE SFP+, 2x 2.5GbE — ~$500. Overkill for most.

Raspberry Pi 4/5 — Not recommended for primary firewall. The USB-connected NIC is a bottleneck and there’s no second built-in port. Fine for learning.

Old enterprise hardware — Dell OptiPlex/Wyse, HP EliteDesk with a PCIe Intel NIC card. Can be had for $50–100 on eBay. Works great if the CPU has AES-NI.

Adding NICs

If your hardware has a PCIe slot, an Intel quad-port NIC (like the Intel I350-T4) adds four Intel NICs for ~$80 used. This is how you turn a mini PC into a multi-port firewall.

# Check NIC detection in pfSense/OPNsense shell:
pciconf -lv | grep -A4 -i ethernet
ifconfig -a

Storage

Use an SSD — spinning rust is a liability for a device that’s always on. A 32GB M.2 SATA SSD (~$15) is more than enough. The OS + packages take under 4 GB; the rest is logs.

If you’re running pfBlockerNG or Suricata with large rulesets, go 64+ GB.


Part 3: Installation

Downloading the Installer

pfSense CE:

  1. Go to pfsense.org/download
  2. Select: Architecture = AMD64, Installer = DVD Image (ISO), Mirror nearest to you
  3. Download the .iso.gz file and extract it (produces a .iso)
  4. Verify SHA256: sha256sum pfSense-CE-2.7.x-RELEASE-amd64.iso

OPNsense:

  1. Go to opnsense.org/download
  2. Select: Architecture = amd64, Image type = dvd, Mirror
  3. Download the .iso.bz2 and extract: bunzip2 OPNsense-25.1-dvd-amd64.iso.bz2
  4. Verify SHA256 against the checksums file on the download page

Creating a Bootable USB

On Linux/macOS:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Find your USB device
lsblk   # Linux
diskutil list   # macOS

# Write the image (replace sdX / diskN with your device)
# Linux:
sudo dd if=pfSense-CE-2.7.x-RELEASE-amd64.iso of=/dev/sdX bs=4M status=progress conv=fsync

# macOS (unmount first):
diskutil unmountDisk /dev/diskN
sudo dd if=OPNsense-25.1-dvd-amd64.iso of=/dev/rdiskN bs=4m

# Verify (optional but good practice):
sudo dd if=/dev/sdX bs=4M count=$(stat -c%s pfSense*.iso | awk '{print int($1/4/1024/1024)+1}') | md5sum

On Windows, use Rufus or balenaEtcher:

  • Rufus: Select the ISO, Partition scheme = MBR, Target system = BIOS or UEFI, leave all else default

BIOS/UEFI Setup

Before booting, enter BIOS setup (usually Del, F2, or F12 at POST):

  1. Disable Secure Boot — neither pfSense nor OPNsense requires it, and it can cause boot failures
  2. Set boot order — USB first, then your target SSD
  3. Enable virtualization (VT-x/AMD-V) — not required, but useful if you’ll run VMs later
  4. Verify AES-NI — should be enabled by default on modern CPUs

pfSense Installation Steps

  1. Boot the USB — the pfSense boot menu appears
  2. Press Enter to accept default boot options
  3. Accept the copyright notice
  4. Select Install pfSense
  5. Choose keymap (typically US)
  6. Partitioning: Select “Auto (ZFS)” for hardware with ≥4 GB RAM, or “Auto (UFS)” for minimal systems
    • ZFS: Select “stripe” for single disk, “mirror” for two disks
    • Select your target disk and confirm
  7. Installation runs (~2–5 minutes)
  8. When prompted, select No for opening a shell (unless you need to manually edit)
  9. Select Reboot
  10. Remove USB when prompted

On first boot, pfSense detects NICs and walks you through interface assignment in the console:

Valid interfaces are:
  igb0    00:1a:8c:xx:xx:xx   Intel(R) PRO/1000
  igb1    00:1a:8c:xx:xx:xx   Intel(R) PRO/1000

Do you want to set up VLANs now? [y|n]: n

Enter the WAN interface name or 'a' for auto-detection: igb0
Enter the LAN interface name or 'a' for auto-detection: igb1
Enter the Optional 1 interface name or 'a' for auto-detection (or nothing if finished):

The interfaces will be assigned as follows:
WAN  -> igb0
LAN  -> igb1

Do you want to proceed? [y|n]: y

OPNsense Installation Steps

  1. Boot the USB — the OPNsense boot menu appears (HardenedBSD kernel)
  2. Default boot proceeds automatically after 3 seconds
  3. At the login prompt: login: installer, password: opnsense
  4. The installer TUI launches:
    • Select keymap
    • Select Install (UFS) or Install (ZFS) — ZFS recommended for ≥4 GB RAM
    • Select target disk
    • Set root password when prompted
    • Select Complete Install and reboot

On first OPNsense boot, you’re greeted by the console menu:

OPNsense 25.1 (amd64)

WAN (igb0)      -> v4: 192.168.1.100/24
LAN (igb1)      -> v4: 192.168.1.1/24

 0) Logout                  7) Ping host
 1) Assign interfaces       8) Shell
 2) Set interface IP        9) pfTop
 3) Reset web GUI password 10) Filter logs
 4) Reset factory defaults 11) Restart web GUI
 5) Power off system       12) Update from console
 6) Reboot system          13) Restore a backup

Use option 1 to assign interfaces if automatic detection got it wrong.


Part 4: Initial Configuration Wizard

Once installed, access the web GUI from a device connected to the LAN port:

  • pfSense: Navigate to https://192.168.1.1 — Login: admin / pfsense
  • OPNsense: Navigate to https://192.168.1.1 — Login: root / opnsense

Both will prompt you to change the default password immediately — do it.

pfSense Setup Wizard

The wizard launches automatically. Work through each screen:

Step 1 — Netgate Registration: Skip unless you have a Plus subscription.

Step 2 — General Information:

  • Hostname: fw01 (or your preferred name)
  • Domain: lan or your actual domain (e.g., home.example.com)
  • Primary DNS: Leave blank for now (Unbound will handle this)
  • Override DNS: Uncheck (prevents ISP DNS from being used)

Step 3 — Time Server:

  • NTP server: pool.ntp.org (or your preferred pool)
  • Timezone: Set your local timezone

Step 4 — WAN Interface: Configure based on your ISP connection type:

DHCP (most residential ISPs):

  • Type: DHCP
  • MAC address: Clone your old router’s MAC if your ISP does MAC-based provisioning
  • MTU: Leave blank (ISP assigns) or set 1500

PPPoE (fiber/DSL with login credentials):

  • Type: PPPoE
  • Username: your ISP-provided PPPoE username
  • Password: your ISP-provided PPPoE password
  • Dial on demand: Leave unchecked for always-on

Static IP:

  • Type: Static
  • IP address / subnet / gateway: as provided by ISP
  • Upstream gateway: ISP gateway IP

Step 5 — LAN Interface:

  • IP address: 192.168.10.1 (change from default 192.168.1.1 if you have upstream gear on that subnet)
  • Subnet: /24

Step 6 — Admin Password: Set a strong password.

Step 7 — Reload: Click Reload. The firewall reboots configuration. Your browser session will reconnect at the new LAN IP.

OPNsense Setup Wizard

Navigate to Lobby > Setup Wizard or it launches automatically.

The wizard covers the same concepts as pfSense but in OPNsense’s cleaner UI:

  1. General Settings — hostname, domain, language, timezone
  2. Time Server — NTP configuration
  3. WAN Configuration — same options: DHCP, PPPoE, Static
  4. LAN IP configuration — set your LAN address
  5. Root Password — set or confirm
  6. Reload — applies settings

After the wizard, OPNsense’s dashboard shows live traffic graphs, gateway status, and service status.


Part 5: Interface Configuration

WAN Interface Types in Depth

Navigate to: pfSense: Interfaces > WAN | OPNsense: Interfaces > [WAN]

DHCP WAN

The most common setup for residential connections.

Type: DHCP
Hostname: (optional — some ISPs require this for DHCP lease)
Alias IP: (leave blank)
MAC: (clone your previous router MAC if needed)
MTU: 1500 (or blank for auto)
MSS: 1452 (for PPPoE underlying connections — prevents fragmentation)

To clone your old router’s MAC:

# Find old router MAC in pfSense/OPNsense:
Interfaces > WAN > MAC Address field > enter the MAC from your old router

PPPoE WAN

Required for most DSL and some fiber ISPs (AT&T fiber, many European ISPs):

Type: PPPoE
Username: user@isp.example.com
Password: yourpassword
Dial on demand: No
Idle timeout: 0
Periodic reset: (optional, set to 0/disabled)

PPPoE adds overhead (8 bytes per frame), so MTU should be 1492, not 1500. pfSense/OPNsense handles this automatically but you can set MSS clamping at System > Advanced > Networking > Firewall Optimization Options.

Static WAN

Used when your ISP assigns a fixed IP:

Type: Static
IPv4 address: 198.51.100.10 / 30
IPv4 Upstream gateway: Add new gateway
  - Gateway IP: 198.51.100.9
  - Description: ISP Gateway

LAN Interface Configuration

Navigate to: pfSense: Interfaces > LAN | OPNsense: Interfaces > [LAN]

Enable: checked
Description: LAN
IPv4 Configuration Type: Static
IPv4 address: 192.168.10.1 / 24
IPv6: None (unless your ISP provides IPv6)

Adding Additional Interfaces (OPT interfaces)

For each additional physical port or VLAN:

pfSense: Interfaces > Assignments > Add OPNsense: Interfaces > Assignments > click the + button

After assigning:

  1. Click the newly created OPT1 (or similar)
  2. Enable the interface
  3. Set a description (e.g., SERVERS, IOT, DMZ)
  4. Configure the IP: e.g., 192.168.20.1/24
  5. Save and Apply

Part 6: DHCP Server Configuration

The DHCP server is what hands out IP addresses to your clients.

pfSense: Services > DHCP Server > [interface tab] OPNsense: Services > DHCPv4 > [interface]

Basic DHCP Setup per Interface

Enable DHCP server on LAN: checked
Range:
  From: 192.168.10.100
  To:   192.168.10.200

Subnet mask: 255.255.255.0
Broadcast: 192.168.10.255
Gateway: 192.168.10.1         ← the firewall's LAN IP
DNS servers: 192.168.10.1     ← point to firewall for Unbound
Domain name: home.example.com
Lease time: 86400             ← 24 hours in seconds

Repeat for each interface with different subnets:

  • SERVERS: 192.168.20.100–192.168.20.200, gateway 192.168.20.1
  • IOT: 192.168.30.100–192.168.30.200, gateway 192.168.30.1

Static DHCP Mappings

Static mappings assign a fixed IP to a specific MAC address. The device always gets the same IP without having to configure it statically on the device.

pfSense: Services > DHCP Server > [interface] > Static Mappings section > Add OPNsense: Services > DHCPv4 > [interface] > Static Mappings tab > +

MAC address: aa:bb:cc:dd:ee:ff    ← from the device's network adapter
IP address:  192.168.10.10
Hostname:    my-server
Description: Primary workstation

Finding a device’s MAC address:

From the pfSense/OPNsense DHCP leases table:

  • pfSense: Status > DHCP Leases
  • OPNsense: Services > DHCPv4 > Leases

From a Linux device: ip link show eth0 | grep ether From a Windows device: ipconfig /all

DHCP Options (Advanced)

You can push additional options to clients via DHCP:

pfSense: Services > DHCP Server > Additional BOOTP/DHCP Options OPNsense: Services > DHCPv4 > [interface] > Additional Options

Common options:

Option 66 (TFTP server): 192.168.50.10    ← for PXE boot
Option 43 (Vendor info): varies by AP vendor
Option 252 (WPAD proxy): http://wpad.home.example.com/wpad.dat

Part 7: DNS Resolver (Unbound) Configuration

Both pfSense and OPNsense ship with Unbound as the DNS resolver. Unbound is a validating, recursive, caching DNS resolver — it queries root servers directly rather than forwarding to upstream resolvers by default, providing better privacy and DNSSEC validation.

pfSense: Services > DNS Resolver OPNsense: Services > Unbound DNS > General

Basic Unbound Settings

Enable: checked
Listen Port: 53
Network interfaces: LAN, [other internal interfaces]  ← do NOT include WAN
DNSSEC: enabled
DNS64: disabled (unless you need IPv6 translation)
Register DHCP leases: checked    ← makes hostnames resolvable
Register DHCP static mappings: checked

Do not bind Unbound to WAN — this would expose your DNS resolver to the internet.

Enabling DNS-over-TLS (DoT)

By default, Unbound queries root servers over unencrypted UDP/TCP on port 53. DNS-over-TLS encrypts upstream queries. To enable DoT, switch Unbound from recursive to forwarding mode with TLS.

pfSense: Services > DNS Resolver > Custom Options OPNsense: Services > Unbound DNS > DNS over TLS tab (native UI support)

OPNsense — DNS over TLS (GUI method):

  1. Services > Unbound DNS > DNS over TLS
  2. Click + to add a DoT server:
    Server IP:  1.1.1.1
    Port:       853
    Verify CN:  cloudflare-dns.com
    
  3. Add a second entry for redundancy:
    Server IP:  1.0.0.1
    Port:       853
    Verify CN:  cloudflare-dns.com
    
  4. Enable Forward mode in General settings
  5. Save and Apply

Popular DoT providers:

Provider IP TLS Name
Cloudflare 1.1.1.1, 1.0.0.1 cloudflare-dns.com
Quad9 9.9.9.9, 149.112.112.112 dns.quad9.net
NextDNS (varies) your-id.dns.nextdns.io
Google 8.8.8.8, 8.8.4.4 dns.google

pfSense — DNS over TLS (Custom Options method):

Services > DNS Resolver > Custom Options:

forward-zone:
  name: "."
  forward-tls-upstream: yes
  forward-addr: 1.1.1.1@853#cloudflare-dns.com
  forward-addr: 1.0.0.1@853#cloudflare-dns.com
  forward-addr: 9.9.9.9@853#dns.quad9.net

Verify DoT is Working

From a shell on the firewall or a client:

1
2
3
4
5
6
7
8
# Test from the firewall shell (Diagnostics > Command Prompt):
drill -p 853 -T example.com @1.1.1.1

# Check Unbound is listening on port 53:
sockstat -l | grep unbound

# Test from a client that uses the firewall as DNS:
dig example.com @192.168.10.1

Local DNS Host Overrides

Create internal DNS entries so hostnames resolve on your LAN:

pfSense: Services > DNS Resolver > Host Overrides > Add OPNsense: Services > Unbound DNS > Host Overrides > +

Host:    plex
Domain:  home.example.com
Type:    A
IP:      192.168.20.10
Description: Plex Media Server

This makes plex.home.example.com resolve to 192.168.20.10 from any client using the firewall’s DNS.

Domain Overrides

Route queries for specific domains to a specific DNS server. Useful for Active Directory or split-horizon DNS:

pfSense: Services > DNS Resolver > Domain Overrides OPNsense: Services > Unbound DNS > Domain Overrides

Domain: corp.example.com
IP:     192.168.50.10    ← your internal AD DNS server
Description: Active Directory domain

Part 8: Firewall Rules

This is where pfSense and OPNsense earn their keep. Understanding the rule engine is essential.

How Firewall Rules Work

Both platforms use a stateful packet filter based on BSD’s pf (packet filter). Key concepts:

Rules are evaluated on the ingress interface — when a packet enters an interface, rules on that interface are checked. Rules do not need to be written for return traffic — state tracking handles that automatically.

First match wins — rules are evaluated top to bottom. The first matching rule determines the action. Rules below the match are not evaluated.

Implicit deny — if no rule matches, traffic is blocked. pfSense adds an invisible default deny at the end.

States — when a connection is permitted, a state table entry is created. Return packets matching an existing state bypass rule evaluation entirely.

Packet arrives on LAN interface
         ↓
Check LAN rules (top to bottom):
  Rule 1: pass TCP from LAN to WAN port 443 → MATCH → create state, forward
  Rule 2: pass TCP from LAN to WAN port 80  → not reached
  Rule 3: block all from LAN to WAN         → not reached

pfSense: Firewall > Rules > [interface tab] OPNsense: Firewall > Rules > [interface]

Rule Anatomy

Each rule contains:

Field Description Example
Action Pass, Block, Reject Pass
Interface Where the packet enters LAN
Protocol TCP, UDP, TCP/UDP, ICMP, any TCP/UDP
Source IP, network, alias, or interface LAN net
Source port Any or specific port(s) any
Destination IP, network, alias, or interface any
Destination port Any or specific port(s) 443
Direction In (default) or Out In
Log Whether to log matches checked
Description Human-readable rule label Allow HTTPS outbound

State Types

Both platforms support pf state types on rules:

  • keep state — default, tracks TCP/UDP/ICMP connections
  • sloppy state — less strict for asymmetric routing scenarios
  • synproxy state — proxy SYN packets to protect against SYN floods (TCP only)
  • none — no state tracking; every packet evaluated independently (rarely used)

pfSense: Firewall > Rules > edit rule > Advanced Options > State Type OPNsense: Firewall > Rules > edit rule > Advanced > State Type

Aliases — The Right Way to Write Rules

Aliases are named groups of IPs, networks, or ports. Use aliases instead of hardcoding IPs in rules. When an IP changes, update the alias and all rules update automatically.

pfSense: Firewall > Aliases OPNsense: Firewall > Aliases

Alias: RFC1918
Type: Network
Networks:
  10.0.0.0/8
  172.16.0.0/12
  192.168.0.0/16
Description: All private IPv4 ranges

Alias: ADMIN_HOSTS
Type: Host
Hosts:
  192.168.10.5    ← sysadmin workstation
  192.168.10.6    ← jump host
Description: Administrators allowed to manage firewall

Alias: WEB_PORTS
Type: Port
Ports: 80, 443
Description: Standard web ports

Alias: MGMT_PORTS
Type: Port
Ports: 22, 443, 8006    ← SSH, HTTPS, Proxmox
Description: Management ports

Common Rule Sets

Default LAN rules (what you typically add):

# Allow LAN clients to use firewall DNS
pass  LAN  TCP/UDP  LAN net  →  192.168.10.1    port 53   "Allow DNS"

# Allow LAN clients internet access
pass  LAN  TCP      LAN net  →  !RFC1918         port 80   "Allow HTTP"
pass  LAN  TCP      LAN net  →  !RFC1918         port 443  "Allow HTTPS"
pass  LAN  UDP      LAN net  →  !RFC1918         port 123  "Allow NTP"
pass  LAN  ICMP     LAN net  →  any                        "Allow Ping out"

# Block LAN from accessing other VLANs (inter-VLAN deny)
block LAN  any      LAN net  →  RFC1918                    "Block LAN to private"

# Default implicit deny (invisible)

IoT VLAN rules (strict isolation):

# Allow IoT DNS via firewall only
pass  IOT  TCP/UDP  IOT net  →  192.168.30.1    port 53   "IoT DNS"

# Allow IoT internet only (no LAN/server access)
pass  IOT  TCP      IOT net  →  !RFC1918         any       "IoT internet"
pass  IOT  UDP      IOT net  →  !RFC1918         any       "IoT internet UDP"

# Block IoT from all private ranges (including returning to LAN)
block IOT  any      IOT net  →  RFC1918                    "Block IoT to private"

WAN rules (normally empty — default deny incoming):

# Only add WAN rules for port forwards or explicit inbound access
# Example: Allow inbound WireGuard
pass  WAN  UDP      any      →  WAN address      port 51820  "WireGuard"

Floating Rules

Floating rules apply across multiple interfaces and can be applied to outbound traffic. They’re evaluated before interface rules.

pfSense: Firewall > Rules > Floating OPNsense: Firewall > Rules > Floating

Use cases:

  • Block specific traffic on all interfaces at once
  • Apply traffic shaping queues
  • Block known-bad IPs across all interfaces
# Example floating rule: block all traffic to known-bad IPs
block  floating  any  any  →  BLOCKLIST_ALIAS  "Block known malicious IPs"
Direction: any
Quick: checked    ← stops further rule evaluation on match

Viewing Firewall Logs

pfSense: Status > System Logs > Firewall OPNsense: Firewall > Log Files > Live View

Live log view is invaluable for debugging. The log shows:

  • Timestamp
  • Interface
  • Action (pass/block)
  • Protocol
  • Source IP:port
  • Destination IP:port
  • Rule description

From the shell, you can also read pf logs directly:

1
2
# pfSense/OPNsense shell
tcpdump -i pflog0 -n -e

Part 9: NAT and Port Forwarding

Understanding NAT in pfSense/OPNsense

NAT (Network Address Translation) is what allows all your private IP devices to share a single public WAN IP. By default, pfSense/OPNsense enables outbound NAT automatically — all traffic leaving the WAN interface is masqueraded behind the WAN IP.

There are three types of NAT configuration:

  • Outbound NAT — controls how LAN traffic appears when leaving to WAN
  • Port Forward (Inbound NAT / DNAT) — maps WAN IP:port to an internal host
  • 1:1 NAT — maps an entire WAN IP to an internal IP

pfSense: Firewall > NAT OPNsense: Firewall > NAT

Outbound NAT Modes

pfSense: Firewall > NAT > Outbound OPNsense: Firewall > NAT > Outbound

Mode Description
Automatic pfSense generates NAT rules for all internal networks automatically
Hybrid Automatic rules + your custom rules
Manual You manage all NAT rules
Disabled No outbound NAT (use with BGP/static routing if you have public IPs)

For most deployments, Hybrid is the right choice — it lets you add custom rules without breaking the auto-generated ones.

Port Forwarding

Port forwarding redirects inbound traffic on a specific WAN port to an internal host.

pfSense: Firewall > NAT > Port Forward > Add OPNsense: Firewall > NAT > Port Forward > +

Example — expose a web server on port 443:

Interface:          WAN
Protocol:           TCP
Destination:        WAN address
Destination port:   443
Redirect target IP: 192.168.20.10    ← internal web server
Redirect target port: 443
Description:        Web server HTTPS

Filter rule association: Add associated filter rule

The “Add associated filter rule” option automatically creates a corresponding firewall rule — always use it. Without a firewall rule, the NAT redirect is made but pf will still block the packet.

After saving, verify the rule under Firewall > Rules > WAN — you should see a rule that passes TCP to the internal IP on port 443.

Test from outside your network:

1
2
3
# From an external host or use online tools:
nmap -p 443 your.wan.ip.address
curl -v https://your.wan.ip.address

Port Forward with Port Translation

You can expose an internal service on a different external port:

Destination port:     8443      ← external port
Redirect target port: 443       ← internal port

This exposes your web server as https://wan-ip:8443 externally but connects to port 443 internally.

1:1 NAT

If you have multiple WAN IPs (from a /29 or larger block), 1:1 NAT dedicates one WAN IP to one internal host:

pfSense: Firewall > NAT > 1:1 > Add OPNsense: Firewall > NAT > One-to-One > +

Interface:      WAN
External IP:    203.0.113.5      ← additional WAN IP
Internal IP:    192.168.20.50    ← internal host
Destination:    any

All traffic to 203.0.113.5 is NATed to 192.168.20.50, and all outbound traffic from 192.168.20.50 appears as 203.0.113.5.

NAT Reflection (NAT Hairpinning)

NAT reflection allows LAN clients to reach port-forwarded services using the WAN IP. Without it, curl https://your-wan-ip from inside your network fails.

pfSense: System > Advanced > Firewall & NAT > Network Address Translation > NAT Reflection for Port Forwards: Enable (Pure NAT)

OPNsense: Firewall > Settings > Advanced > Reflection for Port Forwards: Enabled

For split DNS (preferred approach), create a local DNS host override that resolves your external FQDN to the internal IP — this avoids the double-NAT overhead of NAT reflection.


Part 10: VLANs on pfSense/OPNsense

VLANs let you segment the network logically without additional physical hardware. The firewall terminates VLAN trunks and routes between them.

For the switch configuration side, see the companion post on Network Segmentation with VLANs.

Creating VLANs on the Firewall

pfSense: Interfaces > Assignments > VLANs tab > Add OPNsense: Interfaces > Other Types > VLAN > +

Parent interface:  igb1         ← the physical port connected to your managed switch
VLAN tag:          10
VLAN priority:     0            ← leave at 0 unless using QoS
Description:       VLAN10_TRUSTED

Repeat for each VLAN:

igb1 / VLAN 10  → TRUSTED   (192.168.10.0/24)
igb1 / VLAN 20  → SERVERS   (192.168.20.0/24)
igb1 / VLAN 30  → IOT       (192.168.30.0/24)
igb1 / VLAN 40  → GUEST     (192.168.40.0/24)
igb1 / VLAN 50  → MGMT      (192.168.50.0/24)

Assigning VLAN Interfaces

After creating VLANs, assign them as logical interfaces:

pfSense: Interfaces > Assignments > Available network ports: select VLAN > Add OPNsense: Interfaces > Assignments > select VLAN interface > +

Then configure each:

Interfaces > OPT1 (rename to SERVERS):
  Enable: checked
  IPv4 type: Static
  IPv4 address: 192.168.20.1 /24

VLAN on the Switch Side

The trunk port connecting to the firewall must carry all VLANs. On a typical managed switch:

# Cisco IOS-style:
interface GigabitEthernet 0/1    ← port to firewall
  switchport mode trunk
  switchport trunk allowed vlan 10,20,30,40,50
  switchport trunk native vlan 99

# TP-Link Easy Smart / Web GUI:
VLAN > 802.1Q VLAN
  For each VLAN, add the uplink port as Tagged (T)
  Add access ports as Untagged (U)

Part 11: WireGuard and OpenVPN Integration

WireGuard in pfSense and OPNsense

WireGuard is the preferred VPN protocol — it’s faster, simpler, and has a smaller attack surface than OpenVPN.

pfSense: WireGuard is available as a package (System > Package Manager > WireGuard) OPNsense: WireGuard is built-in (VPN > WireGuard)

OPNsense WireGuard Server Setup

Step 1 — Enable WireGuard: VPN > WireGuard > General: Enable WireGuard

Step 2 — Create a Local Endpoint (Server): VPN > WireGuard > Local > +

Name:        wg0
Listen port: 51820
Tunnel address: 10.10.10.1/24    ← VPN tunnel subnet
Generate key pair: click "Generate"
  Public key: (auto-generated, copy this)
  Private key: (auto-generated, stored in config)

Step 3 — Add Peers (clients): VPN > WireGuard > Peers > +

For each client, generate a keypair on the client first:

1
2
3
# On the client machine:
wg genkey | tee privatekey | wg pubkey > publickey
cat publickey    # paste this into the firewall peer config

In OPNsense:

Name:           laptop-alice
Public key:     <paste client public key>
Allowed IPs:    10.10.10.2/32    ← this client's VPN IP
Endpoint:       (leave blank for road warriors — they connect in)

Step 4 — Assign WireGuard Interface: Interfaces > Assignments: assign wg0 → configure as:

Enable: checked
IPv4: Static, 10.10.10.1/24
Description: WireGuard

Step 5 — Firewall Rules:

WAN rule (allow inbound WireGuard):

pass  WAN  UDP  any  →  WAN address  port 51820  "WireGuard"

WireGuard interface rule (allow VPN clients to reach LAN):

pass  WireGuard  any  10.10.10.0/24  →  192.168.10.0/24  "VPN to LAN"

Step 6 — Client Configuration:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# /etc/wireguard/wg0.conf on the client
[Interface]
PrivateKey = <client private key>
Address = 10.10.10.2/32
DNS = 192.168.10.1          # use firewall DNS

[Peer]
PublicKey = <server public key from step 2>
Endpoint = your.wan.ip:51820
AllowedIPs = 0.0.0.0/0      # full tunnel — route all traffic through VPN
# or: AllowedIPs = 192.168.10.0/24  # split tunnel — LAN only
PersistentKeepalive = 25

Bring up: sudo wg-quick up wg0

pfSense WireGuard Setup

After installing the WireGuard package:

VPN > WireGuard > Tunnels > Add Tunnel:

Description:    wg0
Listen port:    51820
Interface keys: Generate

VPN > WireGuard > Peers > Add Peer:

Tunnel:         wg0
Description:    alice-laptop
Public key:     <client pubkey>
Allowed IPs:    10.10.10.2/32

Then assign the wg0 tunnel as an interface (Interfaces > Assignments) and add firewall rules as above.

OpenVPN Setup (for legacy clients)

OpenVPN is useful when WireGuard is unavailable (some corporate networks block UDP) or when you need client certificate management.

pfSense: VPN > OpenVPN > Wizards (use the server wizard — easiest path) OPNsense: VPN > OpenVPN > Servers > +

OPNsense OpenVPN Server (Road Warrior):

Step 1 — Create a CA: System > Trust > Authorities > +

Method: Create internal Certificate Authority
CN:     Home-VPN-CA

Step 2 — Create a Server Certificate: System > Trust > Certificates > +

Method: Create internal Certificate
CA:     Home-VPN-CA
Type:   Server Certificate
CN:     openvpn-server

Step 3 — OpenVPN Server: VPN > OpenVPN > Servers > +

Server mode:      Remote Access (SSL/TLS + User Auth)
Backend:          Local Database
Protocol:         UDP on IPv4
Device mode:      tun
Interface:        WAN
Port:             1194
TLS Configuration: Use a TLS key (generate one)
CA:               Home-VPN-CA
Certificate:      openvpn-server
Tunnel network:   10.20.0.0/24
Local network:    192.168.10.0/24
DNS server 1:     192.168.10.1

Step 4 — Create VPN users: System > Access > Users > + (set username, password, create user certificate)

Step 5 — Export client configs: Install the OPNsense openvpn-client-export plugin: System > Firmware > Plugins > os-openvpn-client-export

Then: VPN > OpenVPN > Client Export > download .ovpn profile


Part 12: High Availability with CARP

CARP (Common Address Redundancy Protocol) is BSD’s answer to VRRP/HSRP. It allows two pfSense/OPNsense firewalls to share a virtual IP address, with one acting as primary and one as backup. If the primary fails, the backup takes over within seconds.

Requirements

  • Two identical (or similar) firewall machines
  • Three physical connections per firewall:
    • WAN (one per firewall — different cables to same switch)
    • LAN (one per firewall — different cables to same switch)
    • pfsync/sync interface — a dedicated interface for state synchronization (can be a direct crossover or via a separate switch)

CARP IP Planning

For each shared interface, you need:

  • A virtual/shared IP (the CARP VIP) — what clients use
  • A real IP for each firewall node

Example:

Interface   CARP VIP         Primary           Secondary
WAN         203.0.113.1      203.0.113.2       203.0.113.3
LAN         192.168.10.1     192.168.10.2      192.168.10.3
pfsync      (dedicated)      172.16.0.1/30     172.16.0.2/30

Primary Firewall Configuration

Step 1 — Create CARP VIPs:

pfSense: Firewall > Virtual IPs > Add OPNsense: Interfaces > Virtual IPs > +

Type:              CARP
Interface:         LAN
IP address:        192.168.10.1/24
Virtual IP password: carp-secret-pass    ← must match on both nodes
VHID group:        1
Advertising frequency: Base 1, Skew 0   ← lower skew = preferred primary
Description:       LAN CARP VIP

Repeat for WAN interface.

Step 2 — Configure pfsync:

pfSense: System > High Availability > Synchronize States OPNsense: Services > Unbound DNS… (OPNsense uses a different path)

Synchronize states: enabled
Synchronize interface: OPT_SYNC (your dedicated sync interface)
pfsync Synchronize Peer IP: 172.16.0.2    ← secondary's sync IP

Step 3 — Configure Config Sync (XMLRPC sync):

pfSense: System > High Availability > Synchronize Config

Synchronize config to IP: 172.16.0.2
Remote System Username: admin
Remote System Password: secondary-admin-pass
Synchronize rules: checked
Synchronize users: checked
Synchronize certificates: checked

Secondary Firewall Configuration

Install pfSense/OPNsense identically on the second machine. Configure:

  • Same interfaces
  • Unique real IPs on each interface (not the CARP VIPs)
  • Create the same CARP VIPs with Advertising skew: 100 (higher = becomes secondary)

The primary will sync rules, certs, and users to the secondary via XMLRPC/config sync.

Testing Failover

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# On a LAN client, ping the CARP VIP continuously:
ping 192.168.10.1

# While pinging, pull power from the primary firewall
# The ping should resume within 1-3 seconds as secondary takes over

# Check CARP status on either node:
# pfSense: Status > CARP
# OPNsense: Interfaces > Virtual IPs (shows MASTER/BACKUP status)

# From the firewall shell:
ifconfig | grep carp
# Look for: carp0: flags=... status: MASTER

Part 13: Packages and Plugins

pfSense Package Manager

pfSense: System > Package Manager > Available Packages

Key packages:

Package Purpose
pfBlockerNG DNS and IP blocking for ads, malware, threat feeds
Suricata Inline IDS/IPS with Snort-compatible rules
Snort Alternative IDS/IPS
HAProxy L7 load balancer and reverse proxy
Squid Web caching proxy
SquidGuard Content filtering for Squid
ACME Let’s Encrypt certificate management
OpenVPN Client Export Generate client .ovpn profiles
nmap Network scanner
iperf Bandwidth testing
WireGuard WireGuard VPN (if not built-in)
Telegraf Metrics agent for InfluxDB/Grafana
ntopng Network traffic analyzer

OPNsense Plugin Manager

OPNsense: System > Firmware > Plugins

OPNsense uses the os- prefix convention for official plugins:

Plugin Purpose
os-acme-client Let’s Encrypt via ACME
os-haproxy HAProxy load balancer
os-wireguard WireGuard (if not already included)
os-siproxd SIP proxy for VoIP
os-stunnel SSL tunneling
os-telegraf Metrics exporter
os-zerotier ZeroTier VPN mesh
os-mdnsrepeater mDNS/Bonjour across VLANs
os-freeradius RADIUS server
os-qemu-guest-agent QEMU guest agent for VM deployments
os-openvpn-client-export Export OpenVPN configs
os-frr FRRouting (BGP, OSPF, RIP)

pfBlockerNG — DNS Blocking at the Firewall

pfBlockerNG is one of pfSense’s most popular packages. It provides DNS blackholing (blocking malicious/ad domains) and IP reputation-based filtering using public blocklists.

Installation: System > Package Manager > pfBlockerNG-devel (use the devel version — it’s more stable)

Initial setup wizard: Firewall > pfBlockerNG > Wizard

pfBlockerNG mode: DNSBL + IP
DNS resolver integration: Unbound
DNSBL listening interface: LAN (and other internal interfaces)

Adding DNS blocklists: Firewall > pfBlockerNG > DNSBL > DNSBL Feeds > +

Recommended feeds:

Feed name:    EasyList
Feed URL:     https://easylist.to/easylist/easylist.txt
Format:       Auto
Action:       Unbound

Feed name:    Steven Black
Feed URL:     https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts
Format:       Auto

Feed name:    URLhaus
Feed URL:     https://urlhaus.abuse.ch/downloads/hostfile/
Format:       Auto

After configuring, run: Firewall > pfBlockerNG > Update > Run

Adding IP blocking: Firewall > pfBlockerNG > IP > IPv4 > +

Name:       Emerging_Threats
Feed:       https://rules.emergingthreats.net/blockrules/compromised-ips.txt
Format:     auto
Action:     Deny Both (block inbound and outbound)
Frequency:  Every 6 hours

Verify pfBlockerNG is working:

1
2
3
4
5
6
# From a client, try to resolve an ad domain:
dig doubleclick.net @192.168.10.1
# Should return 0.0.0.0 or NXDOMAIN

# Check pfBlockerNG logs:
Firewall > pfBlockerNG > Reports > Alerts

Suricata IDS/IPS

Suricata is a multi-threaded network intrusion detection and prevention system. In IDS mode it alerts; in IPS mode it actively blocks.

pfSense installation: System > Package Manager > Suricata OPNsense: Built-in at Services > Intrusion Detection

pfSense Suricata Configuration

Services > Suricata > Interfaces > Add:

Interface:          WAN
Mode:               Legacy Mode (PCAP)  or  NFQ Mode (IPS)
Blocking mode:      IPS mode for inline blocking
Prometheues:        optional
Block Offenders:    checked (for IPS)
Block Offenders IP: both
Kill States:        checked  ← terminate existing connections for blocked IPs

Services > Suricata > Global Settings > Install ETOpen Rules:

Enable ETOpen: checked
Update interval: 12 hours

Rulesets to enable:

emerging-malware.rules
emerging-exploit.rules
emerging-botcc.rules
emerging-trojan.rules
emerging-web_client.rules

Performance note: Suricata is CPU-intensive. On a quad-core system, expect 20-40% CPU usage with a full rule set on a moderately loaded network. Tune by disabling unnecessary rule categories.

OPNsense Intrusion Detection (Suricata)

Services > Intrusion Detection > Administration > General:

Enabled: checked
IPS mode: checked (for inline blocking)
Interfaces: WAN, LAN (or select interfaces)
Pattern matcher: Hyperscan (if available) or Aho-Corasick

Services > Intrusion Detection > Administration > Download: Enable and download:

  • ET open/emerging-malware
  • ET open/emerging-exploit
  • ET open/emerging-botcc

Services > Intrusion Detection > Administration > Schedule:

Cron schedule: 0 */12 * * *    ← update every 12 hours

HAProxy — Reverse Proxy and Load Balancer

HAProxy in pfSense/OPNsense turns your firewall into a L7 reverse proxy with SSL termination. This lets you expose multiple internal services on a single public IP/port using SNI or HTTP Host header routing.

pfSense: System > Package Manager > HAProxy, then Services > HAProxy OPNsense: System > Firmware > Plugins > os-haproxy, then Services > HAProxy

Basic Setup: HTTPS Reverse Proxy

Step 1 — Backend (your internal server): Services > HAProxy > Backend > +

Name:        plex-backend
Mode:        http
Balance:     roundrobin
Server list:
  Name: plex1  Address: 192.168.20.10  Port: 32400
Health check: HTTP

Step 2 — Frontend (what clients connect to): Services > HAProxy > Frontend > +

Name:               https-frontend
Status:             Active
Bind:               0.0.0.0:443
SSL offloading:     checked
Certificate:        your-acme-cert (from ACME package)
SNI filter/routing:
  Condition:        Host matches plex.example.com
  Backend:          plex-backend
Default backend:    (none or a catch-all)

Step 3 — Firewall rule: Allow TCP 443 to HAProxy (localhost) on WAN.

This setup allows plex.example.com → HAProxy → 192.168.20.10:32400 with TLS termination at the firewall.


Part 14: OPNsense-Specific Features

Zenarmor (Sensei)

Zenarmor (formerly Sensei) is a deep packet inspection engine that runs natively in OPNsense. It provides application-layer visibility and blocking beyond what traditional firewall rules offer.

Installation: System > Firmware > Plugins > os-zenarmor

Zenarmor features:

  • Layer 7 application identification (Netflix, YouTube, Zoom, etc.)
  • TLS inspection (with CA certificate deployed to clients)
  • Policy-based blocking by application category
  • Reporting dashboard with per-device traffic breakdown

Free tier: basic reporting and blocking Paid tiers: advanced features, cloud threat intelligence

Navigation: Zenarmor > Dashboard, Policies, Reports

Note: Zenarmor requires a decent CPU — it’s doing DPI on every packet. A Celeron J6412 can handle typical home lab traffic (200–500 Mbps); anything heavier needs more cores.

OPNcentral

OPNcentral is the centralized management plane for multiple OPNsense instances — analogous to pfSense’s ITAR/pfSense Plus features.

  • Plugin: os-OPNcentral (installed on the central manager node)
  • Manages firmware updates across all instances
  • Pushes configuration templates
  • Centralized monitoring

Primarily useful for MSPs or environments with 5+ firewalls.

Firmware Update Mechanism

OPNsense has a polished, safe firmware update process:

System > Firmware > Status:

Check for updates → shows pending major/minor updates
Business Edition mirrors vs Community mirrors

Types of updates:

  • Minor updates (e.g., 25.1.1 → 25.1.2): Applied via GUI, usually safe to apply immediately
  • Major updates (e.g., 25.1 → 25.7): Larger changes, read release notes first

From the console/shell:

1
2
3
4
5
6
7
8
9
# Check for updates:
opnsense-update -c

# Apply updates:
opnsense-update -u    # upgrade packages only
opnsense-update -uf   # upgrade base system and packages

# List installed packages:
pkg info | grep opnsense

Before major updates:

  1. Take a config backup (next section)
  2. Read the release notes at docs.opnsense.org
  3. Check for breaking changes in your installed plugins

Business Edition vs Community Edition

OPNsense Business Edition adds:

  • Long-term support tracks (LTS) — slower, more stable release cycle
  • Commercial support from Deciso
  • Advanced plugins (OPNcentral, etc.)

For home labs and most SMBs, Community Edition is sufficient.


Part 15: Backup and Restore

Configuration backups are critical. A firewall rebuild from scratch after hardware failure is painful and error-prone. Both platforms make backup trivial.

Manual Backup

pfSense: Diagnostics > Backup & Restore > Download configuration as XML OPNsense: System > Configuration > Backups > Download

The backup is a single XML file containing all configuration: interfaces, rules, NAT, DHCP leases, VPN configs, package settings, users, certificates.

1
2
3
4
# Store backups off-device — on a NAS, backup server, or encrypted cloud storage
# Name them with date:
fw01-pfsense-2026-03-25.xml
fw01-opnsense-25.1-2026-03-25.xml

Automated Backups

pfSense — AutoConfigBackup: Services > AutoConfigBackup (requires free Netgate account) Or use a cron job to SCP the config off the box:

Diagnostics > Command Prompt:

1
2
3
4
5
6
# pfSense shell — SSH is easier; enable under System > Advanced > Admin
# The config is at:
cat /cf/conf/config.xml

# SCP from a remote host:
scp admin@192.168.10.1:/cf/conf/config.xml ./fw-backup-$(date +%Y%m%d).xml

OPNsense — Scheduled Backups: System > Configuration > Backups > Scheduled Backups:

Enabled: checked
Backup count: 7        ← keep 7 days
Remote host:           (optional SFTP destination)

Or use the API:

1
2
3
4
5
# OPNsense has a REST API — back up via curl:
curl -u 'apikey:apisecret' \
  https://192.168.10.1/api/core/backup/download/this \
  -o fw-backup-$(date +%Y%m%d).xml \
  --insecure    # if using self-signed cert

Restore

pfSense: Diagnostics > Backup & Restore > Restore configuration > Choose file > Restore OPNsense: System > Configuration > Backups > choose backup file > Restore

After restore, the firewall reboots with the restored configuration.

Restore a specific section only: Both platforms support partial restores — useful if you only want to restore firewall rules without touching interface config:

pfSense: Diagnostics > Backup & Restore > Restore area: Firewall Rules

Backup Before Package Updates

1
2
3
4
5
# OPNsense — backup before major updates via shell:
cp /conf/config.xml /conf/config.xml.pre-upgrade-$(date +%Y%m%d)

# pfSense:
cp /cf/conf/config.xml /cf/conf/config.xml.pre-upgrade-$(date +%Y%m%d)

Part 16: Troubleshooting Common Issues

Can’t Reach the Internet

Step 1 — Check WAN interface status:

  • pfSense: Status > Interfaces
  • OPNsense: Lobby > Dashboard (WAN widget) or Interfaces > Overview

WAN should show an IP address. If not:

  • DHCP WAN: check if DHCP is working — try Status > DHCP Leases or release/renew
  • PPPoE: check credentials and ISP link status

Step 2 — Test from the firewall itself: Diagnostics > Ping (or SSH into the firewall shell):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Test connectivity from the firewall:
ping -c 3 8.8.8.8          # basic connectivity test
ping -c 3 google.com        # tests DNS resolution from firewall

# Trace route:
traceroute 8.8.8.8

# Check routing table:
netstat -rn     # or: route -n get 0.0.0.0
# Should show a default route via the WAN gateway

# Check gateway status:
# pfSense: Status > Gateways
# OPNsense: System > Gateways > Configuration (shows RTT, loss)

Step 3 — Test from a client:

1
2
3
4
# On a LAN client:
ping 192.168.10.1         # ping the firewall LAN IP — if this fails, it's a LAN issue
ping 8.8.8.8              # if this works but next doesn't, it's DNS
ping google.com           # tests DNS resolution from client

Step 4 — Check outbound NAT:

  • pfSense: Firewall > NAT > Outbound — ensure automatic NAT rules exist for your LAN subnet
  • OPNsense: Firewall > NAT > Outbound — same

Step 5 — Check firewall rules:

1
2
3
4
5
6
7
8
# Check packet filter state table:
pfctl -s state | grep 8.8.8.8

# Check if rules are loaded:
pfctl -s rules | head -50

# View blocked packets in real time:
tcpdump -i pflog0 -n -e | head -50

Firewall Rule Debugging

The live log is your best tool.

pfSense: Status > System Logs > Firewall > click the play button for live view OPNsense: Firewall > Log Files > Live View

Filter by source or destination IP to isolate the problem. When you see a block, note:

  • Which interface
  • Source and destination
  • Protocol and port

Then trace back which rule (or lack of rule) caused the block.

Enable logging on suspect rules temporarily: Edit the rule > Advanced Options > Log packets that are handled by this rule: checked

Use Diagnostics > Packet Capture:

Interface: LAN
Promiscuous mode: checked
Host address: 192.168.10.50    ← the client you're debugging
Packets to capture: 100
Protocol: any

This captures raw packets and lets you download a .pcap for analysis in Wireshark.

pfSense shell:

1
2
3
4
5
6
7
8
# Capture on LAN interface:
tcpdump -i igb1 -n host 192.168.10.50 -w /tmp/capture.pcap

# View pf rules currently loaded:
pfctl -s rules | grep -i block

# Check if a specific IP is blocked by pfBlockerNG:
pfctl -t pfB_DNSBL -T show | grep <ip>

State Table Issues

The state table tracks every active connection. Full state tables cause dropped connections and instability.

Check state table usage:

1
2
3
4
5
6
7
# pfSense/OPNsense shell:
pfctl -s info | grep -i state
# Shows: current entries, searches/inserts/removals per second

# View all states:
pfctl -s state | wc -l    # count of active states
pfctl -s state | head -20  # first 20 states

Default state table size: 1,000,000 entries (pfSense), 400,000 (OPNsense default). Increase if needed:

pfSense: System > Advanced > Firewall & NAT > Firewall Maximum States OPNsense: Firewall > Settings > Advanced > Firewall Maximum States

Flush all states (last resort — drops all connections):

1
pfctl -F states    # flush all states from shell

pfSense: Diagnostics > States > Reset States

Clear states for a specific host:

1
2
pfctl -k 192.168.10.50    # clear states where source is this IP
pfctl -k 0.0.0.0 -k 203.0.113.100   # clear states between specific IPs

DNS Not Resolving

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# Test DNS from the firewall:
drill google.com @127.0.0.1          # query local Unbound
drill google.com @1.1.1.1           # query upstream directly

# Check Unbound is running:
service unbound status   # pfSense
# or check Services > Unbound DNS in the GUI

# Restart Unbound:
service unbound restart  # shell
# or: Services > Unbound DNS > restart button

# Check Unbound logs:
cat /var/log/resolver.log    # pfSense
# OPNsense: Services > Unbound DNS > Log File

# Test DNSSEC:
drill -D sigok.verteiltesysteme.net @192.168.10.1   # should return RRSIG
drill -D sigfail.verteiltesysteme.net @192.168.10.1  # should SERVFAIL if DNSSEC works

PPPoE Disconnects

PPPoE sessions drop periodically. Common causes:

  • ISP-side timeout (many ISPs force reconnect every 24h)
  • MTU mismatch causing large packets to fail
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Check PPPoE status:
ifconfig pppoe0
# Should show "inet <your-ip>" if connected

# Check PPPoE logs:
cat /var/log/pppoeclient.log   # pfSense
# OPNsense: Interfaces > Point-to-Point > Log

# Force reconnect:
# pfSense: Interfaces > WAN > Release/Renew
# OPNsense: Interfaces > WAN > click Renew button

MTU fix for PPPoE — set MSS clamping: pfSense: System > Advanced > Networking > Disable hardware checksum offload: checked (fixes many NIC-related issues) OPNsense: Interfaces > WAN > MSS: 1452


Part 17: Security Hardening

Management Interface Restrictions

Do not expose the web GUI to WAN. This is the single most important security step.

Verify WAN rules have no management access: Firewall > Rules > WAN — there should be NO rules allowing TCP 443 or TCP 80 to the firewall itself from WAN.

Restrict GUI to specific admin hosts:

pfSense: System > Advanced > Admin Access > webConfigurator > Anti-lockout rule: checked Then add a firewall rule:

pass  LAN  TCP  ADMIN_HOSTS  →  LAN address  port 443  "Admin GUI access"
block LAN  TCP  any          →  LAN address  port 443  "Block non-admin GUI"

OPNsense: System > Settings > Administration > Listen Interfaces (restrict to management interface only)

Change Default Ports

pfSense/OPNsense: System > Advanced > Admin Access > TCP Port: Change from 443 to a non-standard port (e.g., 8443). This isn’t security through obscurity for determined attackers, but it reduces noise from internet scanners if WAN GUI is accidentally exposed.

Disable Unused Services

1
2
3
4
5
6
7
8
9
# List running services:
# pfSense: Status > Services
# OPNsense: Services > Services Status

# Disable what you don't use:
# - SNMP (System > Advanced > SNMP) — disable if not monitoring
# - UPnP (Services > UPnP & NAT-PMP) — disable for security-conscious setups
# - mDNS Repeater — only enable if needed
# - SSH — only enable when actively administering

Disable SSH when not in use: pfSense: System > Advanced > Admin Access > Secure Shell: disable OPNsense: System > Settings > Administration > Secure Shell: disable

Or restrict SSH to admin hosts via firewall rules.

SSH Hardening (when enabled)

pfSense/OPNsense shell:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# /etc/ssh/sshd_config additions:
# pfSense stores this at /etc/ssh/sshd_config but it's overwritten on reboot
# Use the GUI options instead:

# pfSense: System > Advanced > Admin Access > SSH:
#   Authentication method: Public key only
#   Add your public key under System > User Manager > admin > Authorized SSH Keys

# OPNsense: System > Settings > Administration > Secure Shell:
#   Authentication method: Public Key Only
#   Add keys under System > Access > Users > admin > Authorized keys

Update Schedule

Keeping firmware current is non-negotiable for a network device.

pfSense: Keep CE up to date via System > Update > Update Settings Consider subscribing to the pfSense subreddit for update announcements.

OPNsense: Set automatic checks: System > Firmware > Updates > Check for updates: Weekly

For OPNsense, the typical cadence: apply minor updates (25.1.x) within a week of release; plan major updates (25.1 → 25.7) within 30 days of release.

Certificate Management

Replace the self-signed web GUI certificate to avoid browser warnings and to enable certificate pinning:

pfSense/OPNsense with ACME (for publicly accessible FQDNs):

  1. Install ACME package/plugin
  2. Create an ACME account with Let’s Encrypt
  3. Issue a certificate for your admin hostname via DNS-01 challenge (doesn’t require port 80/443 on WAN)
  4. Set the GUI to use this certificate: System > Advanced > Admin Access > SSL Certificate

For internal-only management (no public DNS): Create a local CA and issue a certificate:

  • pfSense/OPNsense: System > Certificate Manager > CAs > Add (create internal CA)
  • System > Certificate Manager > Certificates > Add (issue server cert signed by your CA)
  • Deploy your CA certificate to admin browsers/devices

Restrict Management by Interface

Configure the GUI to only listen on the management VLAN:

OPNsense: System > Settings > Administration > Listen interfaces: select only MGMT interface pfSense: System > Advanced > Admin Access: add a firewall rule to block GUI access from non-admin VLANs

Auditability and Logging

Enable logging on all deny rules:

  • Both platforms allow per-rule logging
  • Enable on all block rules to track what’s being denied
  • Send logs to a syslog server for long-term retention

pfSense: Status > System Logs > Settings > Remote logging OPNsense: System > Log Files > Settings > Remote syslog > enable, add destination IP

Example syslog configuration (OPNsense):

Remote syslog server: 192.168.20.100:514
Source address: LAN
Facilities: firewall, system, auth, dhcpd

Pair with Graylog, ELK, or Loki+Promtail on your log server for searchable, retained logs.

Bogon Networks and Anti-Spoofing

Both platforms include built-in anti-spoofing and bogon filtering:

Bogon filtering blocks traffic from IP ranges that should never appear on the internet (unallocated, loopback, private):

  • pfSense: Interfaces > WAN > Block private networks, Block bogon networks: both checked
  • OPNsense: Interfaces > [WAN] > Block private networks, Block bogon networks: both checked

Source routing: Block IP source routing in: pfSense: System > Advanced > Networking > IP Do-Not-Fragment > Block IP source routing


Putting It All Together: A Reference Architecture

Here’s a recommended starting configuration for a home lab or small business:

ISP Modem/ONT
     │
     │ WAN (igb0)
     ▼
┌─────────────────┐
│  pfSense /      │ LAN: 192.168.10.1
│  OPNsense       │ SERVERS: 192.168.20.1
│                 │ IOT: 192.168.30.1
│  WireGuard      │ MGMT: 192.168.50.1
│  Unbound+DoT    │
│  pfBlockerNG    │
│  ACME certs     │
└─────────────────┘
     │
     │ Trunk (igb1) carrying VLANs 10,20,30,50
     ▼
Managed Switch
├── VLAN 10 access ports → Workstations, laptops
├── VLAN 20 access ports → Servers, NAS, Proxmox
├── VLAN 30 access ports → IoT (or Wi-Fi SSID)
└── VLAN 50 access port  → Switch management IP

Firewall policies:

  • TRUSTED → SERVERS: allow specific ports (22, 443, 8006, 32400…)
  • TRUSTED → IOT: block (one-way allow from SERVERS if needed for Home Assistant)
  • IOT → all: internet only, block RFC1918
  • SERVERS → internet: allow HTTP/HTTPS, NTP; block all else unless needed
  • MGMT → firewall GUI: allow; block GUI from all other VLANs
  • WireGuard clients → TRUSTED: allow; full tunnel through firewall

CLI and API Reference

pfSense CLI Essentials

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# SSH into pfSense (or use Diagnostics > Command Prompt):

# Interface status:
ifconfig

# Routing table:
netstat -rn

# Active connections (pftop):
pftop

# Packet filter rules:
pfctl -s rules

# State table:
pfctl -s state | head -50

# Flush state table:
pfctl -F states

# Capture packets (save to file):
tcpdump -i igb1 -w /tmp/cap.pcap -c 1000

# View logs:
cat /var/log/filter.log | tail -100

# Restart services:
/etc/rc.restart_webgui         # restart web GUI
service unbound restart        # restart DNS resolver
service dhcpd restart          # restart DHCP server

# Check pfBlockerNG status:
pfctl -t pfB_DNSBL -T show | wc -l    # count blocked domains

# Show all tables:
pfctl -s Tables
pfctl -t <tablename> -T show

OPNsense CLI and API

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# SSH into OPNsense:

# Interface status:
ifconfig
ifconfig igb0   # specific interface

# Routing:
netstat -rn
route -n get 0/0    # show default route

# Packet filter:
pfctl -s rules
pfctl -s state | wc -l

# Capture:
tcpdump -i igb1 -n port 53 -w /tmp/dns.pcap

# Update from CLI:
opnsense-update -c    # check
opnsense-update -u    # update packages

# Plugin management:
pkg install os-haproxy
pkg remove os-haproxy

# Config backup via API:
curl -su 'key:secret' \
  'https://localhost/api/core/backup/download/this' \
  -o backup.xml --insecure

# Restart services via API:
curl -su 'key:secret' -X POST \
  'https://localhost/api/unbound/service/restart' --insecure

# Firewall rules via API:
curl -su 'key:secret' \
  'https://localhost/api/firewall/filter/searchRule' --insecure | jq .

Generating API Keys in OPNsense

System > Access > Users > admin > API Keys > +

This generates a key+secret pair. Store the secret immediately — it’s only shown once.


Quick Reference: UI Navigation Paths

Task pfSense OPNsense
Interface config Interfaces > [name] Interfaces > [name]
VLAN config Interfaces > Assignments > VLANs Interfaces > Other Types > VLAN
Firewall rules Firewall > Rules > [interface] Firewall > Rules > [interface]
Aliases Firewall > Aliases Firewall > Aliases
NAT/Port Forward Firewall > NAT > Port Forward Firewall > NAT > Port Forward
DHCP server Services > DHCP Server Services > DHCPv4
DHCP leases Status > DHCP Leases Services > DHCPv4 > Leases
DNS resolver Services > DNS Resolver Services > Unbound DNS
DNS-over-TLS Services > DNS Resolver > Custom Options Services > Unbound DNS > DNS over TLS
Certificates System > Certificate Manager System > Trust
Packages System > Package Manager System > Firmware > Plugins
Backup Diagnostics > Backup & Restore System > Configuration > Backups
System logs Status > System Logs System > Log Files
Firewall logs Status > System Logs > Firewall Firewall > Log Files > Live View
Packet capture Diagnostics > Packet Capture Interfaces > Diagnostics > Packet Capture
Ping/Traceroute Diagnostics > Ping / Traceroute Interfaces > Diagnostics > Ping
Shell/console Diagnostics > Command Prompt System > Shell (or SSH)
WireGuard VPN > WireGuard VPN > WireGuard
OpenVPN VPN > OpenVPN VPN > OpenVPN
CARP/HA Firewall > Virtual IPs Interfaces > Virtual IPs
pfsync System > High Availability Services > High Availability
Updates System > Update System > Firmware
SSH enable System > Advanced > Admin System > Settings > Administration

A properly configured pfSense or OPNsense installation will outlast any consumer router by years, and the visibility it gives you into your network — live traffic graphs, per-rule hit counters, DNS query logs, IDS alerts — turns network administration from guesswork into engineering. Start with a basic WAN/LAN setup, add VLANs as you segment devices, enable DNS-over-TLS and pfBlockerNG for security, then grow into WireGuard and high availability as your needs demand. The platform grows with you.

Comments