fix(amneziawg): H1-H4 generator + queue-depth throughput fixes (#6330)

* fix(amneziawg): stop H1-H4 generator misclassifying transport packets

Both the Go generator and its frontend mirror picked a random *range*
per H1-H4 field with only a minimum width enforced (no maximum).
amneziawg-go's packet classifier only ever compares a fixed-size
ciphertext prefix against these bounds, so a wide range buys no DPI
resistance -- the boundaries themselves are never observable on the
wire. It does cost real throughput: with randomTrailers on (the
default here), the handshake-size checks relax from == to >, so a
wide H-range misclassifies a proportional fraction of ordinary
transport packets as handshakes and silently drops them
(amnezia-vpn/amneziawg-go#183). A single value per field is strictly
safer than any range, with no obfuscation trade-off.

Live-tested: narrowing H1-H4 alone took AmneziaWG upload from
2-3 Mbit/s to 200+ Mbit/s on one box, and ~20 Mbit/s to 120-156 Mbit/s
on another, single-variable, no other change.

* fix(amneziawgnet): raise tunQueueDepth to absorb slow-start bursts

1024 was sized for a single-connection buffering problem (the
gVisor-to-amneziawg-go TUN handoff channel needing slack for the
download direction). tcpip.Stack.Stats() during a real many-connection
download (20-28 concurrent TCP flows, e.g. a segmented speed test)
showed SlowStartRetransmits jump by ~770 in a single second the moment
CurrentEstablished crossed ~20 -- consistent with many connections'
simultaneous slow-start growth briefly exceeding 1024 outstanding
packets and gVisor treating the resulting silent drops as real network
loss.

* fix(amneziawg): trim comment blocks to the repo's 2-line cap

Review feedback: four comment blocks in the previous commits exceeded
CLAUDE.md's 2-line-per-block hard rule (up to 13 lines). Trimmed each to
the one non-obvious fact plus the amneziawg-go#183 reference; the fuller
rationale already lives in the commit message. Also refreshed the stale
H1-H4 range example in docs/content/docs/en/config/amneziawg.mdx to match
the new single-value generator output.
This commit is contained in:
kuzzrus
2026-09-03 22:50:23 +03:00
committed by GitHub
parent 0ff3c23948
commit bd1c27b03d
6 changed files with 40 additions and 42 deletions
@@ -51,21 +51,17 @@ const generateHeaderProtectionKey = (): string => {
};
/*
* Four non-overlapping "low-high" ranges for H1-H4: split the space into
* four bands and take a random sub-range from each (>= 1000 wide, low
* bound >= 5 since 1-4 are reserved for vanilla WireGuard message types).
* Four distinct values for H1-H4, one per band; low bound >= 5 (1-4 are vanilla WG message types).
* Single values, not ranges: with randomTrailers on, a wide range misclassifies transport packets as handshakes (amnezia-vpn/amneziawg-go#183).
*/
const generateHRanges = (): [string, string, string, string] => {
const generateHValues = (): [string, string, string, string] => {
const hMax = 2147483647;
const hMinWidth = 1000;
const lo = 5;
const bandSize = Math.floor((hMax - lo + 1) / 4);
return Array.from({ length: 4 }, (_, i) => {
const bandLo = lo + i * bandSize;
const bandHi = bandLo + bandSize - 1;
const start = randInt(bandLo, bandHi - hMinWidth - 1);
const end = randInt(start + hMinWidth, bandHi - 1);
return `${start}-${end}`;
return `${randInt(bandLo, bandHi)}`;
}) as [string, string, string, string];
};
@@ -76,7 +72,7 @@ export function generateAwgObfuscation(): AwgObfuscation {
while (s1 + 56 === s2) {
s2 = randInt(15, 150);
}
const [h1, h2, h3, h4] = generateHRanges();
const [h1, h2, h3, h4] = generateHValues();
/*
* Timing windows bracket WireGuard's stock constants (rekey 120s, reject