Disclaimer: this is a living document - found an error or want to share your favorite trick? Feel free to share it in the comment section or via mail.

Every setup is different, so it is impossible to have a perfect order - I’ll try to prioritize the most common problems and steps, but use whatever you need.

Side note: This is not a A to B follow-through - it is a reference that should give you enough information to solve the problems.


Your Variables #

Use the following form to insert your names to make it easier to copy and paste:

Tunnel Information

Client Information


The Scenario #

  • Wireguard installed, systemd, CLI-only
  • Ubuntu Server 24.04/26.04, with full control
  • 3x Hosts
  • simple Hub-Spoke VPN topology
  • focus on IPv4

Hosts:

  • Server-1 - 10.10.10.1 - Endpoint: example.com A 203.0.113.4
  • Client-2 - 10.10.10.2
  • Client-3 - 10.10.10.3
  • Wireguard VPN Name: wg-random - Port 51820

  ┌───────────────────────────┐  
  │ Server-1                  │  
  │ 10.10.10.1                │  
  │ example.com A 203.0.113.4 │  
  └─────┬───────────────┬─────┘  
        │                │        
  ┌─────┴──────┐  ┌───────┴─────┐  
  │ Client-2   │  │  Client-3   │  
  │ 10.10.10.  │  │  10.10.10.3 │  
  └────────────┘  └─────────────┘  

Most steps should help you in other networks like mesh topologies as well.


Troubleshooting Reference #

Side note: Before we start, be aware to restart the tunnel after every change.

sudo systemctl restart wg-quick@wg-random.service

Make sure Wireguard is running #

# Status
sudo systemctl status wg-quick@wg-random.service

# Restart
sudo systemctl restart wg-quick@wg-random.service

# Check listening port on server
sudo ss -lunp | grep ':51820'

Confirm current loaded config #

sudo wg showconf wg-random

Wireguard Peers Overview #

sudo wg show wg-random

# EXAMPLE OF CLIENT-2
interface: wg-random
  public key: PUBLICKEYOFCLIOENT2=
  private key: (hidden)
  listening port: 41272

peer: PUBLICKEYOFSERVER1=
  preshared key: (hidden)
  endpoint:  203.0.113.4:51820
  allowed ips: 10.10.10.0/24
  latest handshake: 1 minute, 29 seconds ago
  transfer: 36.21 KiB received, 132.98 KiB sent
  persistent keepalive: every 16 seconds

This is my first go-to before I start tcpdump. It answers many questions and allows you to rule out certain problems:

  • is WireGuard running?
  • is the config getting parsed correctly?
  • are the peer informations correct?
  • is the host send or receiving related traffic?
  • is the handshake successful?

Check the tcpdump section for a more detailed checklist.

Check logging #

# Status and last logs
sudo systemctl status wg-quick@wwg-random.service

# Logs for specific Wireguard tunnel
sudo journalctl -u wg-quick@wg-random --since today

# Some example error messages

# wg-quick: `/etc/wireguard/wg-random.conf' does not exist
# wg-quick: `wg-random' already exists
# [#] ip address add 10.10.10.0/24 dev wg-random

# or various parsing or permission errors

Test connection #

# From Client-2 to Server-1 - Layer 3 ICMP Request
ping 10.10.10.1

# From Server-1 to Client-2 - Layer 3 ICMP Request
ping 10.10.10.2

# From Client-2 to Server-1 - Layer 4 TCP (Assuming a service in Server-1 is running)
nc -vz 10.10.10.1 443

# Use those to check connection and 'cause' traffic

Checking traffic with tcpdump

Nowadays tcpdump is the first thing I check myself or request from third-parties.

# Run on Server-1
sudo tcpdump -ni any udp port 51820

# Restart Wireguard on Client-2 and try to reach Server-1 via Wireguard tunnel IP or some previous test
ping 10.10.10.1

# Traffic specific through the tunnel - helpful for the clients
sudo tcpdump -ni wg-random

No traffic

  • Wireguard problem on Client-2
  • host firewall Client-2
  • DNS problem on Client-2
  • network firewall between hosts
  • NAT
  • routing

Incoming traffic, but no response

  • check public/private key pairs
  • check PSK
  • Server-1 host firewall

Response, but no connection / no handshake

  • routing, return path
  • NAT
  • Client-2 host firewall

Handshake works, but no traffic

  • host routing
  • check AllowedIPs in config
  • forwarding disabled

Testing network between #

This section checks of the client can reach the VPN endpoint of the server. If something fails, the next tcpdump section should help.

# Client-2 to WG VPN endpoint Server-1

ping example.com
nslookup example.com

# ICMP could be blocked, but not critical - make sure it resolves the correct IP

# --------------

# Testing UDP connectivity
# Making sure that UDP is not being blocked

# Stop all Wireguard services - Wireguard service won't response to random UDP traffic!

# Start UDP listener on Server-1

sudo systemctl stop wg-quick@wg-random.service
nc -u -l 51820

# Send UDP datagram to Server-1 from Client-2

echo "udp-test" | nc -u -w2 example.com 51820

# Server-1 should display

udp-test
# If it doesn't it might get blocked!

Check IP config - Layer 3 #

# On both end!jj
# Check IP and interface

ip -br -c a
ip -br a show wg-random

# Check IP routing

ip -br -c r

# on Client-2

ip route get 10.10.10.1

# on Server-1

ip route get 10.10.10.2

Check host firewall #

Depends on your setup! - Make sure the Clients can reach the Server-1 via UDP port on the public interfaces.

sudo systemctl --type=service --state=running | grep -Ei 'ufw|firewalld|nftables|iptables'

# then check
sudo nft list ruleset

sudo iptables -vnL
sudo iptables -t nat -vnL

sudo ufw status verbose

sudo firewall-cmd --state
sudo firewall-cmd --get-active-zones
sudo firewall-cmd --list-all

# Modify accordingly.

Check interface network errors #

ip -s link show wg-random

336: wg-random: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1300 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/none 
    RX:  bytes packets errors dropped  missed   mcast           
         35760     326      0       0       0       0 
    TX:  bytes packets errors dropped carrier collsns           
        130072    2688    627       0       0       0 

Client-2 can’t reach Client-3 over Server-1 #

Make sure the server is allowed to forward packets and act like a router:

# Check status
sudo sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 0 # DEACTIVATED

# Enable
sudo sysctl -w net.ipv4.ip_forward=1

# Can be added to the Wireguard Config with a slightly different format