mirror of
https://github.com/amnezia-vpn/amneziawg-go.git
synced 2026-10-14 05:41:54 +00:00
[GH-ISSUE #178] device: RandomTrailers panics the process on every cookie reply, and never appends a trailer #85
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#85
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 @AYastrebov on GitHub (Aug 13, 2026).
Original GitHub issue: https://github.com/amnezia-vpn/amneziawg-go/issues/178
Originally assigned to: @ygurov on GitHub.
Affected upstream source
https://github.com/amnezia-vpn/amneziawg-gov3.1.2026081308271d00b330999cde4ec41edd067e7e1b1d9e89masterwas identical to that revision.1f50ad7("feat: awg 3.1 features").Summary
SendHandshakeCookiepasses the trailer length as the slice capacity insteadof adding it to the length:
github.com/amnezia-vpn/amneziawg-go@08271d00b3/device/send.go (L266)The initiation and response paths add it to the length instead:
make([]byte, len, cap)panics whencapis belowlen. So iftrailerLenis under
padding+64, the call panics.RoutineHandshakehas norecover(),and neither does anything else in
device/, so that takes down the process.If
trailerLenispadding+64or more there is no panic, butbufstill haslength
padding+64. That makesbuf[padding+MessageCookieReplySize:]empty,the
rand.Read(trailer)on the next line writes nothing, and the datagramgoes out at its normal size.
Every reachable value of
trailerLenlands in one branch or the other, so onthis path the trailer is never actually sent.
Safe reproduction
No keys, addresses or configuration involved. This is the allocation on its
own, with the same expression and the same inputs the caller supplies.
randomTrailerreturnsfastrandn(DefaultUdpWindow - packetSize), so withDefaultUdpWindow = 500andpacketSize = padding + MessageCookieReplySizethe reachable values of
trailerLenare[0, 500-(padding+64)).Observed on
go1.26.5:The panic is
panic: runtime error: makeslice: cap out of range.Reachability
SendHandshakeCookieruns inRoutineHandshakewhendevice.IsUnderLoad()is true and the initiation's MAC2 does not verify (
device/receive.go:377).That is the ordinary state during a handshake flood, which is what cookies
exist to answer in the first place.
Reaching it needs a valid MAC1, so the sender has to know the responder's
static public key. On a VPN server that is not secret. Nothing else is
required, no handshake has to complete, and the panic ends the process rather
than dropping one peer.
This only affects devices with
RandomTrailersenabled. When it is off,randomTrailerreturns-1andmax(-1, 0)gives atrailerLenof 0, whichpanics as well, so what matters is whether the feature is on rather than which
value gets drawn.
Suggested fix
That lines up with the initiation and response paths and gives
buf[padding+MessageCookieReplySize:]the trailer those two already writeinto.
Notes
Found while implementing AmneziaWG 3.1 in a Rust port that follows this device
as its reference. Happy to open a PR for the one-line change if it helps.
@ygurov commented on GitHub (Aug 13, 2026):
Hi @AYastrebov,
Oh wow, must be the typo. Appreciate for the quick finding!
Let me make a hotfix
@ygurov commented on GitHub (Aug 13, 2026):
Fixed by
github.com/amnezia-vpn/amneziawg-go@1b86b2ae0e, introduced v3.1.20260814