mirror of
https://github.com/amnezia-vpn/amneziawg-go.git
synced 2026-10-14 05:41:54 +00:00
[GH-ISSUE #185] device: handshake message padding ignores ContentPaddingAddition, unlike transport packets #86
Labels
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
amnezia-vpn/amneziawg-go#86
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @kuzzrus on GitHub (Aug 25, 2026).
Original GitHub issue: https://github.com/amnezia-vpn/amneziawg-go/issues/185
Affected upstream source
https://github.com/amnezia-vpn/amneziawg-gov3.1.20260814Summary
In
device/send.go, transport (data) packets and handshake messages use twodifferent padding-precedence rules, and I don't think that's intentional.
For transport packets,
RoutineEncryptionchecksContentPaddingAdditionfirst and only falls back to
RandomTrailerswhen it's unset:https://github.com/amnezia-vpn/amneziawg-go/blob/v3.1.20260814/device/send.go#L611-L620
randomPaddingAdditiononly returns negative whenContentPaddingAdditionitself is unset (
addition.IsZero()), and its own output is explicitlyclamped to
mtu - packetSize:https://github.com/amnezia-vpn/amneziawg-go/blob/v3.1.20260814/device/send.go#L533-L552
So on the transport path, configuring
ContentPaddingAdditionfullysuppresses
RandomTrailers, and whichever one does run is bounded by thetunnel's own MTU.
sendHandshakeInitiation/sendHandshakeResponsedon't follow this rule atall -- they call
peer.randomTrailer()unconditionally, with noContentPaddingAdditioncheck anywhere on that path:https://github.com/amnezia-vpn/amneziawg-go/blob/v3.1.20260814/device/send.go#L148-L150
https://github.com/amnezia-vpn/amneziawg-go/blob/v3.1.20260814/device/send.go#L198-L200
peer.randomTrailer()itself is bounded only bypeer.udpWindow-- aper-peer high-water mark of the largest packet ever sent to that peer, which
never shrinks and has no relationship to MTU at all:
https://github.com/amnezia-vpn/amneziawg-go/blob/v3.1.20260814/device/send.go#L565-L575
So a device with
ContentPaddingAdditionconfigured -- specifically to keeppadding MTU-safe -- still emits MTU-unbounded,
RandomTrailers-sized paddingon every handshake message, and this isn't a one-time startup cost: it
recurs on every rekey (
RekeyAfterTime, itself a configurable AWG 3.1field, commonly well under 3 minutes).
Empirical confirmation
Real handshakes,
ContentPaddingAddition=22-95configured throughout (aproduction value, not synthetic), 15 rounds per condition, measuring the
real wire size of the server's
MessageResponsepacket:Same
ContentPaddingAdditionvalue active in both rows. If the transportpath's precedence applied here too, both rows should be identical.
Why this seems worth fixing
ContentPaddingAddition's own clamp-to-MTU logic shows the field existsspecifically to give operators an MTU-safe padding option. An operator who
deliberately sets it to stay MTU-safe has no way to know their handshake
traffic is still being padded by an entirely different, MTU-unbounded
mechanism -- the
random_trailersUAPI key doesn't mention handshakemessages, and nothing about
ContentPaddingAdditionsuggests it onlyapplies to some packet types.
I don't have a proven end-to-end throughput measurement tying this
specifically to a real-world slowdown -- flagging it as a data point, not a
claim -- but the asymmetry itself seems clear and, I'd guess, unintentional
given how carefully the transport path's precedence is implemented.
Possible fix directions
Not sure which of these matches the intended design, so not proposing a
specific diff:
ContentPaddingAddition-first precedenceRoutineEncryptionalreadyuses, or
randomTrailer()call by MTU thesame way
randomPaddingAdditionalready is, instead of leaving it keyedonly to the unbounded
peer.udpWindowhistory.Happy to share the two Go tests that produced the numbers above if useful,
though they live in a downstream project's test suite rather than this
repo's own.
@HeisLuka commented on GitHub (Sep 14, 2026):
I can prepare a focused fix for this, but I want to confirm the intended AWG 3.1 semantics before choosing the patch shape.
Should handshake messages follow the same precedence as the transport path:
ContentPaddingAddition-> suppressRandomTrailersor should
RandomTrailersstill apply to handshakes, but be bounded by MTU?If the transport-path precedence is intentional, I can submit a small PR that applies the same rule to handshake initiation/response and adds regression tests covering both features enabled together. If trailers are intentionally independent for handshakes, I would instead keep them and only add the MTU bound.
I would prefer not to encode one of those protocol semantics without maintainer confirmation.