Troubleshooting WireGuard with Tcpdump
When a WireGuard connection isn’t working, it’s usually one of four things: a WireGuard configuration problem, a firewall problem, a routing problem, or a DNS problem. The tcpdump utility can help you quickly diagnose what kind of problem it is, by identifying where packets are going awry.
For example, say we’re trying to set up a point-to-site WireGuard network, like the one shown by the Point-to-Site WireGuard Configuration guide. In this scenario, we’re trying to access Endpoint B through a WireGuard tunnel from Endpoint A to Host β. We can use tcpdump to identify if packets are being dropped or misdirected at the following points (labeled A1-A6 on Endpoint A, and B1-B8 on Host β):
In this scenario, Endpoint A has a WireGuard interface wg0
, with an IP address of 10.0.0.1
, that we want to connect to the wg0
WireGuard interface on Host β, with an IP address of 10.0.0.2
. Endpoint A is connected to the Site A LAN (Local Area Network) through its WiFi interface wlan0
, with an IP address of 192.168.1.11
; and there’s a NAT (Network Address Translation) router with a public IP address of 198.51.100.1
between it and the Internet.
Host β has a WAN (Wide Area Network) interface of eth0
, with a public IP address of 203.0.113.2
, connected to the Internet. It’s connected to the Site B LAN through a second network interface, eth1
, with an IP address of 192.168.200.2
. Endpoint B has an IP address of 192.168.200.22
in the Site B LAN; and it’s running a webserver on TCP port 80
that we want to connect to from Endpoint A.
Running Tcpdump
On Endpoint A, run the following command, using the host’s own WireGuard listen port 51821
, and the IP address of a host you want Endpoint A to be able to contact via WireGuard — in this example, Endpoint B, with an IP address of 192.168.200.22
:
$ sudo tcpdump -niany udp port 51821 or host 192.168.200.22
On Host β, run the following command, this time using Host β’s own WireGuard listen port 51822
, and the same IP address:
$ sudo tcpdump -niany udp port 51822 or host 192.168.200.22
While both tcpdump commands are running, open up another terminal on Endpoint A, and attempt to connect from Endpoint A to Endpoint B, using Endpoint B’s IP address:
$ curl 192.168.200.22
Tip
|
When troubleshooting WireGuard like this, make sure to use always use IP addresses instead of DNS names for any hosts running WireGuard (eg Endpoint A and Host β), and any hosts that you’re trying to access through WireGuard (eg Endpoint B). Using DNS names will only add a confounding factor to your troubleshooting efforts. First test out everything without DNS names; if it all works as expected, but stops working when you try to access a host by its DNS name instead of IP address, you’ve eliminated all other types of problems, so now you know that you “just” have a DNS problem. In that case, see the Troubleshooting WireGuard DNS Issues article for help. |
Tip
|
When troubleshooting WireGuard like this, don’t use ping (unless it is actually in fact the network service you’re trying to troubleshoot) — instead, test using the network service that you actually want to access directly. For example, if you want to access a webserver, use curl (or a web browser); if you want to access a mailserver, use sendmail (or your regular mail client); etc. Like DNS, ping will just add another confounding factor to your troubleshooting efforts: Firewalls between Endpoint A, Host β, and Endpoint B (or the firewalls on those hosts themselves) may block ping packets, but allow through connections to the actual network service you’re trying to access — or vice versa: they may allow ping, but block the network service you actually want to access. |
When everything is working correctly with the WireGuard connection between Endpoint A and Host β, you’d expect to see the following output from tcpdump on Endpoint A (except for the labels in bold, which we’ve added to mark each key point):
$ sudo tcpdump -niany udp port 51821 or host 192.168.200.22 tcpdump: data link type LINUX_SLL2 tcpdump: verbose output suppressed, use -v[v]... for full protocol decode listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes A1. 19:47:20.751416 wg0 Out IP 10.0.0.1.45734 > 192.168.200.22.80: Flags [S], seq 1045811890, win 62167, options [mss 1380,sackOK,TS val 133588375 ecr 0,nop,wscale 6], length 0 A2. 19:47:20.751785 wlan0 Out IP 192.168.1.11.51821 > 203.0.113.2.51822: UDP, length 148 A3. 19:47:20.753212 wlan0 In IP 203.0.113.2.51822 > 192.168.1.11.51821: UDP, length 92 A4. 19:47:20.753591 wlan0 Out IP 192.168.1.11.51821 > 203.0.113.2.51822: UDP, length 96 A5. 19:47:20.754497 wlan0 In IP 203.0.113.2.51822 > 192.168.1.11.51821: UDP, length 96 A6. 19:47:20.754516 wg0 In IP 192.168.200.22.80 > 10.0.0.1.45734: Flags [S.], seq 2143248836, ack 1045811891, win 62643, options [mss 1460,sackOK,TS val 659394353 ecr 133588375,nop,wscale 6], length 0 19:47:20.754534 wg0 Out IP 10.0.0.1.45734 > 192.168.200.22.80: Flags [.], ack 1, win 972, options [nop,nop,TS val 133588379 ecr 659394353], length 0 19:47:20.754549 wlan0 Out IP 192.168.1.11.51821 > 203.0.113.2.51822: UDP, length 96 19:47:20.754587 wg0 Out IP 10.0.0.1.45734 > 192.168.200.22.80: Flags [P.], seq 1:79, ack 1, win 972, options [nop,nop,TS val 133588379 ecr 659394353], length 78: HTTP: GET / HTTP/1.1 19:47:20.754630 wlan0 Out IP 192.168.1.11.51821 > 203.0.113.2.51822: UDP, length 176 19:47:20.755411 wlan0 In IP 203.0.113.2.51822 > 192.168.1.11.51821: UDP, length 96 19:47:20.755420 wg0 In IP 192.168.200.22.80 > 10.0.0.1.45734: Flags [.], ack 79, win 978, options [nop,nop,TS val 659394354 ecr 133588379], length 0 19:47:20.756127 wlan0 In IP 203.0.113.2.51822 > 192.168.1.11.51821: UDP, length 240 19:47:20.756144 wg0 In IP 192.168.200.22.80 > 10.0.0.1.45734: Flags [P.], seq 1:156, ack 79, win 978, options [nop,nop,TS val 659394355 ecr 133588379], length 155: HTTP: HTTP/1.0 200 OK 19:47:20.756152 wg0 Out IP 10.0.0.1.45734 > 192.168.200.22.80: Flags [.], ack 156, win 970, options [nop,nop,TS val 133588380 ecr 659394355], length 0 19:47:20.756160 wlan0 In IP 203.0.113.2.51822 > 192.168.1.11.51821: UDP, length 384 19:47:20.756170 wg0 In IP 192.168.200.22.80 > 10.0.0.1.45734: Flags [FP.], seq 156:453, ack 79, win 978, options [nop,nop,TS val 659394355 ecr 133588379], length 297: HTTP 19:47:20.756179 wlan0 Out IP 192.168.1.11.51821 > 203.0.113.2.51822: UDP, length 96 19:47:20.756252 wg0 Out IP 10.0.0.1.45734 > 192.168.200.22.80: Flags [F.], seq 79, ack 454, win 966, options [nop,nop,TS val 133588380 ecr 659394355], length 0 19:47:20.756278 wlan0 Out IP 192.168.1.11.51821 > 203.0.113.2.51822: UDP, length 96 19:47:20.757068 wlan0 In IP 203.0.113.2.51822 > 192.168.1.11.51821: UDP, length 96 19:47:20.757099 wg0 In IP 192.168.200.22.80 > 10.0.0.1.45734: Flags [.], ack 80, win 978, options [nop,nop,TS val 659394356 ecr 133588380], length 0 19:47:30.984489 wlan0 Out IP 192.168.1.11.51821 > 203.0.113.2.51822: UDP, length 32
And you’d see the following output from tcpdump on Host β:
$ sudo tcpdump -niany udp port 51822 or host 192.168.200.22 tcpdump: data link type LINUX_SLL2 tcpdump: verbose output suppressed, use -v[v]... for full protocol decode listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes B1. 19:47:20.752059 eth0 In IP 198.51.100.1.51821 > 203.0.113.2.51822: UDP, length 148 B2. 19:47:20.752802 eth0 Out IP 203.0.113.2.51822 > 198.51.100.1.51821: UDP, length 92 B3. 19:47:20.753831 eth0 In IP 198.51.100.1.51821 > 203.0.113.2.51822: UDP, length 96 B4. 19:47:20.753857 wg0 In IP 10.0.0.1.45734 > 192.168.200.22.80: Flags [S], seq 1045811890, win 62167, options [mss 1380,sackOK,TS val 133588375 ecr 0,nop,wscale 6], length 0 B5. 19:47:20.753880 eth1 Out IP 192.168.200.2.45734 > 192.168.200.22.80: Flags [S], seq 1045811890, win 62167, options [mss 1380,sackOK,TS val 133588375 ecr 0,nop,wscale 6], length 0 B6. 19:47:20.754071 eth1 In IP 192.168.200.22.80 > 192.168.200.2.45734: Flags [S.], seq 2143248836, ack 1045811891, win 62643, options [mss 1460,sackOK,TS val 659394353 ecr 133588375,nop,wscale 6], length 0 B7. 19:47:20.754079 wg0 Out IP 192.168.200.22.80 > 10.0.0.1.45734: Flags [S.], seq 2143248836, ack 1045811891, win 62643, options [mss 1460,sackOK,TS val 659394353 ecr 133588375,nop,wscale 6], length 0 B8. 19:47:20.754110 eth0 Out IP 203.0.113.2.51822 > 198.51.100.1.51821: UDP, length 96 19:47:20.754786 eth0 In IP 198.51.100.1.51821 > 203.0.113.2.51822: UDP, length 96 19:47:20.754797 wg0 In IP 10.0.0.1.45734 > 192.168.200.22.80: Flags [.], ack 1, win 972, options [nop,nop,TS val 133588379 ecr 659394353], length 0 19:47:20.754806 eth1 Out IP 192.168.200.2.45734 > 192.168.200.22.80: Flags [.], ack 1, win 972, options [nop,nop,TS val 133588379 ecr 659394353], length 0 19:47:20.754863 eth0 In IP 198.51.100.1.51821 > 203.0.113.2.51822: UDP, length 176 19:47:20.754881 wg0 In IP 10.0.0.1.45734 > 192.168.200.22.80: Flags [P.], seq 1:79, ack 1, win 972, options [nop,nop,TS val 133588379 ecr 659394353], length 78: HTTP: GET / HTTP/1.1 19:47:20.754886 eth1 Out IP 192.168.200.2.45734 > 192.168.200.22.80: Flags [P.], seq 1:79, ack 1, win 972, options [nop,nop,TS val 133588379 ecr 659394353], length 78: HTTP: GET / HTTP/1.1 19:47:20.754996 eth1 In IP 192.168.200.22.80 > 192.168.200.2.45734: Flags [.], ack 79, win 978, options [nop,nop,TS val 659394354 ecr 133588379], length 0 19:47:20.754999 wg0 Out IP 192.168.200.22.80 > 10.0.0.1.45734: Flags [.], ack 79, win 978, options [nop,nop,TS val 659394354 ecr 133588379], length 0 19:47:20.755020 eth0 Out IP 203.0.113.2.51822 > 198.51.100.1.51821: UDP, length 96 19:47:20.755719 eth0 In IP 192.168.200.22.80 > 192.168.200.2: Flags [P.], seq 1:156, ack 79, win 978, options [nop,nop,TS val 659394355 ecr 133588379], length 155: HTTP: HTTP/1.0 200 OK 19:47:20.755722 wg0 Out IP 192.168.200.22.80 > 10.0.0.1.45734: Flags [P.], seq 1:156, ack 79, win 978, options [nop,nop,TS val 659394355 ecr 133588379], length 155: HTTP: HTTP/1.0 200 OK 19:47:20.755743 eth0 Out IP 203.0.113.2.51822 > 198.51.100.1.51821: UDP, length 240 19:47:20.755750 eth1 In IP 192.168.200.22.80 > 192.168.200.2.45734: Flags [FP.], seq 156:453, ack 79, win 978, options [nop,nop,TS val 659394355 ecr 133588379], length 297: HTTP 19:47:20.755756 wg0 Out IP 192.168.200.22.80 > 10.0.0.1.45734: Flags [FP.], seq 156:453, ack 79, win 978, options [nop,nop,TS val 659394355 ecr 133588379], length 297: HTTP 19:47:20.755773 eth0 Out IP 203.0.113.2.51822 > 198.51.100.1.51821: UDP, length 384 19:47:20.756453 eth0 In IP 198.51.100.1.51821 > 203.0.113.2.51822: UDP, length 96 19:47:20.756461 wg0 In IP 10.0.0.1.45734 > 192.168.200.22.80: Flags [.], ack 156, win 970, options [nop,nop,TS val 133588380 ecr 659394355], length 0 19:47:20.756465 eth1 Out IP 192.168.200.2.45734 > 192.168.200.22.80: Flags [.], ack 156, win 970, options [nop,nop,TS val 133588380 ecr 659394355], length 0 19:47:20.756519 eth0 In IP 198.51.100.1.51821 > 203.0.113.2.51822: UDP, length 96 19:47:20.756535 wg0 In IP 10.0.0.1.45734 > 192.168.200.22.80: Flags [F.], seq 79, ack 454, win 966, options [nop,nop,TS val 133588380 ecr 659394355], length 0 19:47:20.756539 eth1 Out IP 192.168.200.2.45734 > 192.168.200.22.80: Flags [F.], seq 79, ack 454, win 966, options [nop,nop,TS val 133588380 ecr 659394355], length 0 19:47:20.756656 eth1 In IP 192.168.200.22.80 > 192.168.200.2.45734: Flags [.], ack 80, win 978, options [nop,nop,TS val 659394356 ecr 133588380], length 0 19:47:20.756659 wg0 Out IP 192.168.200.22.80 > 10.0.0.1.45734: Flags [.], ack 80, win 978, options [nop,nop,TS val 659394356 ecr 133588380], length 0 19:47:20.756676 eth0 Out IP 203.0.113.2.51822 > 198.51.100.1.51821: UDP, length 96 19:47:30.984753 eth0 In IP 198.51.100.1.51821 > 203.0.113.2.51822: UDP, length 32
A1. On initiating host, before packet is encrypted
The first entry you should see from tcpdump on Endpoint A is the following:
19:47:20.751416 wg0 Out IP 10.0.0.1.45734 > 192.168.200.22.80: Flags [S], seq 1045811890, win 62167, options [mss 1380,sackOK,TS val 133588375 ecr 0,nop,wscale 6], length 0
This entry indicates that Endpoint A is attempting to initiate a TCP connection from its WireGuard address of 10.0.0.1
to port 80
of Endpoint B’s IP address, 192.168.200.22
, which will go out Endpoint A’s wg0
interface.
Problem signs:
- No tcpdump entry
-
If you see nothing from tcpdump on Endpoint A, you have a routing problem: Endpoint A doesn’t have a usable route for Endpoint B’s IP address of
192.168.200.22
. First run thewg
command on Endpoint A to double-check that its WireGuard interface is up, and that192.168.200.22
is included itsAllowedIPs
address ranges; then try running theip route
andip rule
commands on Endpoint A to debug its routes and policy-routing rules. - Wrong interface name
-
If you see an interface name other than
wg0
in this entry, you have a routing problem: Endpoint A isn’t routing Endpoint B’s IP address of192.168.200.22
to WireGuard. First run thewg
command on Endpoint A to double-check that its WireGuard interface is up, and that192.168.200.22
is included itsAllowedIPs
address ranges; then try running theip route
andip rule
commands on Endpoint A to debug its routes and policy-routing rules.
A2. On initiating host, sending WireGuard handshake
The second entry you should see from tcpdump on Endpoint A is the following:
19:47:20.751785 wlan0 Out IP 192.168.1.11.51821 > 203.0.113.2.51822: UDP, length 148
This entry indicates that Endpoint A is attempting to send a UDP packet from its LAN address of 192.168.1.11
to Host β’s public address of 203.0.113.2
at Host β’s WireGuard listen port of 51822
. The packet will go out Endpoint A’s own WireGuard port of 51821
, using its wireless network interface wlan0
.
This is the WireGuard handshake initiation packet. However, if Endpoint A and Host β have already successfully completed a handshake in the last 2 minutes, you won’t see this entry (or B1 or B2 or A3) — you’ll instead see A4.
Problem signs:
- No tcpdump entry
-
First double-check the A1 entry for problems; if it looks good, but Endpoint A and Host β haven’t yet successfully completed a handshake, and you don’t see this entry, you may have a WireGuard configuration problem: Run the
wg
command on Endpoint A to check that you have anEndpoint
set for Host β (and that it is Host β’s correct public IP address and WireGuard listen port:203.0.113.2:51822
in this example).Otherwise if you don’t see this tcpdump entry, you may have a routing problem: Endpoint A may not have a usable route for Host β’s IP address of
203.0.113.2
. Try running theip route
andip rule
commands on Endpoint A to debug its routes and policy-routing rules. - Wrong destination address or port
-
If you see a destination IP address other than Host β’s public address of
203.0.113.2
, or a destination port other than Host β’s WireGuard listen port of51822
, you have a WireGuard configuration problem: Correct theEndpoint
setting for Host β in Endpoint A’s WireGuard config file, and restart the WireGuard interface.TipOne side of every WireGuard connection must have a publicly-accessible IP address and WireGuard listen port, and the other side must be pre-configured with that address and port as its
Endpoint
setting. In this example, Host β has a publicly-accessible IP address and WireGuard listen port, and Endpoint A does not, so Endpoint A must be pre-configured with Host β’s address and port.If Endpoint A had a publicly-accessible IP address and WireGuard listen port, and Host β did not, Host β would have to be pre-configured with Endpoint A’s address and port — and Host β would also have to be configured with
PersistentKeepalive
setting, to proactively initiate a WireGuard connection with Endpoint A and keep it alive (ensuring that Endpoint A is dynamically set with a usable endpoint for Host β). - Wrong length
-
If this packet’s data length is not exactly
148
bytes, it’s not a WireGuard handshake initiation packet. Most likely, a WireGuard handshake between Endpoint A and Host β has already occurred in last 2 minutes, and this is actually an encrypted WireGuard data packet — the A4 tcpdump entry. - Repeated entries
-
If you see the exact same A2 entry repeated about 20 times in a row, spaced 5 seconds apart, first check the B1 and B2 tcpdump entries on Host β. If they are both present and look good, follow the advice under the “No tcpdump entry” heading for the A3 entry.
B1. On receiving host, receiving WireGuard handshake
The first entry you should see from tcpdump on Host β is the following:
19:47:20.752059 eth0 In IP 198.51.100.1.51821 > 203.0.113.2.51822: UDP, length 148
This entry indicates that Host β has received a UDP packet sent from Endpoint A’s public address of 198.51.100.1
(technically the WAN address of the NAT router in front of Endpoint A) to Host β’s WAN address of 203.0.113.2
and WireGuard listen port of 51822
on Host β’s eth0
interface.
This is the WireGuard handshake initiation packet. If Endpoint A and Host β have already successfully completed a handshake in the last 2 minutes, you won’t see this entry (or A2 or B2 or A3) — instead you’ll see B3.
Problem signs:
- No tcpdump entry
-
First double-check the A2 entry on Endpoint A for problems; if it looks good, but Endpoint A and Host β haven’t yet successfully completed a handshake, and you don’t see this entry, you either have a firewall problem or a routing problem in the networks between Endpoint A and Host β: Try checking any firewalls or routers in front of Host β to which you have access. Make sure any such firewalls allow forwarding new connections at least to Host β’s UDP port
51822
and public IP address of203.0.113.2
from Endpoint A’s public IP address of198.51.100.1
.If it’s not a firewall or routing problem between networks, it could possibly be a routing problem on Host β: Try running the
ip route get 198.51.100.1
command on Host β to ensure that a) it has a route to Endpoint A, and b) this route goes out Host β’s WAN network interface,eth0
. - Wrong length
-
If this packet’s data length is not exactly
148
bytes, it’s not a WireGuard handshake initiation packet. Most likely, a WireGuard handshake between Endpoint A and Host β has already occurred in last 2 minutes, and this is actually an encrypted WireGuard data packet — the B3 tcpdump entry.
B2. On receiving host, sending WireGuard handshake reply
The second entry you should see from tcpdump on Host β is the following:
19:47:20.752802 eth0 Out IP 203.0.113.2.51822 > 198.51.100.1.51821: UDP, length 92
This entry indicates that Host β is attempting to send a UDP packet from its WAN address of 203.0.113.2
and WireGuard listen port of 51822
. This packet will be sent to the exact same source address and port from which B1 was received, regardless of any Endpoint
setting for Endpoint A in Host β’s WireGuard config.
This is the WireGuard handshake response packet. If Endpoint A and Host β have already successfully completed a handshake in the last 2 minutes, you won’t see this entry (or A2 or B1 or A3).
Problem signs:
- No tcpdump entry
-
If Endpoint A and Host β haven’t yet successfully completed a handshake, and you don’t see this entry, you either have a WireGuard configuration problem, or a firewall problem on Host β: First, run the
wg
command on Host β to check that you have a peer configured for Endpoint A.If you have a peer configured on Host β for Endpoint A, also run the
wg
command on Endpoint A to compare the keys shown it its output to that of Host β. Thepublic key
listed for theinterface
in the output on Endpoint A should match thepeer
for Endpoint A listed in the output on Host β; and vice versa. If correctly configured, you should see a match like the following:justin@endpoint-a:~$ sudo wg interface: wg0 public key: /TOE4TKtAqVsePRVR+5AA43HkAK5DSntkOCO7nYq5xU= private key: (hidden) listening port: 51821 peer: fE/wdxzl0klVp/IR8UcaoGUMjqaWi3jAd7KzHKFS6Ds= endpoint: 203.0.113.2:51822 allowed ips: 192.168.200.0/24 transfer: 0 B received, 148 B sent
justin@host-b:~$ sudo wg interface: wg0 public key: fE/wdxzl0klVp/IR8UcaoGUMjqaWi3jAd7KzHKFS6Ds= private key: (hidden) listening port: 51822 peer: /TOE4TKtAqVsePRVR+5AA43HkAK5DSntkOCO7nYq5xU= allowed ips: 10.0.0.1/32
Also, if you’re using a preshared key for this WireGuard connection, check the WireGuard config file on both Endpoint A and Host β to verify that the
PresharedKey
setting for the corresponding peer is identical in both config files.If the WireGuard keys match, try running the
iptables-save
andnft list ruleset
commands on Host β to debug problems with its own host-based firewall. Make sure Host β’s own firewall allows inbound access for new connections to itseth0
interface, at least for its UDP port51822
, from Endpoint A’s public IP address of198.51.100.1
. - Wrong interface name
-
If you see an interface name other than
eth0
in this tcpdump entry (ie a different interface than the B1 entry), you may have a routing problem: Host β isn’t routing Endpoint A’s public IP address of198.51.100.1
out the same interface from which Endpoint A’s packets are coming in. Unless this is an deliberate routing choice you have made, try running theip route
andip rule
commands on Host β to debug its routes and policy-routing rules. - Wrong length
-
If this packet’s data length is not exactly
92
bytes, it’s not a WireGuard handshake response packet. Most likely, a WireGuard handshake between Endpoint A and Host β has already occurred in last 2 minutes, and this is some other packet. If this entry matches the example above perfectly except for the data length, then it is actually an encrypted WireGuard data packet being sent from Host β to Endpoint A — the B8 tcpdump entry.
A3. On initiating host, receiving WireGuard handshake reply
The third entry you should see from tcpdump on Endpoint A is the following:
19:47:20.753212 wlan0 In IP 203.0.113.2.51822 > 192.168.1.11.51821: UDP, length 92
This entry indicates that Endpoint A has received a UDP packet sent from Host β’s address of 203.0.113.2
to its WireGuard listen port of 51821
on its wlan0
interface.
This is the WireGuard handshake response packet. If Endpoint A and Host β have already successfully completed a handshake in the last 2 minutes, you won’t see this entry (or A2 or B1 or B2).
Problem signs:
- No tcpdump entry
-
First double-check the B2 entry on Host β for problems; if it looks good, but Endpoint A and Host β haven’t yet successfully completed a handshake, and you don’t see this entry, you either have a firewall problem or a routing problem in the networks between Host β and Endpoint A: Try checking any firewalls or routers in front of Endpoint A to which you have access. Make sure any such firewalls allow forwarding established connections at least to Endpoint A’s UDP port
51821
and public IP address of198.51.100.1
(or LAN address of192.168.1.11
for the path between Endpoint A and its NAT router) from Host β’s public IP address of203.0.113.2
. - Wrong length
-
If this packet’s data length is not exactly
92
bytes, it’s not a WireGuard handshake response packet. Most likely, a WireGuard handshake between Endpoint A and Host β has already occurred in last 2 minutes, and this is actually an encrypted WireGuard data packet — the A5 tcpdump entry. - Repeated entries
-
If you see the exact same A2 and A3 entries repeated one after the other about 20 times, you have a firewall problem on Endpoint A: Try running the
iptables-save
andnft list ruleset
commands on Endpoint A to debug problems with its own host-based firewall. Make sure Endpoint A’s own firewall allows inbound access for established connections to itswlan0
interface, at least for its UDP port51821
, from Host β’s public IP address of203.0.113.2
.
A4. On initiating host, sending encrypted packet
The fourth entry you should see from tcpdump on Endpoint A is the following:
19:47:20.753591 wlan0 Out IP 192.168.1.11.51821 > 203.0.113.2.51822: UDP, length 96
This entry indicates that Endpoint A is attempting to send its first encrypted WireGuard data packet from its LAN address of 192.168.1.11
to Host β’s public address of 203.0.113.2
at Host β’s WireGuard listen port of 51822
. The packet will go out Endpoint A’s own WireGuard port of 51821
, using its wireless network interface wlan0
.
The data payload of this packet is the original TCP packet from the A1 entry, encrypted and wrapped as a UDP packet. If you see an entry for this packet (and the packet length is not 148
), the WireGuard handshake between Endpoint A and Host β has completed successfully.
Problem signs:
- No tcpdump entry
-
First double-check the B2 entry on Host β for problems; if it looks good, but Endpoint A and Host β haven’t yet successfully completed a handshake, and you don’t see this entry, you have a firewall problem on Endpoint A: Try running the
iptables-save
andnft list ruleset
commands on Endpoint A to debug problems with its own host-based firewall. Make sure Endpoint A’s own firewall allows inbound access for established connections to itswlan0
interface, at least for its UDP port51821
, from Host β’s public IP address of203.0.113.2
. - Wrong length
-
This packet’s data length will vary based on the underlying data it’s encrypting, but if its length is exactly
148
bytes, it’s probably actually a WireGuard handshake attempt, and this is actually another A2 entry. If WireGuard on Endpoint A does not receive a successful handshake response, you will see about 20 A2 entries, spaced 5 seconds apart, as WireGuard tries again and again to initiate a handshake with Host β. If you see these entries interspersed with corresponding A3 entries, you have a firewall problem on Endpoint A (see above). If don’t see any A3 entries, you have a firewall or routing problem between Host β and Endpoint A (see A3).
B3. On receiving host, receiving encrypted packet
The third entry you should see from tcpdump on Host β is the following:
19:47:20.753831 eth0 In IP 198.51.100.1.51821 > 203.0.113.2.51822: UDP, length 96
This entry indicates that Host β has received its first encrypted WireGuard data packet sent from Endpoint A’s public address of 198.51.100.1
to Host β’s WAN address of 203.0.113.2
and WireGuard listen port of 51822
on Host β’s eth0
interface.
The data payload of this packet is the original TCP packet from the A1 entry, encrypted and wrapped as a UDP packet. If you see the A4 entry sent on Endpoint A (and its packet length is not 148
), you should always see this corresponding entry received.
Problem signs:
- Wrong length
-
This packet’s data length will vary based on the underlying data it’s encrypting, but if its length is exactly
148
bytes, it’s probably actually a WireGuard handshake attempt, and this is actually another B1 entry. If WireGuard on Endpoint A does not receive a successful handshake response, you may see about 20 B1 entries, spaced 5 seconds apart, as WireGuard tries again and again to initiate a handshake with Host β. If you see these entries interspersed with corresponding B2 entries, you likely have a firewall or routing problem between Host β and Endpoint A (see A3). If you don’t see any B2 entries, you likely have a firewall or WireGuard configuration problem on Host β (see B1).
B4. On receiving host, after packet is decrypted
The fourth entry you should see from tcpdump on Host β is the following:
19:47:20.753857 wg0 In IP 10.0.0.1.45734 > 192.168.200.22.80: Flags [S], seq 1045811890, win 62167, options [mss 1380,sackOK,TS val 133588375 ecr 0,nop,wscale 6], length 0
This entry should mirror the original A1 entry from Endpoint A, indicating that Host β has received its first data packet through its WireGuard tunnel, and decrypted it successfully. It should show a TCP packet incoming through Host β’s wg0
interface, from Endpoint A’s WireGuard address of 10.0.0.1
, with a destination of Endpoint B’s LAN address of 192.168.200.22
, on port 80
.
Problem signs:
- No tcpdump entry
-
If you see the B3 entry, but not this entry, you have a WireGuard configuration problem: Run the
wg
command on Host β to check that itsAllowedIPs
setting for Endpoint A includes Endpoint A’s WireGuard address of10.0.0.1
.
B5. On receiving host, forwarding packet
The fifth entry you should see from tcpdump on Host β is the following:
19:47:20.753880 eth1 Out IP 192.168.200.2.45734 > 192.168.200.22.80: Flags [S], seq 1045811890, win 62167, options [mss 1380,sackOK,TS val 133588375 ecr 0,nop,wscale 6], length 0
It should show essentially the same packet details as the B4 entry, but this entry should show the packet going out Host β’s LAN network interface eth1
; and if you’re using NAT on Host β to masquerade connections from Endpoint A with Host β’s own LAN address, as we are in this example, the packet’s source IP address should be Host β’s LAN address of 192.168.200.2
(instead of Endpoint A’s WireGuard address of 10.0.0.1
).
Note
|
In a WireGuard Hub-and-Spoke Configuration, where Endpoint A is using Host β as a central hub to forward connections to other endpoints also using WireGuard, this entry should show the packet leaving out its WireGuard interface |
Note
|
In a WireGuard Point-to-Point Configuration, where Endpoint A is simply trying to connect to a network service on Host β itself, instead of using Host β to forward its connections on to other hosts, you won’t see this entry, or B6 — the next entry you see on Host β should be B7. |
Problem signs:
- No tcpdump entry
-
If you see the B4 entry, but not this entry, you either have a firewall problem or a routing problem on Host β. First run the
sysctl net.ipv4.conf.all.forwarding
command on Host β to check that you’re allowing any IPv4 packet forwarding at all (the output should have a value of1
, indicating that forwarding is allowed).If packet forwarding is allowed, try running the
iptables-save
andnft list ruleset
commands on Host β to debug problems with its firewall (the output should show that it allows at minimum the forwarding of new connections to TCP port80
of Endpoint B’s LAN address of192.168.200.22
, using Host β’s LAN interfaceeth1
, from Endpoint A’s WireGuard address of10.0.0.1
, using Host β WireGuard interfacewg0
).TipConsult the “Configure Firewall on Host β” section of the Point-to-Site WireGuard Configuration guide, or the “Point to Site” section of the How to Use WireGuard with Nftables guide, for a detailed explanation of the firewall rules you should be using with this example.
If it’s not a firewall problem, try running the
ip route get 192.168.200.22
command on Host β to ensure that a) it has a route to Endpoint B, and b) this route goes out Host β’s LAN network interface,eth1
. - Wrong source address
-
If you’re expecting to use SNAT (Source Network Address Translation, aka packet masquerading) with this connection, you should see the source address change between the B4 entry and this one (in this example, we’re using SNAT to translate Endpoint A’s WireGuard address of
10.0.0.1
to Host β’s own LAN address of192.168.200.2
). If it’s not being translated to the correct address, you have a firewall problem: Try running theiptables-save
andnft list ruleset
commands on Host β to debug problems with its firewall rules. - Wrong destination address
-
If you’re expecting to use DNAT (Destination Network Address Translation, aka port forwarding) with this connection, you should see the destination address change between the B4 entry and this one (however, in this example, we’re not using DNAT, so we should see no changes). If it’s not being translated to the correct address, you have a firewall problem: Try running the
iptables-save
andnft list ruleset
commands on Host β to debug problems with its firewall rules.
B6. On receiving host, forwarding packet reply
The sixth entry you should see from tcpdump on Host β is the following:
19:47:20.754071 eth1 In IP 192.168.200.22.80 > 192.168.200.2.45734: Flags [S.], seq 2143248836, ack 1045811891, win 62643, options [mss 1460,sackOK,TS val 659394353 ecr 133588375,nop,wscale 6], length 0
This entry should show the reply from Endpoint B, with a new packet coming in Host β’s LAN interface eth1
from Endpoint B’s LAN IP address 192.168.200.22
. If you’re using NAT on Host β to masquerade connections from Endpoint A with Host β’s own LAN address, as we are in this example, the packet’s destination IP address should be Host β’s LAN address of 192.168.200.2
— the packet’s source and destination should be reversed exactly between this entry and B5.
Note
|
In a WireGuard Hub-and-Spoke Configuration, where Endpoint A is using Host β as a central WireGuard hub to forward connections to other WireGuard endpoints, you should see at least two more entries on Host β between B5 and this entry, showing encrypted WireGuard packets being sent between Host β and Endpoint B. For example, if Endpoint B was not in the Site B LAN, and instead was a remote host accessible somewhere on the Internet at
You may also see additional packets sent between Host β and Endpoint B for their own WireGuard handshake, if 2 minutes or more has elapsed since they last exchanged a handshake. However, if you don’t see any additional entries, it may mean the WireGuard connection between Host β and Endpoint B is itself not working — if so, you should stop and debug it separately before continuing on. Also, with a hub-and-spoke configuration, this entry should show the packet coming in |
Note
|
In a WireGuard Point-to-Point Configuration, where Endpoint A is simply trying to connect to a network service on Host β, instead of using Host β to forward its connections on to other hosts, you won’t see this entry, or B5 — the next entry you see on Host β should be B7. |
Problem signs:
- No tcpdump entry
-
First double-check the B5 entry for problems; if it looks good, you either have a firewall problem or a routing problem at the Site B LAN (or in the networks between Host β and Endpoint B, if they are not simply on the same LAN), or on Endpoint B itself.
If you are using NAT on Host β to masquerade connections from Endpoint A with Host β’s own LAN address, as we are in this example, connections from Endpoint A should appear to the Site B LAN as if they were coming from Host β’s own LAN address of
192.168.200.2
. In that case, check that any firewalls between Host β and Endpoint B allow new connections to be forwarded from192.168.200.2
to TCP port80
of Endpoint B’s IP address192.168.200.22
; and on Endpoint B, check that its own host-based firewall allows new incoming connections on its LAN network interface from192.168.200.2
to TCP port80
.If, unlike this example, you’re not using NAT on Host β, connections from Endpoint A will appear to the Site B LAN as if they were coming from Endpoint A’s WireGuard address of
10.0.0.1
. In that case, check that the Site B LAN is configured to route10.0.0.1
back to Host β’s LAN address of192.168.200.2
, and that any firewalls between Host β and Endpoint B allow new connections to be forwarded from10.0.0.1
to TCP port80
of Endpoint B’s IP address192.168.200.22
; and on Endpoint B, check that its own host-based firewall allows new incoming connections on its LAN network interface from10.0.0.1
to TCP port80
.
B7. On receiving host, before packet reply is encrypted
The seventh entry you should see from tcpdump on Host β is the following:
19:47:20.754079 wg0 Out IP 192.168.200.22.80 > 10.0.0.1.45734: Flags [S.], seq 2143248836, ack 1045811891, win 62643, options [mss 1460,sackOK,TS val 659394353 ecr 133588375,nop,wscale 6], length 0
It should show essentially the same packet details as the B6 entry, but this entry should show the packet going out Host β’s WireGuard network interface wg0
; and if you’re using NAT on Host β to masquerade connections from Endpoint A with Host β’s own LAN address, as we are in this example, the packet’s destination IP address will be changed back to Endpoint A’s WireGuard address of 10.0.0.1
(if you’re not using NAT, then the destination address would have been 10.0.0.1
in the B6 entry, as well).
Note
|
In a WireGuard Point-to-Point Configuration, where Endpoint A is simply trying to connect to a network service on Host β itself, instead of using Host β to forward its connections on to other hosts, you should see this entry directly after B4. If you don’t, you have a firewall problem on Host β: Try running the |
Problem signs:
- No tcpdump entry
-
If you see the B6 entry, but not this entry, you have a firewall problem on Host β. Try running the
iptables-save
andnft list ruleset
commands on Host β to debug problems with its firewall (the output should show that it allows at minimum the forwarding of established connections to Endpoint A’s WireGuard address of10.0.0.1
, using Host β’s WireGuard interfacewg0
, from Endpoint B’s LAN address of192.168.200.22
, using Host β’s LAN interfaceeth1
). - Wrong interface name
-
If you see an interface name other than
wg0
in this entry, you have a routing problem: Host β isn’t routing Endpoint A’s WireGuard address of10.0.0.1
to WireGuard. Try running theip route
andip rule
commands on Host β to debug its routes and policy-routing rules.
B8. On receiving host, sending encrypted packet reply
The eighth entry you should see from tcpdump on Host β is the following:
19:47:20.754110 eth0 Out IP 203.0.113.2.51822 > 198.51.100.1.51821: UDP, length 96
This entry shows Host β sending an encrypted WireGuard data packet out its WAN network interface eth0
from its public IP address 203.0.113.2
back to Endpoint A’s public IP address 198.51.100.1
. The data payload of this packet is the TCP packet from the B7 entry, encrypted and wrapped as a UDP packet.
If this entry doesn’t match what you’re seeing, go back and double-check previous entries — there should be a tell-tale sign of the problem in an earlier entry.
A5. On initiating host, receiving encrypted packet reply
The fifth entry you should see from tcpdump on Endpoint A is the following:
19:47:20.754497 wlan0 In IP 203.0.113.2.51822 > 192.168.1.11.51821: UDP, length 96
This entry shows Endpoint A has received an encrypted WireGuard data packet on UDP port 51821
of its wlan0
interface from Host β’s public IP address 203.0.113.2
. The data payload of this packet is the TCP packet from the B7 entry, encrypted and wrapped as a UDP packet.
Problem signs:
- Wrong length
-
This packet’s data length will vary based on the underlying data it’s encrypting, but if its length is exactly
92
bytes, it’s probably actually a WireGuard handshake response, and this is actually another A3 entry. If you see multiple handshake-initiation A2 entries interspersed with multiple handshake-response A3 entries, you have a firewall problem on Endpoint A: Try running theiptables-save
andnft list ruleset
commands on Endpoint A to debug problems with its own host-based firewall. Make sure Endpoint A’s own firewall allows inbound access for established connections to itswlan0
interface, at least for its UDP port51821
, from Host β’s public IP address of203.0.113.2
.
A6. On initiating host, after packet is decrypted
The sixth entry you should see from tcpdump on Endpoint A is the following:
19:47:20.754516 wg0 In IP 192.168.200.22.80 > 10.0.0.1.45734: Flags [S.], seq 2143248836, ack 1045811891, win 62643, options [mss 1460,sackOK,TS val 659394353 ecr 133588375,nop,wscale 6], length 0
This entry should mirror the B7 entry from Host β, indicating that Endpoint A has received its first data packet response through its WireGuard tunnel, and has decrypted it successfully. The entry should show a TCP packet incoming through Endpoint A’s wg0
interface, from port 80
of Endpoint B’s LAN address of 192.168.200.22
, with a destination of Endpoint A’s WireGuard address of 10.0.0.1
.
Problem signs:
- Repeated entries
-
If you see the same exact A5 and A6 entries repeated several times (and no other entries besides keepalive entries), you have a firewall problem on Endpoint A: Try running the
iptables-save
andnft list ruleset
commands on Endpoint A to debug problems with its firewall (the output should show that it allows at minimum established connections incoming to Endpoint A’s WireGuard interfacewg0
from Endpoint B’s LAN address of192.168.200.22
). - Application receives nothing
-
If this tcpdump entry looks good, but the underlying application (eg curl) does not report receiving anything, you have a firewall problem on Endpoint A: Try running the
iptables-save
andnft list ruleset
commands on Endpoint A to debug problems with its firewall (the output should show that it allows at minimum established connections incoming to Endpoint A’s WireGuard interfacewg0
from Endpoint B’s LAN address of192.168.200.22
).
Keepalive packets
The rest of the entries in the example tcpdump output either show additional UDP WireGuard data packets being sent back and forth between Endpoint A and Host β, or show the underlying TCP packets that are being tunneled through WireGuard. You’ll see lots of this traffic once your WireGuard connection is up and working.
The lone exceptions to this are the last entries shown for Endpoint A and Host β: they are small “keepalive” packets that you may see when the WireGuard connection is otherwise inactive.
In the Endpoint A tcpdump output, the last entry is the following:
19:47:30.984489 wlan0 Out IP 192.168.1.11.51821 > 203.0.113.2.51822: UDP, length 32
And in the Host β tcpdump output, the last entry is the following:
19:47:30.984753 eth0 In IP 198.51.100.1.51821 > 203.0.113.2.51822: UDP, length 32
These packets are recognizable because they’re UDP packets of length 32
, sent between the two WireGuard listen ports of 51821
and 51822
.
You’ll see these packets only if the WireGuard handshake has previously been completed successfully. WireGuard will send a keepalive automatically a few seconds after any burst of traffic from one side or the other, to try to keep the connection open through stateful firewalls in case the other side still has some packets left it wants to send.
Also, if you configure the PersistentKeepalive
setting for a peer, WireGuard will repeatedly send a keepalive packet from the configured side of the connection every X seconds after the last data (or keepalive) packet was previously sent (where X is the value of the PersistentKeepalive
setting) — keeping the connection open indefinitely.