OPNsense Router
Flat isometric illustration of a dark cube topped by a pink keyhole shield, a curved cable linking it to a second server cube on a pink-edged pad.
Troubleshooting

OPNsense WireGuard Setup Problems: Handshake, NAT, MTU

Fix an OPNsense WireGuard tunnel that won't connect: read the handshake, then check the WAN rule, keys, allowed addresses, outbound NAT, DNS and MTU.

By OPNsense Router Editorial · ·Updated · 13 min read

If OPNsense WireGuard is not connecting, read the peer’s latest handshake under VPN, WireGuard, Status first. No handshake means UDP never reaches the firewall or the keys are wrong: check the WAN pass rule for the listen port (51820 in the docs), the peer selection and the keys. A handshake with no traffic means rules, Allowed IPs or NAT.

WireGuard is a quiet protocol. It sends no errors, does not warn about mismatched configuration, and never tells the client why nothing happened; its own quick start calls it “not a chatty protocol”. A wrong tunnel usually presents as a client that says “connected” and moves no data, so troubleshooting works by elimination rather than by reading a message.

Read the handshake before changing anything

Under VPN, WireGuard, Status, the VPN reference lists every instance and peer with its last known handshake and the amount of data exchanged; the site-to-site guide labels the same page Diagnostics. 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, although WireGuard resolves an endpoint hostname only once, when the tunnel starts, so a client must reconnect after a change. Where OPNsense itself dials a hostname, the site-to-site routing setup covers the cron job that re-resolves it.

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.

Still no handshake? Follow the packet

Capture UDP on the listen port on WAN while the client connects. Nothing arriving puts the fault upstream of OPNsense. Packets arriving with no reply mean the firewall dropped them or the key did not match. Replies leaving mean OPNsense answered and the client’s network is losing them.

  1. Live log. Enable logging on the WAN pass rule and watch Firewall, Log Files, Live View while the client connects, the method the firewall manual gives for confirming a rule matches. A block on the listen port means the rule is missing or on the wrong interface.
  2. Packet capture. Under Interfaces, Diagnostics, Packet Capture, select WAN, protocol UDP and the listen port, then bring the tunnel up; the capture can be viewed live or downloaded as a pcap. A key mismatch looks exactly like a closed port, because WireGuard does not respond at all to an unauthorized client.
  3. Debug messages. WireGuard itself logs very little, so the VPN reference says to check VPN, WireGuard, Log File first for setup errors, then use ifconfig from the console. ifconfig wg0 debug enables runtime debugging on wg0; Interfaces, Overview shows which wgX device belongs to which instance.

With debugging on, the FreeBSD wg(4) manual documents four messages:

MessageMeaningFix
Handshake for peer X did not complete after 5 seconds, retryingThis side’s initiation got no answerConfirm the far end has this side as a peer, check the endpoint address, open the firewall path
Invalid handshake initiationAn incoming initiation could not be processedPaste the client’s public key into the OPNsense peer again
Invalid initiation MACThe sender used the wrong public key for this sideGive the client the instance’s current public key
Packet has unallowed src IP from peer XA decrypted packet’s source is outside that peer’s Allowed IPsMatch the peer’s Allowed IPs to the client’s tunnel address

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.

These drops are hard to see. The VPN reference warns that inbound traffic outside a peer’s Allowed IPs is dropped silently and will not appear in a packet capture, so the “unallowed src IP” debug message above is the way to confirm it.

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, open Firewall, NAT, Source NAT (Outbound), which is what current releases call outbound NAT, switch to hybrid rule 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; in manual mode no automatic rules are generated, so any network added later goes untranslated until someone writes a rule for it.

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.

To measure rather than guess, run Interfaces, Diagnostics, Ping toward a host across the tunnel with Do not fragment set, raising the packet size until replies stop; the diagnostics documentation names that option for locating MTU problems.

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.

If a guide points to a plugin or page that does not exist, it predates your release. Since 24.1, released January 30, 2024, WireGuard is part of core with its kernel module installed by default, and os-wireguard-go is discontinued, so there is nothing to install. The same move renamed Local to Instances and Endpoints to Peers.

The 26.7 series, released July 15, 2026 on FreeBSD 15.1, changed three more things:

  • The API-driven rules page became the default and the classic pages moved to the os-firewall-legacy plugin, so “Firewall, Rules, WAN” now means choosing WAN in the new page’s interface filter. The firewall manual lists that page as Firewall, Rules [new].
  • Source NAT replaces outbound NAT, and 26.7.5 (September 30, 2026) moved the old outbound NAT page to the legacy plugin.
  • 26.7.3 (August 27, 2026) includes a WireGuard fix for FreeBSD 15 no longer allowing addresses without netmasks. Update before deeper debugging (26.7.6 shipped October 8, 2026), and write tunnel addresses in CIDR form.

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

  1. Read the latest handshake time. It splits the problem in half.
  2. Confirm a WAN pass rule for UDP on the listen port exists.
  3. Confirm the peer is selected inside the instance and applied.
  4. Confirm the client’s public key is in the peer, and the instance’s public key is in the client.
  5. Confirm the instance tunnel address is a subnet, not a /32.
  6. If there is still no handshake, capture UDP on the listen port on WAN and run ifconfig wg0 debug.
  7. Confirm a pass rule exists on the assigned WireGuard interface or the WireGuard group.
  8. Confirm allowed addresses mean the client’s tunnel address on OPNsense, and the routed destinations on the client.
  9. Confirm outbound NAT covers the tunnel subnet if internet access through the tunnel is wanted.
  10. Leave the instance DNS field blank and reload the resolver after assigning the interface.
  11. 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.

FAQ

why is opnsense wireguard connected but no internet

It usually means the tunnel is up but nothing translates its traffic to the WAN address. Assign the WireGuard device as an interface so OPNsense generates the IPv4 Source NAT rule, or add a hybrid-mode rule for the tunnel subnet. Then confirm the tunnel-side pass rule allows destinations beyond LAN.

what port does wireguard use on opnsense

WireGuard on OPNsense uses whatever UDP listen port is set on the instance; the official road warrior guide uses 51820 or a higher unique port. The WAN pass rule’s destination port must equal that number, and any router in front of OPNsense must forward the same UDP port. WireGuard never runs over TCP.

what does handshake did not complete after 5 seconds mean

It means this side sent a handshake initiation and the peer never answered. The FreeBSD wg(4) manual lists three usual causes: the far end does not have this side configured as a peer, the endpoint address is wrong, or a firewall blocks the traffic. WireGuard keeps retrying while traffic is queued, so the message repeats.

why did wireguard stop working after an opnsense update

Start with VPN, WireGuard, Log File, where OPNsense records setup errors. On the 26.7 series, move to 26.7.3 or later, which carries a fix for FreeBSD 15 rejecting WireGuard addresses without netmasks. Then confirm the WAN and tunnel rules and the Source NAT rule still exist after the move to the new rule pages.

Sources

  1. WireGuard Road Warrior Setup - OPNsense documentation
  2. Firewall - OPNsense documentation
  3. Network Address Translation - OPNsense documentation
  4. WireGuard: Protocol & Cryptography
  5. WireGuard: Quick Start (PersistentKeepalive)
  6. Virtual Private Networking - OPNsense documentation
  7. WireGuard Site-to-Site Setup - OPNsense documentation
  8. Interfaces Diagnostics - OPNsense documentation
  9. wg(4) - FreeBSD Manual Pages
  10. OPNsense 24.1 Savvy Shark series release notes
  11. OPNsense 26.7 Xenial Xenops series release notes
  12. interfaces: move WireGuard kernel plugin to core - opnsense/core issue 6827

Related