Firewall Appliance: OPNsense & pfSense Management
Manage, troubleshoot, and harden OPNsense and pfSense firewalls via SSH. Both are FreeBSD-based, pf-powered firewall distributions - most concepts, commands, and patterns apply to both.
Target versions (May 2026):
- OPNsense CE: 26.1.7 (current Community Edition stable, "Witty Woodpecker"; CE ships odd quarters .1/.7). Business Edition is 26.4.x (even quarters .4/.10) - do not quote the BE number as the CE version
- pfSense CE: 2.8.1 / pfSense Plus: 26.03
- CrowdSec: v1.7.7
When to use
- Managing or troubleshooting OPNsense and pfSense firewalls over SSH
- Reviewing pf rules, NAT, CARP, Unbound, WireGuard, CrowdSec, or pfBlockerNG on these appliances
- Configuring VLANs, CARP HA failover, or interface assignments on firewall appliances
- Debugging connectivity between networks or VLANs routed through OPNsense/pfSense
- Hardening BSD firewall appliances and validating safe remote-change workflows
When NOT to use
- Linux networking, reverse proxies, VPN setup, or nftables work outside firewall appliances - use networking
- Cloud firewall rules, WAF configuration, or AWS/GCP/Azure network ACLs - use networking or the relevant IaC skill (terraform, ansible)
- General shell scripting or local shell behavior outside the BSD firewall context - use command-prompt
- Fleet-wide configuration management via playbooks - use ansible
- Offensive testing, exploitation, or post-exploitation - use lockpick
- Application-level security review or dependency scanning - use security-audit
AI Self-Check
Before returning any firewall commands, verify:
- Platform confirmed (OPNsense vs pfSense) - commands differ between them
- No commands that could lock out SSH or management access
- Config backup taken (or reminded) before destructive changes
-
pfctlrules tested with-n(dry run) before applying - Service names correct for the target platform (
configctlvsservice) - Plugin names use correct prefix (
os-*for OPNsense, unprefixed for pfSense) - CARP changes target the master node, not the backup
- Shell syntax is POSIX sh (heredoc), not bash/zsh (csh/tcsh is the default shell on both)
- No firmware or plugin updates without explicit user confirmation
- Blast radius stated for any change affecting network connectivity
- DNS impact considered - changes to Unbound, DHCP, or firewall rules on port 53 can break name resolution for all clients on affected VLANs
- CrowdSec/pfBlockerNG checked when diagnosing blocks - bans look identical to firewall drops from the client side
- VLAN interface assigned before adding rules - unassigned VLANs pass no traffic through the firewall even if the trunk is tagged correctly
- Current source checked: dated versions, CLI flags, API names, and support windows are verified against primary docs before repeating them
- Hidden state identified: local config, credentials, caches, contexts, branches, cluster targets, or previous runs are made explicit before acting
- Verification is real: final checks exercise the actual runtime, parser, service, or integration point instead of only linting prose or happy paths
- Routing overlap checked: overlapping skills, trigger terms, and "When NOT to use" boundaries are checked before returning guidance
- Spec claims verified: claims about tool behavior, output contracts, or repo conventions are checked against current docs, scripts, or skill files
- Platform/version checked: OPNsense, pfSense, FreeBSD, pf, and plugin commands match the appliance version
- Lockout path prevented: remote firewall changes preserve management access and rollback
Performance
- Prefer rule ordering that rejects high-volume unwanted traffic early and keeps expensive inspection scoped.
- Use aliases/tables for large address sets instead of expanding repetitive rules.
- Check state table, DNSBL, IDS/IPS, and plugin load before blaming WAN latency.
Best Practices
- Export configuration before rule, NAT, VPN, CARP, or package changes.
- Make HA changes one node at a time and verify CARP state before touching the peer.
- Keep emergency console or out-of-band access available for management-plane changes.
Workflow
Step 1: Detect platform
If the platform is not obvious from context, ask the user which one they're running before issuing commands. Identify the target device explicitly - never assume which firewall you're talking to. Key differences at a glance:
| OPNsense | pfSense | |
|---|---|---|
| Base OS | FreeBSD (migrated from HardenedBSD in 2021) | FreeBSD |
| Config path | /conf/config.xml | /cf/conf/config.xml |
| Service control | configctl service restart <svc> | pfSsh.php playback svc restart <svc> or service <svc> restart |
| Plugin prefix | os-<name> (e.g., os-wireguard) | No prefix (e.g., pfSense-pkg-WireGuard) |
| PHP shell | N/A | pfSsh.php (interactive PHP shell) |
| Quick rule add | N/A | easyrule pass wan tcp <src> <dst> <port> |
| IP blocking | CrowdSec (os-crowdsec) | pfBlockerNG |
| Root shell | csh | tcsh (same heredoc workaround applies) |
| IDS/IPS config | /tmp/suricata_*.log, eve.json | /var/log/suricata/suricata.log, eve.json |
| Firmware CLI | configctl firmware check/status | pkg-static update + GUI |
| Template engine | configd + configctl template | PHP-generated configs |
| REST API | Yes (/api/, key/secret auth) | Yes (similar, different endpoints) |
| Licensing | Free, open source | CE: free but slower updates; Plus: $129/yr on non-Netgate HW |
| Release cadence | Bi-weekly, fixed schedule | Irregular, Netgate hardware prioritized |
2026 status: OPNsense is the clear choice for new deployments. pfSense CE gets slower updates and zero priority; Plus costs $129/year on non-Netgate hardware. Migration from pfSense to OPNsense has no automated path - expect ~60% clean config transfer, manual rebuild for NAT rules, VPN, and DNS forwarder settings.
When platform is unknown, these commands work on both:
pfctl -sr # firewall rules
pfctl -ss # state table
ifconfig # interfaces
pkg info # installed packages
netstat -rn # routing table
sockstat -4l # listening sockets
Step 2: Back up config
Before any change that modifies rules, services, plugins, or firmware:
- OPNsense:
configctl firmware backupor GUI export (System > Configuration > Backups) - pfSense: GUI export (Diagnostics > Backup & Restore) or copy
/cf/conf/config.xml - For major upgrades on virtualized firewalls, pair config backup with a hypervisor snapshot
Skip this step only for read-only operations (diagnostics, log review, status checks).
Step 3: Execute the task
Apply changes using the platform-appropriate commands. Refer to the domain sections below and the reference files for specifics. For any change that affects connectivity:
- Test
pfctlrules with-n(dry run) before applying - State the blast radius ("this will drop all VPN tunnels for ~30s")
- On HA pairs, always change on the master node and let XMLRPC sync propagate
Step 4: Verify
After every change, confirm the firewall is healthy:
- Connectivity: can you still reach the device? Can clients reach the internet?
- Logs: check
/var/log/filter.log, service logs, and CrowdSec/Suricata if active - Service status:
configctl service list(OPNsense) orservice -e(pfSense) - State table:
pfctl -si | grep entries- watch for unexpected drops or state exhaustion
Quick Task Procedures
Creating a firewall rule (VLAN to server)
- Identify the interface the traffic originates from (e.g.,
opt1for VLAN 50) - Confirm the VLAN interface is assigned:
ifconfigmust show the VLAN interface UP. If the VLAN is not assigned to an OPNsense/pfSense in