[GH-ISSUE #2582] AmneziaVPN-Android 4.8.15.5 still drops S3/S4 — followup to #2219 #1173

Closed
opened 2026-10-13 20:35:43 +00:00 by bsakaguchi · 7 comments
Owner

Originally created by @remotetohome on GitHub (May 7, 2026).
Original GitHub issue: https://github.com/amnezia-vpn/amnezia-client/issues/2582

Filing as a new issue because I (original reporter of #2219) don't have permission to reopen the closed thread. Original analysis and discussion: #2219.

Per the comments in #2219, this was reportedly fixed in 4.8.12.9 (Feb 2026). I'm confirming today (2026-05-08) that the bug still reproduces on the latest published Android build (4.8.15.5, build b4c03ed from 4 days ago). Single-variable A/B test isolates the failure to client-side handling of non-zero S3/S4.

Bug still present in 4.8.15.5 (3 months / 5 versions after claimed fix)

The bug is reproducible today on the latest published Android build.

Build provenance

  • AmneziaVPN Android: 4.8.15.5 (UI version string)
  • Build hash: b4c03ed = b4c03ede8c8c3686155fdd6bb4e431139e612f57
  • Build date: 2026-05-04 (4 days ago at posting)
  • Build commit message: "chore: bump qt version fo android"
  • awg-go version embedded (per phone runtime log): v0.2.16
  • AmneziaVPN release with claimed fix (per @vkamn comment 2026-02-17): 4.8.12.9
  • Versions tagged between claimed fix and current confirmed-still-broken (per amnezia-client git tags): 4.8.14.1 → 4.8.14.5 → 4.8.15.0 → 4.8.15.4 → 4.8.15.5 — 5 minor releases over ~3 months

Reproducer (single-variable A/B test, 2026-05-08)

Environment with network-path variables held constant — both test devices on the same home WiFi behind the same residential NAT, connecting to the same AmneziaWG server (different ISP, public-IP'd at the server end) with identical [Interface] parameters (only peer keys/tunnel-IP differ between profiles):

  • Server: GL.iNet AXT1800 running amneziawg-linux-kernel-module v1.0.20260329-2. AmneziaWG 2.0 profile: S1=47, S2=45, S3=38, S4=22, randomized non-overlapping H1–H4 in [256, 4.29B], standard Jc/Jmin/Jmax randomization, full I1–I5 CPS junk including STUN-shaped I1.
  • Phone: OnePlus CPH2513, Android 14, AmneziaVPN 4.8.15.5 / awg-go v0.2.16 (per runtime log line Wireguard: awg-go backend v0.2.16).
  • Control device: Linux laptop with same [Interface] parameters.

Test 1 — full S3/S4 (S3=38, S4=22 server-side):

  • Phone: handshake completes (CONNECTED state reached); 0 web traffic observed; pages spin indefinitely. Server-side awg show for the phone peer: 740 B received, 31.13 KiB sent (asymmetric — phone barely transmits, server retries). Phone log: peer(...) - Retrying handshake because we stopped hearing back after 15 seconds repeating.
  • Laptop: 259/219 Mbps speedtest, browses normally, DNS resolves through tunnel.

Test 2 — mobile-compat (S3=0, S4=0 server-side, single-variable change):

  • Phone: 25/25 Mbps speedtest, browses normally, DNS resolves through tunnel.
  • All other parameters (S1, S2, H1–H4, Jc/Jmin/Jmax, I1–I5) identical to Test 1.

The single-variable change of S3 and S4 between tests, with the same physical network path proven working for the laptop in Test 1, isolates the failure to client-side handling of non-zero S3/S4 in awg-go v0.2.16 / AmneziaVPN-Android 4.8.15.5.

  • amneziawg-go#110 — arm64: outbound H4 header corrupted in transport packets (still open). Reports corrupted H4 bytes in outbound transport on arm64 with CGO disabled. AmneziaVPN-Android runs awg-go on Android arm64 (this phone's ABI: arm64-v8a per runtime log). The on-the-wire symptom — transport-packet handling failing when S3/S4 introduce a byte-offset shift — is the same shape as #110's report. When S3/S4 are non-zero, the H4 field's byte offset in the transport packet shifts by S4 bytes; if there's an alignment/offset bug in the H4 writer, setting S3=S4=0 would hide it because no offset shift occurs.
  • amneziawg-go#89 — Transport packet lined up with another msg type (still open). Same code path that emits the Received message with unknown type symptom referenced in the original #2219 report.

Request

Please re-investigate. The on-the-wire effect — Android clients cannot pass transport data when the server uses non-zero S3/S4 — has not changed since the original report in #2219. Happy to provide additional captures (server-side WAN tcpdump, awg-show counter snapshots, full phone-side awg-go logs) on request.

Originally created by @remotetohome on GitHub (May 7, 2026). Original GitHub issue: https://github.com/amnezia-vpn/amnezia-client/issues/2582 > Filing as a new issue because I (original reporter of #2219) don't have permission to reopen the closed thread. Original analysis and discussion: #2219. > > Per the comments in #2219, this was reportedly fixed in **4.8.12.9** (Feb 2026). I'm confirming today (2026-05-08) that the bug **still reproduces** on the latest published Android build (4.8.15.5, build `b4c03ed` from 4 days ago). Single-variable A/B test isolates the failure to client-side handling of non-zero S3/S4. ## Bug still present in 4.8.15.5 (3 months / 5 versions after claimed fix) The bug is reproducible **today** on the latest published Android build. ### Build provenance - AmneziaVPN Android: **4.8.15.5** (UI version string) - Build hash: **`b4c03ed`** = `b4c03ede8c8c3686155fdd6bb4e431139e612f57` - Build date: **2026-05-04** (4 days ago at posting) - Build commit message: "chore: bump qt version fo android" - awg-go version embedded (per phone runtime log): **v0.2.16** - AmneziaVPN release with claimed fix (per [@vkamn comment 2026-02-17](https://github.com/amnezia-vpn/amnezia-client/issues/2219#issuecomment-3911651196)): **4.8.12.9** - Versions tagged between claimed fix and current confirmed-still-broken (per `amnezia-client` git tags): 4.8.14.1 → 4.8.14.5 → 4.8.15.0 → 4.8.15.4 → 4.8.15.5 — **5 minor releases over ~3 months** ### Reproducer (single-variable A/B test, 2026-05-08) Environment with network-path variables held constant — both test devices on the **same home WiFi behind the same residential NAT**, connecting to the same AmneziaWG server (different ISP, public-IP'd at the server end) with identical `[Interface]` parameters (only peer keys/tunnel-IP differ between profiles): - **Server**: GL.iNet AXT1800 running `amneziawg-linux-kernel-module v1.0.20260329-2`. AmneziaWG 2.0 profile: S1=47, S2=45, **S3=38, S4=22**, randomized non-overlapping H1–H4 in `[256, 4.29B]`, standard Jc/Jmin/Jmax randomization, full I1–I5 CPS junk including STUN-shaped I1. - **Phone**: OnePlus CPH2513, Android 14, AmneziaVPN **4.8.15.5** / awg-go **v0.2.16** (per runtime log line `Wireguard: awg-go backend v0.2.16`). - **Control device**: Linux laptop with same `[Interface]` parameters. **Test 1 — full S3/S4 (S3=38, S4=22 server-side):** - Phone: handshake completes (CONNECTED state reached); **0 web traffic** observed; pages spin indefinitely. Server-side `awg show` for the phone peer: `740 B received, 31.13 KiB sent` (asymmetric — phone barely transmits, server retries). Phone log: `peer(...) - Retrying handshake because we stopped hearing back after 15 seconds` repeating. - Laptop: 259/219 Mbps speedtest, browses normally, DNS resolves through tunnel. **Test 2 — mobile-compat (S3=0, S4=0 server-side, single-variable change):** - Phone: 25/25 Mbps speedtest, browses normally, DNS resolves through tunnel. - All other parameters (S1, S2, H1–H4, Jc/Jmin/Jmax, I1–I5) **identical** to Test 1. The single-variable change of S3 and S4 between tests, with the same physical network path proven working for the laptop in Test 1, isolates the failure to client-side handling of non-zero S3/S4 in awg-go v0.2.16 / AmneziaVPN-Android 4.8.15.5. ### Likely related (root-cause sibling?) - **[amneziawg-go#110](https://github.com/amnezia-vpn/amneziawg-go/issues/110)** — *arm64: outbound H4 header corrupted in transport packets* (still open). Reports corrupted H4 bytes in outbound transport on arm64 with CGO disabled. AmneziaVPN-Android runs awg-go on Android arm64 (this phone's `ABI: arm64-v8a` per runtime log). The on-the-wire symptom — transport-packet handling failing when S3/S4 introduce a byte-offset shift — is the same shape as #110's report. When S3/S4 are non-zero, the H4 field's byte offset in the transport packet shifts by S4 bytes; if there's an alignment/offset bug in the H4 writer, setting S3=S4=0 would hide it because no offset shift occurs. - **[amneziawg-go#89](https://github.com/amnezia-vpn/amneziawg-go/issues/89)** — *Transport packet lined up with another msg type* (still open). Same code path that emits the `Received message with unknown type` symptom referenced in the original #2219 report. ### Request Please re-investigate. The on-the-wire effect — Android clients cannot pass transport data when the server uses non-zero S3/S4 — has not changed since the original report in #2219. Happy to provide additional captures (server-side WAN tcpdump, awg-show counter snapshots, full phone-side awg-go logs) on request.
Author
Owner

@ygurov commented on GitHub (May 11, 2026):

Hi @remotetohome
Let's try to collect facts more precisely

That's the setup we have:

  1. Endpoint running awg-kmod v1.0.20260329-2, with all S1-S4 being set
  2. Mobile device running amnezia-client v4.8.15.5 under Android
  3. Laptop running (supposedly) amnezia-client v4.8.15.5 under Linux

What happens:

  • Mobile device attempts to connect to the endpoint with S1-S4 fully-configured and fails. Zeroing S3&S4 resolves the situation.
  • Linux laptop meanwhile is able to connect with S3+S4 configured.

Since AWG does not have any compatibility settings and options as is, there is the only one format acceptable for each packet type. So I assume one of the things described above could only happen in reason of misconfiguration (it could happen in some piece of software though). One of the following is true:

  • Both laptop and the endpoint are misconfigured with S3/S4 fields
  • Mobile device has misconfigured S3/S4 (or set explicitly from somewhere else)

So, I think we would like to dig a little bit deeper in the config files/keys used in AWG from each side. Do you mind providing us configuration files of each item?

Please do not include any keys in the files

<!-- gh-comment-id:4426125475 --> @ygurov commented on GitHub (May 11, 2026): Hi @remotetohome Let's try to collect facts more precisely That's the setup we have: 1. Endpoint running awg-kmod v1.0.20260329-2, with all S1-S4 being set 2. Mobile device running amnezia-client v4.8.15.5 under Android 3. Laptop running (supposedly) amnezia-client v4.8.15.5 under Linux What happens: - Mobile device attempts to connect to the endpoint with S1-S4 fully-configured and fails. Zeroing S3&S4 resolves the situation. - Linux laptop meanwhile is able to connect with S3+S4 configured. Since AWG does not have any compatibility settings and options as is, there is the only one format acceptable for each packet type. So I assume one of the things described above could only happen in reason of misconfiguration (it could happen in some piece of software though). One of the following is true: - Both laptop and the endpoint are misconfigured with S3/S4 fields - Mobile device has misconfigured S3/S4 (or set explicitly from somewhere else) So, I think we would like to dig a little bit deeper in the config files/keys used in AWG from each side. Do you mind providing us configuration files of each item? Please do not include any keys in the files
Author
Owner

@remotetohome commented on GitHub (May 12, 2026):

EDITs for further clarity.

@ygurov - Thank you for the response. To clarify:

  1. Endpoint running awg-kmod v1.0.20260329-2, with all S1-S4 being set
  2. Mobile device running amnezia-client v4.8.15.5 under Android
  3. Laptop not running amnezia-client. Laptop is running awg-quick via CLI with amneziawg.ko kernel module.

To further elaborate across all devices:

These VPN client platforms are able to connect with proper s3/4 params:

  1. Laptop running awg-quick with amneziawg.ko kernel module (kernel C implementation)
  2. GL router amneziawg-tools with amneziawg.ko kernel module (custom compiled from latest source kernel C)

These VPN client platforms are NOT able to connect unless s3/4 params have been set to 0.

  1. AmneziaVPN-Android v4.8.15.5 with awg-go v0.2.16
  2. AmneziaVPN-Desktop on Linux with awg-go

The awg-go clients consistently fail with any non-zero s3/4 param, even though the exact same profiles work fine with amneziawg.ko (C implementation).

I am happy to provide sanitized config files (keys redacted), but I believe the above highlights this is not the concern. I have done dozens of AWG2 deployments for my customers and the results are consistently repeatable. For all of these setups I've had to revert to zero'd s3/4 implementations for them to also have compatibility with their mobile device clients.

To further elaborate, in each of these deployments I started with specific protocol decoy profiles that include s3/4 params generated within the range of:

  • S3 = random integer in [16, 48]
  • S4 = random integer in [8, 24]

These profiles were tested across client devices, and only failed on the awg-go based clients. Reverting just the s3/4 values to zero (no other changes) for the server and all peer configs causes the awg-go clients to now also successfully connect.

<!-- gh-comment-id:4426333444 --> @remotetohome commented on GitHub (May 12, 2026): EDITs for further clarity. @ygurov - Thank you for the response. To clarify: 1. Endpoint running awg-kmod v1.0.20260329-2, with all S1-S4 being set 2. Mobile device running amnezia-client v4.8.15.5 under Android 3. Laptop *not* running amnezia-client. Laptop is running awg-quick via CLI with amneziawg.ko kernel module. To further elaborate across all devices: These VPN client platforms are able to connect with proper s3/4 params: 1. Laptop running awg-quick with amneziawg.ko kernel module (kernel C implementation) 2. GL router amneziawg-tools with amneziawg.ko kernel module (custom compiled from latest source kernel C) These VPN client platforms are NOT able to connect unless s3/4 params have been set to 0. 1. AmneziaVPN-Android v4.8.15.5 with awg-go v0.2.16 2. AmneziaVPN-Desktop on Linux with awg-go The awg-go clients consistently fail with any non-zero s3/4 param, even though the exact same profiles work fine with amneziawg.ko (C implementation). I am happy to provide sanitized config files (keys redacted), but I believe the above highlights this is not the concern. I have done dozens of AWG2 deployments for my customers and the results are consistently repeatable. For all of these setups I've had to revert to zero'd s3/4 implementations for them to also have compatibility with their mobile device clients. To further elaborate, in each of these deployments I started with specific protocol decoy profiles that include s3/4 params generated within the range of: - S3 = random integer in [16, 48] - S4 = random integer in [8, 24] These profiles were tested across client devices, and only failed on the awg-go based clients. Reverting *just* the s3/4 values to zero (no other changes) for the server and all peer configs causes the awg-go clients to now also successfully connect.
Author
Owner

@ygurov commented on GitHub (May 12, 2026):

So you state here that awg-go <-> awg-kmod does not work with S3 and S4 properly, but awg-kmod <-> awg-kmod does
Hmm, let me check it

<!-- gh-comment-id:4428686618 --> @ygurov commented on GitHub (May 12, 2026): So you state here that awg-go <-> awg-kmod does not work with S3 and S4 properly, but awg-kmod <-> awg-kmod does Hmm, let me check it
Author
Owner

@ygurov commented on GitHub (May 12, 2026):

Just tested it out with the following setup:

  • EP under awg-kmod. Config:
[Interface]
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o <iface> -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o <iface> -j MASQUERADE
Address = 10.0.0.0/24
ListenPort = <port>
PrivateKey = MKkmOiwkjeSiZ2eqKa7C+UcCBi2BQ9pGkgxpo4Yp1kw=
S3 = 20
S4 = 11

[Peer]
AllowedIPs = 10.0.0.1/32
PublicKey = 7Iz1JPdQbwY+/AEwVGEOYXl7366pLwuI4UZDhi1ez3Q=
  • "Client", tested under arm64/amd64 Linux hosts (awg-go + awg-kmod), Android device with amnezia-client (arm64), and iOS device (arm64) with amnezia-client. Config:
[Interface]
Jc = 1
Jmin = 1
Jmax = 2
H1 = 1
H2 = 2
H3 = 3
H4 = 4
S1 = 0
S2 = 0
S3 = 20
S4 = 11
Address = 10.0.0.1/32
PrivateKey = mCa76dYIsAX8LzXqJFi8NJAhWrlsAlAQ/W4NTAT/bEc=

[Peer]
PublicKey = 4Z0bAvJZyCetk/cgn1EF4ULpmMNs7SRHyGK1g5hljgU=
Endpoint = <addr>:<port>
AllowedIPs = 0.0.0.0/0, ::/0

Works fine on my machine(s) :D

<!-- gh-comment-id:4430030417 --> @ygurov commented on GitHub (May 12, 2026): Just tested it out with the following setup: - EP under awg-kmod. Config: ``` [Interface] PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o <iface> -j MASQUERADE PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o <iface> -j MASQUERADE Address = 10.0.0.0/24 ListenPort = <port> PrivateKey = MKkmOiwkjeSiZ2eqKa7C+UcCBi2BQ9pGkgxpo4Yp1kw= S3 = 20 S4 = 11 [Peer] AllowedIPs = 10.0.0.1/32 PublicKey = 7Iz1JPdQbwY+/AEwVGEOYXl7366pLwuI4UZDhi1ez3Q= ``` - "Client", tested under arm64/amd64 Linux hosts (awg-go + awg-kmod), Android device with amnezia-client (arm64), and iOS device (arm64) with amnezia-client. Config: ``` [Interface] Jc = 1 Jmin = 1 Jmax = 2 H1 = 1 H2 = 2 H3 = 3 H4 = 4 S1 = 0 S2 = 0 S3 = 20 S4 = 11 Address = 10.0.0.1/32 PrivateKey = mCa76dYIsAX8LzXqJFi8NJAhWrlsAlAQ/W4NTAT/bEc= [Peer] PublicKey = 4Z0bAvJZyCetk/cgn1EF4ULpmMNs7SRHyGK1g5hljgU= Endpoint = <addr>:<port> AllowedIPs = 0.0.0.0/0, ::/0 ``` Works fine on my machine(s) :D
Author
Owner

@remotetohome commented on GitHub (May 13, 2026):

@ygurov - Thank you for testing, but I think the test config you used doesn't exercise the failure path. Two issues:

  1. Server [Interface] has no H1-H4 set, which I'm sure you know causes amneziawg.ko to fall back to standard WG message-type bytes (1/2/3/4). The client config explicitly sets H1=1, H2=2, H3=3, H4=4, which matches the server defaults. The net result: no header randomization is actually happening on the wire.

  2. The likely root-cause sibling amneziawg-go#110 reports byte-1 and byte-2 of the H4 uint32 corrupted in outbound transport packets on arm64. When H4 = 4, its little-endian byte representation is {0x04, 0x00, 0x00, 0x00} - bytes 1-2 are already zero, so any corruption is invisible. The bug requires H4 to have non-zero bytes 1-2 to surface.

Our generator produces H values from [100M, 4.29B] - e.g. H4 = 2037315187 = {0x73, 0xf6, 0x6e, 0x79} in little-endian. Bytes 1-2 (0xf6, 0x6e) are meaningful and observable if corrupted.

Could you re-test with realistic Path C parameters?

  • H1, H2, H3, H4 = random uint32 in [100,000,000, 4,294,967,295]
    (e.g. H1=1667376553, H2=1909203890, H3=509293734, H4=2037315187)
  • S1 = random in [40, 80] (e.g. 42)
  • S2 = random in [30, 60] (e.g. 59)
  • S3 = random in [16, 48] (e.g. 38)
  • S4 = random in [8, 24] (e.g. 22)
  • Jc = random in [3, 5] (e.g. 3)
  • Jmin = random in [40, 50] (e.g. 46)
  • Jmax = random in [60, 70] (e.g. 67)

Server [Interface] needs to have ALL of these set identically too, not just S3/S4. AmneziaWG params must match exactly on both sides.

These are the actual ranges our generator produces, and the real-world values shape that surfaces the bug in production.

TLDR; This isn't an S3/S4 bug per se - it's the suspected #110 H4 corruption surfacing only when BOTH conditions hit:
(1) S4 ≠ 0 (shifts H4's byte offset in transport packets), AND
(2) H4 has non-zero bytes 1-2 (the corruption is observable).

If either condition absent > bug hidden. That's why your test (H4 = 4, trivial bytes) showed no failure even with S3/S4 non-zero.

<!-- gh-comment-id:4436080764 --> @remotetohome commented on GitHub (May 13, 2026): @ygurov - Thank you for testing, but I think the test config you used doesn't exercise the failure path. Two issues: 1. Server [Interface] has no H1-H4 set, which I'm sure you know causes amneziawg.ko to fall back to standard WG message-type bytes (1/2/3/4). The client config explicitly sets H1=1, H2=2, H3=3, H4=4, which matches the server defaults. The net result: no header randomization is actually happening on the wire. 2. The likely root-cause sibling [amneziawg-go#110](https://github.com/amnezia-vpn/amneziawg-go/issues/110) reports byte-1 and byte-2 of the H4 uint32 corrupted in outbound transport packets on arm64. When H4 = 4, its little-endian byte representation is {0x04, 0x00, 0x00, 0x00} - bytes 1-2 are already zero, so any corruption is invisible. The bug requires H4 to have non-zero bytes 1-2 to surface. Our generator produces H values from [100M, 4.29B] - e.g. H4 = 2037315187 = {0x73, 0xf6, 0x6e, 0x79} in little-endian. Bytes 1-2 (0xf6, 0x6e) are meaningful and observable if corrupted. Could you re-test with realistic Path C parameters? - H1, H2, H3, H4 = random uint32 in [100,000,000, 4,294,967,295] (e.g. H1=1667376553, H2=1909203890, H3=509293734, H4=2037315187) - S1 = random in [40, 80] (e.g. 42) - S2 = random in [30, 60] (e.g. 59) - S3 = random in [16, 48] (e.g. 38) - S4 = random in [8, 24] (e.g. 22) - Jc = random in [3, 5] (e.g. 3) - Jmin = random in [40, 50] (e.g. 46) - Jmax = random in [60, 70] (e.g. 67) Server [Interface] needs to have ALL of these set identically too, not just S3/S4. AmneziaWG params must match exactly on both sides. These are the actual ranges our generator produces, and the real-world values shape that surfaces the bug in production. **TLDR;** This isn't an S3/S4 bug per se - it's the suspected #110 H4 corruption surfacing only when BOTH conditions hit: (1) S4 ≠ 0 (shifts H4's byte offset in transport packets), AND (2) H4 has non-zero bytes 1-2 (the corruption is observable). If either condition absent > bug hidden. That's why your test (H4 = 4, trivial bytes) showed no failure even with S3/S4 non-zero.
Author
Owner

@remotetohome commented on GitHub (May 13, 2026):

@ygurov - retested to reproduce again (to be 100% sure), then went bug hunting.. underlying issue and PR fix here:
https://github.com/amnezia-vpn/amneziawg-go/pull/137

<!-- gh-comment-id:4437487859 --> @remotetohome commented on GitHub (May 13, 2026): @ygurov - retested to reproduce again (to be 100% sure), then went bug hunting.. underlying issue and PR fix here: https://github.com/amnezia-vpn/amneziawg-go/pull/137
Author
Owner

@remotetohome commented on GitHub (May 13, 2026):

@ygurov - Annnd.. after submitting the PR, I notice this one.. closing mine as dup (though you may want to consider also adding the spy bind from mine).
https://github.com/amnezia-vpn/amneziawg-go/pull/129

<!-- gh-comment-id:4437765743 --> @remotetohome commented on GitHub (May 13, 2026): @ygurov - Annnd.. after submitting the PR, I notice this one.. closing mine as dup (though you may want to consider also adding the spy bind from mine). https://github.com/amnezia-vpn/amneziawg-go/pull/129
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/amnezia-client#1173
No description provided.