OPNsense as the routing peer for a NetBird mesh
In short. Put the NetBird agent on both firewalls and register them with a setup key into a routing-peers group. In the dashboard, add one network route per VLAN, not a site /16, with that group as the routing peers. On the firewall, assign the overlay interface, add an outbound NAT rule for traffic leaving into the overlay, and write filter rules on the overlay interface as you would on any other. Never let a peer's tunnel endpoint sit inside a prefix it advertises.
NetBird peers can reach the firewall but nothing behind it
The agent is up, netbird status says connected, you can ping the firewall's overlay address, and every host on the VLAN behind it times out. Usually one of three things: the route was never added in the dashboard, the return path is missing because nothing translates traffic back into the overlay, or the firewall is dropping it on an interface with no rules yet. Occasionally it is a fourth thing, which gets its own gotcha.
What you need
- Two OPNsense 26.1 nodes in a CARP pair. The agent runs on both, so an operator's route survives a node failure.
- A self-hosted NetBird management server, reachable from both firewalls on its public name, and a setup key for the group that will hold routing peers.
- The NetBird agent for FreeBSD. Check System > Firmware > Plugins for a NetBird plugin first; if your release has one, use it so upgrades are handled. Otherwise the FreeBSD package works on the OPNsense base.
- The overlay range. The estate reserves
10.254.0.0/16for NetBird and nothing else uses it. - A laptop with the NetBird client, in a group that a policy allows to reach the routing peers.
Steps
- Install the agent on each firewall. With the plugin, install it from the Plugins tab and configure the management URL and setup key on its settings page. With the package:
pkg install netbird
sysrc netbird_enable=YES
service netbird start
netbird up --management-url https://nb.example.net --setup-key "$SETUP_KEY"
The setup key comes from the secret manager, puts the peer straight into the routing-peers group, and is expired once both nodes are registered.
-
Name the peers. In the dashboard, rename them
fw01-site1andfw02-site1. Every policy, route and conversation from here on refers to peers by name. -
Assign the overlay interface on each firewall. The agent creates a WireGuard-style interface (
wt0on FreeBSD). Interfaces > Assignments shows it; add it, enable it with the descriptionNETBIRD, no address configuration (the agent manages the address). Do this on both nodes; the sync does not assign interfaces. -
Add the network routes in the dashboard. Networks, add a network for the site, then add one resource per VLAN:
10.1.101.0/24for tenant 1,10.1.10.0/24for OPS-INT, and so on. Routing peers: the group containingfw01-site1andfw02-site1, so a failed node does not take the route with it. Access control: the groups that should reach each resource. One resource per VLAN rather than a site /16 means a policy can grant an operator the tenant VLAN and not the storage network, and the management VLAN is never included by accident. -
Add the outbound NAT for traffic leaving into the overlay. The agent's masquerade covers packets arriving from the overlay and going into the VLAN. It does nothing for connections that start on the VLAN side and go into the overlay, such as monitoring from OPS-INT probing a remote peer. Firewall > NAT > Outbound: set the mode to hybrid, then add a rule: interface
NETBIRD, source10.1.0.0/16(the site's VLANs), destination10.254.0.0/16, translation the interface address. Both nodes. -
Write filter rules on the overlay interface. Firewall > Rules > NETBIRD. Use the same block-first ordering as a tenant interface: block to MGMT, block to STORAGE, then pass from
10.254.0.0/16to the VLAN resources you advertised. NetBird policies decide which peer may send packets to the routing peer; the packet filter decides what those packets may reach. The policy is transport; authorisation lives here and at the service. -
Check the endpoints. No peer may use a tunnel endpoint inside a prefix that is advertised through the overlay. The firewalls peer from their WAN address, outside everything they advertise, so they are fine. The case to watch is a VM inside a tenant VLAN running its own agent while the firewall advertises that VLAN: the VLAN route pulls the VM's own tunnel into the overlay, it is encapsulated twice, and large packets are dropped silently. Exclude that host from the route, or do not run an agent on it.
flowchart LR
L["Operator laptop<br/>10.254.0.21"] -->|"WireGuard"| M["NetBird management<br/>and relay"]
L -->|"direct or relayed"| A["fw01-site1<br/>wt0 10.254.0.2<br/>routing peer"]
L -.-> B["fw02-site1<br/>wt0 10.254.0.3<br/>routing peer"]
A -->|"route 10.1.101.0/24<br/>filter on NETBIRD"| T["Tenant 1 VLAN<br/>10.1.101.0/24"]
A -->|"outbound NAT<br/>10.1.0.0/16 to overlay"| LVerify it worked
On each firewall:
netbird status --detail
netbird networks list
On agents older than the 0.30 series the second command is netbird routes list; the output is the same idea. Status should show the management connection, the relay, and the laptop as a connected peer, ideally direct. The networks list should show each VLAN resource with this peer as a routing peer. ifconfig wt0 shows the overlay address.
From the laptop: netbird status should list fw01-site1, ping 10.1.101.10 should reach the tenant ingress, and ssh to a host in OPS-INT should work if the policy allows it. Then stop the agent on fw01 (service netbird stop) and ping again; after a few seconds it should recover through fw02. Start fw01 again before you forget.
Gotchas
- One resource per VLAN, never a site /16. A /16 includes MGMT, the sync VLAN and whatever you add next year.
- The agent's masquerade is one direction only. Without the outbound NAT rule on the firewall, anything from the VLAN side into the overlay leaves with a VLAN source address and never comes back.
- No endpoint inside an advertised prefix. The symptom is that small packets work and anything over about 1400 bytes vanishes. It looks like an MTU problem; the fix is the route.
- Both firewalls need the agent and the assigned interface. The sync pushes the NAT and filter rules; it does not install agents or assign interfaces.
- Policies are transport. If a NetBird policy is the only thing between an operator and the storage VLAN, you have one control where you wanted two. The filter rule on the overlay interface is the second.
FAQ
Should the laptop route all traffic through the firewall as an exit node? Only if you make the firewall an exit node deliberately, per region, opt-in. A routing peer for VLAN resources is not a default route, and most operators want only the VLANs.
Does CARP matter here?
Not for the overlay. Each firewall is its own peer with its own overlay address and its own routes; NetBird picks a routing peer and fails over at that layer. CARP keeps .254 alive for the VLAN side. The two mechanisms do not need to know about each other.
Why the firewall and not a small VM as the routing peer? Because the firewall is already on every VLAN with the packet filter in the path, and it is already a pair. A VM would need an interface on each VLAN and its own rules, a third thing to keep in sync.