OPNsense WireGuard Not Connecting: Handshake Fixes
Why an OPNsense WireGuard tunnel shows no handshake, connects but passes no traffic, or stalls on large transfers, and how to isolate each cause in order.
WireGuard is a quiet protocol. It does not send errors, it does not warn about mismatched configuration, and it does not tell the client why nothing happened. A tunnel that is wrong in any way usually presents as a client that says “connected” and moves no data. That silence is by design, and it means troubleshooting has to be done by elimination rather than by reading a message.
The single most useful habit is to stop guessing and read one number first.
Read the handshake before changing anything
Under VPN, WireGuard, the status view shows the latest handshake time for each peer. Everything downstream depends on which side of that line the problem sits.
No handshake, ever. The two ends have never authenticated each other. Either the client’s packets are not reaching the OPNsense box, or the keys do not match. Nothing about routing, NAT, DNS or MTU is relevant yet, and changing those settings will waste time.
A handshake exists and is recent, but no traffic flows. The cryptographic layer is fine. The problem is a firewall rule, an allowed-address mismatch, outbound translation, or DNS.
A handshake exists and small traffic works, but large transfers stall. This is packet size, essentially always.
Those three states split the rest of this guide.
No handshake: causes in order of frequency
The WAN rule is missing
WireGuard listens on a UDP port, and OPNsense blocks unsolicited inbound traffic by default. The documented setup requires an explicit pass rule on the WAN interface: action pass, direction in, protocol UDP, destination WAN address, destination port equal to the listen port configured on the instance, commonly 51820.
This is the most common cause by a wide margin, and it catches experienced people too, because the tunnel is configured under the VPN menu while the rule that makes it reachable lives under Firewall, Rules, WAN. Nothing in the VPN configuration screen fails without it. If the underlying model of per-interface, inbound-direction rules is unfamiliar, how OPNsense firewall rules, NAT and interfaces actually work covers why the rule belongs on WAN specifically.
The peer is not attached to the instance
Creating a peer is only half the operation. The documented flow requires going back into the instance afterwards, selecting the new peer in the instance’s peers list, saving, and applying. A peer that exists but is not selected on any instance is inert, and the interface gives no indication that anything is incomplete.
The keys are crossed
WireGuard uses public key cryptography, and the direction of each key is easy to invert. The client’s public key goes into the peer entry on OPNsense. The instance’s public key goes into the client’s configuration under the peer section. Private keys never move between machines.
One detail causes repeated trouble: when an instance is first created, its key fields are blank until the generator is used, and the public key must be copied out after saving. Copying a value from a half-completed form yields a key that no longer matches the one in use.
The client cannot reach your public address at all
If the rule exists and the keys are right, the next question is whether the packets arrive. Three situations account for most of these.
The OPNsense box sits behind another router that is doing its own NAT, so the UDP port has to be forwarded through that device as well. A firewall configuration inside OPNsense cannot fix a translation happening upstream of it.
The connection uses carrier-grade NAT, in which case the public address is shared and no inbound port can be forwarded to you at all. A tunnel initiated from the other direction, or a rendezvous point with a routable address, is the only way out of this.
The dynamic public address changed and the client’s endpoint still points at the previous one. A dynamic DNS name as the endpoint, rather than a literal address, removes this recurrence.
The listen port is blocked upstream
Some networks block outbound UDP to unusual ports. If the tunnel works from one location and never from another, this is the likely explanation. Moving the listen port to a commonly permitted number sometimes helps, though a network that only passes TCP will never carry WireGuard at all. That is a structural limit of the protocol and one of the reasons OpenVPN over TCP still has a role.
The tunnel address is a single host address
The documentation states directly that the instance tunnel address must not be a /32 for IPv4 or a /128 for IPv6. It has to be a real subnet large enough to contain every peer, for example 10.10.10.1/24. Configuring it as a single address produces a tunnel that cannot route to its own peers.
Handshake works, but nothing passes
There is no rule on the tunnel side
The WAN rule permits the tunnel to be established. It says nothing about what the connected client may then reach. A second pass rule is required, on the interface assigned to the WireGuard device, permitting traffic from the tunnel subnet to whatever the client should be able to access.
If the WireGuard device was never assigned as an interface, that rule has to go on the automatically created WireGuard group instead. Assigning the interface is worth doing anyway: the documentation notes that it generates an alias for the tunnel subnet that can be used in rules, adds an IPv4 outbound NAT rule automatically, and keeps rules for multiple instances separate.
Allowed addresses are being read backwards
The allowed-addresses field means different things on each end, and reversing them is a classic failure.
On the OPNsense peer entry, it is the address the client will use inside the tunnel, expressed as a single host address within the instance’s subnet, such as 10.10.10.2/32. It functions as an access control list: packets arriving from that peer with a source outside this range are dropped.
On the client, the equivalent field lists the destinations that should be routed into the tunnel. A local-only tunnel lists the internal subnets. A full tunnel lists 0.0.0.0/0, and ::/0 if IPv6 should also go through.
A client set to route everything through a tunnel that only permits access to one subnet loses all connectivity the moment it connects, which looks like the tunnel breaking the internet.
Two peers must not claim overlapping addresses. WireGuard resolves an inbound packet to a peer by its source address, so an overlap makes the association ambiguous and the results inconsistent.
Local network works, internet does not
The client can reach internal hosts but nothing beyond them. This is outbound translation, not filtering. Traffic arriving from the tunnel subnet and leaving through WAN needs to be translated to the WAN address, and by default the automatically generated outbound NAT rules do not know about a tunnel subnet that was added later.
Assigning the WireGuard device as an interface causes the IPv4 rule to be generated. Otherwise, switch outbound NAT to hybrid generation and add a rule with the tunnel subnet as source, WAN as the interface, and the interface address as the translation target. Hybrid mode is the safer choice because it keeps the automatic rules alongside the added one, where manual mode freezes everything and silently omits translation for any network added afterwards.
Names do not resolve
Two distinct problems produce this.
The instance configuration has a DNS server field visible in advanced mode. The documentation warns to leave it blank, because a value there overwrites the DNS configuration of OPNsense itself. DNS for the client belongs in the client’s own configuration.
Separately, if the resolver is bound to specific interfaces rather than all of them, a newly assigned WireGuard interface is not among them until the resolver is reloaded. Queries into the tunnel then go unanswered while everything else works.
Also confirm the resolver address the client uses is inside the range it routes through the tunnel. A client pointed at an internal resolver but not routing that resolver’s subnet through the tunnel will send queries out of its local connection instead, where they will not be answered.
Handshake works, small traffic works, large transfers stall
The signature is unmistakable: pings succeed, name resolution succeeds, a web page starts to load and then hangs, and file transfers stop partway. Interactive traffic is fine while anything bulk dies.
This is encapsulation overhead. WireGuard adds headers to every packet, so the usable payload inside the tunnel is smaller than outside it. The default instance MTU is 1420, and the documentation notes it should be 1412 on a PPPoE connection, which is 80 bytes below the WAN MTU in each case.
MTU alone is often not enough, because path MTU discovery depends on ICMP messages that many networks discard. The documented remedy is a normalization rule that clamps the maximum segment size: under Firewall, Settings, Normalization, a rule on the WireGuard group with a maximum segment size of 1380 for IPv4, or 1372 with PPPoE, which is 40 bytes below the tunnel MTU. If IPv6 traffic also crosses the tunnel, the corresponding value is 1360, or 1352 with PPPoE, reflecting the larger IPv6 header.
The documentation is blunt about the symptom this fixes: without it, ICMP and UDP can work while some encrypted TCP sessions refuse to.
Handshakes that succeed then stop
A tunnel that works for a minute or two after each use and then goes quiet, requiring traffic from the client to revive it, is a NAT timeout on an intermediate device. WireGuard sends nothing when there is nothing to send, so the translation entry holding the path open expires.
Setting a persistent keepalive of 25 seconds on the peer behind the restrictive network keeps that entry alive. It is not needed on both ends, and it is not needed at all when both endpoints have directly reachable addresses.
After changing anything structural
Interface assignment changes, instance changes and toggling the service all need WireGuard restarted before they take effect. The documented method is switching it off under VPN, WireGuard, General, applying, switching it back on, and applying again. A configuration that looks correct but behaves as though it were not saved is frequently one restart away from working.
A short checklist
- Read the latest handshake time. It splits the problem in half.
- Confirm a WAN pass rule for UDP on the listen port exists.
- Confirm the peer is selected inside the instance and applied.
- Confirm the client’s public key is in the peer, and the instance’s public key is in the client.
- Confirm the instance tunnel address is a subnet, not a /32.
- Confirm a pass rule exists on the assigned WireGuard interface or the WireGuard group.
- Confirm allowed addresses mean the client’s tunnel address on OPNsense, and the routed destinations on the client.
- Confirm outbound NAT covers the tunnel subnet if internet access through the tunnel is wanted.
- Leave the instance DNS field blank and reload the resolver after assigning the interface.
- Set MTU and a maximum segment size normalization rule before blaming anything else for stalled transfers.
If the box itself is struggling rather than the configuration, several concurrent tunnels are a CPU question rather than a firewall one, and OPNsense hardware requirements covers why WireGuard throughput tracks single-core clock speed rather than AES acceleration. The state table and bandwidth sizer on this site takes an active tunnel count as one of its inputs.
Sources
Related
OPNsense VPN: WireGuard vs OpenVPN vs IPsec
How the three OPNsense VPN options differ in cryptography, roaming, CPU cost and interoperability, and which one fits each type of tunnel you need.
OPNsense Hardware Requirements: How to Size a Box
OPNsense hardware requirements explained: the official CPU, RAM and disk tiers, what state tables and Suricata add, and why ARM boards are not supported.
OPNsense Firewall Rules and NAT: How They Work
How OPNsense firewall rules, NAT and interfaces fit together: per-interface evaluation, rule order, stateful returns, and the mistakes each causes.