[Bug]
[Bug] AmneziaWG v3 (Header Protection) handshake never completes — silent failure, no errors in logs
Description
WireGuard proxies configured with amnezia-wg-option.version: 3 and header-protection-key (AmneziaWG 3.0/3.1 protocol, per [official Amnezia spec](https://docs.amnezia.org/documentation/amnezia-wg/)) never establish a connection. The proxy is silently dropped from group delay-test results — no error is logged anywhere, even with log-level: debug.
Plain WireGuard and other proxy types (VLESS+Reality, Hysteria2, etc.) on the same mihomo instance work correctly. Raw UDP connectivity to the AmneziaWG server is confirmed open (nc -u -zv succeeds). The config was independently verified field-by-field against the actual struct definition in adapter/outbound/wireguard.go (commit 8453e58, "feat: support AmneziaWG v3.0") and against the [official Amnezia protocol documentation](https://docs.amnezia.org/documentation/amnezia-wg/) — every field name, type, and value matches the expected schema exactly.
Reproduction Steps
- Obtain an AmneziaWG v3 client config (
.conf) from an Amnezia Premium/self-hosted server that has Header Protection enabled (i.e. the exported config includesHeaderProtectionKey). - Convert it to mihomo YAML format (mapping confirmed correct against source):
proxies:
- name: "amneziawg-v3-test"
type: wireguard
server: <server-ip>
port: <port>
ip: <client-tunnel-ip>/32
private-key: <REDACTED>
public-key: <REDACTED>
udp: true
pre-shared-key: <REDACTED>
persistent-keepalive: 25
amnezia-wg-option:
jc: 6
jmin: 10
jmax: 80
s1: 381
s2: 865
s3: 209
s4: 12
h1: 1
h2: 2
h3: 3
h4: 4
version: 3
header-protection-key: <REDACTED, 32-byte base64>
content-padding-addition: 10-100
rekey-after-time: 100-120
rekey-timeout: 3-8
reject-after-time: 150-180
keepalive-timeout: 7-13
max-handshake-attempts: 15-20- Add the proxy to a
url-testgroup, or query directly:GET /proxies/{name}/delay?url=http://www.gstatic.com/generate_204&timeout=10000 - Observe: request returns
404 Not Foundwhen queried individually by name; the proxy is simply absent from/group/{name}/delaybatch results (all other proxies in the group return normally).
Expected behavior
The proxy either connects successfully, or mihomo logs a specific handshake/connection error (even at debug level) that would help diagnose a config mismatch.
Actual behavior
- No log line is ever produced mentioning the proxy, WireGuard, or a handshake attempt/failure — confirmed via
log-level: debugand/log printfiltering oncontainer,wireguard, and the proxy name. - The proxy is silently excluded from delay-test group results, exactly as if it never existed.
- Direct
/proxies/{name}/delayreturns404, even though the same name is confirmed present in/proxies(GLOBAL/groupalllist) and in/providers/proxies/{provider}.
What I've already ruled out
- Config correctness: field names/types verified line-by-line against
adapter/outbound/wireguard.godiff for commit8453e58(feat: support AmneziaWG v3.0). No typos, no missing/extra fields. - Network reachability:
nc -u -zv -w5 <server> <port>from inside the mihomo container returnsopen. - mihomo version: reproduced specifically on
v1.19.30(release that introduced AmneziaWG v3.0/v3.1 support), confirmed via/versionendpoint. Also briefly tested against aPrerelease-Alphabuild (alpha-dca26db) with the same result. - Non-AmneziaWG proxies: dozens of other proxy types (VLESS+Reality, VLESS+gRPC, Hysteria2, standard WireGuard without
amnezia-wg-option) on the exact same mihomo instance work normally.
Possible root cause (unconfirmed)
Other projects that implement AmneziaWG v3 support have independently documented that even officially tagged/published amneziawg-go artifacts have shipped without a fully working v3 UAPI implementation — see [amnezia-control v0.47.0 changelog](https://github.com/mihsergeev/amnezia-control/releases/tag/v0.47.0):
"The published amneziavpn/amneziawg-go image — even tagged 3.0.2 — still ships amneziawg-tools v1.0.20210914 and an engine without the 3.0 UAPI keys, so
awg setconfrejectsHeaderProtectionKeyoutright (verified on a live node)."
mihomo depends on github.com/metacubex/amneziawg-go (a fork, not upstream amnezia-vpn/amneziawg-go). It's possible this fork has a similar staleness/incompleteness issue specifically around the v3 UAPI handshake path, even though the Go struct/config-parsing layer (AmneziaWGOption) is fully wired up correctly.
Confirmed working reference implementations (v3.1, full Header Protection)
Importantly, this is not an inherent protocol limitation — multiple independent, actively maintained community projects have successfully implemented full AmneziaWG 3.1 support (including HeaderProtectionKey, ContentPaddingAddition, and all the other v3+ timing/obfuscation fields), which strongly suggests the gap is specific to metacubex/amneziawg-go's handshake path rather than something fundamentally unsupportable:
- [mrnman66/awg-openwrt](https://github.com/mrnman66/awg-openwrt) — OpenWrt packages with an explicit
-a 3.1install profile and direct.confimport (sh amneziawg-install.sh -e -a auto -c /root/client.conf). Confirms working AWG-3.1 on OpenWrt 24.10.7 through 25.12.5. - [2Grey/awg-openwrt](https://github.com/2Grey/awg-openwrt) — kernel module (
kmod-amneziawgv3.1.20260906) + LuCI integration, explicitly listing support forHeaderProtectionKey,ContentPaddingAddition,RekeyAfterTime,RekeyTimeout,RejectAfterTime,KeepaliveTimeout,MaxHandshakeAttempts,RandomTrailers,DisableCookies, and rangedH1-H4/PersistentKeepalive. - [LamFex/openwrt-amneziawg3](https://github.com/LamFex/openwrt-amneziawg3) — userspace
amneziawg-govia TUN (same general approach as mihomo's own WireGuard outbound), also targeting full v3.1 support.
Since at least one of these (LamFex/openwrt-amneziawg3) uses the same userspace-Go-over-TUN architecture as mihomo rather than a kernel module, it may be a useful direct comparison point for whichever part of the v3 handshake/header-protection path is failing silently in metacubex/amneziawg-go.
Environment
- mihomo version:
v1.19.30(also reproduced onalpha-dca26db) - Platform: MikroTik RouterOS 7.x,
containerpackage,linux/arm64(also reproducible cross-platform in principle, not RouterOS-specific — the config/API-level symptoms are platform-independent) - Proxy type:
wireguardwithamnezia-wg-option.version: 3
Additional notes
Would be happy to provide a redacted pcap if a maintainer can point me to how to enable amneziawg-go-level debug tracing specifically (separate from mihomo's own log-level: debug, which does not surface anything for this code path).
Source: MetaCubeX/mihomo