Remote Access with WireGuard
Reach your home network securely from anywhere with a self-managed WireGuard tunnel -- and know when a managed mesh VPN or plain port forwarding would actually serve you better.
What you'll build and why
WireGuard is a VPN protocol built to be small, fast, and simple to reason about: each side has a key pair, each side knows the other's public key, and an encrypted tunnel exists between them -- no certificate authority, no session negotiation ceremony, no legacy protocol baggage. This guide sets up a WireGuard server (on OPNsense, if you have it, or a standalone Linux host) and a client, so you can reach your home network securely from anywhere.
Don't build this if: you want the least operational overhead and don't specifically need to self-host the control plane -- Tailscale (a separate guide) uses WireGuard under the hood but handles key distribution and NAT traversal for you, at the cost of trusting a third party's coordination server (or self-hosting Headscale as an alternative). This guide is for when you want to run and understand the whole thing yourself, or when Tailscale's model doesn't fit your situation.
Comparison at a glance:
| Approach | Best for | Watch out | Trust model |
|---|---|---|---|
| WireGuard (this guide) | Full control, no third party in the connection path, understanding exactly what's exposed | You manage key distribution and NAT traversal yourself -- no automatic "it just works from anywhere" | Only you and whoever you give keys to |
| Tailscale | Easiest setup, works behind almost any NAT without port forwarding, multi-device management | Tailscale's own coordination servers are in the loop for device discovery (though not for the actual encrypted traffic) | You, plus trust in Tailscale's coordination service |
| Headscale (self-hosted Tailscale control plane) | Tailscale's ease of use without trusting Tailscale's own servers | More to self-host and maintain than either of the above | Only you |
| Plain port forwarding (no VPN) | Never actually recommended for exposing an internal service directly | Every forwarded service is its own attack surface, directly reachable by anyone scanning the internet | Whoever can reach that port |
How it works
Your phone/laptop (WireGuard client)
│
│ Encrypted tunnel, one UDP port
▼
Your router -- forwards that one UDP port to
│ the WireGuard server
▼
WireGuard server (OPNsense, or a Linux host)
│
▼
Your home network -- now reachable as if you
were on it locally
The key distinction from forwarding a service's own port directly: WireGuard exposes exactly one UDP port, and without the correct private key, a connection attempt to it produces no response at all -- not even an error, just silence. An internet-wide scanner sees nothing distinguishing it from a closed port. Compare that to forwarding, say, a web app's port directly: that port responds, identifies itself, and is a real target the moment it's reachable.
Before you start
Decision: where does the WireGuard server run? If you've built the OPNsense guide, WireGuard is built into OPNsense itself (VPN → WireGuard) -- the simplest option, since it's on the same box already handling your firewall. If you don't have OPNsense, any always-on Linux host works via the wireguard-tools package. This guide covers the OPNsense path; the standalone Linux path uses the same key-generation and config concepts with wg/wg-quick commands instead of a web UI.
Plan your addressing: WireGuard needs its own small subnet for the tunnel itself, separate from your LAN. This guide uses 10.100.0.0/24 for the tunnel, with the server at 10.100.0.1 and clients getting addresses from there.
Steps
Step 1: Confirm WireGuard is available
On OPNsense, it's built in -- VPN → WireGuard should already be present. On a standalone Linux host: sudo apt install wireguard (Debian/Ubuntu) or your distribution's equivalent. Editor's note: wireguard-tools doesn't version-release via GitHub releases the way most software in this section does -- it's distributed through each OS's own package manager and tracks that OS's packaging, not a single upstream version number. This isn't a gap in verification, it's genuinely how this specific package is distributed.
Step 2: Generate a key pair for the server
On OPNsense: VPN → WireGuard → Local, add a new instance -- it generates a key pair for you. On standalone Linux:
$ wg genkey | tee server_private.key | wg pubkey > server_public.key
Never share the private key. The public key is what you give to clients.
Step 3: Configure the server
On OPNsense: set the server's tunnel address (10.100.0.1/24), listen port (the default 51820 is fine unless you have a specific reason to change it), and save.
Step 4: Generate a client key pair and add the client as a peer
Each device gets its own key pair, not a shared one. On OPNsense: VPN → WireGuard → Peers → Add, generate a key pair for the client, assign it a tunnel address (10.100.0.2), and note the values -- you'll need the server's public key, the peer's tunnel address, and the server's public endpoint (your home's public IP or dynamic DNS hostname) to configure the client side.
Step 5: Configure the client
Most platforms have a WireGuard app (mobile) or the wg-quick tool (desktop Linux). The client config needs: its own private key, the server's public key, the server's public endpoint and port, and which traffic to route through the tunnel (just your home subnet, or everything -- "everything" also routes your general internet traffic through home, useful on untrusted networks but adds latency).
Step 6: Forward the WireGuard port on your router
Port forward UDP 51820 (or whatever you set in Step 3) from your router to the WireGuard server's address. This is the one port genuinely exposed to the internet by this guide.
Verify it works
- From outside your home network (mobile data, a different Wi-Fi), the client connects and shows a handshake
- Once connected, you can reach something on your home LAN (e.g. ping the router's LAN address) that you couldn't reach before connecting
- Disconnecting the client immediately loses that access -- confirms the tunnel, not some other path, was providing it
- Failure test: from outside, attempt to connect to the forwarded UDP port with an incorrect/no key (e.g. a generic UDP probe). Confirm there's no response distinguishing an open-but-unauthenticated port from a closed one -- this is WireGuard's actual security property, worth confirming rather than assuming
Secure it
- What's exposed: exactly one UDP port, and only to holders of a valid key pair the server has been told to trust. This is WireGuard's whole design point.
- Key management: each device's private key should exist only on that device -- don't email keys around or store them somewhere shared. Revoking a lost/compromised device means removing its peer entry from the server, immediately cutting its access.
- The failure that hurts most: routing "everything" through the tunnel on a device, then losing connectivity because the tunnel itself went down and there's no fallback -- know which mode (split tunnel vs. full tunnel) each client is using and why.
- Update strategy: WireGuard's kernel implementation is mature and stable; updates come through your OS's normal update process (OPNsense firmware updates, or your Linux distribution's package updates) rather than a separate WireGuard-specific release cycle to track.
Back it up and maintain it
What matters: the server's own private key and the full peer list (each client's public key and assigned address) -- on OPNsense, this is part of the same configuration export as the rest of your firewall config. Losing it means regenerating keys and reconfiguring every client, not a quick recovery.
What to monitor: OPNsense's WireGuard status page shows each peer's last handshake time -- a peer that should be connecting regularly but hasn't recently is worth investigating (device lost, config drift, or a network change on the client side).
Troubleshooting
Logs: OPNsense's WireGuard status page for handshake state; sudo wg show on standalone Linux.
| Symptom | Likely cause | Diagnostic | Fix |
|---|---|---|---|
| Client never connects, no handshake | Port forwarding misconfigured, or wrong server public key/endpoint on the client | Confirm the port forward rule on the router; double-check the server's public key was copied correctly | Fix the port forward; regenerate/re-copy keys carefully if mismatched |
| Client connects but can't reach anything on the LAN | Missing route/AllowedIPs configuration, or the server isn't forwarding traffic between the tunnel and LAN interfaces | Check the client's AllowedIPs includes the LAN subnet; check OPNsense firewall rules on the WireGuard interface |
Add the LAN subnet to AllowedIPs; add a firewall rule allowing the WireGuard interface to reach LAN |
| Works on one network, fails on another | A restrictive network (some corporate/public Wi-Fi) blocking outbound UDP | Try a different network to confirm | Outside this guide's control -- some networks block UDP-based VPN traffic; a TCP-based fallback would need a different tool |
| Handshake succeeds but traffic doesn't flow | A firewall rule between the WireGuard interface and the destination is blocking it, separate from the tunnel itself connecting | Check Firewall → Rules on the WireGuard interface specifically | Add the needed rule -- a successful handshake only proves the tunnel exists, not that firewall policy allows the traffic through it |
| Dynamic home IP breaks the client's server endpoint | Your home ISP connection doesn't have a static IP, and it changed | Check your current public IP against what the client is configured to reach | Use a dynamic DNS service and configure the client with that hostname instead of a raw IP |
Undo
On OPNsense: VPN → WireGuard, remove the peer entries and the local instance. Remove the port forward rule on your router. On standalone Linux: sudo wg-quick down wg0 then remove the config file and generated keys.
Go further
- Mesh VPN with Tailscale -- the managed alternative this guide compared against, if you want less to maintain yourself
- Add more clients following the same peer-generation pattern (Step 4-5) for each additional device
- Split-tunnel vs. full-tunnel client configs for different use cases (a phone that should only reach home vs. a laptop that should route all traffic through home on untrusted networks)
Resources
Official documentation:
Community:
Related DaemonPress projects:
Last verified: 2026-09-21, checked against official WireGuard documentation.