WireGuard / Troubleshooting

WireGuard Handshake Succeeds but Traffic Does Not Pass

Confirm the handshake is recent, separate a universal WireGuard configuration issue (AllowedIPs and routes) from a platform-specific Ubuntu Server gateway forwarding or NAT issue, then apply a bounded configuration or gateway change with console recovery and rollback.

The wg(8) man page defines AllowedIPs as a comma-separated list of IP addresses with CIDR masks from which incoming traffic for this peer is allowed and to which outgoing traffic for this peer is directed. The wg-quick(8) man page states that wg-quick infers all routes from the list of peers' allowed IPs and automatically adds them to the system routing table, with separate handling for the default route. AllowedIPs and the routes inferred from it are the universal configuration boundary for a WireGuard tunnel.[1][2]

When one peer is expected to route traffic on behalf of another, the routing host needs IPv4 forwarding and, for internet passthrough, a source-NAT or masquerade rule. The Canonical Ubuntu Server WireGuard default-gateway how-to documents enabling net.ipv4.ip_forward via a sysctl drop-in and adding iptables MASQUERADE for the WireGuard subnet, and notes that the outgoing interface name must match the host. That design is specific to the Ubuntu Server default-gateway topology; other distributions and firewall backends use their own documented procedures.[4]

Applicability

Products
WireGuard
Scope
For a Linux WireGuard tunnel managed with the wireguard-tools wg and wg-quick utilities, where wg show reports a recent handshake (latest-handshakes) and transfer counters may show some packets, but intended traffic through the tunnel does not flow. The current upstream wireguard-tools is 1.0.20260223, released 2026-02-23, and the man pages are obtained from the upstream git repository. The gateway forwarding and NAT remediation described in this page is scoped specifically to the Ubuntu Server WireGuard VPN default-gateway topology documented by Canonical, and is not a universal Linux recipe. This page does not cover a tunnel that never establishes a handshake, a key or endpoint mismatch, an MTU-related partial degradation, a mobile-app packaging problem, or a DNS resolver design tutorial.[1][2][3][4]
Last verified

Symptoms

  • wg show for the interface reports a recent or latest-handshakes entry for the peer, and transfer counters may show some packets, but the intended traffic (a service on a remote subnet or internet access through the tunnel) does not flow. A tunnel that never establishes a handshake is a different observation; a handshake that establishes but drops the peer immediately is also outside this page.[1][2]

Quick diagnosis

Establish that the tunnel really has a recent handshake, then separate universal AllowedIPs and route evidence from an Ubuntu Server gateway forwarding or NAT condition.

Read-only

Confirm the handshake and the transfer counters

Run wg show for the interface and read the latest-handshakes and transfer fields. The wg(8) man page documents the latest-handshakes field as the time of the most recent authenticated handshake and the transfer field as the bytes sent and received. A non-zero recent handshake with non-moving transfer counters indicates that the tunnel is up at the cryptographic layer but traffic is not entering or leaving the interface.[1]

wg show <iface>
Read-only

Record each peer's AllowedIPs and the local interface address

Run wg show with the allowed-ips field for the interface, and note the Address entry from the wg-quick configuration. The wg(8) man page describes AllowedIPs as both the allowed incoming addresses and the routing target for outgoing traffic, and the wg-quick(8) man page describes the routes that wg-quick infers from AllowedIPs.[1][2]

wg show <iface> allowed-ips
Read-only

Inspect the route for the intended destination

Use the system route table (for example ip route) to confirm whether a route for the intended destination points at the WireGuard interface or, when wg-quick handles a default route, whether the policy routing rule and fwmark match the tunnel. The wg-quick(8) man page states that wg-quick infers routes from AllowedIPs and uses ip-rule to handle overriding of the default gateway when one of the routes is 0.0.0.0/0 or ::/0.[2]

Read-only

Do not change the forwarding or NAT state before classification

Do not enable IPv4 forwarding, change sysctl values, or insert iptables or nftables rules before classifying whether the issue is a universal WireGuard configuration problem or a platform-specific gateway problem. A host network change made before classification can remove the only remote-access path or weaken the host firewall.[4]

Interactive troubleshooter

Your answers stay in this browser tab. The tool does not connect to your systems or send diagnostic results.

Guided check / step 1

Safe diagnostic guidance

Is this a Linux WireGuard tunnel where wg show reports a recent handshake but intended traffic does not flow?

Use wg show <iface> and read the latest-handshakes field. The wg(8) man page documents the latest-handshakes field as the time of the most recent authenticated handshake. A tunnel that never establishes a handshake, or a handshake that drops the peer immediately, is a different observation.[1]

Read the complete diagnostic tree without using the controls
  1. Is this a Linux WireGuard tunnel where wg show reports a recent handshake but intended traffic does not flow?

    Use wg show <iface> and read the latest-handshakes field. The wg(8) man page documents the latest-handshakes field as the time of the most recent authenticated handshake. A tunnel that never establishes a handshake, or a handshake that drops the peer immediately, is a different observation.[1]

    • Yes, recent handshake and no trafficOn both peers, does AllowedIPs cover the intended destination?
    • No, no handshake or different observationInvestigate the actual observation or environment
  2. On both peers, does AllowedIPs cover the intended destination?

    The wg(8) man page defines AllowedIPs as the addresses from which incoming traffic is allowed and to which outgoing traffic is directed. This discriminator checks WireGuard interface configuration coverage only; it does not decide whether the host system route table contains the expected route.[1]

    • Yes, AllowedIPs covers the destinationIf AllowedIPs is correct, does the expected system route for the destination point at the WireGuard interface?
    • No, AllowedIPs is missing or too narrowCorrect AllowedIPs on both peers and re-apply the configuration
    • AllowedIPs coverage is unclearIf AllowedIPs is correct, does the expected system route for the destination point at the WireGuard interface?
  3. If AllowedIPs is correct, does the expected system route for the destination point at the WireGuard interface?

    Confirm that a route for the intended destination exists and points at the WireGuard interface, or, when the tunnel carries a default route, that the wg-quick policy routing rule and fwmark match the tunnel. The wg-quick(8) man page states that wg-quick infers all routes from the list of peers' allowed IPs and automatically adds them to the system routing table, with separate handling for the default route. A missing or wrong system route is a different branch from a wrong AllowedIPs entry.[2]

    • Yes, the expected route is presentIs the deployment a VPN gateway where the host is expected to forward or NAT traffic for peers?
    • No, the expected route is missing or wrongAllowedIPs is correct but the expected system route is missing; preserve route evidence
    • Route state is unclearIs the deployment a VPN gateway where the host is expected to forward or NAT traffic for peers?
  4. Is the deployment a VPN gateway where the host is expected to forward or NAT traffic for peers?

    The Canonical Ubuntu Server WireGuard default-gateway how-to describes a topology in which the routing host forwards or NATs traffic for the WireGuard peers. Other deployments are pure peer-to-peer tunnels; the wg(8) and wg-quick(8) man pages do not require any extra forwarding or NAT for a pure peer-to-peer tunnel.[1][2][4]

    • Yes, Ubuntu Server VPN gatewayOn the routing host, is IPv4 forwarding enabled and is the masquerade or source-NAT rule present, matching the actual outgoing interface?
    • No, pure peer-to-peer tunnelUniversal WireGuard configuration is correct; investigate the destination path
    • Deployment topology is unclearUniversal WireGuard configuration is correct; investigate the destination path
  5. On the routing host, is IPv4 forwarding enabled and is the masquerade or source-NAT rule present, matching the actual outgoing interface?

    The Canonical Ubuntu Server WireGuard default-gateway how-to documents enabling net.ipv4.ip_forward via a sysctl drop-in and adding an iptables MASQUERADE rule for the WireGuard subnet, and notes that the interface name must match the host.[4]

    • Yes, forwarding and NAT are configuredVerify the tunnel subnet and the outgoing interface in the existing rule
    • No, forwarding or NAT is missingEnable IPv4 forwarding and add a masquerade or source-NAT rule (Ubuntu Server default-gateway topology)
    • Forwarding and NAT state is unclearEnable IPv4 forwarding and add a masquerade or source-NAT rule (Ubuntu Server default-gateway topology)
  6. Investigate the actual observation or environment

    A tunnel that never establishes a handshake, a key or endpoint mismatch, a mobile-app packaging problem, or a DNS resolver design problem needs its own investigation. The wg(8) and wg-quick(8) man pages do not describe a generic handshake or endpoint procedure.[1][2]

  7. Correct AllowedIPs on both peers and re-apply the configuration

    Edit the wg-quick configuration on each peer so that the AllowedIPs entry on the server covers the intended client tunnel address and the entries on the client cover the intended remote networks, and re-apply the configuration. The wg(8) man page documents syncconf as not disrupting current peer sessions; the wg-quick(8) man page documents the strip subcommand to output a configuration file with wg-quick-specific options removed, suitable for use with wg syncconf. This path corrects WireGuard interface configuration; it does not repair the host system route table.[1][2]

  8. AllowedIPs is correct but the expected system route is missing; preserve route evidence

    Record the route-table output, the wg show output, the wg-quick configuration, the policy-rule and fwmark state for a default route, and the deployment distribution. Do not use wg syncconf as a route repair: the wg(8) boundary is interface configuration, while wg-quick(8) describes interface setup and routes inferred from AllowedIPs. This page does not prescribe ip route mutations or a generic Linux route recipe; send the sanitized evidence to the operator for a topology-specific repair.[1][2]

  9. Universal WireGuard configuration is correct; investigate the destination path

    When the universal WireGuard configuration is correct and the deployment is not a VPN gateway, the wg(8) and wg-quick(8) man pages do not require any extra forwarding or NAT. Verify the destination reachability from the tunnel endpoint on a different path, the destination peer firewall, and the application listener before changing WireGuard settings.[1][2]

  10. Enable IPv4 forwarding and add a masquerade or source-NAT rule (Ubuntu Server default-gateway topology)

    On the routing host, create a sysctl drop-in (for example /etc/sysctl.d/70-wireguard-routing.conf) containing net.ipv4.ip_forward = 1 and apply it with sudo sysctl -p /etc/sysctl.d/70-wireguard-routing.conf -w. Record the current value of net.ipv4.ip_forward before any change. Add an iptables MASQUERADE rule that matches the WireGuard subnet and the actual outgoing interface. The Canonical Ubuntu Server how-to scopes this design to the Ubuntu Server default-gateway topology and notes that the interface name must match the host. Other distributions and firewall backends use their own documented procedures.[4]

  11. Verify the tunnel subnet and the outgoing interface in the existing rule

    When forwarding and masquerade are already configured, verify that the rule matches the actual WireGuard subnet and the actual outgoing interface. The Canonical how-to notes that the interface name must match the host. A rule that references a different interface or a different subnet does not forward the traffic that arrives on the tunnel.[4]

Detailed diagnosis

Read-only

1. Classify the universal vs platform-specific boundary

Determine whether the issue is a universal WireGuard configuration problem (AllowedIPs and the routes inferred from it) or a platform-specific VPN-gateway problem (forwarding and source-NAT or masquerade on the routing host). The wg(8) and wg-quick(8) man pages ground the universal boundary; the Canonical Ubuntu Server how-to grounds the platform-specific gateway boundary for the Ubuntu Server default-gateway topology.[1][2][4]

Read-only

2. Verify AllowedIPs coverage on both peers

Compare the intended destination networks with the AllowedIPs entry on each peer. The wg(8) man page states that AllowedIPs is the list of IP addresses with CIDR masks from which incoming traffic for this peer is allowed and to which outgoing traffic for this peer is directed. A missing or narrow entry on either side means the peer will not direct the matching traffic through the tunnel.[1]

Read-only

3. Verify the route for the intended destination

Confirm that a route for the intended destination exists and points at the WireGuard interface, or, when the tunnel carries a default route, that the wg-quick policy routing rule and fwmark match the tunnel. The wg-quick(8) man page states that wg-quick infers all routes from the list of peers' allowed IPs and automatically adds them to the system routing table, with separate handling for the default route.[2]

Read-only

4. If the routing host forwards traffic, verify forwarding and NAT

When the deployment is a VPN gateway where the routing host is expected to forward or NAT traffic for peers, verify IPv4 forwarding and the source-NAT or masquerade rule. The Canonical Ubuntu Server WireGuard default-gateway how-to documents enabling net.ipv4.ip_forward via a sysctl drop-in and adding an iptables MASQUERADE rule for the WireGuard subnet, and notes that the outgoing interface name must match the host. Other distributions and firewall backends use their own documented procedures; this page does not claim a universal command set.[4]

Supported scenarios

These observations narrow the next investigation; they do not establish a unique cause.

AllowedIPs on one or both peers does not cover the intended destination

The wg(8) man page defines AllowedIPs as the addresses from which incoming traffic is allowed and to which outgoing traffic is directed. A missing or narrow entry means the matching traffic is not routed through the tunnel and is not accepted from the peer.[1]

How to check: Use wg show <iface> allowed-ips on both peers, compare the entries with the intended destination networks, and correct the wg-quick configuration to include those destinations.[1]

The routing host does not forward or NAT the tunnel subnet (Ubuntu Server default-gateway topology)

When the routing host is expected to forward or NAT traffic for peers, the Canonical Ubuntu Server WireGuard default-gateway how-to documents enabling net.ipv4.ip_forward and adding an iptables MASQUERADE rule for the WireGuard subnet. Without forwarding, packets that arrive on the tunnel interface are not routed onward; without the masquerade rule, replies from the internet cannot reach the tunnel subnet.[4]

How to check: On the routing host, verify net.ipv4.ip_forward is 1 and verify the source-NAT or masquerade rule for the WireGuard subnet, matching the actual outgoing interface, before applying the documented sysctl drop-in and iptables rule.[4]

The deployment is not a VPN gateway; the issue is elsewhere

When neither side is expected to route traffic on behalf of the other, forwarding and NAT are not the boundary. A pure peer-to-peer tunnel needs only the universal WireGuard configuration; if the universal configuration is correct and the intended traffic still does not flow, the cause is on the destination path (destination reachability, peer firewall, application listener, or MTU), not in WireGuard.[1][2]

How to check: Verify the destination is reachable from the tunnel endpoint on a different path, verify the application listener, and check the peer firewall before changing the WireGuard configuration.[1]

Next actions and procedure boundaries

Safe / low risk

Correct AllowedIPs on both peers and re-apply the configuration

Edit the wg-quick configuration on each peer so that the AllowedIPs entry on the server covers the intended client tunnel address and the entries on the client cover the intended remote networks, and re-apply the configuration. The wg(8) man page documents the syncconf subcommand as reading back the existing configuration and only making changes that are explicitly different, without disrupting current peer sessions; the wg-quick(8) man page documents the strip subcommand to output a configuration file with wg-quick-specific options removed, suitable for use with wg syncconf. This correction changes the WireGuard interface configuration; it does not repair the host system route table.[1][2]

wg syncconf <iface> <(wg-quick strip <iface>)
Read-only

If AllowedIPs is correct but the expected system route is missing: preserve route evidence and hand off

When AllowedIPs covers the intended destination but the expected route for that destination does not point at the WireGuard interface, or the wg-quick policy routing rule and fwmark for a default route do not match the tunnel, preserve the route-table output, the wg show output, the wg-quick configuration, the policy-rule and fwmark state, and the deployment distribution before any change. Do not use wg syncconf as a route repair: the wg(8) boundary is interface configuration, while wg-quick(8) describes interface setup and routes inferred from AllowedIPs. This page does not prescribe ip route mutations or a generic Linux route recipe; send the sanitized evidence to the operator for a topology-specific repair.[1][2]

Read-only

If the universal configuration is correct and the host does not forward: investigate the destination path

When the deployment is a pure peer-to-peer tunnel (the host does not forward traffic for the peer), the wg(8) and wg-quick(8) man pages do not require any extra forwarding or NAT. If the universal WireGuard configuration is correct and the intended traffic still does not flow, verify the destination reachability from the tunnel endpoint on a different path, the destination peer firewall, and the application listener before changing WireGuard settings.[1][2]

Potentially disruptive

Ubuntu Server default-gateway topology: enable IPv4 forwarding and add a masquerade rule for the tunnel subnet

This solution applies specifically to the Ubuntu Server default-gateway topology described in the Canonical how-to. On the routing host, create a sysctl drop-in (for example /etc/sysctl.d/70-wireguard-routing.conf) containing net.ipv4.ip_forward = 1 and apply it with sudo sysctl -p /etc/sysctl.d/70-wireguard-routing.conf -w. Record the current value of net.ipv4.ip_forward before any change. Add an iptables MASQUERADE rule that matches the WireGuard subnet and the actual outgoing interface on the host. The Canonical how-to notes that the interface name must match the host. Other distributions and firewall backends (nftables, firewalld, and so on) use their own documented procedures; do not copy the Ubuntu iptables example into a deployment that uses a different backend. Forwarding and firewall changes are host network changes; require console or out-of-band access, a saved configuration, and a verified restoration path before proceeding.[4]

iptables -t nat -A POSTROUTING -s <vpn-subnet> -o <outgoing-iface> -j MASQUERADE

Before changing anything

Risk
Enabling IPv4 forwarding and adding a source-NAT or masquerade rule changes the host network behavior and can remove the only remote-access path or weaken the host firewall. The Canonical how-to scopes the commands to the Ubuntu Server default-gateway topology; other distributions and firewall backends use their own documented procedures.[4]
Safer check
Confirm that the deployment is the Ubuntu Server default-gateway topology and that the host is expected to forward or NAT traffic for the WireGuard peers. Record the current value of net.ipv4.ip_forward, the existing iptables NAT rules, and the host firewall state. Identify the actual outgoing interface and the actual WireGuard subnet before issuing the commands.[4]
Expected result
After enabling forwarding and adding the masquerade rule, the intended traffic that arrives on the tunnel interface is routed onward and the replies reach the tunnel subnet. A successful ping through the tunnel alone does not prove that the broader forwarding configuration is correct.[4]
Backup / recovery access
Record the current sysctl drop-ins, the current iptables NAT and FORWARD rules, and the current WireGuard configuration before changing them. Establish a console or out-of-band access path that does not depend on the WireGuard tunnel.[4]
Rollback
If the intended traffic does not flow or any other change is undesirable, restore the recorded prior value of net.ipv4.ip_forward, remove only the exact iptables MASQUERADE rule that was added, and restore the recorded prior WireGuard configuration. Do not hardcode net.ipv4.ip_forward to 0; only the recorded prior value is the correct rollback target. If the Ubuntu iptables example is not appropriate for the deployment, do not apply it and consult the distribution or firewall-backend documentation instead.[4]
Read-only

If forwarding and masquerade are already configured: verify the tunnel subnet and the outgoing interface

When the routing host already has IPv4 forwarding and a source-NAT or masquerade rule, verify that the rule matches the actual WireGuard subnet and the actual outgoing interface, and not a different subnet or interface. The Canonical Ubuntu Server WireGuard default-gateway how-to notes that the interface name must match the host. A rule that references a different interface or a different subnet does not forward the traffic that arrives on the tunnel.[4]

Read-only

If the boundary cannot be classified: preserve the evidence

Record the wg show output for both peers, the wg-quick configuration on each side, the system route table, the value of net.ipv4.ip_forward on the routing host, the existing iptables or nftables NAT and FORWARD rules, and the deployment distribution and firewall backend. Send the sanitized evidence to the operator before any further change. The wg(8) and wg-quick(8) man pages and the Canonical Ubuntu Server how-to do not describe a procedure for a tunnel whose boundary cannot be classified.[1][2][4]

Potentially disruptive

Before any separately scoped host network or firewall change

Planning boundary only. The operator must consider the current sysctl values, the current iptables or nftables state, the host firewall, the deployment distribution and firewall backend, and the recovery access path. This page does not disable the host firewall, copy the Ubuntu iptables example into a non-Ubuntu deployment, or assume the outgoing interface name.[4]

Before changing anything

Risk
Host network changes (forwarding, NAT, firewall) can remove the only remote-access path to the routing host. The Canonical how-to scopes its commands to the Ubuntu Server default-gateway topology; other distributions and firewall backends use their own documented procedures.[4]
Safer check
First confirm the deployment topology, the current sysctl values, the current iptables or nftables rules, and the actual outgoing interface. Establish a console or out-of-band access path that does not depend on the WireGuard tunnel.[4]
Expected result
A later owner-approved host change must leave the tunnel working, must not weaken the host firewall, and must not change the deployment's distribution or firewall backend without consulting the corresponding documentation. A successful tunnel connection alone does not validate the broader forwarding and firewall state.[4]
Backup / recovery access
Record the current sysctl drop-ins, the current iptables or nftables rules, and the current WireGuard configuration before any change. Identify the operators and access paths that can recover the host without depending on the tunnel.[4]
Rollback
If the intended traffic does not flow or any host network behavior is undesirable, restore the recorded prior sysctl values, the recorded prior iptables or nftables rules, and the recorded prior WireGuard configuration. If the Ubuntu iptables example is not appropriate for the deployment, do not apply it and consult the distribution or firewall-backend documentation before further changes.[4]

Warnings and boundaries

Do not disable the host firewall, assume the outgoing interface name, or copy the Ubuntu Server iptables example into a deployment that uses a different distribution or firewall backend. The Canonical how-to scopes its commands to the Ubuntu Server default-gateway topology; the wg(8) and wg-quick(8) man pages do not prescribe a universal iptables or nftables recipe.[1][2][4]
A non-zero recent handshake with non-moving transfer counters indicates that the tunnel is up at the cryptographic layer but traffic is not entering or leaving the interface. A tunnel that never establishes a handshake, or a handshake that drops the peer immediately, is a different observation and is not diagnosed by this page.[1]

Sources

Links were reviewed on 2026-09-06. Reachability and automated validation do not replace editorial verification of each claim.

  1. wg(8)
    WireGuard / wireguard-tools · Tier A · accessed 2026-09-06
  2. wg-quick(8)
    WireGuard / wireguard-tools · Tier A · accessed 2026-09-06
  3. wireguard-tools source repository (wg, wg-quick)
    wireguard-tools project · Tier B · accessed 2026-09-06
  4. Using the VPN as the default gateway (WireGuard)
    Canonical / Ubuntu · Tier A · accessed 2026-09-06