mirror of
https://github.com/amnezia-vpn/amneziawg-linux-kernel-module.git
synced 2026-10-14 05:41:56 +00:00
[GH-ISSUE #227] AWG 3.x timer ranges are applied inconsistently: RejectAfterTime is ignored on data paths #131
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-linux-kernel-module#131
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 @2Grey on GitHub (Aug 31, 2026).
Original GitHub issue: https://github.com/amnezia-vpn/amneziawg-linux-kernel-module/issues/227
Summary
The configurable AWG 3.x timing parameters are not applied consistently in the kernel module.
The current code has at least three related problems:
RejectAfterTimeis ignored when validating sending and receiving keypairs. Both paths still use the fixed WireGuard constantREJECT_AFTER_TIME.RekeyAfterTimeinstead ofRejectAfterTime.amneziawg-goexplicitly clamps the equivalent value to zero.These inconsistencies can cause the kernel implementation to expire keys earlier or later than configured and to behave differently from
amneziawg-go.Affected source
amnezia-vpn/amneziawg-linux-kernel-modulev3.1.20260828This report is based on source review. A target-router runtime reproduction has not yet been completed.
Problem 1: data paths ignore RejectAfterTime
The sending path always uses the fixed
REJECT_AFTER_TIMEconstant:https://github.com/amnezia-vpn/amneziawg-linux-kernel-module/blob/v3.1.20260828/src/send.c#L464-L475
The receiving path does the same:
https://github.com/amnezia-vpn/amneziawg-linux-kernel-module/blob/v3.1.20260828/src/receive.c#L331-L346
Neither path reads:
This means, for example:
still causes the data paths to reject a key after the fixed 180-second default.
Conversely:
does not make those checks reject the key after 60 seconds.
This also differs from
amneziawg-go, where both send and receive usekeychainExpireTime():github.com/amnezia-vpn/amneziawg-go@b5928efb6c/device/send.go (L431-L440)github.com/amnezia-vpn/amneziawg-go@b5928efb6c/device/receive.go (L194-L198)The Go helper uses the upper bound of the configured
RejectAfterTimerange:github.com/amnezia-vpn/amneziawg-go@b5928efb6c/device/timers.go (L290-L297)Problem 2: failed-handshake cleanup uses RekeyAfterTime
After the maximum number of handshake attempts is exceeded, the kernel schedules destruction of residual key material.
The timeout is currently selected from
rekey_after_time:https://github.com/amnezia-vpn/amneziawg-linux-kernel-module/blob/v3.1.20260828/src/timers.c#L43-L66
This is inconsistent with
wg_timers_session_derived(), which correctly derives the same zero-key-material timer fromreject_after_time:https://github.com/amnezia-vpn/amneziawg-linux-kernel-module/blob/v3.1.20260828/src/timers.c#L221-L230
For example:
can schedule cleanup after approximately:
instead of a value derived from:
The fallback is also
REJECT_AFTER_TIME, which makes the use ofrekey_after_timein the configured branch look unintended.Problem 3: negative receive refresh timeout is not clamped
The receive-side refresh timeout is calculated as:
https://github.com/amnezia-vpn/amneziawg-linux-kernel-module/blob/v3.1.20260828/src/receive.c#L302-L307
A configuration such as:
produces:
The result is an
int, but it is passed to:https://github.com/amnezia-vpn/amneziawg-linux-kernel-module/blob/v3.1.20260828/src/timers.h#L24-L28
The negative value is therefore converted to
u64, and the subsequent nanosecond multiplication can wrap. This does not represent the intended immediate refresh behavior.The equivalent
amneziawg-goimplementation explicitly clamps the result:github.com/amnezia-vpn/amneziawg-go@b5928efb6c/device/timers.go (L272-L287)Expected behavior
RejectAfterTime.RejectAfterTime, notRekeyAfterTime.wg_birthdate_has_expired().Actual behavior
RekeyAfterTime × 3.amneziawg-gofor the same configuration.Suggested direction
A shared helper could provide the effective keychain expiration time, matching the Go implementation:
It could then be used by:
The exact range semantics should be confirmed by the maintainers. If a random value is intended per session, it should be selected once and stored with the keypair rather than selected independently during packet checks.
For the receive refresh calculation, the result should be clamped before conversion to
u64, for example:Suggested tests
Configure
RejectAfterTimeabove 180 seconds and verify that send and receive keys remain valid beyond 180 seconds.Configure
RejectAfterTimebelow 180 seconds and verify expiration at the configured boundary.Use different
RekeyAfterTimeandRejectAfterTimevalues, force handshake retries to fail, and verify that key cleanup followsRejectAfterTime.Verify that a configuration where:
produces a zero receive-refresh delay rather than unsigned wraparound.
Run the same timing configurations against
amneziawg-goand the kernel module and compare rekey/expiration behavior.