skip to content

Why is an idle WireGuard tunnel completely silent, and what do its passive keepalive and optional persistent keepalive each do?

level: middleimportance: should knowfreq 24%

answer

  1. no data, no packets
  2. reply only when spoken to
  3. ten seconds, empty payload
  4. the paper gives no interval
  5. who must reach whom

basics

~20 s

WireGuard sends nothing without data to carry. The passive keepalive answers received data with an empty authenticated packet after 10 idle seconds; the optional persistent keepalive sends one periodically to hold NAT or firewall state open.

solid answer

~50 s

The WireGuard paper wants an idle tunnel to be silent: no hellos and no dead-peer probes. Liveness comes from the **passive keepalive**. If a peer has received an authenticated transport data message and has had nothing of its own to send for `Keepalive-Timeout` (10 s), it sends a keepalive. That is a transport data message with a zero-length inner packet, still carrying its 16-byte authentication tag. Every data packet therefore earns some reply, and a sender that hears nothing for `Keepalive-Timeout + Rekey-Timeout` (15 s) starts a new handshake. This only works while someone is talking. The **persistent keepalive** is optional and sends an authenticated keepalive on a fixed period, traffic or not. The paper gives no interval; the common 25 seconds comes from implementation documentation. Enable it on the peer behind a NAT only when the far side must start traffic toward it. It costs a steady trickle of packets and the tunnel's silence.

go deeper

for a junior

Remember that an unused WireGuard tunnel sends nothing at all, and that the persistent keepalive is an optional setting, not a protocol default.

for a middle

Explain the passive keepalive's trigger (data received, nothing to send for 10 s), what a keepalive looks like, and the 15-second silence that starts a new handshake.

for a senior

Decide where a persistent keepalive is needed: only on peers behind a translator that the far side must reach first, and say why roaming covers the rest.

for a principal

Weigh silence against reachability across a fleet: keepalives cost battery and stealth on every endpoint, so enable them where a use case needs inbound reach.

## Silence by design The WireGuard paper has two related goals. It stores no state for unauthenticated packets and sends no response to them. And when **neither side has transport data to send, the link is silent**. There is no hello message and no periodic dead-peer probe. Unless a persistent keepalive is configured, a tunnel with nobody using it sends nothing at all. WireGuard still has to notice when a peer has gone away, and the passive keepalive does that job. ## The passive keepalive The paper's rule, step by step: 1. A peer receives a valid, authenticated **transport data message**. 2. If it has **no packet of its own** to send back within `Keepalive-Timeout` (10 seconds), it sends a **keepalive**. 3. A keepalive is an ordinary transport data message whose encrypted inner packet has **zero length**. Its encrypted field is still 16 bytes, the Poly1305 tag, because even an empty payload must be authenticated. 4. The receiver recognises it by that zero length, since any real IP packet is at least as long as an IP header. On the wire, a keepalive is 16 bytes of WireGuard header plus 16 bytes of tag, a **32-byte** UDP payload. With 8 bytes of UDP header and 20 of IPv4, that is a 60-byte packet. The point is that **every data message earns a reply**, either a real packet or a keepalive. A peer that sent data can therefore treat silence as failure. ## Detecting a dead peer | Constant (paper) | Value | Role here | |---|---|---| | `Keepalive-Timeout` | 10 s | wait before answering received data with a keepalive | | `Rekey-Timeout` | 5 s | gap between handshake initiation retries | | `Rekey-Attempt-Time` | 90 s | how long retries continue before giving up | | `Reject-After-Time` | 180 s | maximum age of a usable session | If a peer has sent data and received no transport data for `Keepalive-Timeout + Rekey-Timeout`, which is 10 + 5 = **15 seconds**, it sends a handshake initiation. It repeats every 5 seconds until a session is re-established or 90 seconds have passed. If no new session appears for `Reject-After-Time × 3` (540 s), all session keys are discarded and zeroed. ## The persistent keepalive The passive mechanism only runs while someone is sending. That is a problem when one side is behind a translator or a stateful firewall. Those devices forget an idle UDP mapping after a while, and the other side then has no working address to reach it on. RFC 4787 (REQ-5) says a UDP mapping timer must not expire in under two minutes, except on some well-known ports, and recommends five minutes or more. Comparing how other tunnel protocols handle this is a separate topic. For this case the paper describes an optional **persistent keepalive**. The interface can be configured to send authenticated keepalives periodically, whether or not there is traffic. Two points matter: - **The paper gives no interval.** The widely quoted 25 seconds comes from implementation documentation, not from the protocol. It is also **off unless configured**. - **It belongs on the peer behind the translator.** RFC 4787 requires a mapping to be refreshed by outbound packets and only allows refresh by inbound ones. Keepalives the gateway sends toward a stale address do not help. ## When a remote-access gateway needs it Take 50 engineers' laptops connecting to one office gateway: - **Laptop-initiated traffic needs nothing.** When a laptop sends after a quiet spell, its translator creates a fresh mapping. The gateway authenticates the packet and learns the new outer address as the laptop's endpoint. This roaming also covers a laptop moving from home to a mobile network. - **Gateway-initiated traffic needs it.** If the office must reach an idle laptop, for example to push an update or open a connection to it, the gateway's stored endpoint may point at a mapping that no longer exists. A persistent keepalive on the **laptop** keeps that mapping alive. - **The cost is small but real.** At a 25-second interval, 50 laptops send 50 / 25 = 2 keepalives per second to the gateway, about 120 bytes per second of 60-byte packets. The real costs are a mobile radio that never sleeps and a tunnel that is no longer silent to an observer. ## Common confusions - The passive keepalive is not a timer that fires on idle tunnels. It fires only in reply to received data. - A keepalive is encrypted and authenticated like any data message. It is not a cleartext ping. - Roaming does not depend on keepalives. Any authenticated packet updates the endpoint.

  • Should a WireGuard persistent keepalive be enabled on the office gateway or on the laptop behind a home NAT?
    On the laptop. RFC 4787 requires a translator to refresh a mapping on outbound packets and only allows refresh on inbound ones, so the laptop's own packets are what keep it open. Keepalives from the gateway travel toward an address that may already be gone. The gateway learns the laptop's current endpoint from those authenticated keepalives, so it can reach the laptop when it needs to.
  • How does WireGuard conclude that a peer has gone away, and what does it do next?
    Silence after sending. If a peer sent transport data and received none for `Keepalive-Timeout + Rekey-Timeout` (15 s), it sends a handshake initiation and retries every `Rekey-Timeout` (5 s) for up to `Rekey-Attempt-Time` (90 s). If no new session forms within `Reject-After-Time × 3` (540 s), the paper has all session keys discarded and zeroed.

saying these in an interview costs you the question

  • WireGuard sends a keepalive every 25 seconds by protocol default.
  • An idle WireGuard tunnel exchanges hello packets to stay up.
  • Without a persistent keepalive, a roaming WireGuard laptop cannot reconnect after its address changes.
  • WireGuard's passive keepalive fires on a timer even when neither side has data.
  • A WireGuard keepalive is an unencrypted packet that any observer can read.