Your firewall works. Is it hardened? The OPNsense pass most setups skip
OPNsense out of the box is a solid firewall. A deliberate hardening pass makes it a great one: ISP DNS that can't sneak back in, modest blocklists, a VPN kill switch that really fails closed, Suricata sized to your RAM, and an update routine with a rollback.

OPNsense out of the box is a solid firewall. It routes, it NATs, it blocks inbound traffic, and the dashboard is green. That is "works." Hardened is a different list: private DNS that stays private, ad and malware blocking that doesn't break half the internet, a VPN that fails closed, an IPS that doesn't eat all your RAM, and updates you can roll back.
Each of those has a trap where the setting looks done and isn't. This is the pass, in the order the Homelab the Right Way book does it.
Before you change anything
Snapshot the firewall VM. On the Proxmox host:
qm snapshot 100 pre-hardening
It takes seconds and turns a lockout into a two-minute rollback. Then make sure you have a way into the console that doesn't depend on the firewall itself: the Proxmox web UI's noVNC console works even when OPNsense's LAN rules are broken.
DNS: the ISP servers that sneak back in
By default your DNS questions go to your ISP in plain text. The fix lives in Services → Unbound DNS: enable Unbound, turn on DNSSEC support, and add at least two DNS over TLS upstreams with their TLS hostnames, for example Quad9 (9.9.9.9, port 853, dns.quad9.net) and Cloudflare (1.1.1.1, port 853, cloudflare-dns.com).
The trap is the step after it. In System → Settings → General, remove the ISP DNS servers and uncheck Allow DNS server list to be overridden by DHCP/PPP on WAN. Leave that box checked and your ISP's servers come back on their own.
The second leak is devices that ignore the firewall entirely. Some devices, smart TVs mostly, hard-code 8.8.8.8. A port-forward on LAN that redirects any outbound TCP/UDP 53 to the firewall's own address catches them.
Verify from a LAN client:
dig +dnssec example.com @<firewall-ip> # look for the "ad" flag
dig dnssec-failed.org @<firewall-ip> # deliberately broken: should SERVFAIL
Blocklists: start modest
Services → Unbound DNS → Blocklist has built-in feeds. The tempting move is to enable everything. Huge combined lists cause more breakage than benefit. Start with one ads/tracking list and one malware list, whitelist domains as complaints arrive, and keep a note of why each whitelist entry exists.
Guests get the internet and nothing else
Give guests (and IoT gear you don't trust) their own interface or VLAN, and block that network from every private range with an RFC1918 alias. The full five-rule table, in order, is in the guest Wi-Fi post.
The VPN kill switch that doesn't kill
Sending a network's traffic through a WireGuard VPN is easy: a firewall rule on that interface with the Gateway set to the VPN gateway. Making it fail closed is the part most guides skip.
Here is the trap. By default, if a gateway is down, OPNsense creates the rule without the gateway, so traffic falls through to your normal WAN. Your "VPN-only" network leaks the moment the tunnel drops.
Close it with three layers:
- Firewall → Settings → Advanced: check Skip rules when gateway is down. A policy rule with a dead gateway is now skipped instead of silently rerouted.
- Outbound NAT (Hybrid or Manual): add a rule that NATs the VPN network out the WireGuard interface, and a Do not NAT rule (or simply no rule) for that network on WAN. Without NAT on WAN, any packet that tries to escape that way just dies.
- A block rule right after the policy rule on that interface: block the VPN network to any. If the policy rule is skipped, this catches everything.
For belt and suspenders, tag the policy rule's traffic (Advanced options → Set local tag) and add a floating rule on WAN that blocks anything carrying the tag. It survives rule reordering.
Then test it like you mean it: disable the WireGuard instance and try to load a page from a client on that network. It should fail. Re-enable it, and it should work again. A kill switch you have never seen kill is a guess.
Suricata: the fastest way to slow your network
Services → Intrusion Detection runs Suricata. In IPS mode it can drop malicious traffic inline. It is also the easiest way to make a firewall VM slow or crash. If memory runs short, Suricata restarts or the box swaps, and your whole network stutters.
The book's rules of thumb:
- RAM: at least 4 GB for the firewall VM with a moderate ruleset; 8 GB if you want large rule categories on several interfaces.
- Rules: a handful of ET Open categories that matter (malware, exploit, C2/botnet, compromised IP lists), not "enable all." Every category costs memory and CPU.
- Interfaces: watch the internal ones (LAN, servers) rather than WAN. You see real internal IPs in alerts and don't waste cycles on internet background noise the firewall drops anyway.
- Offloading: IPS mode uses netmap. Disable hardware CRC, TSO and LRO under Interfaces → Settings, or IPS can misbehave. On a VM with VirtIO NICs, this matters too.
- IDS first: run in IDS mode (alert only) for a week. Read the alerts, disable the noisy false positives, then switch to IPS.
Updates with a way back
OPNsense ships two major releases a year (the .1 and .7 versions) with minor updates in between. The safe routine:
- Read the release notes. Look for "plugin removed," "deprecated" and anything about the features you use.
- Snapshot the VM:
qm snapshot 100 pre-update-$(date +%F) - Download a configuration backup (System → Configuration → Backups) to a different machine.
- Update from the console or UI, then reboot if asked.
- Check: WAN up, DNS resolves, VPN tunnel connected, guest network isolated.
- After a week without problems, delete the snapshot. Old snapshots grow and slow the disk.
Step 6 is the one people forget. A snapshot is a rollback, not an archive.
Checklist: OPNsense hardening
- ☐
qm snapshot 100 pre-hardeningtaken, noVNC console reachable - ☐ Unbound with DNSSEC and at least two DNS over TLS upstreams
- ☐ ISP DNS removed, "Allow DNS server list to be overridden by DHCP/PPP on WAN" unchecked
- ☐ LAN port-forward redirecting outbound TCP/UDP 53 to the firewall
- ☐ One ads/tracking list and one malware list, whitelist entries noted with a reason
- ☐ Guest network on its own interface or VLAN, blocked from RFC1918
- ☐ Kill switch: "Skip rules when gateway is down", no NAT for the VPN network on WAN, block rule after the policy rule
- ☐ Kill switch tested with the WireGuard instance disabled
- ☐ Suricata: 4 GB+ RAM, a few ET Open categories, internal interfaces, CRC/TSO/LRO off, a week in IDS first
- ☐ Update routine: release notes, snapshot, config backup, check, delete the snapshot after a week


