DEV Community

Cover image for How to build a custom router and firewall with Opnsense in your Homelab
George Ezejiofor
George Ezejiofor

Posted on

How to build a custom router and firewall with Opnsense in your Homelab

A complete guide to deploying a production-grade firewall with remote management

Introduction

Navigating the world of home networking can be a "plug-and-play" experience - until you decide to build a professional-grade lab. When I set out to install OPNsense on an Intel N150 fanless mini-PC, I ran into the classic "locked out" scenarios, interface mismatches, and DNS rebind attacks.
Here is the definitive guide on how I moved from a broken installer to a fully headless, domain-accessible firewall that I can manage from anywhere in the world.

Three days. That's how long it took me to get a working headless OPNsense setup on my Intel N150 mini-PC.

Not because OPNsense is hard. Because nobody documents the gotchas.

Interface mismatches. DNS rebind protection blocking your own domain. The "Live mode" trap where nothing persists. Plugging in two cables at the wrong moment and watching interface detection implode.

I hit every single one. So you don't have to.


My Setup

┌─────────────────┐      ┌─────────────────┐
│  Home Router    │ WAN  │  OPNsense N150  │
│  192.168.1.xxx  │─────▶│  WAN: igc1      │
└─────────────────┘      │  LAN: igc0      │
                         └────────┬────────┘
                                  │ LAN
                         ┌────────▼────────┐
                         │  Mac Studio     │
                         │  10.0.1.xxx/16  │
                         └─────────────────┘
Enter fullscreen mode Exit fullscreen mode
  • Device: Intel N150 (4 cores, fanless, silent)
  • ETH0 (igc0): LAN → Mac Studio
  • ETH1 (igc1): WAN → Home ISP Router
  • Target Network: 10.0.1.0/16
  • Remote Access: TinyPilot KVM for when I inevitably lock myself out

Gotcha #1: The "Live Mode" Trap

OPNsense boots into Live mode by default. You configure everything, reboot, and it's gone. Poof.

The fix: Actually select "Install" from the boot menu. Sounds obvious. Cost me an evening.

# Installation flow:
1. Boot USB
2. Select "Install" (NOT Live)
3. Login: installer / opnsense
4. Target: internal SSD, GPT/EFI
5. ONLY plug WAN cable first → assign igc1 ETH1
6. THEN plug LAN cable → assign igc0 ETH0
7. Reboot, remove USB
Enter fullscreen mode Exit fullscreen mode

Why the cable dance? OPNsense interface detection chokes when both ports are active during assignment. Three reinstalls taught me this.


Gotcha #2: IP Conflict Hell

OPNsense defaults to 192.168.1.1 for LAN. Your home router? Probably 192.168.1.1 too.

Same subnet. Routing chaos. Web UI unreachable.

Console fix (Option 2):

LAN Interface: igc0 ETH0
IPv4: 10.0.1.x
Subnet: /16
DHCP: Yes (10.0.1.xxx-yyy)
Enter fullscreen mode Exit fullscreen mode

On your Mac, set Ethernet to DHCP. Test:

ping 10.0.1.x
# If replies → https://10.0.1.x works
Enter fullscreen mode Exit fullscreen mode

Gotcha #3: Wi-Fi Management Blocked

I wanted to manage the firewall from my couch, not tethered to Ethernet. But Wi-Fi traffic comes in on WAN, and OPNsense blocks it by default.

Three settings to fix:

1. Unblock Private Networks

Interfaces → [WAN] → Uncheck "Block private networks"

Your home router hands OPNsense a 192.168.x.x address. That checkbox blocks it. Genius security feature that locked me out for hours.

2. Add WAN Management Rule

Firewall → Rules → WAN → Add

Action: Pass
Protocol: TCP
Destination: WAN address
Port: 443
Description: Wi-Fi Management
Enter fullscreen mode Exit fullscreen mode

3. Listen on All Interfaces

System → Settings → Administration

Listen Interfaces: All
Protocol: HTTPS
Port: 443
Enter fullscreen mode Exit fullscreen mode

Gotcha #4: DNS Rebind Attack Protection

I set up a DNS override for firewall.homelab.com. Loaded it in my browser. Blocked.

OPNsense has DNS rebind protection — it blocks external domains resolving to internal IPs. Good security. Terrible for homelabs.

Fix at System → Settings → Administration:

Option A (quick): Check "Disable DNS Rebind Checks"

Option B (safer): Add domain to "Alternate Hostnames"


Complete Firewall Rules

LAN (igc0 / 10.0.1.0/16)

Seq Action Source Destination Description
10 Pass LAN net Any Internet
20 Pass LAN net 10.0.1.xxx:443 Management
30 Pass 10.0.1.xxx/20 10.0.16.xxx/20 DC1→DC2
40 Pass 10.0.1.xxx/20 10.0.32.xxx/20 DC1→DC3
999 Block Any Any Default deny

WAN (igc1 / DHCP)

Seq Action Protocol Port Description
10 Pass TCP 443 Wi-Fi mgmt
20 Pass UDP 51820 WireGuard
999 Block Any - Drop rest

WireGuard for Remote Access

I'm frequently in Nigeria. Need to hit my homelab from 5,000 miles away.

Quick Setup

# Install plugin
System → Firmware → Plugins → os-wireguard

# Server config
VPN → WireGuard → Settings
  Enable: Yes
  Port: 51820
  Interface: WAN

# Endpoint
  Name: Remote_VPN
  Tunnel: 10.0.100.1/24
  DNS: 10.0.1.x

# Peer (for each client)
  Name: Nigeria_Laptop
  Public Key: [from client]
  Allowed IPs: 10.0.100.xxx/32
Enter fullscreen mode Exit fullscreen mode

Don't forget the WAN firewall rule for UDP 51820.


Ansible Automation

Everything above? I codified it. If my N150 dies, one command rebuilds everything.

- name: Deploy Firewall Rules
  hosts: opnsense
  tasks:
    - name: Allow LAN to Internet
      oxlorg.opnsense.rule:
        description: LAN_to_Internet
        interface: igc0
        protocol: any
        source_net: 10.0.1.xxx/16
        destination_net: any
        action: pass
        sequence: 10

    - name: Wi-Fi Management
      oxlorg.opnsense.rule:
        description: WiFi_Mgmt
        interface: igc1
        protocol: tcp
        destination_port: 443
        action: pass
        sequence: 10
Enter fullscreen mode Exit fullscreen mode

Using the oxlorg.opnsense collection. Full playbook handles interfaces, DHCP, DNS, WireGuard — everything.


Pre-Flight Checklist

Before you call it done:

  • [ ] Interfaces → WAN: "Block private networks" UNCHECKED
  • [ ] Firewall → WAN: Port 443 rule exists
  • [ ] Firewall → WAN: Port 51820 rule exists (if using WireGuard)
  • [ ] System → Admin: DNS Rebind disabled OR alternate hostname set
  • [ ] System → Admin: Listen Interfaces = All
  • [ ] Services → Unbound: Domain override configured
  • [ ] NAT → Outbound: Hybrid mode, networks masqueraded

Troubleshooting Quick Reference

Problem Fix
Can't reach 10.0.1.x Check Ethernet DHCP, verify igc0 connection
Wi-Fi blocked "Block private networks" still checked
Domain fails DNS Rebind protection blocking
WireGuard dead Port 51820 not open on WAN
No inter-subnet traffic LAN rules missing or wrong subnets

Access Methods After Setup

Location URL Method
Desk (Ethernet) https://10.0.1.xxx Direct LAN
Home Wi-Fi https://192.168.1.xxx WAN address
Remote https://10.0.1.x WireGuard
Domain https://firewall.homelab.com DNS

What's Next

Full Ansible automation. Zero-touch rebuild capability. One command:

ansible-playbook -i inventory.yml playbooks/99_full_rebuild.yml --ask-vault-pass
Enter fullscreen mode Exit fullscreen mode

Working on that now. Article coming when it's battle-tested.


Resources:


Part of my homelab series — Proxmox clusters, bare-metal Kubernetes, and eventually low-latency trading systems. Follow if you're into infrastructure chaos.

Questions? Drop them below. I've probably made your mistake already.

Top comments (0)