Network Edge & Security (OPNsense)
Source: Anshin Engineering, Rev 1.0, 2026-03-22
This document covers the OPNsense high-availability firewall pair that forms the secure perimeter of the Anshin Health network. All ingress and egress traffic passes through this layer before reaching internal infrastructure.
OPNsense is free and open-source (BSD license). Every feature โ IDS/IPS, VPN, HAProxy, HA failover, REST API โ is included at zero cost. There are no subscription tiers, no feature paywalls, and no vendor lock-in. This is a deliberate policy: Anshin will not pay recurring firewall/security licensing fees.
Why OPNsenseโ
| Requirement | OPNsense |
|---|---|
| HIPAA-compliant audit logging | โ Full flow logging โ syslog โ Graylog |
| IDS/IPS | โ Suricata + ET Open rules (free) |
| Dual WAN / multi-WAN failover | โ Gateway Groups (built-in) |
| HA failover (zero downtime) | โ CARP โ sub-2-second failover |
| VPN (WireGuard + OpenVPN) | โ Built-in, zero config UI |
| Load balancing | โ HAProxy plugin (free) |
| REST API for automation | โ Full JSON API on all settings |
| Web GUI accessible to non-DevOps users | โ Excellent UI, wizard-driven |
| Infrastructure-as-Code (Claude Code) | โ Ansible + REST API + git XML backup |
| License cost | โ $0 forever |
Hardware โ 2ร Beelink EQ12 Proโ
Two identical nodes run in a CARP high-availability pair. If the primary fails, the secondary takes over automatically in under 2 seconds โ no manual intervention, no session drops for existing TCP connections.
| Spec | Value |
|---|---|
| Model | Beelink EQ12 Pro |
| CPU | Intel N100 (4-core, 3.4 GHz, 6W TDP) |
| RAM | 16GB DDR5 |
| NIC 1 | Intel i226-V 2.5GbE (WAN) |
| NIC 2 | Intel i226-V 2.5GbE (LAN trunk to switches) |
| Storage | 500GB NVMe (OPNsense OS + logs) |
| Power | ~12โ20W at idle |
| Cost |
OPNsense requires Intel network interface chipsets (i226, i225, i350, etc.) for production stability. Realtek NICs (found in cheaper mini-PCs) cause packet drops and instability under load. The Beelink EQ12 Pro ships with Intel i226-V NICs โ verify this before ordering.
Why not the TP-Link ER7412-M2? The ER7412-M2 is a Layer 3 SDN routing appliance โ suitable for inter-VLAN routing inside a trusted network. It is not a stateful security firewall. It lacks IDS/IPS, full audit logging, HA failover (CARP), and API depth. OPNsense provides all of this at lower total cost (~$350 for the HA pair vs. $399 for a single ER7412-M2 with no HA). The Omada SDN switches (SX3008F, SG3428, SG3452) are retained โ only the ER router is dropped.
Network Topologyโ
Internet
โ
โโโ Fiber WAN A (primary) e.g. 65.182.226.97/29
โโโ Fiber WAN B (secondary) e.g. second fiber circuit
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ OPNsense HA Pair (CARP Virtual IPs) โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ opnsense-01 PRIMARY โ 10.10.96.51 โ
โ โ BeeLink EQ12 Pro #1 โ โ
โ โโโโโโโโโโโโฌโโโโโโโโโโโ โ
โ โ CARP sync link (dedicated cat6)โ
โ โโโโโโโโโโโโผโโโโโโโโโโโ โ
โ โ opnsense-02 STANDBY โ 10.10.96.52 โ
โ โ BeeLink EQ12 Pro #2 โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ CARP VIP (LAN gateway): 10.10.96.1 โ
โ CARP VIP (WAN): 65.182.226.97 โ
โโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโ
โ 2.5GbE โ TL-SX3008F-01 (network plane)
โ
โโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโ
โ Omada Switch Fabric โ
โ SX3008F-01 (10G network) โ
โ SX3008F-02 (10G storage) โ
โ SG3428-01 (1G access) โ
โ SG3428-02 (1G access) โ
โ SG3452 (homestead) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
CARP behavior: The two OPNsense nodes share a Virtual IP (VIP) via CARP (Common Address Redundancy Protocol, RFC 3768). All downstream devices use the VIP as their gateway โ they never need to know which physical node is active. Failover is automatic and sub-2-second.
OPNsense Features in Useโ
Dual WAN โ Failover and Load Balancingโ
OPNsense Gateway Groups handle multi-WAN natively:
Gateway Group: WAN_FAILOVER
Tier 1: Fiber WAN A (primary โ lowest latency, full bandwidth)
Tier 2: Fiber WAN B (failover โ activates if Fiber A fails)
Gateway Group: WAN_LOADBALANCE (optional)
Tier 1: Fiber WAN A (equal weight)
Tier 1: Fiber WAN B (equal weight โ round-robin across both circuits)
Health monitoring: OPNsense pings configurable targets (e.g., 8.8.8.8, 1.1.1.1) every 500ms per WAN. If a gateway fails its health check, traffic automatically shifts to the next tier โ no manual intervention.
A third WAN (cable broadband) can be added later as Tier 3 by configuring a USB โ Ethernet adapter on each BeeLink node.
IDS/IPS โ Suricata with ET Open Rulesโ
Inline IDS/IPS powered by Suricata with Emerging Threats Open ruleset (free, updated daily):
| Setting | Value |
|---|---|
| Engine | Suricata |
| Ruleset | ET Open (free) |
| Mode | Inline IPS (block mode) |
| Interface | WAN (inspect inbound before routing) |
| Update schedule | Daily auto-update |
HIPAA relevance: All IDS alerts are logged with source IP, destination, rule name, and timestamp. Forwarded to Graylog for 90-day retention and search.
VPN โ WireGuard (Primary) + OpenVPN (Legacy)โ
WireGuard for all new VPN clients (Bryan, Marc, remote staff):
- Sub-100ms setup per new peer
- Apps available: Windows, macOS, iOS, Android
- QR code provisioning: scan and connected in 30 seconds
- HIPAA-compliant: all traffic encrypted (ChaCha20-Poly1305)
OpenVPN available for legacy devices or clients that cannot run WireGuard.
Split tunneling optional: configure so only lab traffic routes through VPN, internet stays local.
Load Balancing โ HAProxy (Built-In)โ
HAProxy is available as a free OPNsense plugin. It can:
- Load balance HTTP/HTTPS to multiple backends (e.g., multiple K8s ingress replicas)
- Health check backends and automatically remove failed nodes
- Terminate SSL (using the ZeroSSL wildcard certs)
- Replace a dedicated load-balancer pair (the "2 BeeLinks as LBs" idea is not needed if HAProxy handles it)
Firewall Rules โ Zone-Based Policyโ
OPNsense uses interfaces + rules, equivalent to zone-based firewall:
| Zone | Interface | Default Policy |
|---|---|---|
| WAN | Fiber WAN A/B | Block all inbound (allowlist only) |
| LAN | Internal VLAN trunk | Permit internal, inspect with IDS |
| VLAN_MGMT (100) | OOB management | Block from other VLANs; iLO/UPS only |
| VLAN_STORAGE (300/400) | Storage planes | Block from all except compute VLANs |
| PHI_ISOLATED | Dedicated VLAN (TBD) | Strict egress, full logging, no internet |
| VPN | WireGuard/OpenVPN | Limited access per user group |
HIPAA Compliance Implementationโ
Audit Logging Pipelineโ
OPNsense (firewall logs, IDS alerts, auth events)
โ
โ syslog/UDP to Graylog input (10.10.x.x:5514)
โผ
Graylog (K8s โ infra namespace)
โ
โโโ Index: firewall-logs (90-day retention)
โโโ Index: ids-alerts (90-day retention)
โโโ Index: vpn-auth (90-day retention)
โ
โผ
QNAP NFS (qnap-01) โ long-term archive (1-year retention)
What is logged:
- Every connection allowed/denied (source IP, destination, port, protocol, bytes, timestamp)
- Every IDS/IPS alert (rule triggered, severity, action taken)
- Every VPN authentication (user, timestamp, source IP, session duration)
- OPNsense admin logins and configuration changes
HIPAA audit control (ยง164.312(b)): Logs are write-once to Graylog + NFS. Admin cannot delete individual log entries without MongoDB access. All access to Graylog is VPN-only.
PHI Network Isolationโ
When PHI-processing systems come online, they will be placed on a dedicated PHI_ISOLATED VLAN with:
- No direct internet access (all egress through a proxy)
- Full firewall logging (every packet)
- Encrypted at rest (Ceph encryption for block volumes)
- Encrypted in transit (mTLS between services, TLS 1.3 only)
- IDS in inline mode on the VLAN interface
Encryption Standardsโ
| Connection | Protocol | Minimum TLS |
|---|---|---|
| WAN (external clients) | TLS 1.3 (ZeroSSL ECDSA certs) | 1.3 |
| VPN (remote access) | WireGuard ChaCha20-Poly1305 | N/A |
| Inter-service (K8s) | mTLS (SPIFFE/SPIRE, planned) | 1.3 |
| Admin access | SSH key-only, TOTP on web UI | N/A |
Infrastructure-as-Code & Claude Code Integrationโ
Configuration Backup in Gitโ
OPNsense exports its entire configuration as a single XML file. This is committed to sre-iac (Ansible Vault encrypted) after every change:
# Export config from running node (via API)
curl -k -u admin:$OPNSENSE_KEY https://opnsense-01/api/core/backup/download/this \
> opnsense-01-$(date +%Y%m%d).xml
# Encrypt and commit
ansible-vault encrypt opnsense-01-$(date +%Y%m%d).xml
git add opnsense-01-$(date +%Y%m%d).xml
git commit -m "chore(network): OPNsense config backup $(date +%Y-%m-%d)"
This means the entire firewall config is version-controlled, reviewable in git, and can be restored from scratch in minutes.
OPNsense REST APIโ
Every OPNsense setting is configurable via REST API (JSON over HTTPS). No GUI click required for any operation:
# Add a firewall rule
curl -k -u $API_KEY:$API_SECRET \
-X POST https://opnsense-01/api/firewall/filter/addRule \
-H "Content-Type: application/json" \
-d '{"rule": {"interface": "lan", "type": "pass", "source_net": "10.10.97.0/24", "destination_net": "10.10.98.0/24", "description": "K8s worker to K8s service subnet"}}'
# Apply changes
curl -k -u $API_KEY:$API_SECRET \
-X POST https://opnsense-01/api/firewall/filter/apply
MCP Server for Claude Code (Planned)โ
A lightweight mcp-opnsense MCP server (Bun/TypeScript, hosted in K8s mcp-servers namespace) will expose the OPNsense API as Claude tools:
| MCP Tool | Action |
|---|---|
add_firewall_rule(description) | Bryan describes the rule in plain English, Claude constructs and applies it |
block_ip(ip, reason) | Instant IP block โ threat response in seconds |
show_active_ids_alerts() | See what Suricata is detecting right now |
provision_vpn_user(name) | New employee gets WireGuard config + QR code |
show_traffic_summary(hours) | See top talkers, bandwidth by host |
get_firewall_logs(filter) | Search audit logs for HIPAA investigations |
check_wan_status() | Which WAN is active, latency, packet loss |
This means Bryan can type in Claude: "Block all traffic from 192.0.2.0/24 โ suspicious scan" and it happens. No GUI needed.
Initial Setup Procedureโ
1. Install OPNsense on Both BeeLink Nodesโ
# Download OPNsense ISO from opnsense.org (verify SHA256)
# Flash to USB: dd if=OPNsense-24.x-dvd-amd64.iso of=/dev/sdX bs=4M
# Boot each BeeLink from USB
# Run installer โ target: NVMe drive
# Repeat for both nodes
2. Configure opnsense-01 (Primary)โ
Via console or direct browser to https://192.168.1.1 (default):
- System โ General: Set hostname
opnsense-01.anshinhealth.net, domain, DNS - Interfaces โ WAN: Assign NIC 1 โ Fiber WAN A (static or DHCP per ISP)
- Interfaces โ LAN: Assign NIC 2 โ 2.5GbE to Omada switch fabric
- Interfaces โ WAN2: Add second WAN for Fiber B (USB Ethernet or additional NIC)
- Firewall โ NAT: Configure outbound masquerade for all VLANs
- VPN โ WireGuard: Generate server keypair, configure peer for each VPN client
- Services โ Intrusion Detection: Enable Suricata, select ET Open, enable inline mode
- System โ High Availability: Enable CARP, configure sync interface and pre-shared key
3. Configure opnsense-02 (Standby)โ
On opnsense-01: System โ High Availability โ Settings โ configure synchronization to opnsense-02 IP. Select all items to sync (firewall rules, aliases, VPN, certs, etc.).
OPNsense will automatically push the full config to opnsense-02. The standby node needs only network connectivity โ it does not need separate manual configuration.
4. Verify HAโ
# On opnsense-01 console:
ifconfig | grep carp # Should show MASTER state
# On opnsense-02 console:
ifconfig | grep carp # Should show BACKUP state
# Test failover (on opnsense-01):
service carp stop # opnsense-02 takes over in ~2 seconds
service carp start # opnsense-01 reclaims MASTER role
5. Connect to Omada Switch Fabricโ
opnsense-01 and opnsense-02 LAN ports both connect to TL-SX3008F-01 (network plane). Configure the switch port as a VLAN trunk (all VLANs tagged). OPNsense sees one physical interface (igc1) with VLAN sub-interfaces per segment.
Omada Integrationโ
The Omada SDN controller (OC200) manages all TP-Link switches. OPNsense handles routing and firewall policy; Omada handles switch-level VLAN assignment, port profiles, and QoS.
Separation of duties:
- OPNsense: WAN, firewall rules, IDS/IPS, VPN, inter-VLAN routing, logging
- Omada: Switch port assignments, VLAN tagging, 10G link aggregation, SDN dashboard
No TP-Link ER router is needed. The ER-series routers in the Omada lineup are redundant when OPNsense handles routing. Connecting OPNsense's LAN interface directly to the SX3008F (as the upstream gateway) is the correct architecture.
Secrets Managementโ
All OPNsense credentials follow the Infisical-first policy:
| Secret | Infisical Path | Used By |
|---|---|---|
opnsense-api-key | /network/opnsense | Ansible, MCP server |
opnsense-api-secret | /network/opnsense | Ansible, MCP server |
opnsense-admin-password | /network/opnsense | Break-glass access only |
carp-preSharedKey | /network/opnsense | CARP sync authentication |
wireguard-server-private-key | /network/vpn | OPNsense WireGuard config |
See Infisical Secrets Management for the full secrets workflow.
Document Controlโ
| Rev | Date | Author | Description |
|---|---|---|---|
| 1.0 | 2026-03-22 | Anshin Engineering | Initial release โ OPNsense HA pair on Beelink EQ12 Pro; replaces TP-Link ER router |