2026年11月13日
2026年11月13日
WireGuard Keeps Disconnecting: Causes, Fixes and Monitoring
This article is a localized edition of the Japanese original. Read the Japanese original
When WireGuard "disconnects after a while" or "is connected but traffic stops," the cause is usually one of three things: a NAT or firewall idle timeout, a change in the destination IP address, or an MTU mismatch. First check with wg show whether handshakes are continuing, then adjust PersistentKeepalive, endpoint re-resolution or the MTU to match the symptom. This article explains how to recognize a disconnection, how to check and fix the causes in order of frequency, and how to monitor to prevent recurrence.
Understanding what a WireGuard “disconnection” really is
WireGuard has no "connected" or "disconnected" state like OpenVPN. It performs a key exchange (handshake) when traffic needs to be sent, and refreshes the keys about every 2 minutes while traffic continues. If there is no traffic, it sends nothing.
So what looks like a "disconnection" is actually one of the following.
- Handshakes no longer succeed (packets do not reach the peer, or no reply comes back)
- Handshakes succeed, but some data does not arrive (an MTU or routing problem)
- The interface is not up at all (it did not come up after a reboot)
The fix depends on which one applies, so check the state first.
Check the state first
# State of the interface and peers
sudo wg show
# Time of the last handshake for each peer (UNIX time)
sudo wg show wg0 latest-handshakes
These are the items to look at in the output of wg show.
- latest handshake: The time the last key exchange succeeded. If you are sending traffic and it is still several minutes or more in the past, handshakes are failing. If it is never shown, your packets never reached the peer in the first place
- transfer: The amount sent and received. If only the sent amount grows and the received amount does not, the packets are not reaching the peer or the peer's replies are not coming back
- endpoint: The peer's actual IP address and port. Check that it is not an unexpected address
Also use a packet capture to check whether packets are reaching the server.
# On the server: check whether UDP is arriving on the WireGuard port (use the port number from your configuration)
sudo tcpdump -ni any udp port 51820
If nothing is displayed when you send traffic from the client, something along the way (a firewall, a router, or a cloud security group) is stopping it.
Causes and fixes (most common first)
1. NAT or firewall idle timeout
This is the most common cause. The NAT in a home router or a mobile connection deletes its UDP mapping table entries after a period without traffic. After that, even if the server tries to send, nothing arrives, which gives symptoms such as "it drops if left idle for a while" or "only traffic from the server to the client does not work."
The fix is to add PersistentKeepalive to the peer settings on the side that sits behind the NAT. It sends a small packet every specified number of seconds to keep the NAT mapping alive.
[Peer]
PublicKey = your-server-public-key
Endpoint = vpn.example.com:51820
AllowedIPs = 10.8.0.0/24
PersistentKeepalive = 25
25 seconds is a widely used value that is shorter than the timeout of most NATs. In a setup where neither side is behind NAT (both have fixed public addresses), it is usually not needed.
2. The destination IP address changed
Even if you write a host name in Endpoint, WireGuard resolves the name only when it loads the configuration. If the IP address of a server run with dynamic DNS changes, the client keeps sending to the old address.
Use one of the following.
- Restart the interface to look up the name again (
sudo systemctl restart wg-quick@wg0) - Run a script such as
reresolve-dns.sh, included in the wireguard-tools distribution, on a schedule (where it is bundled differs by package) - Set the new endpoint directly with
wg set
sudo wg set wg0 peer your-server-public-key endpoint vpn.example.com:51820
Note that the side with a fixed address learns the new address from the packets it receives even if the other side's address changes (roaming). The problem arises when you send toward the side whose address changed.
3. The MTU does not match
If "ping works, but a web page, a file transfer or an SSH session stalls partway," suspect the MTU. WireGuard adds a header to the original packet, so if packets larger than the path MTU are dropped, only large data fails to arrive.
wg-quick determines the MTU automatically from the route, but it can be too large on PPPoE connections, multiplexed tunnels or connections over IPv6. Check by changing the size inside the tunnel.
# Prohibit fragmentation and specify the size (1372 + 28 bytes of headers = 1400 bytes)
ping -M do -s 1372 -c 3 10.8.0.1
If you find a size that does not get through, lower the MTU in the interface settings.
[Interface]
MTU = 1380
The right value differs by environment, so decide it as you test. If the server relays the client's traffic to the internet, also consider a firewall setting that adjusts the TCP MSS to the path (MSS clamping).
4. Firewalls and security groups
Check that the WireGuard UDP port is allowed on the server. It must be allowed in both ufw and the cloud security group (or the VPS provider's packet filter). If you do not specify ListenPort, the port may change every time it starts, so specify it explicitly on the server side.
sudo ufw allow 51820/udp
sudo ss -ulnp | grep 51820
5. The interface did not come up after a reboot
If it does not connect after rebooting the server or client, check the autostart setting.
sudo systemctl enable --now wg-quick@wg0
systemctl status wg-quick@wg0
6. Overlapping AllowedIPs or route conflicts
If you write the same AllowedIPs for multiple peers, traffic goes only to the peer configured later, and the other appears to have "dropped." Also, if the tunnel's address range overlaps with the address range of the site you connect to or a café's Wi-Fi, the routes conflict. Check the routes for the tunnel with ip route and choose address ranges that do not overlap.
7. The clock jumped far back
WireGuard uses timestamp information to prevent old handshakes from being reused. On small devices without a clock, if the time is still set in the past after a reboot and the device tries a handshake, the peer may reject it. Start the interface only after the time has been set by NTP, or restart the interface on the peer side, to resolve it.
Monitoring to prevent recurrence
If you regularly check the time since the last handshake, you can notice a problem before users contact you.
#!/bin/sh
# Show peers whose last handshake was more than 300 seconds ago
now=$(date +%s)
wg show wg0 latest-handshakes | while read -r key ts; do
if [ "$ts" -eq 0 ] || [ $((now - ts)) -gt 300 ]; then
echo "stale peer: $key"
fi
done
A peer without PersistentKeepalive does not perform handshakes when there is no traffic, so this check will report it as "stale." Limit the monitoring to peers that have keepalive configured. Before changing configuration files, back up the current /etc/wireguard/, and when working on a remote server, secure a management path that does not go through the VPN (such as a console) before you start. The packages for each OS and the screens of client apps may change with updates, so check the official documentation for details (as of October 2026).
Summary
- WireGuard has no connection state, so judge the state by the handshake time and the sent and received amounts in
wg show - If it drops when left idle, it is the NAT timeout. Add
PersistentKeepalive = 25to the peer on the NAT side - For a server whose IP address changes, run endpoint re-resolution on a schedule
- If only small traffic gets through, it is the MTU. Check with
ping -M doand lower it - Also check the firewall, autostart, overlapping AllowedIPs and the clock in turn, and monitor the time since the last handshake
- How to build a VPN server with WireGuard
- How to build a site-to-site and internal VPN with WireGuard
Questions about WordPress? The publisher of this site is based in Japan and replies in Japanese. Contact (Japanese)