[PR #161] [CLOSED] device: AWG 3.0 - don't count S4-padded keepalives as data (idle re-handshake storm) #174

Closed
opened 2026-10-13 21:04:17 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/amnezia-vpn/amneziawg-go/pull/161
Author: @william-aqn
Created: 7/26/2026
Status: ❌ Closed

Base: master ← Head: fix-s4-keepalive-rehandshake


📝 Commits (1)

  • 77060e0 device: don't count S4-padded keepalives as data (idle re-handshake storm)

📊 Changes

1 file changed (+9 additions, -1 deletions)

View changed files

📝 device/send.go (+9 -1)

📄 Description

AWG 3.0 moved the S4 transport padding into RoutineEncryption, which now seals from elem.buffer[:elem.padding+MessageTransportHeaderSize]. The sealed keepalive therefore measures elem.padding+MessageKeepaliveSize, but RoutineSequentialSender still compared it against the bare MessageKeepaliveSize constant.

With S4 > 0 every keepalive was consequently classified as data, so timersDataSent() armed newHandshake (~15 s + jitter) on a completely idle tunnel. Nothing inbound ever answers a keepalive, so the timer expired into markEndpointSrcForClearing() + SendHandshakeInitiation() and the peer re-handshaked forever.

Measured on an idle tunnel with PersistentKeepalive=5s over 75 s (handshake count read from last_handshake_time_*):

          S4=0   S4=30

v0.2.19 1 1
v3.0.1 1 5 <- storm, ~1 handshake / 15 s
v3.0.1+fix 1 1

Also reproduced with a v3 client against an unmodified v0.2.19 peer, so it breaks existing deployments on upgrade, not just v3-to-v3 ones.

Compare against elem.padding+MessageKeepaliveSize instead. Real data is unaffected: a data packet is padding+16+content+16 with content > 0, so it still exceeds the keepalive size and still arms the data timers.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/amnezia-vpn/amneziawg-go/pull/161 **Author:** [@william-aqn](https://github.com/william-aqn) **Created:** 7/26/2026 **Status:** ❌ Closed **Base:** `master` ← **Head:** `fix-s4-keepalive-rehandshake` --- ### 📝 Commits (1) - [`77060e0`](https://github.com/amnezia-vpn/amneziawg-go/commit/77060e0ff111ca811308e5fb5a9350c1df45d68a) device: don't count S4-padded keepalives as data (idle re-handshake storm) ### 📊 Changes **1 file changed** (+9 additions, -1 deletions) <details> <summary>View changed files</summary> 📝 `device/send.go` (+9 -1) </details> ### 📄 Description AWG 3.0 moved the S4 transport padding into RoutineEncryption, which now seals from elem.buffer[:elem.padding+MessageTransportHeaderSize]. The sealed keepalive therefore measures elem.padding+MessageKeepaliveSize, but RoutineSequentialSender still compared it against the bare MessageKeepaliveSize constant. With S4 > 0 every keepalive was consequently classified as data, so timersDataSent() armed newHandshake (~15 s + jitter) on a completely idle tunnel. Nothing inbound ever answers a keepalive, so the timer expired into markEndpointSrcForClearing() + SendHandshakeInitiation() and the peer re-handshaked forever. Measured on an idle tunnel with PersistentKeepalive=5s over 75 s (handshake count read from last_handshake_time_*): S4=0 S4=30 v0.2.19 1 1 v3.0.1 1 5 <- storm, ~1 handshake / 15 s v3.0.1+fix 1 1 Also reproduced with a v3 client against an unmodified v0.2.19 peer, so it breaks existing deployments on upgrade, not just v3-to-v3 ones. Compare against elem.padding+MessageKeepaliveSize instead. Real data is unaffected: a data packet is padding+16+content+16 with content > 0, so it still exceeds the keepalive size and still arms the data timers. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-13 21:04:17 +00:00
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
amnezia-vpn/amneziawg-go#174
No description provided.