The failover worked exactly as configured, and that was the problem. When the primary tunnel dropped, the router moved the default route to the cable modem, laptops kept browsing, and nobody called. Two days later someone noticed the finance share had been reachable over the open internet path for six hours. A router VPN failover policy is not a routing trick; it is a decision about what traffic should do when the preferred path is gone, and that decision has to exist before the path disappears.

Decide the outcome before you pick the detector

Three outcomes are usually on the table: send affected clients through a backup tunnel, let them use the ordinary WAN, or block them outright. Write down which one applies to which VLAN, SSID or device class. A single flat "fail over to WAN" rule is how the finance share above ended up on a public path.

The three are not interchangeable. WAN fallback keeps a support desk answering phones while exposing internal names to the local resolver. A backup tunnel preserves the policy but may land on an exit address the far side does not accept. Blocking is correct for a payroll VLAN and wrong for a guest network that never used the tunnel in the first place.

OutcomeRight forWhat breaks
Backup tunnelPolicy must hold, remote access requiredNew exit address, return route, slower rekey
Plain WANGuest or public-only trafficInternal names, DNS and IPv6 exposure
BlockPayroll, admin, anything VPN-onlyUsers lose all access and call you

Match the detector to the failure you actually fear

Handshake state, interface state and usable forwarding are three different signals, and only the last one matters to a user. A WireGuard peer can show a recent handshake while the provider's upstream is black-holing packets. An OpenVPN client can sit at "connected" after the route it pushed stopped resolving.

On pfSense the practical arrangement is a gateway group fed by dpinger, which probes a monitor address and marks a gateway down when loss or latency crosses its thresholds. Point that monitor at something beyond the tunnel, such as a host on the far LAN or a public address you reach through it. Aiming it at the tunnel's own peer address measures the part you already know is alive.

Build the group so the backup stays a last resort

Use tiers rather than one flat member list. Primary in tier 1, backup tunnel in tier 2, WAN in tier 3 only for the VLANs whose policy allows it. In pfSense this lives under System > Routing > Gateway Groups: add both gateways, give them different tiers, set Trigger Level to member down plus packet loss, save, then apply the group as the interface default or in the Gateway field of the firewall rules that need it.

For an OpenVPN client instance on pfSense 2.5 and later, the instance's Default Gateway setting decides whether the tunnel replaces the system default route at all. Policy routing by rule only behaves the way you expect when the route you assume exists is actually installed. Check Status > Gateways after the change instead of trusting the tunnel status icon.

Two settings cause most of the flapping. One is a probe interval shorter than the provider's own reconvergence. The other is a group where primary and backup share a tier, so both stay eligible at all times. Add hysteresis through loss and latency thresholds before your users feel the transitions for you.

Close the paths the tunnel never owned

DNS leaks first. The resolver keeps answering on the WAN and forwards out of it, so names keep resolving through the ISP while traffic is pinned to the tunnel. Restrict the resolver's outbound interfaces, push the internal resolver to clients, and block port 53 to everything else on the VPN-only VLANs.

IPv6 needs its own decision. A dual-stack LAN can lose the tunnel and keep a working global IPv6 default route, so browsers prefer IPv6 and leave through the WAN while IPv4 looks perfectly contained. Either route IPv6 into the tunnel or stop advertising a global prefix while the tunnel is down. Half a policy is worse than none, because it looks like it works.

Then the return path. If the backup exit uses a different source address, the far side must know how to send traffic back to it, and every state keyed to the old address is already dead. Sessions open when the primary dropped do not migrate; they stall until they time out and the application decides what to do about it.

Test the drop, the flap and the way back in

Pull the primary with harmless traffic running, then read four things: Status > Gateways for the group's member states, pfctl -ss for states still pinned to the old gateway, a traceroute from a client for the exit path, and a resolver query to see which server answered.

Now flap it. Bring the primary up for thirty seconds, down for thirty, twice. If traffic chases every transition, the thresholds are too tight or the tiers are wrong. Fix that on your schedule, because otherwise a provider will do it on theirs.

Last, confirm you can still administer the router. Keep an out-of-band path such as a console cable, a management VLAN or a cellular modem. A failover test that locks you out is a test you cannot finish, and an unreachable router cannot fail back on its own.

Before you call the policy done, you should be able to answer four questions without opening a terminal: which VLANs may use the WAN while the tunnel is down, what the detector watches and how long it waits, which name servers and IPv6 routes move with the path, and how you get back in if the backup fails too. If any answer is "whatever the default was", the policy still belongs to the router rather than to you.

Pennadoù liammet