DiyMediaServer
Featured image of post WireGuard Client on OPNsense: VPS Tunnel LAN Routing Guide

WireGuard Client on OPNsense: VPS Tunnel LAN Routing Guide

Configure a WireGuard client on OPNsense for VPS tunnel routing. Step-by-step firewall rules, policy routing, asymmetric routing fixes, and pfSense equivalents.

If you’re running services at home and hiding them behind a VPS, or you want your entire LAN to egress through a remote server, configuring a WireGuard client on OPNsense is one of the cleanest ways to do it.

But here’s the part most guides skip: getting the tunnel up is easy. Getting LAN routing, firewall rules, static routes, and return-path routing correct is where things break.

Ask me how I know.

Traffic left on the WireGuard interface fine. Return packets came back on WAN and got dropped. I had to understand asymmetric routing and add policy-based routing to fix it. The good news? Once you know where to look, OPNsense makes this straightforward.

In this guide, you’ll configure OPNsense as a WireGuard client for a VPS tunnel, route LAN traffic through it, and avoid the common asymmetric routing traps. I also include pfSense WireGuard equivalents with enough detail to follow along on either platform.


💭 TL;DR
Set up a WireGuard client instance in OPNsense. Assign it as an interface. Add firewall rules and policy-based routing for LAN traffic. Ensure return-path routing via outbound NAT or proper gateway rules to avoid asymmetric routing. pfSense can do the same with its WireGuard package, but OPNsense's integration is generally cleaner and more consistent.

Why Run a VPS WireGuard Tunnel From Your Router?

Common use cases:

  • Expose home services safely via a VPS reverse proxy
  • Bypass CGNAT
  • Force LAN traffic out through a VPS IP
  • Site-to-site networking
  • WireGuard port forwarding setups
  • Segmented VLAN traffic through different egress paths

Instead of configuring WireGuard on individual devices, configure it once on your router. Every LAN device can then use the VPS tunnel without touching its own network config.

This is where OPNsense shines.


Prerequisites

Before touching OPNsense:

  • VPS running WireGuard server
  • VPS public IP and port, default 51820/UDP
  • VPS public key
  • Client tunnel IP, example 10.10.10.2/24
  • Server tunnel IP, example 10.10.10.1
  • Server configured to allow this client with AllowedIPs set appropriately. For a full tunnel, that’s usually 0.0.0.0/0 on the client peer entry.

Recommended:

  • OPNsense 24.x or newer
  • Config backup before changes

If your VPS setup differs, follow the VPS provider’s docs first.


Step 1: Install and Enable WireGuard on OPNsense

WireGuard is a plugin in OPNsense.

  1. Go to System > Firmware > Plugins
  2. Install os-wireguard
  3. Go to VPN > WireGuard > General
  4. Enable WireGuard

OPNsense uses an Instances and Peers model. It’s cleaner than pfSense’s layout, which we’ll get to later.

Protectli FW6C/FW6D: A fanless, six-port Intel-based firewall appliance built for pfSense/OPNsense, with Intel NICs and hardware AES-NI for fast, secure routing.
Protectli FW6C/FW6D A fanless, six-port Intel-based firewall appliance built for pfSense/OPNsense, with Intel NICs and hardware AES-NI for fast, secure routing. Silent and compact yet expandable (RAM and SSD), it’s a favorite for gigabit-plus WANs, VLAN-heavy homelabs, and always-on IDS/IPS.
Amazon Price: Loading...
Availability: Checking...
Contains affiliate links. I may earn a commission at no cost to you.

Step 2: Create the WireGuard Client Instance

Go to:

VPN > WireGuard > Instances > Add

Configure:

  • Enabled: Yes
  • Name: VPS_Tunnel
  • Tunnel Address: 10.10.10.2/24
  • MTU: 1420
    • If using PPPoE or VLAN tagging on WAN, start with 1412. More on MTU below.
  • Disable Routes: Unchecked

Now add a Peer under this instance:

  • Public Key: VPS public key
  • Endpoint Address: VPS_PUBLIC_IP:51820
  • Allowed IPs:
    • 0.0.0.0/0 for full tunnel
    • Or specific VPS subnets for split tunnel
  • Persistent Keepalive: 25 seconds. Important if OPNsense is behind NAT.

Save and Apply.


Verify the Handshake

Go to:

VPN > WireGuard > Status

You should see:

  • A recent handshake timestamp
  • RX/TX counters increasing

If not:

  • Check outbound UDP 51820 is allowed on your WAN
  • Verify VPS firewall rules
  • Confirm keys match
  • Run wg show from the OPNsense shell

Handshake failures are almost always:

  • Port blocked (check both sides)
  • Key mismatch
  • Wrong endpoint IP or port

Step 3: Assign the WireGuard Interface

This is where many people stop too early. And it’s where things start breaking.

Go to:

Interfaces > Assignments

Add the new interface, typically wg0.

Then:

  • Enable it
  • Rename to WG_VPS
  • IPv4 Configuration: Static
  • Set address to 10.10.10.2/24

Save and apply.

Do You Need to Assign It?

If you only want the firewall itself to use the tunnel, technically no.

If you want any of the following, you must assign it:

  • LAN routing through the tunnel
  • Policy-based routing
  • Gateway control
  • VLAN routing
  • Internet over the tunnel

No assignment means no gateway. No gateway means no policy routing. No policy routing means LAN traffic goes out your WAN and you wonder why nothing works.


Step 4: Firewall Rules for the pfSense WireGuard Client

Now we make traffic flow. You need rules in two places.

WAN Rule (Usually Not Needed)

Most default OPNsense setups allow all outbound traffic. If yours restricts outbound, you need to allow the WireGuard handshake:

Firewall > Rules > WAN

  • Action: Pass
  • Direction: Out (this is an outbound rule, not inbound)
  • Protocol: UDP
  • Destination Port: 51820

If your WAN already has a permissive outbound rule, skip this. Don’t poke holes you don’t need.


WireGuard Interface Rule

Go to:

Firewall > Rules > WG_VPS

Add:

  • Action: Pass
  • Source: WG_VPS net
  • Destination: LAN net or any

For multi-peer or multi-subnet setups, create explicit aliases instead of relying on auto-generated “WireGuard net” entries. Those can behave unexpectedly when you add more peers later.


Step 5: Gateway and Static Routes

Go to:

System > Gateways > Configuration

Ensure a gateway exists for WG_VPS.

If not, add:

  • Interface: WG_VPS
  • Gateway IP: 10.10.10.1
  • Name: WG_VPS_GW

Now static routes:

System > Routes > Configuration

Add routes for:

  • VPS internal subnets
  • Remote private networks reachable over the tunnel

Example:

  • Network: 172.16.0.0/24
  • Gateway: WG_VPS_GW

If you used 0.0.0.0/0 in AllowedIPs and want a full tunnel for selected devices, use policy routing instead. Do not change the system default gateway unless you intend to send all firewall traffic through the VPS. That includes DNS, package updates, and everything else.

TP-Link Omada SG3210X-M2: Full-featured managed switch with eight multi-gig ports, dual 10GbE uplinks, VLAN/QoS/ACL/LACP support.
TP-Link Omada SG3210X-M2 Full-featured, compact, rack-ready. Eight multi-gig ports, dual 10GbE uplinks, VLAN/QoS/ACL/LACP, and seamless integration with TP-Link’s Omada controller. It locks down your Jellyfin/NAS traffic while scaling effortlessly with your homelab.
Amazon Price: Loading...
Availability: Checking...
Contains affiliate links. I may earn a commission at no cost to you.

Step 6: LAN Routing Through the VPS Tunnel

This is where it actually works.

Go to:

Firewall > Rules > LAN

Add a rule:

  • Action: Pass
  • Source: LAN net (or an alias for specific hosts/subnets)
  • Destination: any or specific subnet
  • Advanced > Gateway: WG_VPS_GW

This is policy-based routing. Traffic matching this rule exits through the WireGuard tunnel instead of WAN.

Place this rule above the default “allow LAN to any” rule. Rule order matters in OPNsense. First match wins.


The Asymmetric Routing Problem (And How to Fix It)

Here’s what broke me.

Traffic left LAN through WG_VPS. Replies returned via the WAN default gateway. The firewall dropped them because the state table didn’t match.

That’s asymmetric routing. It’s the number one reason people think their tunnel is broken when it’s actually working.

Why It Happens

OPNsense sends traffic out WireGuard because of your policy routing rule. But return traffic from the internet may:

  • Follow the system default route back out WAN
  • Miss the expected connection state
  • Bypass the tunnel entirely

The firewall sees a reply arriving on a different interface than the outbound packet left on. State mismatch. Drop.


Fix 1: Outbound NAT on WireGuard Interface (Most Common)

Go to:

Firewall > NAT > Outbound

Switch to Hybrid Mode.

Add a rule:

  • Interface: WG_VPS
  • Source: LAN net
  • Translation: Interface address

This source NATs LAN traffic to the tunnel IP (10.10.10.2). Replies come back through the tunnel because the VPS sees the tunnel IP as the source.

This is the most reliable fix for full-tunnel setups.

The tradeoff: you’re hiding original LAN IPs from the VPS side. The VPS only sees 10.10.10.2 for every client. That means VPS-side logging, ACLs, and per-device access controls won’t see individual LAN addresses. For most homelab full-tunnel scenarios, that’s fine. For site-to-site setups where you need source IP visibility, see Fix 2.


Fix 2: Routed Tunnel Without NAT

If you need the VPS to see original LAN IPs (site-to-site, per-device ACLs, granular logging):

  1. On the VPS, add a static route for your LAN subnet (192.168.1.0/24) pointing to the tunnel IP (10.10.10.2)
  2. On OPNsense, make sure the WireGuard peer’s AllowedIPs includes the VPS subnet
  3. Skip the outbound NAT rule on WG_VPS

The VPS now routes replies back through the tunnel because it knows your LAN subnet lives behind 10.10.10.2.

This is cleaner architecturally but requires you to control routing on the VPS side. If your VPS is a cloud instance with limited routing options, NAT is simpler.


Fix 3: Policy-Based Routing on Every Interface

If you use VLANs:

  • Add a policy route rule on each VLAN interface
  • Set gateway to WG_VPS_GW

Miss one VLAN and that traffic leaks out WAN. Every interface that should use the tunnel needs its own rule.


A Note on Reply-To

OPNsense and pfSense both use reply-to directives on interface rules. This tells the firewall to send reply traffic back out the interface it arrived on, which normally prevents asymmetric routing for WAN traffic.

But reply-to can interfere with policy-based routing on internal interfaces. If you see traffic ignoring your policy route, check whether a reply-to on the WG_VPS interface rule is overriding your intended path. You can disable reply-to on specific rules under Advanced Options in the rule editor.

MINISFORUM MS-A2: A compact mini-workstation with dual 10GbE SFP+ plus dual 2.5GbE, flexible storage, and up to a 16-core Ryzen 9 9955HX.
MINISFORUM MS-A2 A compact mini-workstation built around up to a 16-core Ryzen 9 9955HX, with dual 10GbE SFP+ plus dual 2.5GbE, flexible storage (U.2 + M.2 including 22110), and triple 8K display outputs. Great as a homelab node or small server with serious I/O.
Amazon Price: Loading...
Availability: Checking...
Contains affiliate links. I may earn a commission at no cost to you.

VLAN Considerations

If your LAN is segmented:

  • Apply policy routing per VLAN interface
  • Add firewall rules on each VLAN
  • Add static routes if required

MTU becomes more sensitive with VLANs.

If you use PPPoE or VLAN tagging on WAN, set WireGuard MTU to 1412 and test. The reason: WireGuard adds 60 bytes of overhead. Standard Ethernet MTU is 1500. PPPoE eats 8 bytes. VLAN tagging eats 4. So 1500 - 8 - 60 = 1432 for PPPoE, and lower if you also tag VLANs. Start conservative.

Test with a do-not-fragment ping:

ping -s 1392 -M do 10.10.10.1

Why 1392? Because ping adds 28 bytes of ICMP/IP header. 1392 + 28 = 1420, which matches the default WireGuard MTU. If that fragments or times out, reduce MTU further.


WireGuard Port Forwarding Through a VPS

If you use the VPS as a reverse proxy or need to expose services, here’s the packet flow:

  1. Internet client sends a request to VPS_PUBLIC_IP:443
  2. VPS receives it and forwards to 10.10.10.2:443 via the WireGuard tunnel (using iptables DNAT or a reverse proxy like nginx/caddy)
  3. OPNsense receives it on the WG_VPS interface
  4. OPNsense NAT port forward sends it to the internal LAN host (e.g., 192.168.1.50:443)
  5. LAN host replies, traffic goes back through OPNsense, through the tunnel, back to VPS, back to the client

On OPNsense:

  • Create a NAT port forward on WG_VPS
  • Destination: 10.10.10.2
  • Redirect target: internal LAN IP and port

Make sure the corresponding firewall rule is created (OPNsense can auto-generate it, or add it manually).

VPS side: you need either iptables DNAT rules or a reverse proxy forwarding to the tunnel IP. If the VPS doesn’t NAT or forward properly, traffic reaches the tunnel but has nowhere to go.

This enables clean WireGuard port forwarding through the VPS tunnel. It’s one of the best ways to expose services without opening ports on your home IP.


pfSense WireGuard Setup (Step-by-Step)

Now let’s talk pfSense WireGuard. The concepts are identical, but the UI and some behaviors differ.

Installation

  • Go to System > Package Manager > Available Packages
  • Install the WireGuard package

Unlike OPNsense, pfSense doesn’t ship WireGuard integrated. It’s package-based. Recent versions improved stability significantly, but OPNsense still feels more cohesive for WireGuard-heavy setups.


pfSense Client Configuration

Go to:

VPN > WireGuard > Tunnels > Add

  • Enable: Yes
  • Description: VPS_Tunnel
  • Listen Port: leave blank (client mode)
  • Interface Keys: generate or paste your private key

Save, then go to VPN > WireGuard > Peers > Add:

  • Tunnel: select VPS_Tunnel
  • Public Key: VPS public key
  • Endpoint: VPS_PUBLIC_IP:51820
  • Allowed IPs: 0.0.0.0/0 (full tunnel) or specific subnets
  • Persistent Keepalive: 25

Save.

Assign the Interface in pfSense

Interfaces > Assignments

The WireGuard tunnel appears as tun_wgX. Add it, enable it, rename to WG_VPS.

Set IPv4 to Static, address 10.10.10.2/24.

Gateway in pfSense

Go to System > Routing > Gateways. Add:

  • Interface: WG_VPS
  • Gateway: 10.10.10.1
  • Name: WG_VPS_GW

pfSense quirk: gateway monitoring. pfSense pings the gateway IP to check health. If your VPS doesn’t respond to ICMP on the tunnel IP, pfSense marks the gateway as down and stops routing traffic through it. Fix this by either:

  • Allowing ICMP on the VPS tunnel interface
  • Setting the monitor IP to something that responds (like 1.1.1.1) under Advanced gateway settings
  • Disabling gateway monitoring for this gateway

Firewall Rules in pfSense

Same logic as OPNsense:

  • WAN: allow outbound UDP 51820 if restricted
  • WireGuard interface: allow traffic from WG net
  • LAN rule with Gateway set to WG_VPS_GW (under Advanced)
  • Outbound NAT in Hybrid mode with a rule for WG_VPS

The UI flow is different, but the rule structure is conceptually identical.

TP-Link 2.5GB PCIe Network Card (TX201): Plug-and-play 2.5GbE PCIe card for multi-gig speeds.
TP-Link 2.5GB PCIe Network Card (TX201) Plug-and-play 2.5GbE PCIe card that unlocks multi-gig speeds for about $30. Works out of the box with Proxmox, Linux, and Windows. No drama, faster transfers.
Amazon Price: Loading...
Availability: Checking...
Contains affiliate links. I may earn a commission at no cost to you.

pfSense vs OPNsense for WireGuard

Feature OPNsense pfSense
WireGuard integration Plugin (feels native) Package (add-on)
Config model Instances + Peers Tunnels + Peers tabs
Stability (2024+) Strong Much improved, still package-based
Gateway monitoring Straightforward Requires ICMP tuning for WG gateways
UI clarity More intuitive Functional but more legacy

For WireGuard-heavy homelab setups, I’d lean OPNsense. But pfSense works. Both get the job done once configured.


Troubleshooting Guide

No Handshake

Check:

  • VPS firewall allows UDP on the WireGuard port
  • Endpoint IP and port are correct
  • Keys match (double-check copy-paste errors)
  • Run wg show on both OPNsense and VPS

If behind NAT, ensure Persistent Keepalive is set to 25.


LAN Traffic Still Uses WAN

Common causes:

  • Missing gateway in LAN rule (the Advanced > Gateway dropdown)
  • Rule order wrong (policy route rule is below the default LAN allow rule)
  • A floating rule is overriding your LAN rule

Fix: move the policy route rule above the default LAN allow rule. Check for floating rules under Firewall > Rules > Floating.


Traffic Leaves Tunnel but Replies Drop

Cause: asymmetric routing. The return path doesn’t match the outbound path.

Fix:

  • Add outbound NAT rule on WG_VPS (see Fix 1 above)
  • Verify gateway is selected in the LAN rule
  • Check reply-to isn’t interfering

“no such device wg0”

Usually means:

  • Instance not enabled in WireGuard settings
  • WireGuard service not started

Check: VPN > WireGuard > General and make sure the service is enabled and running.


MTU Issues

Symptoms:

  • Websites partially load (small requests work, large ones stall)
  • Large downloads stall or time out
  • SSH works but SCP hangs

Fix:

  • Reduce MTU to 1412
  • Test with do-not-fragment ping (see MTU section above)
  • If still broken, try 1400 or lower

Static Routes Not Working

Check:

  • Gateway is assigned and active
  • Interface is enabled
  • “Disable Routes” is not checked in the WireGuard instance settings

OPNsense auto-adds routes based on AllowedIPs unless “Disable Routes” is checked. For complex multi-subnet environments, manage routes manually instead.


Frequently Asked Questions

How do I fix WireGuard handshake timeout on OPNsense?

Check VPS firewall, endpoint IP, and UDP 51820 access. Run wg show on both sides to confirm handshake attempts. Make sure Persistent Keepalive is set to 25 if either side is behind NAT. Key mismatch is the most common cause after port issues.


Why does LAN traffic go out WAN instead of the WireGuard tunnel?

Because the LAN firewall rule doesn’t have the gateway set to WG_VPS_GW. Open the rule, go to Advanced, and select the WireGuard gateway. Then move the rule above your default LAN allow rule. First match wins.


Do I need to assign the WireGuard interface for a basic client tunnel?

Not if you only need the firewall itself to use the tunnel. You do need it assigned if you want LAN routing, policy routing, VLAN support, or port forwarding. No assignment means no gateway, which means no policy routing options.


pfSense WireGuard client vs OPNsense: which is more stable?

As of 2024+, both work. OPNsense’s plugin is generally more consistent and better integrated into the UI. pfSense’s package has improved a lot but still feels like an add-on. For a dedicated WireGuard router, I’d pick OPNsense.


What firewall rules do I need for a WireGuard client tunnel?

Three places: WAN (allow outbound UDP 51820 if your rules are restrictive), the WG_VPS interface (allow traffic from WG net), and LAN (policy route via WG gateway under Advanced). Plus outbound NAT if you’re doing a full tunnel.


What MTU should I use for WireGuard over PPPoE or VLAN?

Start with 1412. WireGuard adds 60 bytes overhead. PPPoE subtracts 8 from the standard 1500. Test with ping -s 1384 -M do 10.10.10.1 and increase only if it passes. Lower is safer than higher.


How do I route only specific LAN devices through the VPS tunnel?

Create an alias containing the IPs or subnets you want to route. Add a LAN firewall rule with that alias as the source and WG_VPS_GW as the gateway. Leave the default LAN rule below it for everything else.


AllowedIPs 0.0.0.0/0 on client: full tunnel or split?

On the client side, 0.0.0.0/0 in AllowedIPs means “send everything through the tunnel.” Whether your LAN actually uses it depends on your policy routing rules. You control which traffic goes through the tunnel with firewall rules, not AllowedIPs alone.


Auto-routes vs static routes in OPNsense WireGuard?

If “Disable Routes” is unchecked, OPNsense auto-creates routes based on AllowedIPs. That works for simple setups. For multi-subnet or multi-peer environments, check “Disable Routes” and manage everything manually through System > Routes. You get more control and fewer surprises.


Wrapping Up

The tunnel coming up is not the hard part. Routing is.

If you remember three things:

  1. Assign the WireGuard interface
  2. Use policy-based routing on LAN rules
  3. Fix asymmetric routing with outbound NAT (or proper VPS-side routes)

Once those are correct, everything clicks.

OPNsense makes this easier than expected once you understand where routing decisions happen. pfSense gets you there too, with a few extra steps around gateway monitoring and package management.

If you’re building a serious homelab, mastering this setup unlocks:

  • Secure VPS reverse proxy
  • Clean WireGuard port forwarding
  • Multi-VLAN routing
  • Dual-WAN failover via tunnel
  • Encrypted site-to-site networking

Next step: experiment with gateway groups and failover tunnels.

That’s where things get fun.


This is Part 3 of a 3-part series on building a VPS-fronted homelab.