Skip to content

/config/wireguard/persistentkeepalive

WireGuard PersistentKeepalive = 25: keep a tunnel open behind NAT

The commands on this page have not been executed by our verification runner yet.updated
tool
WireGuard
file
/etc/wireguard/wg0.conf
key
[Peer] PersistentKeepalive
type
integer seconds (1-65535) or off
default
off (0): no keepalive packets

PersistentKeepalive = 25 in a [Peer] section makes WireGuard send an empty authenticated packet to that peer every 25 seconds, so a NAT router or stateful firewall between them keeps the connection mapping alive. WireGuard is otherwise silent when no data flows, and NAT mappings usually expire after 30 seconds to a few minutes; after that, the peer outside the NAT can no longer reach the peer inside it. Set it on the side that is behind NAT (typically the client), for the peer that must be able to reach it. 25 is the value the WireGuard documentation suggests.

Configuration

ini
# Client behind NAT: /etc/wireguard/wg0.conf
[Interface]
PrivateKey = <client private key>
Address = 10.0.0.2/24

[Peer]
PublicKey = <server public key>
Endpoint = vpn.example.com:51820
AllowedIPs = 10.0.0.0/24
PersistentKeepalive = 25

Apply it to a running interface without restarting:

bash
sudo wg set wg0 peer '<server public key>' persistent-keepalive 25
sudo wg show wg0 | grep -E 'peer|keepalive|handshake'

wg show lists persistent keepalive: every 25 seconds for the peer and the time of the latest handshake.

When to set it

SituationPersistentKeepalive
Client behind home or mobile NAT, server must push traffic or reach the client25 on the client
Client only initiates connections (browsing through the VPN)Often not needed: outgoing packets refresh the mapping
Server with a public IP and no NATNot needed on the server
Site-to-site where both ends are behind NATSet on both; at least one side needs a reachable Endpoint
Battery-sensitive mobile device that rarely needs incoming trafficLeave off to save power

Symptoms it fixes

  • The tunnel works for a while, then the server cannot ping the client until the client sends something.
  • latest handshake in wg show is minutes old on a connection that should be up.
  • Services hosted on the client (SSH, a home server) are unreachable through the VPN after idle periods.

Keepalives do not fix a wrong Endpoint, blocked UDP port or mismatched keys: if there is never a handshake, check those first.

Sources